From c87660480d8c18d94cee61a20276f70919639012 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 12 Mar 2022 15:47:39 +0100 Subject: [PATCH] [d3d11] Reimplement R11G11B10 UAV clears without R32 views --- src/d3d11/d3d11_context.cpp | 53 +++++++++++++++++++++++++++++++------ src/dxgi/dxgi_format.cpp | 2 +- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 412f5e81..0d530abb 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -576,7 +576,7 @@ namespace dxvk { Logger::err(str::format("D3D11: ClearUnorderedAccessViewUint: No raw format found for ", uavFormat)); return; } - + // Set up clear color struct VkClearValue clearValue; clearValue.color.uint32[0] = Values[0]; @@ -584,13 +584,20 @@ namespace dxvk { clearValue.color.uint32[2] = Values[2]; clearValue.color.uint32[3] = Values[3]; - // This is the only packed format that has UAV support - if (uavFormat == VK_FORMAT_B10G11R11_UFLOAT_PACK32) { + // R11G11B10 is a special cases since there's no corresponding integer format + // with the same bit layout, and creating an R32 view may disable compression, + // so if we can't preserve the bit pattern for non-zero values, we can create + // a temporary buffer instead and perform a copy from that. + bool useBuffer = false; + + if (rawFormat == VK_FORMAT_B10G11R11_UFLOAT_PACK32) { + useBuffer = (Values[0] | Values[1] | Values[2]) != 0; + clearValue.color.uint32[0] = ((Values[0] & 0x7FF) << 0) | ((Values[1] & 0x7FF) << 11) | ((Values[2] & 0x3FF) << 22); } - + if (uav->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) { // In case of raw and structured buffers as well as typed // buffers that can be used for atomic operations, we can @@ -599,9 +606,10 @@ namespace dxvk { if (bufferView->info().format == VK_FORMAT_R32_UINT || bufferView->info().format == VK_FORMAT_R32_SINT - || bufferView->info().format == VK_FORMAT_R32_SFLOAT) { + || bufferView->info().format == VK_FORMAT_R32_SFLOAT + || bufferView->info().format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) { EmitCs([ - cClearValue = Values[0], + cClearValue = clearValue.color.uint32[0], cDstSlice = bufferView->slice() ] (DxvkContext* ctx) { ctx->clearBuffer( @@ -630,6 +638,36 @@ namespace dxvk { cClearValue.color); }); } + } else if (useBuffer) { + Rc imageView = uav->GetImageView(); + + DxvkBufferCreateInfo bufferInfo; + bufferInfo.size = imageView->formatInfo()->elementSize + * imageView->info().numLayers + * util::flattenImageExtent(imageView->mipLevelExtent(0)); + bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + bufferInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + bufferInfo.access = VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_TRANSFER_WRITE_BIT; + + Rc buffer = m_device->createBuffer(bufferInfo, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + EmitCs([ + cDstView = std::move(imageView), + cSrcBuffer = std::move(buffer), + cClearValue = clearValue.color.uint32[0] + ] (DxvkContext* ctx) { + ctx->clearBuffer(cSrcBuffer, 0, + cSrcBuffer->info().size, cClearValue); + + ctx->copyBufferToImage(cDstView->image(), + vk::pickSubresourceLayers(cDstView->subresources(), 0), + VkOffset3D { 0, 0, 0 }, + cDstView->mipLevelExtent(0), + cSrcBuffer, 0, 0, 0); + }); } else { // Create a view with an integer format if necessary Rc imageView = uav->GetImageView(); @@ -638,8 +676,7 @@ namespace dxvk { DxvkImageViewCreateInfo info = imageView->info(); info.format = rawFormat; - imageView = m_device->createImageView( - imageView->image(), info); + imageView = m_device->createImageView(imageView->image(), info); } EmitCs([ diff --git a/src/dxgi/dxgi_format.cpp b/src/dxgi/dxgi_format.cpp index a8551da6..080458bc 100644 --- a/src/dxgi/dxgi_format.cpp +++ b/src/dxgi/dxgi_format.cpp @@ -129,7 +129,7 @@ namespace dxvk { // DXGI_FORMAT_R11G11B10_FLOAT { VK_FORMAT_B10G11R11_UFLOAT_PACK32, VK_FORMAT_UNDEFINED, - VK_FORMAT_R32_UINT, + VK_FORMAT_B10G11R11_UFLOAT_PACK32, VK_IMAGE_ASPECT_COLOR_BIT }, // DXGI_FORMAT_R8G8B8A8_TYPELESS { VK_FORMAT_R8G8B8A8_UNORM,