DECLARE_EXPORT Operation* BufferProcure::getOperation() const { if (!oper) { Operation *o = Operation::find(PURCHASE_OPERATION); if (!o) { // Create a new purchase operation o = new OperationFixedTime(); o->setName(PURCHASE_OPERATION); static_cast<OperationFixedTime*>(o)->setDuration(leadtime); new FlowEnd(o, const_cast<BufferProcure*>(this), 1); } // Copy procurement parameters to the existing operation if (o->getType() == *OperationFixedTime::metadata) static_cast<OperationFixedTime*>(o)->setDuration(leadtime); const_cast<BufferProcure*>(this)->oper = o; o->setFence(getFence()); o->setSizeMaximum(getSizeMaximum()); o->setSizeMinimum(getSizeMinimum()); o->setSizeMultiple(getSizeMultiple()); if (!o->getLocation()) o->setLocation(getLocation()); o->setSource(getSource()); } return oper; }
vkts::IImageDataSP Example::gatherImageData() const { VkResult result; auto fence = vkts::fenceCreate(device->getDevice(), 0); if (!fence.get()) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not create fence."); return vkts::IImageDataSP(); } // auto imageData = vkts::imageDataCreate(VKTS_IMAGE_NAME, VKTS_IMAGE_LENGTH, VKTS_IMAGE_LENGTH, 1, 1.0f, 0.0f, 0.0f, 1.0f, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM); // Check, if we can use a linear tiled image for staging. if (physicalDevice->isImageTilingAvailable(VK_IMAGE_TILING_LINEAR, imageData->getFormat(), imageData->getImageType(), 0, imageData->getExtent3D(), imageData->getMipLevels(), 1, VK_SAMPLE_COUNT_1_BIT, imageData->getSize())) { vkts::IImageSP stageImage; vkts::IDeviceMemorySP stageDeviceMemory; if (!createTexture(stageImage, stageDeviceMemory, VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0)) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not create stage image and device memory."); return vkts::IImageDataSP(); } // cmdBuffer->reset(); result = cmdBuffer->beginCommandBuffer(0, VK_NULL_HANDLE, 0, VK_NULL_HANDLE, VK_FALSE, 0, 0); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not begin command buffer."); return vkts::IImageDataSP(); } VkImageSubresourceRange imageSubresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; // Prepare stage image for final layout etc. stageImage->cmdPipelineBarrier(cmdBuffer->getCommandBuffer(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageSubresourceRange); VkImageCopy imageCopy; imageCopy.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; imageCopy.srcOffset = {0, 0, 0}; imageCopy.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; imageCopy.dstOffset = {0, 0, 0}; imageCopy.extent = { VKTS_IMAGE_LENGTH, VKTS_IMAGE_LENGTH, 1u }; // Copy form device to host visible image / memory. This command also sets the needed barriers. image->copyImage(cmdBuffer->getCommandBuffer(), stageImage, imageCopy); stageImage->cmdPipelineBarrier(cmdBuffer->getCommandBuffer(), VK_ACCESS_HOST_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, imageSubresourceRange); result = cmdBuffer->endCommandBuffer(); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not end command buffer."); return VK_FALSE; } VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.waitSemaphoreCount = 0; submitInfo.pWaitSemaphores = nullptr; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = cmdBuffer->getCommandBuffers(); submitInfo.signalSemaphoreCount = 0; submitInfo.pSignalSemaphores = nullptr; result = queue->submit(1, &submitInfo, fence->getFence()); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not submit queue."); return vkts::IImageDataSP(); } // result = fence->waitForFence(UINT64_MAX); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not wait for fence."); return vkts::IImageDataSP(); } // // Copy pixel data from device memory into image data memory. // VkImageSubresource imageSubresource; imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageSubresource.mipLevel = 0; imageSubresource.arrayLayer = 0; VkSubresourceLayout subresourceLayout; stageImage->getImageSubresourceLayout(subresourceLayout, imageSubresource); // result = stageDeviceMemory->mapMemory(0, VK_WHOLE_SIZE, 0); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not map memory."); return vkts::IImageDataSP(); } imageData->upload(stageDeviceMemory->getMemory(), 0, 0, subresourceLayout); if (!(stageDeviceMemory->getMemoryPropertyFlags() & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { result = stageDeviceMemory->invalidateMappedMemoryRanges(0, VK_WHOLE_SIZE); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not invalidate memory."); return VK_FALSE; } } stageDeviceMemory->unmapMemory(); // Stage image and device memory are automatically destroyed. } else { // As an alternative, use the buffer. vkts::IBufferSP stageBuffer; vkts::IDeviceMemorySP stageDeviceMemory; VkBufferCreateInfo bufferCreateInfo{}; bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferCreateInfo.size = imageData->getSize(); bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; bufferCreateInfo.flags = 0; bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; bufferCreateInfo.queueFamilyIndexCount = 0; bufferCreateInfo.pQueueFamilyIndices = nullptr; if (!createBuffer(stageBuffer, stageDeviceMemory, bufferCreateInfo, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not create buffer."); return vkts::IImageDataSP(); } // cmdBuffer->reset(); result = cmdBuffer->beginCommandBuffer(0, VK_NULL_HANDLE, 0, VK_NULL_HANDLE, VK_FALSE, 0, 0); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not begin command buffer."); return vkts::IImageDataSP(); } VkBufferImageCopy bufferImageCopy; bufferImageCopy.bufferOffset = 0; bufferImageCopy.bufferRowLength = VKTS_IMAGE_LENGTH; bufferImageCopy.bufferImageHeight = VKTS_IMAGE_LENGTH; bufferImageCopy.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; bufferImageCopy.imageOffset = {0, 0, 0}; bufferImageCopy.imageExtent = {VKTS_IMAGE_LENGTH, VKTS_IMAGE_LENGTH, 1}; image->copyImageToBuffer(cmdBuffer->getCommandBuffer(), stageBuffer, bufferImageCopy); result = cmdBuffer->endCommandBuffer(); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not end command buffer."); return VK_FALSE; } VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.waitSemaphoreCount = 0; submitInfo.pWaitSemaphores = nullptr; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = cmdBuffer->getCommandBuffers(); submitInfo.signalSemaphoreCount = 0; submitInfo.pSignalSemaphores = nullptr; result = queue->submit(1, &submitInfo, fence->getFence()); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not submit queue."); return vkts::IImageDataSP(); } // result = fence->waitForFence(UINT64_MAX); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not wait for fence."); return vkts::IImageDataSP(); } // // Copy pixel data from device memory into image data memory. // VkSubresourceLayout subresourceLayout; subresourceLayout.offset = 0; subresourceLayout.size = stageBuffer->getSize(); subresourceLayout.rowPitch = VKTS_IMAGE_LENGTH * 4 * sizeof(uint8_t); subresourceLayout.arrayPitch = VKTS_IMAGE_LENGTH * VKTS_IMAGE_LENGTH * 4 * sizeof(uint8_t); subresourceLayout.depthPitch = VKTS_IMAGE_LENGTH * VKTS_IMAGE_LENGTH * 4 * sizeof(uint8_t); result = stageDeviceMemory->mapMemory(0, VK_WHOLE_SIZE, 0); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not map memory."); return vkts::IImageDataSP(); } imageData->upload(stageDeviceMemory->getMemory(), 0, 0, subresourceLayout); if (!(stageDeviceMemory->getMemoryPropertyFlags() & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { result = stageDeviceMemory->invalidateMappedMemoryRanges(0, VK_WHOLE_SIZE); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, __FILE__, __LINE__, "Could not invalidate memory."); return VK_FALSE; } } stageDeviceMemory->unmapMemory(); // Stage image and device memory are automatically destroyed. } // Fence is automatically destroyed. return imageData; }