From 484308347aa7f6c4a5a8e02ed66104f805cff83d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 5 Mar 2018 02:21:34 +0100 Subject: [PATCH] [d3d11] Treat D3D11SamplerState as state object --- src/d3d11/d3d11_device.cpp | 67 +++---------------------------------- src/d3d11/d3d11_device.h | 4 +-- src/d3d11/d3d11_sampler.cpp | 51 +++++++++++++++++++++++++--- src/d3d11/d3d11_sampler.h | 8 +++-- src/d3d11/d3d11_state.cpp | 39 +++++++++++++++++++++ src/d3d11/d3d11_state.h | 3 ++ src/d3d11/d3d11_util.cpp | 25 ++++++++++++++ src/d3d11/d3d11_util.h | 3 ++ 8 files changed, 127 insertions(+), 73 deletions(-) diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 1701861c..86f861d4 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -1123,50 +1123,16 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D11Device::CreateSamplerState( const D3D11_SAMPLER_DESC* pSamplerDesc, ID3D11SamplerState** ppSamplerState) { - DxvkSamplerCreateInfo info; + HRESULT hr = D3D11SamplerState::ValidateDesc(pSamplerDesc); - // While D3D11_FILTER is technically an enum, its value bits - // can be used to decode the filter properties more efficiently. - const uint32_t filterBits = static_cast(pSamplerDesc->Filter); + if (FAILED(hr)) + return hr; - info.magFilter = (filterBits & 0x04) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; - info.minFilter = (filterBits & 0x10) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; - info.mipmapMode = (filterBits & 0x01) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST; - info.useAnisotropy = (filterBits & 0x40) ? VK_TRUE : VK_FALSE; - info.compareToDepth = (filterBits & 0x80) ? VK_TRUE : VK_FALSE; - - // Check for any unknown flags - if (filterBits & 0xFFFFFF2A) { - Logger::err(str::format("D3D11: Unsupported filter bits: ", filterBits)); - return E_INVALIDARG; - } - - // Set up the remaining properties, which are - // stored directly in the sampler description - info.mipmapLodBias = pSamplerDesc->MipLODBias; - info.mipmapLodMin = pSamplerDesc->MinLOD; - info.mipmapLodMax = pSamplerDesc->MaxLOD; - info.maxAnisotropy = pSamplerDesc->MaxAnisotropy; - info.addressModeU = DecodeAddressMode(pSamplerDesc->AddressU); - info.addressModeV = DecodeAddressMode(pSamplerDesc->AddressV); - info.addressModeW = DecodeAddressMode(pSamplerDesc->AddressW); - info.compareOp = DecodeCompareOp(pSamplerDesc->ComparisonFunc); - info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; - info.usePixelCoord = VK_FALSE; // Not supported in D3D11 - - // Try to find a matching border color if clamp to border is enabled - if (info.addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER - || info.addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER - || info.addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) - info.borderColor = DecodeBorderColor(pSamplerDesc->BorderColor); - - // Create sampler object if the application requests it if (ppSamplerState == nullptr) return S_FALSE; try { - *ppSamplerState = ref(new D3D11SamplerState(this, - *pSamplerDesc, m_dxvkDevice->createSampler(info))); + *ppSamplerState = m_samplerObjects.Create(this, *pSamplerDesc); return S_OK; } catch (const DxvkError& e) { Logger::err(e.message()); @@ -2330,31 +2296,6 @@ namespace dxvk { } - VkSamplerAddressMode D3D11Device::DecodeAddressMode( - D3D11_TEXTURE_ADDRESS_MODE mode) const { - switch (mode) { - case D3D11_TEXTURE_ADDRESS_WRAP: - return VK_SAMPLER_ADDRESS_MODE_REPEAT; - - case D3D11_TEXTURE_ADDRESS_MIRROR: - return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; - - case D3D11_TEXTURE_ADDRESS_CLAMP: - return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - - case D3D11_TEXTURE_ADDRESS_BORDER: - return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; - - case D3D11_TEXTURE_ADDRESS_MIRROR_ONCE: - return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; - - default: - Logger::err(str::format("D3D11: Unsupported address mode: ", mode)); - return VK_SAMPLER_ADDRESS_MODE_REPEAT; - } - } - - HRESULT D3D11Device::GetFormatSupportFlags(DXGI_FORMAT Format, UINT* pFlags) const { const VkFormat fmt = m_dxgiAdapter->LookupFormat(Format, DxgiFormatMode::Any).format; const VkFormatProperties fmtInfo = m_dxvkAdapter->formatProperties(fmt); diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index 19f1f19d..89a2cff2 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -283,6 +283,7 @@ namespace dxvk { D3D11StateObjectSet m_bsStateObjects; D3D11StateObjectSet m_dsStateObjects; D3D11StateObjectSet m_rsStateObjects; + D3D11StateObjectSet m_samplerObjects; HRESULT CreateShaderModule( D3D11ShaderModule* pShaderModule, @@ -330,9 +331,6 @@ namespace dxvk { ID3D11Resource* pResource, D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc); - VkSamplerAddressMode DecodeAddressMode( - D3D11_TEXTURE_ADDRESS_MODE mode) const; - HRESULT GetFormatSupportFlags(DXGI_FORMAT Format, UINT* pFlags) const; void CreateCounterBuffer(); diff --git a/src/d3d11/d3d11_sampler.cpp b/src/d3d11/d3d11_sampler.cpp index 2e133b21..3809e0a1 100644 --- a/src/d3d11/d3d11_sampler.cpp +++ b/src/d3d11/d3d11_sampler.cpp @@ -1,16 +1,45 @@ #include "d3d11_device.h" #include "d3d11_sampler.h" +#include "d3d11_util.h" namespace dxvk { D3D11SamplerState::D3D11SamplerState( D3D11Device* device, - const D3D11_SAMPLER_DESC& desc, - const Rc& sampler) - : m_device(device), - m_desc(desc), - m_sampler(sampler) { + const D3D11_SAMPLER_DESC& desc) + : m_device(device), m_desc(desc) { + DxvkSamplerCreateInfo info; + // While D3D11_FILTER is technically an enum, its value bits + // can be used to decode the filter properties more efficiently. + const uint32_t filterBits = static_cast(desc.Filter); + + info.magFilter = (filterBits & 0x04) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; + info.minFilter = (filterBits & 0x10) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST; + info.mipmapMode = (filterBits & 0x01) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST; + info.useAnisotropy = (filterBits & 0x40) ? VK_TRUE : VK_FALSE; + info.compareToDepth = (filterBits & 0x80) ? VK_TRUE : VK_FALSE; + + // Set up the remaining properties, which are + // stored directly in the sampler description + info.mipmapLodBias = desc.MipLODBias; + info.mipmapLodMin = desc.MinLOD; + info.mipmapLodMax = desc.MaxLOD; + info.maxAnisotropy = desc.MaxAnisotropy; + info.addressModeU = DecodeAddressMode(desc.AddressU); + info.addressModeV = DecodeAddressMode(desc.AddressV); + info.addressModeW = DecodeAddressMode(desc.AddressW); + info.compareOp = DecodeCompareOp(desc.ComparisonFunc); + info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + info.usePixelCoord = VK_FALSE; // Not supported in D3D11 + + // Try to find a matching border color if clamp to border is enabled + if (info.addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER + || info.addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER + || info.addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) + info.borderColor = DecodeBorderColor(desc.BorderColor); + + m_sampler = device->GetDXVKDevice()->createSampler(info); } @@ -38,4 +67,16 @@ namespace dxvk { *pDesc = m_desc; } + + HRESULT D3D11SamplerState::ValidateDesc(const D3D11_SAMPLER_DESC* desc) { + const uint32_t filterBits = static_cast(desc->Filter); + + if (filterBits & 0xFFFFFF2A) { + Logger::err(str::format("D3D11SamplerState: Unhandled filter: ", filterBits)); + return E_INVALIDARG; + } + + return S_OK; + } + } diff --git a/src/d3d11/d3d11_sampler.h b/src/d3d11/d3d11_sampler.h index fcc0d4d5..7702b4b7 100644 --- a/src/d3d11/d3d11_sampler.h +++ b/src/d3d11/d3d11_sampler.h @@ -12,10 +12,11 @@ namespace dxvk { public: + using DescType = D3D11_SAMPLER_DESC; + D3D11SamplerState( D3D11Device* device, - const D3D11_SAMPLER_DESC& desc, - const Rc& sampler); + const D3D11_SAMPLER_DESC& desc); ~D3D11SamplerState(); HRESULT STDMETHODCALLTYPE QueryInterface( @@ -32,6 +33,9 @@ namespace dxvk { return m_sampler; } + static HRESULT ValidateDesc( + const D3D11_SAMPLER_DESC* desc); + private: Com m_device; diff --git a/src/d3d11/d3d11_state.cpp b/src/d3d11/d3d11_state.cpp index 4d5f47b2..3896a3cf 100644 --- a/src/d3d11/d3d11_state.cpp +++ b/src/d3d11/d3d11_state.cpp @@ -77,6 +77,26 @@ namespace dxvk { } + size_t D3D11StateDescHash::operator () ( + const D3D11_SAMPLER_DESC& desc) const { + std::hash fhash; + + DxvkHashState hash; + hash.add(desc.Filter); + hash.add(desc.AddressU); + hash.add(desc.AddressV); + hash.add(desc.AddressW); + hash.add(fhash(desc.MipLODBias)); + hash.add(fhash(desc.MaxAnisotropy)); + hash.add(desc.ComparisonFunc); + for (uint32_t i = 0; i < 4; i++) + hash.add(fhash(desc.BorderColor[i])); + hash.add(fhash(desc.MinLOD)); + hash.add(fhash(desc.MaxLOD)); + return hash; + } + + bool D3D11StateDescEqual::operator () ( const D3D11_BLEND_DESC& a, const D3D11_BLEND_DESC& b) const { @@ -147,4 +167,23 @@ namespace dxvk { && a.RenderTargetWriteMask == b.RenderTargetWriteMask; } + + bool D3D11StateDescEqual::operator () ( + const D3D11_SAMPLER_DESC& a, + const D3D11_SAMPLER_DESC& b) const { + return a.Filter == b.Filter + && a.AddressU == b.AddressU + && a.AddressV == b.AddressV + && a.AddressW == b.AddressW + && a.MipLODBias == b.MipLODBias + && a.MaxAnisotropy == b.MaxAnisotropy + && a.ComparisonFunc == b.ComparisonFunc + && a.BorderColor[0] == b.BorderColor[0] + && a.BorderColor[1] == b.BorderColor[1] + && a.BorderColor[2] == b.BorderColor[2] + && a.BorderColor[3] == b.BorderColor[3] + && a.MinLOD == b.MinLOD + && a.MaxLOD == b.MaxLOD; + } + } \ No newline at end of file diff --git a/src/d3d11/d3d11_state.h b/src/d3d11/d3d11_state.h index 1206a123..b4a2d36b 100644 --- a/src/d3d11/d3d11_state.h +++ b/src/d3d11/d3d11_state.h @@ -5,6 +5,7 @@ #include "d3d11_blend.h" #include "d3d11_depth_stencil.h" #include "d3d11_rasterizer.h" +#include "d3d11_sampler.h" namespace dxvk { @@ -16,6 +17,7 @@ namespace dxvk { size_t operator () (const D3D11_DEPTH_STENCIL_DESC& desc) const; size_t operator () (const D3D11_RASTERIZER_DESC& desc) const; size_t operator () (const D3D11_RENDER_TARGET_BLEND_DESC& desc) const; + size_t operator () (const D3D11_SAMPLER_DESC& desc) const; }; @@ -25,6 +27,7 @@ namespace dxvk { bool operator () (const D3D11_DEPTH_STENCIL_DESC& a, const D3D11_DEPTH_STENCIL_DESC& b) const; bool operator () (const D3D11_RASTERIZER_DESC& a, const D3D11_RASTERIZER_DESC& b) const; bool operator () (const D3D11_RENDER_TARGET_BLEND_DESC& a, const D3D11_RENDER_TARGET_BLEND_DESC& b) const; + bool operator () (const D3D11_SAMPLER_DESC& a, const D3D11_SAMPLER_DESC& b) const; }; diff --git a/src/d3d11/d3d11_util.cpp b/src/d3d11/d3d11_util.cpp index b9e41523..10473bf5 100644 --- a/src/d3d11/d3d11_util.cpp +++ b/src/d3d11/d3d11_util.cpp @@ -15,6 +15,31 @@ namespace dxvk { } + VkSamplerAddressMode DecodeAddressMode( + D3D11_TEXTURE_ADDRESS_MODE mode) { + switch (mode) { + case D3D11_TEXTURE_ADDRESS_WRAP: + return VK_SAMPLER_ADDRESS_MODE_REPEAT; + + case D3D11_TEXTURE_ADDRESS_MIRROR: + return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; + + case D3D11_TEXTURE_ADDRESS_CLAMP: + return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + + case D3D11_TEXTURE_ADDRESS_BORDER: + return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + + case D3D11_TEXTURE_ADDRESS_MIRROR_ONCE: + return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; + + default: + Logger::err(str::format("D3D11: Unsupported address mode: ", mode)); + return VK_SAMPLER_ADDRESS_MODE_REPEAT; + } + } + + VkBorderColor DecodeBorderColor(const FLOAT BorderColor[4]) { struct BorderColorEntry { float r, g, b, a; diff --git a/src/d3d11/d3d11_util.h b/src/d3d11/d3d11_util.h index 2d8487e3..f688aa8f 100644 --- a/src/d3d11/d3d11_util.h +++ b/src/d3d11/d3d11_util.h @@ -11,6 +11,9 @@ namespace dxvk { HRESULT GetSampleCount( UINT Count, VkSampleCountFlagBits* pCount); + + VkSamplerAddressMode DecodeAddressMode( + D3D11_TEXTURE_ADDRESS_MODE mode); VkBorderColor DecodeBorderColor( const FLOAT BorderColor[4]);