From d9eacc87b60417f1e8aa3fdf020c9d0b7c11818d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 3 Nov 2024 11:21:15 +0100 Subject: [PATCH] [d3d9] Fix various other ColorFill edge cases Fixes all remaining validation in wine's color_fill_test. Some failed tests remain because apparently we do not validate resource txpes properly. --- src/d3d9/d3d9_common_texture.h | 4 +- src/d3d9/d3d9_device.cpp | 97 ++++++++++++++++++++-------------- 2 files changed, 60 insertions(+), 41 deletions(-) diff --git a/src/d3d9/d3d9_common_texture.h b/src/d3d9/d3d9_common_texture.h index 6640e12b..58aa40ae 100644 --- a/src/d3d9/d3d9_common_texture.h +++ b/src/d3d9/d3d9_common_texture.h @@ -75,6 +75,8 @@ namespace dxvk { public: + static constexpr UINT AllLayers = UINT32_MAX; + D3D9CommonTexture( D3D9DeviceEx* pDevice, IUnknown* pInterface, @@ -555,8 +557,6 @@ namespace dxvk { D3DRESOURCETYPE Dimension, UINT Layer); - static constexpr UINT AllLayers = UINT32_MAX; - }; } diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index dee6b3a8..f1ae522e 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -1445,6 +1445,9 @@ namespace dxvk { D3D9CommonTexture* dstTextureInfo = dst->GetCommonTexture(); + if (dstTextureInfo->IsNull()) + return D3D_OK; + if (unlikely(dstTextureInfo->Desc()->Pool != D3DPOOL_DEFAULT)) return D3DERR_INVALIDCALL; @@ -1453,37 +1456,38 @@ namespace dxvk { VkOffset3D offset = VkOffset3D{ 0u, 0u, 0u }; VkExtent3D extent = mipExtent; - bool isFullExtent = true; - if (pRect != nullptr) { + if (pRect != nullptr) ConvertRect(*pRect, offset, extent); - isFullExtent = offset == VkOffset3D{ 0u, 0u, 0u } - && extent == mipExtent; - } - - Rc rtView = dst->GetRenderTargetView(false); - - if (unlikely(!rtView)) { - const D3D9Format format = dstTextureInfo->Desc()->Format; - - if (format != D3D9Format::NULL_FORMAT) - Logger::err(str::format("D3D9DeviceEx::ColorFill: Unsupported format ", format)); - - return D3D_OK; - } - VkClearValue clearValue = { }; DecodeD3DCOLOR(Color, clearValue.color.float32); - if (rtView && rtView->formatInfo()->flags.test(DxvkFormatFlag::BlockCompressed)) { + Rc image = dstTextureInfo->GetImage(); + + if (image->formatInfo()->aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) + return D3DERR_INVALIDCALL; + + VkImageSubresourceLayers subresource = { }; + subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + subresource.mipLevel = dst->GetMipLevel(); + + if (dst->GetFace() == D3D9CommonTexture::AllLayers) { + subresource.baseArrayLayer = 0u; + subresource.layerCount = image->info().numLayers; + } else { + subresource.baseArrayLayer = dst->GetFace(); + subresource.layerCount = 1u; + } + + if (image->formatInfo()->flags.test(DxvkFormatFlag::BlockCompressed)) { EmitCs([ - cImage = rtView->image(), - cViewKey = rtView->info(), + cImage = std::move(image), + cSubresource = subresource, cOffset = offset, cExtent = extent, cClearValue = clearValue ] (DxvkContext* ctx) { - auto formatInfo = lookupFormatInfo(cViewKey.format); + auto formatInfo = cImage->formatInfo(); VkFormat blockFormat = formatInfo->elementSize == 16u ? VK_FORMAT_R32G32B32A32_UINT @@ -1500,14 +1504,20 @@ namespace dxvk { ctx->ensureImageCompatibility(cImage, usage); - DxvkImageViewKey viewKey = cViewKey; + DxvkImageViewKey viewKey = { }; + viewKey.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; viewKey.format = blockFormat; viewKey.usage = VK_IMAGE_USAGE_STORAGE_BIT; + viewKey.aspects = cSubresource.aspectMask; + viewKey.mipIndex = cSubresource.mipLevel; + viewKey.mipCount = 1u; + viewKey.layerIndex = cSubresource.baseArrayLayer; + viewKey.layerCount = cSubresource.layerCount; Rc view = cImage->createView(viewKey); VkClearValue clearBlock = { }; - clearBlock.color = util::encodeClearBlockValue(cViewKey.format, cClearValue.color); + clearBlock.color = util::encodeClearBlockValue(cImage->info().format, cClearValue.color); VkOffset3D offset = util::computeBlockOffset(cOffset, formatInfo->blockSize); VkExtent3D extent = util::computeBlockExtent(cExtent, formatInfo->blockSize); @@ -1515,28 +1525,37 @@ namespace dxvk { ctx->clearImageView(view, offset, extent, VK_IMAGE_ASPECT_COLOR_BIT, clearBlock); }); - } else if (isFullExtent) { - EmitCs([ - cImageView = rtView, - cClearValue = clearValue - ] (DxvkContext* ctx) { - ctx->clearRenderTarget( - cImageView, - VK_IMAGE_ASPECT_COLOR_BIT, - cClearValue); - }); } else { EmitCs([ - cImageView = rtView, + cImage = std::move(image), + cSubresource = subresource, cOffset = offset, cExtent = extent, cClearValue = clearValue ] (DxvkContext* ctx) { - ctx->clearImageView( - cImageView, - cOffset, cExtent, - VK_IMAGE_ASPECT_COLOR_BIT, - cClearValue); + DxvkImageUsageInfo usage = { }; + usage.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + ctx->ensureImageCompatibility(cImage, usage); + + DxvkImageViewKey viewKey = { }; + viewKey.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewKey.format = cImage->info().format; + viewKey.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + viewKey.aspects = cSubresource.aspectMask; + viewKey.mipIndex = cSubresource.mipLevel; + viewKey.mipCount = 1u; + viewKey.layerIndex = cSubresource.baseArrayLayer; + viewKey.layerCount = cSubresource.layerCount; + + Rc view = cImage->createView(viewKey); + + if (cOffset == VkOffset3D() && cExtent == cImage->mipLevelExtent(viewKey.mipIndex)) { + ctx->clearRenderTarget(view, cSubresource.aspectMask, cClearValue); + } else { + ctx->clearImageView(view, cOffset, cExtent, + cSubresource.aspectMask, cClearValue); + } }); }