diff --git a/src/dxgi/dxgi_presenter.cpp b/src/dxgi/dxgi_presenter.cpp index 1ad17d3a..956c34f0 100644 --- a/src/dxgi/dxgi_presenter.cpp +++ b/src/dxgi/dxgi_presenter.cpp @@ -120,9 +120,16 @@ namespace dxvk { void DxgiPresenter::initBackBuffer(const Rc& image) { + VkImageSubresourceRange sr; + sr.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + sr.baseMipLevel = 0; + sr.levelCount = image->info().mipLevels; + sr.baseArrayLayer = 0; + sr.layerCount = image->info().numLayers; + m_context->beginRecording( m_device->createCommandList()); - m_context->initImage(image, nullptr); + m_context->initImage(image, sr); m_device->submitCommandList( m_context->endRecording(), nullptr, nullptr); @@ -133,8 +140,9 @@ namespace dxvk { m_context->beginRecording( m_device->createCommandList()); - auto framebuffer = m_swapchain->getFramebuffer(m_acquireSync); + auto framebuffer = m_swapchain->getFramebuffer(m_acquireSync); auto framebufferSize = framebuffer->size(); + m_context->bindFramebuffer(framebuffer); VkViewport viewport; diff --git a/src/dxvk/dxvk_barrier.cpp b/src/dxvk/dxvk_barrier.cpp index ce1cf033..c218212d 100644 --- a/src/dxvk/dxvk_barrier.cpp +++ b/src/dxvk/dxvk_barrier.cpp @@ -9,20 +9,22 @@ namespace dxvk { const Rc& buffer, VkDeviceSize offset, VkDeviceSize size, - VkPipelineStageFlags stages, - VkAccessFlags access) { + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess) { const DxvkResourceAccessTypes accessTypes - = this->getAccessTypes(access); + = this->getAccessTypes(srcAccess); - m_srcStages |= stages; - m_dstStages |= buffer->info().stages; + m_srcStages |= srcStages; + m_dstStages |= dstStages; if (accessTypes.test(DxvkResourceAccessType::Write)) { VkBufferMemoryBarrier barrier; barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; barrier.pNext = nullptr; - barrier.srcAccessMask = access; - barrier.dstAccessMask = buffer->info().access; + barrier.srcAccessMask = srcAccess; + barrier.dstAccessMask = dstAccess; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.buffer = buffer->handle(); @@ -33,26 +35,35 @@ namespace dxvk { } - void DxvkBarrierSet::initImage( + void DxvkBarrierSet::accessImage( const Rc& image, const VkImageSubresourceRange& subresources, + VkImageLayout srcLayout, + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, VkImageLayout dstLayout, VkPipelineStageFlags dstStages, VkAccessFlags dstAccess) { + const DxvkResourceAccessTypes accessTypes + = this->getAccessTypes(srcAccess); + + m_srcStages |= srcStages; m_dstStages |= dstStages; - VkImageMemoryBarrier barrier; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.pNext = nullptr; - barrier.srcAccessMask = 0; - barrier.dstAccessMask = dstAccess; - barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - barrier.newLayout = dstLayout; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = image->handle(); - barrier.subresourceRange = subresources; - m_imgBarriers.push_back(barrier); + if ((srcLayout != dstLayout) || accessTypes.test(DxvkResourceAccessType::Write)) { + VkImageMemoryBarrier barrier; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.pNext = nullptr; + barrier.srcAccessMask = srcAccess; + barrier.dstAccessMask = dstAccess; + barrier.oldLayout = srcLayout; + barrier.newLayout = dstLayout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = image->handle(); + barrier.subresourceRange = subresources; + m_imgBarriers.push_back(barrier); + } } diff --git a/src/dxvk/dxvk_barrier.h b/src/dxvk/dxvk_barrier.h index ac08a6a2..8ed23e64 100644 --- a/src/dxvk/dxvk_barrier.h +++ b/src/dxvk/dxvk_barrier.h @@ -24,12 +24,17 @@ namespace dxvk { const Rc& buffer, VkDeviceSize offset, VkDeviceSize size, - VkPipelineStageFlags stages, - VkAccessFlags access); + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, + VkPipelineStageFlags dstStages, + VkAccessFlags dstAccess); - void initImage( + void accessImage( const Rc& image, const VkImageSubresourceRange& subresources, + VkImageLayout srcLayout, + VkPipelineStageFlags srcStages, + VkAccessFlags srcAccess, VkImageLayout dstLayout, VkPipelineStageFlags dstStages, VkAccessFlags dstAccess); diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index cb57c593..41d58334 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -148,7 +148,7 @@ namespace dxvk { if (image != nullptr) { descriptor.image.imageView = image->handle(); - descriptor.image.imageLayout = image->imageLayout(); + descriptor.image.imageLayout = VK_IMAGE_LAYOUT_GENERAL; } rc->bindShaderResource(slot, resource, descriptor); @@ -194,12 +194,27 @@ namespace dxvk { const VkImageSubresourceRange& subresources) { this->renderPassEnd(); - m_cmd->cmdClearColorImage( - image->handle(), - VK_IMAGE_LAYOUT_GENERAL, + if (image->info().layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + m_barriers.accessImage(image, subresources, + VK_IMAGE_LAYOUT_UNDEFINED, 0, 0, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + m_barriers.recordCommands(m_cmd); + } + + m_cmd->cmdClearColorImage(image->handle(), + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &value, 1, &subresources); - // TODO memory barrier + m_barriers.accessImage(image, subresources, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + image->info().layout, + image->info().stages, + image->info().access); + m_barriers.recordCommands(m_cmd); m_cmd->trackResource(image); } @@ -215,6 +230,8 @@ namespace dxvk { m_cmd->cmdClearAttachments( 1, &attachment, 1, &clearArea); + + // FIXME add barriers if required } @@ -238,12 +255,16 @@ namespace dxvk { m_barriers.accessBuffer( srcBuffer, srcOffset, numBytes, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_READ_BIT); + VK_ACCESS_TRANSFER_READ_BIT, + srcBuffer->info().stages, + srcBuffer->info().access); m_barriers.accessBuffer( dstBuffer, dstOffset, numBytes, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT); + VK_ACCESS_TRANSFER_WRITE_BIT, + dstBuffer->info().stages, + dstBuffer->info().access); m_barriers.recordCommands(m_cmd); @@ -293,32 +314,15 @@ namespace dxvk { } - void DxvkContext::initBuffer( - const Rc& buffer, - const Rc& data) { - // TODO implement - } - - void DxvkContext::initImage( - const Rc& image, - const Rc& data) { - const DxvkImageCreateInfo& info = image->info(); - - VkImageSubresourceRange sr; - sr.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - sr.baseMipLevel = 0; - sr.levelCount = info.mipLevels; - sr.baseArrayLayer = 0; - sr.layerCount = info.numLayers; - - m_barriers.initImage(image, sr, - VK_IMAGE_LAYOUT_GENERAL, - info.stages, - info.access); + const Rc& image, + const VkImageSubresourceRange& subresources) { + m_barriers.accessImage(image, subresources, + VK_IMAGE_LAYOUT_UNDEFINED, 0, 0, + image->info().layout, + image->info().stages, + image->info().access); m_barriers.recordCommands(m_cmd); - - // TODO implement data upload } @@ -399,6 +403,9 @@ namespace dxvk { && (m_state.om.framebuffer != nullptr)) { m_flags.set(DxvkContextFlag::GpRenderPassBound); + this->transformLayoutsRenderPassBegin( + m_state.om.framebuffer->renderTargets()); + const DxvkFramebufferSize fbSize = m_state.om.framebuffer->size(); @@ -427,6 +434,9 @@ namespace dxvk { if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) { m_flags.clr(DxvkContextFlag::GpRenderPassBound); m_cmd->cmdEndRenderPass(); + + this->transformLayoutsRenderPassEnd( + m_state.om.framebuffer->renderTargets()); } } @@ -569,6 +579,99 @@ namespace dxvk { } + void DxvkContext::transformLayoutsRenderPassBegin( + const DxvkRenderTargets& renderTargets) { + // Ensure that all color attachments are in the optimal layout. + // Any image that is used as a present source requires special + // care as we cannot use it for reading. + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + const Rc target = renderTargets.getColorTarget(i); + + if ((target != nullptr) + && (target->imageInfo().layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)) { + VkImageLayout srcLayout = target->imageInfo().layout; + + if (srcLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) + srcLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + m_barriers.accessImage( + target->image(), + target->subresources(), + srcLayout, + target->imageInfo().stages, + target->imageInfo().access, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); + } + } + + // Transform the depth-stencil view to the optimal layout + const Rc dsTarget = renderTargets.getDepthTarget(); + + if ((dsTarget != nullptr) + && (dsTarget->imageInfo().layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)) { + m_barriers.accessImage( + dsTarget->image(), + dsTarget->subresources(), + dsTarget->imageInfo().layout, + dsTarget->imageInfo().stages, + dsTarget->imageInfo().access, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); + } + + m_barriers.recordCommands(m_cmd); + } + + + void DxvkContext::transformLayoutsRenderPassEnd( + const DxvkRenderTargets& renderTargets) { + // Transform color attachments back to their original layouts and + // make sure that they can be used for subsequent draw or compute + // operations. Swap chain images are treated like any other image. + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + const Rc target = renderTargets.getColorTarget(i); + + if (target != nullptr) { + m_barriers.accessImage( + target->image(), + target->subresources(), + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + target->imageInfo().layout, + target->imageInfo().stages, + target->imageInfo().access); + } + } + + // Transform the depth-stencil attachment back to its original layout. + const Rc dsTarget = renderTargets.getDepthTarget(); + + if (dsTarget != nullptr) { + m_barriers.accessImage( + dsTarget->image(), + dsTarget->subresources(), + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + dsTarget->imageInfo().layout, + dsTarget->imageInfo().stages, + dsTarget->imageInfo().access); + } + + m_barriers.recordCommands(m_cmd); + } + + DxvkShaderResourceSlots* DxvkContext::getShaderResourceSlots(VkPipelineBindPoint pipe) { switch (pipe) { case VK_PIPELINE_BIND_POINT_GRAPHICS: return &m_gResources; diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 240d031f..64b26c5c 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -144,7 +144,7 @@ namespace dxvk { const DxvkBufferBinding& buffer); /** - * \brief Clears subresources of an image + * \brief Clears subresources of a color image * * \param [in] image The image to clear * \param [in] value Clear value @@ -224,31 +224,16 @@ namespace dxvk { uint32_t firstInstance); /** - * \brief Initializes a buffer - * - * Uploads initial data to the buffer so that it - * can be used for read-only operations. Unlike - * \ref initImage, calling this is optional. - * \param [in] buffer The buffer to initialize - * \param [in] data Initial data buffer - */ - void initBuffer( - const Rc& buffer, - const Rc& data); - - /** - * \brief Initializes an image + * \brief Initializes or invalidates an image * * Sets up the image layout for future operations - * and uploads data to the image. Note that this - * method \e must be executed on the GPU before - * the image can be used for any other operations. + * while discarding any previous contents. * \param [in] image The image to initialize - * \param [in] data Initial data. Can be omitted. + * \param [in] subresources Image subresources */ void initImage( - const Rc& image, - const Rc& data); + const Rc& image, + const VkImageSubresourceRange& subresources); /** * \brief Sets viewports @@ -336,6 +321,12 @@ namespace dxvk { void commitComputeBarriers(); + void transformLayoutsRenderPassBegin( + const DxvkRenderTargets& renderTargets); + + void transformLayoutsRenderPassEnd( + const DxvkRenderTargets& renderTargets); + DxvkShaderResourceSlots* getShaderResourceSlots( VkPipelineBindPoint pipe); diff --git a/src/dxvk/dxvk_image.h b/src/dxvk/dxvk_image.h index fd92fd64..6bacdf8e 100644 --- a/src/dxvk/dxvk_image.h +++ b/src/dxvk/dxvk_image.h @@ -170,6 +170,14 @@ namespace dxvk { return m_info; } + /** + * \brief Image properties + * \returns Image properties + */ + const DxvkImageCreateInfo& imageInfo() const { + return m_image->info(); + } + /** * \brief Image * \returns Image @@ -178,14 +186,6 @@ namespace dxvk { return m_image; } - /** - * \brief Image layout - * \returns Image layout - */ - VkImageLayout imageLayout() const { - return m_image->info().layout; - } - /** * \brief Subresource range * \returns Subresource range diff --git a/src/dxvk/dxvk_renderpass.cpp b/src/dxvk/dxvk_renderpass.cpp index 13a31248..fdabd288 100644 --- a/src/dxvk/dxvk_renderpass.cpp +++ b/src/dxvk/dxvk_renderpass.cpp @@ -40,9 +40,7 @@ namespace dxvk { DxvkRenderPass::DxvkRenderPass( const Rc& vkd, - const DxvkRenderPassFormat& fmt, - VkImageLayout initialLayout, - VkImageLayout finalLayout) + const DxvkRenderPassFormat& fmt) : m_vkd(vkd), m_format(fmt) { std::vector attachments; @@ -51,23 +49,17 @@ namespace dxvk { // Render passes may not require the previous // contents of the attachments to be preserved. - VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - VkAttachmentStoreOp storeOp = VK_ATTACHMENT_STORE_OP_STORE; - - if (initialLayout == VK_IMAGE_LAYOUT_UNDEFINED) - loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - if (fmt.getDepthFormat() != VK_FORMAT_UNDEFINED) { VkAttachmentDescription desc; desc.flags = 0; desc.format = fmt.getDepthFormat(); desc.samples = fmt.getSampleCount(); - desc.loadOp = loadOp; - desc.storeOp = storeOp; - desc.stencilLoadOp = loadOp; - desc.stencilStoreOp = storeOp; - desc.initialLayout = initialLayout; - desc.finalLayout = finalLayout; + desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; + desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; depthRef.attachment = attachments.size(); depthRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; @@ -81,15 +73,15 @@ namespace dxvk { if (fmt.getColorFormat(i) != VK_FORMAT_UNDEFINED) { VkAttachmentDescription desc; - desc.flags = 0; - desc.format = fmt.getColorFormat(i); - desc.samples = fmt.getSampleCount(); - desc.loadOp = loadOp; - desc.storeOp = storeOp; - desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - desc.initialLayout = initialLayout; - desc.finalLayout = finalLayout; + desc.flags = 0; + desc.format = fmt.getColorFormat(i); + desc.samples = fmt.getSampleCount(); + desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + desc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; colorRef.at(i).attachment = attachments.size(); colorRef.at(i).layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; @@ -160,9 +152,7 @@ namespace dxvk { Rc DxvkRenderPassPool::createRenderPass( const DxvkRenderPassFormat& fmt) { - return new DxvkRenderPass(m_vkd, fmt, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_GENERAL); + return new DxvkRenderPass(m_vkd, fmt); } } \ No newline at end of file diff --git a/src/dxvk/dxvk_renderpass.h b/src/dxvk/dxvk_renderpass.h index 4ced82b8..e2297578 100644 --- a/src/dxvk/dxvk_renderpass.h +++ b/src/dxvk/dxvk_renderpass.h @@ -110,9 +110,7 @@ namespace dxvk { DxvkRenderPass( const Rc& vkd, - const DxvkRenderPassFormat& fmt, - VkImageLayout initialLayout, - VkImageLayout finalLayout); + const DxvkRenderPassFormat& fmt); ~DxvkRenderPass(); /** diff --git a/src/dxvk/dxvk_swapchain.cpp b/src/dxvk/dxvk_swapchain.cpp index 060e0f89..ab3533f9 100644 --- a/src/dxvk/dxvk_swapchain.cpp +++ b/src/dxvk/dxvk_swapchain.cpp @@ -129,9 +129,7 @@ namespace dxvk { renderTargetFormat.setColorFormat(0, fmt.format); m_renderPass = new DxvkRenderPass( - m_vkd, renderTargetFormat, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + m_vkd, renderTargetFormat); // Retrieve swap images auto swapImages = this->retrieveSwapImages(); @@ -152,7 +150,7 @@ namespace dxvk { imageInfo.access = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT; - imageInfo.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + imageInfo.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; DxvkImageViewCreateInfo viewInfo; viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;