[d3d11] Treat D3D11SamplerState as state object

This commit is contained in:
Philip Rebohle 2018-03-05 02:21:34 +01:00
parent 7a6e20f3a8
commit 484308347a
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
8 changed files with 127 additions and 73 deletions

View File

@ -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<uint32_t>(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);

View File

@ -283,6 +283,7 @@ namespace dxvk {
D3D11StateObjectSet<D3D11BlendState> m_bsStateObjects;
D3D11StateObjectSet<D3D11DepthStencilState> m_dsStateObjects;
D3D11StateObjectSet<D3D11RasterizerState> m_rsStateObjects;
D3D11StateObjectSet<D3D11SamplerState> 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();

View File

@ -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<DxvkSampler>& 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<uint32_t>(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<uint32_t>(desc->Filter);
if (filterBits & 0xFFFFFF2A) {
Logger::err(str::format("D3D11SamplerState: Unhandled filter: ", filterBits));
return E_INVALIDARG;
}
return S_OK;
}
}

View File

@ -12,10 +12,11 @@ namespace dxvk {
public:
using DescType = D3D11_SAMPLER_DESC;
D3D11SamplerState(
D3D11Device* device,
const D3D11_SAMPLER_DESC& desc,
const Rc<DxvkSampler>& 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<D3D11Device> m_device;

View File

@ -77,6 +77,26 @@ namespace dxvk {
}
size_t D3D11StateDescHash::operator () (
const D3D11_SAMPLER_DESC& desc) const {
std::hash<float> 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;
}
}

View File

@ -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;
};

View File

@ -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;

View File

@ -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]);