From b3c391d0716eaff9912b1f638f398383cfdd22b6 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 9 Dec 2017 03:53:42 +0100 Subject: [PATCH] [d3d11] Implemented depth-stencil binding and clear methods --- src/d3d11/d3d11_context.cpp | 68 +++++++++++++++++++++++++-------- src/d3d11/d3d11_context_state.h | 3 +- src/dxvk/dxvk_cmdlist.cpp | 12 ++++++ src/dxvk/dxvk_cmdlist.h | 7 ++++ src/dxvk/dxvk_context.cpp | 32 ++++++++++++++++ src/dxvk/dxvk_context.h | 12 ++++++ src/dxvk/dxvk_framebuffer.cpp | 20 ---------- src/dxvk/dxvk_framebuffer.h | 12 ------ 8 files changed, 116 insertions(+), 50 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 9ec5cd53..897fe724 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -276,17 +276,15 @@ namespace dxvk { ID3D11RenderTargetView* pRenderTargetView, const FLOAT ColorRGBA[4]) { auto rtv = static_cast(pRenderTargetView); - - const Rc dxvkView = rtv->GetDXVKImageView(); - const Rc dxvkImage = dxvkView->image(); + const Rc dxvkView = rtv->GetDXVKImageView(); // Find out whether the given attachment is currently bound // or not, and if it is, which attachment index it has. int32_t attachmentIndex = -1; - if (m_state.om.framebuffer != nullptr) { - attachmentIndex = m_state.om.framebuffer - ->renderTargets().getAttachmentId(dxvkView); + for (uint32_t i = 0; i < m_state.om.renderTargetViews.size(); i++) { + if (m_state.om.renderTargetViews.at(i) == rtv) + attachmentIndex = i; } // Copy the clear color into a clear value structure. @@ -309,10 +307,10 @@ namespace dxvk { VkClearRect clearRect; clearRect.rect.offset.x = 0; clearRect.rect.offset.y = 0; - clearRect.rect.extent.width = dxvkImage->info().extent.width; - clearRect.rect.extent.height = dxvkImage->info().extent.height; + clearRect.rect.extent.width = dxvkView->imageInfo().extent.width; + clearRect.rect.extent.height = dxvkView->imageInfo().extent.height; clearRect.baseArrayLayer = 0; - clearRect.layerCount = dxvkImage->info().numLayers; + clearRect.layerCount = dxvkView->imageInfo().numLayers; if (m_parent->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0) clearRect.layerCount = 1; @@ -321,7 +319,7 @@ namespace dxvk { } else { // Image is not bound to the pipeline. We can still clear // it, but we'll have to use a generic clear function. - m_context->clearColorImage(dxvkImage, + m_context->clearColorImage(dxvkView->image(), clearValue, dxvkView->subresources()); } } @@ -346,7 +344,45 @@ namespace dxvk { UINT ClearFlags, FLOAT Depth, UINT8 Stencil) { - Logger::err("D3D11DeviceContext::ClearDepthStencilView: Not implemented"); + auto dsv = static_cast(pDepthStencilView); + const Rc dxvkView = dsv->GetDXVKImageView(); + + VkClearDepthStencilValue clearValue; + clearValue.depth = Depth; + clearValue.stencil = Stencil; + + if (m_state.om.depthStencilView == dsv) { + // Image is bound to the pipeline for rendering. We can + // use the clear function that operates on attachments. + VkClearAttachment clearInfo; + clearInfo.aspectMask = 0; + clearInfo.colorAttachment = 0; + clearInfo.clearValue.depthStencil = clearValue; + + if (ClearFlags & D3D11_CLEAR_DEPTH) + clearInfo.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; + + if (ClearFlags & D3D11_CLEAR_STENCIL) + clearInfo.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + + // Clear the full area + VkClearRect clearRect; + clearRect.rect.offset.x = 0; + clearRect.rect.offset.y = 0; + clearRect.rect.extent.width = dxvkView->imageInfo().extent.width; + clearRect.rect.extent.height = dxvkView->imageInfo().extent.height; + clearRect.baseArrayLayer = 0; + clearRect.layerCount = dxvkView->imageInfo().numLayers; + + // FIXME Is this correct? Docs don't say anything + if (m_parent->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0) + clearRect.layerCount = 1; + + m_context->clearRenderTarget(clearInfo, clearRect); + } else { + m_context->clearDepthStencilImage(dxvkView->image(), + clearValue, dxvkView->subresources()); + } } @@ -1109,7 +1145,6 @@ namespace dxvk { UINT NumViews, ID3D11RenderTargetView* const* ppRenderTargetViews, ID3D11DepthStencilView* pDepthStencilView) { - // Update state vector for OMGetRenderTargets for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) { D3D11RenderTargetView* view = nullptr; @@ -1119,6 +1154,9 @@ namespace dxvk { m_state.om.renderTargetViews.at(i) = view; } + m_state.om.depthStencilView = static_cast(pDepthStencilView); + + // TODO unbind overlapping shader resource views Rc framebuffer = nullptr; @@ -1134,15 +1172,13 @@ namespace dxvk { attachments.setColorTarget(i, m_state.om.renderTargetViews.at(i)->GetDXVKImageView()); } - // TODO implement depth-stencil views - if (pDepthStencilView != nullptr) - Logger::err("D3D11DeviceContext::OMSetRenderTargets: Depth-stencil view not supported"); + if (m_state.om.depthStencilView != nullptr) + attachments.setDepthTarget(m_state.om.depthStencilView->GetDXVKImageView()); framebuffer = m_device->createFramebuffer(attachments); } // Bind the framebuffer object to the context - m_state.om.framebuffer = framebuffer; m_context->bindFramebuffer(framebuffer); } diff --git a/src/d3d11/d3d11_context_state.h b/src/d3d11/d3d11_context_state.h index 71baa063..57b426fc 100644 --- a/src/d3d11/d3d11_context_state.h +++ b/src/d3d11/d3d11_context_state.h @@ -74,8 +74,7 @@ namespace dxvk { struct D3D11ContextStateOM { std::array, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> renderTargetViews; - - Rc framebuffer; + Com depthStencilView; }; diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp index 63bfba04..dc99b857 100644 --- a/src/dxvk/dxvk_cmdlist.cpp +++ b/src/dxvk/dxvk_cmdlist.cpp @@ -194,6 +194,18 @@ namespace dxvk { } + void DxvkCommandList::cmdClearDepthStencilImage( + VkImage image, + VkImageLayout imageLayout, + const VkClearDepthStencilValue* pDepthStencil, + uint32_t rangeCount, + const VkImageSubresourceRange* pRanges) { + m_vkd->vkCmdClearDepthStencilImage(m_buffer, + image, imageLayout, pDepthStencil, + rangeCount, pRanges); + } + + void DxvkCommandList::cmdCopyBuffer( VkBuffer srcBuffer, VkBuffer dstBuffer, diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index 5ba73218..0039a206 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -117,6 +117,13 @@ namespace dxvk { uint32_t rangeCount, const VkImageSubresourceRange* pRanges); + void cmdClearDepthStencilImage( + VkImage image, + VkImageLayout imageLayout, + const VkClearDepthStencilValue* pDepthStencil, + uint32_t rangeCount, + const VkImageSubresourceRange* pRanges); + void cmdCopyBuffer( VkBuffer srcBuffer, VkBuffer dstBuffer, diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 521cb968..69d5f21a 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -229,6 +229,38 @@ namespace dxvk { } + void DxvkContext::clearDepthStencilImage( + const Rc& image, + const VkClearDepthStencilValue& value, + const VkImageSubresourceRange& subresources) { + this->renderPassEnd(); + + 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->cmdClearDepthStencilImage(image->handle(), + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + &value, 1, &subresources); + + 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); + } + + void DxvkContext::clearRenderTarget( const VkClearAttachment& attachment, const VkClearRect& clearArea) { diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index dce1c60e..0bbb4d7f 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -155,6 +155,18 @@ namespace dxvk { const VkClearColorValue& value, const VkImageSubresourceRange& subresources); + /** + * \brief Clears subresources of a depth-stencil image + * + * \param [in] image The image to clear + * \param [in] value Clear value + * \param [in] subresources Subresources to clear + */ + void clearDepthStencilImage( + const Rc& image, + const VkClearDepthStencilValue& value, + const VkImageSubresourceRange& subresources); + /** * \brief Clears an active render target * diff --git a/src/dxvk/dxvk_framebuffer.cpp b/src/dxvk/dxvk_framebuffer.cpp index 21376294..b1d7a46b 100644 --- a/src/dxvk/dxvk_framebuffer.cpp +++ b/src/dxvk/dxvk_framebuffer.cpp @@ -53,26 +53,6 @@ namespace dxvk { } - int32_t DxvkRenderTargets::getAttachmentId( - const Rc& view) const { - if (view == nullptr) - return -1; - - if (m_depthTarget == view) - return 0; - - uint32_t colorAttachmentBaseId = - m_depthTarget == nullptr ? 0 : 1; - - for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { - if (m_colorTargets.at(i) == view) - return i + colorAttachmentBaseId; - } - - return -1; - } - - DxvkFramebufferSize DxvkRenderTargets::renderTargetSize( const Rc& renderTarget) const { auto extent = renderTarget->image()->info().extent; diff --git a/src/dxvk/dxvk_framebuffer.h b/src/dxvk/dxvk_framebuffer.h index a644e2d3..5851bf47 100644 --- a/src/dxvk/dxvk_framebuffer.h +++ b/src/dxvk/dxvk_framebuffer.h @@ -94,18 +94,6 @@ namespace dxvk { */ DxvkFramebufferSize getImageSize() const; - /** - * \brief Retrieves the ID of an attachment - * - * This can be used to locate a color attachment - * or the depth-stencil attachment. Returns -1 - * if the given view is not an attachment. - * \param [in] view View to find - * \returns Attachment ID, or \c -1 - */ - int32_t getAttachmentId( - const Rc& view) const; - private: std::array, MaxNumRenderTargets> m_colorTargets;