From af0009c5debe33cffd5e412d0ff3d8adcd064c55 Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Sat, 8 Apr 2023 03:15:39 +0200 Subject: [PATCH] [d3d9] Use DxvkFormatInfo for video formats And fix UYUY and YUY2 in the process. --- src/d3d9/d3d9_common_texture.cpp | 27 +++++++++++++---- src/d3d9/d3d9_common_texture.h | 2 ++ src/d3d9/d3d9_device.cpp | 51 ++++++++++++++++++++------------ src/d3d9/d3d9_format.cpp | 24 +++++++-------- src/d3d9/d3d9_format.h | 1 - 5 files changed, 68 insertions(+), 37 deletions(-) diff --git a/src/d3d9/d3d9_common_texture.cpp b/src/d3d9/d3d9_common_texture.cpp index 8cb723d2..8a0b1bd0 100644 --- a/src/d3d9/d3d9_common_texture.cpp +++ b/src/d3d9/d3d9_common_texture.cpp @@ -238,13 +238,21 @@ namespace dxvk { const VkExtent3D mipExtent = util::computeMipLevelExtent( GetExtent(), MipLevel); + VkExtent3D blockSize = formatInfo->blockSize; + uint32_t elementSize = formatInfo->elementSize; + if (unlikely(formatInfo->flags.test(DxvkFormatFlag::MultiPlane))) { + // D3D9 doesn't allow specifying the plane when locking a texture. + // So the subsampled planes inherit the pitch of the first plane. + // That means the size is the size of plane 0 * plane count + elementSize = formatInfo->planes[0].elementSize; + blockSize = { formatInfo->planes[0].blockSize.width, formatInfo->planes[0].blockSize.height, 1u }; + } + const VkExtent3D blockCount = util::computeBlockCount( - mipExtent, formatInfo->blockSize); + mipExtent, blockSize); - const uint32_t planeCount = m_mapping.ConversionFormatInfo.PlaneCount; - - return std::min(planeCount, 2u) - * align(formatInfo->elementSize * blockCount.width, 4) + return std::min(GetPlaneCount(), 2u) + * align(elementSize * blockCount.width, 4) * blockCount.height * blockCount.depth; } @@ -675,4 +683,13 @@ namespace dxvk { return DxvkBufferSlice(GetBuffer(), m_memoryOffset[Subresource], GetMipSize(Subresource)); } + + uint32_t D3D9CommonTexture::GetPlaneCount() const { + const DxvkFormatInfo* formatInfo = m_mapping.FormatColor != VK_FORMAT_UNDEFINED + ? lookupFormatInfo(m_mapping.FormatColor) + : m_device->UnsupportedFormatInfo(m_desc.Format); + + return vk::getPlaneCount(formatInfo->aspectMask); + } + } diff --git a/src/d3d9/d3d9_common_texture.h b/src/d3d9/d3d9_common_texture.h index 764159b6..58cb854e 100644 --- a/src/d3d9/d3d9_common_texture.h +++ b/src/d3d9/d3d9_common_texture.h @@ -315,6 +315,8 @@ namespace dxvk { return m_type; } + uint32_t GetPlaneCount() const; + const D3D9_VK_FORMAT_MAPPING& GetMapping() { return m_mapping; } void SetLocked(UINT Subresource, bool value) { m_locked.set(Subresource, value); } diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index eadcdd34..b44ddd69 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -4229,10 +4229,15 @@ namespace dxvk { if (FormatInfo != nullptr) { elementSize = FormatInfo->elementSize; + VkExtent3D blockSize = FormatInfo->blockSize; + if (unlikely(FormatInfo->flags.test(DxvkFormatFlag::MultiPlane))) { + elementSize = FormatInfo->planes[0].elementSize; + blockSize = { FormatInfo->planes[0].blockSize.width, FormatInfo->planes[0].blockSize.height, 1u }; + } - offsets[0] = offsets[0] / FormatInfo->blockSize.depth; - offsets[1] = offsets[1] / FormatInfo->blockSize.height; - offsets[2] = offsets[2] / FormatInfo->blockSize.width; + offsets[0] = offsets[0] / blockSize.depth; + offsets[1] = offsets[1] / blockSize.height; + offsets[2] = offsets[2] / blockSize.width; } return offsets[0] * SlicePitch + @@ -4419,10 +4424,16 @@ namespace dxvk { pLockedBox->RowPitch = align(std::max(desc.Width >> MipLevel, 1u), 4); pLockedBox->SlicePitch = pLockedBox->RowPitch * std::max(desc.Height >> MipLevel, 1u); } - else { - // Data is tightly packed within the mapped buffer. + else if (likely(!formatInfo->flags.test(DxvkFormatFlag::MultiPlane))) { pLockedBox->RowPitch = align(formatInfo->elementSize * blockCount.width, 4); pLockedBox->SlicePitch = pLockedBox->RowPitch * blockCount.height; + } else { + auto plane = &formatInfo->planes[0]; + uint32_t planeElementSize = plane->elementSize; + VkExtent3D planeBlockSize = { plane->blockSize.width, plane->blockSize.height, 1u }; + VkExtent3D blockCount = util::computeBlockCount(levelExtent, planeBlockSize); + pLockedBox->RowPitch = align(planeElementSize * blockCount.width, 4); + pLockedBox->SlicePitch = pLockedBox->RowPitch * blockCount.height; } pResource->SetLocked(Subresource, true); @@ -4555,7 +4566,7 @@ namespace dxvk { // Now that data has been written into the buffer, // we need to copy its contents into the image - auto formatInfo = lookupFormatInfo(image->info().format); + auto formatInfo = lookupFormatInfo(pDestTexture->GetFormatMapping().FormatColor); auto srcSubresource = pSrcTexture->GetSubresourceFromIndex( formatInfo->aspectMask, SrcSubresource); @@ -4565,7 +4576,6 @@ namespace dxvk { VkExtent3D dstTexLevelExtent = image->mipLevelExtent(dstSubresource.mipLevel); VkExtent3D srcTexLevelExtent = util::computeMipLevelExtent(pSrcTexture->GetExtent(), srcSubresource.mipLevel); - VkExtent3D srcTexLevelExtentBlockCount = util::computeBlockCount(srcTexLevelExtent, formatInfo->blockSize); auto convertFormat = pDestTexture->GetFormatMapping().ConversionFormatInfo; @@ -4613,8 +4623,7 @@ namespace dxvk { slice.mapPtr, srcData, extentBlockCount, formatInfo->elementSize, pitch, pitch * srcTexLevelExtentBlockCount.height); - - VkFormat packedFormat = GetPackedDepthStencilFormat(pDestTexture->Desc()->Format); + VkFormat packedDSFormat = GetPackedDepthStencilFormat(pDestTexture->Desc()->Format); EmitCs([ cSrcSlice = slice.slice, @@ -4622,7 +4631,7 @@ namespace dxvk { cDstLayers = dstLayers, cDstLevelExtent = alignedExtent, cOffset = alignedDestOffset, - cPackedFormat = packedFormat + cPackedDSFormat = packedDSFormat ] (DxvkContext* ctx) { if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { ctx->copyBufferToImage( @@ -4638,20 +4647,15 @@ namespace dxvk { cSrcSlice.buffer(), cSrcSlice.offset(), VkOffset2D { 0, 0 }, VkExtent2D { cDstLevelExtent.width, cDstLevelExtent.height }, - cPackedFormat); + cPackedDSFormat); } }); TrackTextureMappingBufferSequenceNumber(pSrcTexture, SrcSubresource); } else { - const DxvkFormatInfo* formatInfo = lookupFormatInfo(pDestTexture->GetFormatMapping().FormatColor); const void* mapPtr = MapTexture(pSrcTexture, SrcSubresource); - // Add more blocks for the other planes that we might have. - // TODO: PLEASE CLEAN ME - srcTexLevelExtentBlockCount.height *= std::min(convertFormat.PlaneCount, 2u); - if (unlikely(SrcOffset.x != 0 || SrcOffset.y != 0 || SrcOffset.z != 0 || DestOffset.x != 0 || DestOffset.y != 0 || DestOffset.z != 0 || SrcExtent != srcTexLevelExtent)) { @@ -4663,13 +4667,22 @@ namespace dxvk { return; } + uint32_t formatElementSize = formatInfo->elementSize; + VkExtent3D srcBlockSize = formatInfo->blockSize; + if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { + formatElementSize = formatInfo->planes[0].elementSize; + srcBlockSize = { formatInfo->planes[0].blockSize.width, formatInfo->planes[0].blockSize.height, 1u }; + } + VkExtent3D srcBlockCount = util::computeBlockCount(srcTexLevelExtent, srcBlockSize); + srcBlockCount.height *= std::min(pSrcTexture->GetPlaneCount(), 2u); + // the converter can not handle the 4 aligned pitch so we always repack into a staging buffer D3D9BufferSlice slice = AllocStagingBuffer(pSrcTexture->GetMipSize(SrcSubresource)); - VkDeviceSize pitch = align(srcTexLevelExtentBlockCount.width * formatInfo->elementSize, 4); + VkDeviceSize pitch = align(srcBlockCount.width * formatElementSize, 4); util::packImageData( - slice.mapPtr, mapPtr, srcTexLevelExtentBlockCount, formatInfo->elementSize, - pitch, std::min(convertFormat.PlaneCount, 2u) * pitch * srcTexLevelExtentBlockCount.height); + slice.mapPtr, mapPtr, srcBlockCount, formatElementSize, + pitch, std::min(pSrcTexture->GetPlaneCount(), 2u) * pitch * srcBlockCount.height); Flush(); SynchronizeCsThread(DxvkCsThread::SynchronizeAll); diff --git a/src/d3d9/d3d9_format.cpp b/src/d3d9/d3d9_format.cpp index 4fe96bb4..87431a87 100644 --- a/src/d3d9/d3d9_format.cpp +++ b/src/d3d9/d3d9_format.cpp @@ -132,7 +132,7 @@ namespace dxvk { VK_IMAGE_ASPECT_COLOR_BIT, { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }, - { D3D9ConversionFormat_L6V5U5, 1u, + { D3D9ConversionFormat_L6V5U5, // Convert -> float (this is a mixed snorm and unorm type) VK_FORMAT_R16G16B16A16_SFLOAT } }; @@ -142,7 +142,7 @@ namespace dxvk { VK_IMAGE_ASPECT_COLOR_BIT, { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE }, - { D3D9ConversionFormat_X8L8V8U8, 1u, + { D3D9ConversionFormat_X8L8V8U8, // Convert -> float (this is a mixed snorm and unorm type) VK_FORMAT_R16G16B16A16_SFLOAT } }; @@ -164,7 +164,7 @@ namespace dxvk { VK_IMAGE_ASPECT_COLOR_BIT, { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }, - { D3D9ConversionFormat_A2W10V10U10, 1u, + { D3D9ConversionFormat_A2W10V10U10, // Convert -> float (this is a mixed snorm and unorm type) VK_FORMAT_R16G16B16A16_SFLOAT } }; @@ -174,17 +174,17 @@ namespace dxvk { VK_IMAGE_ASPECT_COLOR_BIT, { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE }, - { D3D9ConversionFormat_W11V11U10, 1u, + { D3D9ConversionFormat_W11V11U10, // can't use B10G11R11 bc this is a snorm type VK_FORMAT_R16G16B16A16_SNORM } }; case D3D9Format::UYVY: return { - VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_G8B8G8R8_422_UNORM, VK_FORMAT_UNDEFINED, VK_IMAGE_ASPECT_COLOR_BIT, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }, - { D3D9ConversionFormat_UYVY, 1u } + { D3D9ConversionFormat_UYVY, VK_FORMAT_B8G8R8A8_UNORM } }; case D3D9Format::R8G8_B8G8: return { @@ -193,12 +193,12 @@ namespace dxvk { VK_IMAGE_ASPECT_COLOR_BIT }; case D3D9Format::YUY2: return { - VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_G8B8G8R8_422_UNORM, VK_FORMAT_UNDEFINED, VK_IMAGE_ASPECT_COLOR_BIT, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }, - { D3D9ConversionFormat_YUY2, 1u } + { D3D9ConversionFormat_YUY2, VK_FORMAT_B8G8R8A8_UNORM } }; case D3D9Format::G8R8_G8B8: return { @@ -410,21 +410,21 @@ namespace dxvk { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R }}; case D3D9Format::NV12: return { - VK_FORMAT_R8_UNORM, + VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, VK_FORMAT_UNDEFINED, VK_IMAGE_ASPECT_COLOR_BIT, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }, - { D3D9ConversionFormat_NV12, 2u, VK_FORMAT_B8G8R8A8_UNORM } + { D3D9ConversionFormat_NV12, VK_FORMAT_B8G8R8A8_UNORM } }; case D3D9Format::YV12: return { - VK_FORMAT_R8_UNORM, + VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, VK_FORMAT_UNDEFINED, VK_IMAGE_ASPECT_COLOR_BIT, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }, - { D3D9ConversionFormat_YV12, 3u, VK_FORMAT_B8G8R8A8_UNORM } + { D3D9ConversionFormat_YV12, VK_FORMAT_B8G8R8A8_UNORM } }; case D3D9Format::RAWZ: return {}; // Unsupported diff --git a/src/d3d9/d3d9_format.h b/src/d3d9/d3d9_format.h index c38f6fe4..6054717d 100644 --- a/src/d3d9/d3d9_format.h +++ b/src/d3d9/d3d9_format.h @@ -143,7 +143,6 @@ namespace dxvk { struct D3D9_CONVERSION_FORMAT_INFO { D3D9ConversionFormat FormatType = D3D9ConversionFormat_None; - uint32_t PlaneCount = 1; VkFormat FormatColor = VK_FORMAT_UNDEFINED; VkFormat FormatSrgb = VK_FORMAT_UNDEFINED; };