From 0b1b898be4c839d04aeb726ebfc3388361303ded Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 15 Aug 2018 19:02:14 +0200 Subject: [PATCH] [d3d11] Implement ID3D11DeviceContext1::ClearView Required for Feature Level 11_1. --- src/d3d11/d3d11_context.cpp | 137 +++++++++++++++++++++++++++++++++++- src/d3d11/d3d11_device.cpp | 2 +- 2 files changed, 137 insertions(+), 2 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index d6217652..ab3a1e12 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -805,7 +805,142 @@ namespace dxvk { const FLOAT Color[4], const D3D11_RECT* pRect, UINT NumRects) { - Logger::err("D3D11DeviceContext::ClearView: not implemented"); + // ID3D11View has no methods to query the exact type of + // the view, so we'll have to check each possible class + auto dsv = dynamic_cast(pView); + auto rtv = dynamic_cast(pView); + auto uav = dynamic_cast(pView); + + // Retrieve underlying resource view + Rc bufView; + Rc imgView; + + if (dsv != nullptr) + imgView = dsv->GetImageView(); + + if (rtv != nullptr) + imgView = rtv->GetImageView(); + + if (uav != nullptr) { + bufView = uav->GetBufferView(); + imgView = uav->GetImageView(); + } + + // 3D views are unsupported + if (imgView != nullptr + && imgView->info().type == VK_IMAGE_VIEW_TYPE_3D) + return; + + // Query the view format. We'll have to convert + // the clear color based on the format's data type. + VkFormat format = VK_FORMAT_UNDEFINED; + + if (bufView != nullptr) + format = bufView->info().format; + + if (imgView != nullptr) + format = imgView->info().format; + + if (format == VK_FORMAT_UNDEFINED) + return; + + // We'll need the format info to determine the buffer + // element size, and we also need it for depth images. + const DxvkFormatInfo* formatInfo = imageFormatInfo(format); + + // Convert the clear color format. ClearView takes + // the clear value for integer formats as a set of + // integral floats, so we'll have to convert. + VkClearValue clearValue; + + if (imgView == nullptr || imgView->info().aspect & VK_IMAGE_ASPECT_COLOR_BIT) { + for (uint32_t i = 0; i < 4; i++) { + if (formatInfo->flags.test(DxvkFormatFlag::SampledUInt)) + clearValue.color.uint32[i] = uint32_t(Color[i]); + else if (formatInfo->flags.test(DxvkFormatFlag::SampledSInt)) + clearValue.color.int32[i] = int32_t(Color[i]); + else + clearValue.color.float32[i] = Color[i]; + } + } else { + clearValue.depthStencil.depth = Color[0]; + clearValue.depthStencil.stencil = 0; + } + + // Clear all the rectangles that are specified + for (uint32_t i = 0; i < NumRects; i++) { + if (pRect[i].left >= pRect[i].right + || pRect[i].top >= pRect[i].bottom) + continue; + + if (bufView != nullptr) { + VkDeviceSize offset = pRect[i].left; + VkDeviceSize length = pRect[i].right - pRect[i].left; + + EmitCs([ + cBufferView = bufView, + cRangeOffset = offset, + cRangeLength = length, + cClearValue = clearValue + ] (DxvkContext* ctx) { + ctx->clearBufferView( + cBufferView, + cRangeOffset, + cRangeLength, + cClearValue.color); + }); + } + + if (imgView != nullptr) { + VkOffset3D offset = { pRect[i].left, pRect[i].top, 0 }; + VkExtent3D extent = { + uint32_t(pRect[i].right - pRect[i].left), + uint32_t(pRect[i].bottom - pRect[i].top), 1 }; + + EmitCs([ + cImageView = imgView, + cAreaOffset = offset, + cAreaExtent = extent, + cClearValue = clearValue + ] (DxvkContext* ctx) { + ctx->clearImageView( + cImageView, + cAreaOffset, + cAreaExtent, + cClearValue); + }); + } + } + + // The rect array is optional, so if it is not + // specified, we'll have to clear the entire view + if (pRect == nullptr) { + if (bufView != nullptr) { + EmitCs([ + cBufferView = bufView, + cClearValue = clearValue, + cElementSize = formatInfo->elementSize + ] (DxvkContext* ctx) { + ctx->clearBufferView(cBufferView, + cBufferView->info().rangeOffset / cElementSize, + cBufferView->info().rangeLength / cElementSize, + cClearValue.color); + }); + } + + if (imgView != nullptr) { + EmitCs([ + cImageView = imgView, + cClearValue = clearValue + ] (DxvkContext* ctx) { + VkOffset3D offset = { 0, 0, 0 }; + VkExtent3D extent = cImageView->mipLevelExtent(0); + + ctx->clearImageView(cImageView, + offset, extent, cClearValue); + }); + } + } } diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index c6a0e6a2..f239cee8 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -1140,7 +1140,7 @@ namespace dxvk { info->UAVOnlyRenderingForcedSampleCount = FALSE; info->DiscardAPIsSeenByDriver = TRUE; info->FlagsForUpdateAndCopySeenByDriver = TRUE; - info->ClearView = FALSE; + info->ClearView = TRUE; info->CopyWithOverlap = FALSE; info->ConstantBufferPartialUpdate = TRUE; info->ConstantBufferOffsetting = TRUE;