diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 9f0b7523..abc4a5a8 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -5,6 +5,7 @@ #include "d3d11_device.h" #include "d3d11_input_layout.h" #include "d3d11_present.h" +#include "d3d11_sampler.h" #include "d3d11_shader.h" #include "d3d11_texture.h" #include "d3d11_view.h" @@ -822,8 +823,54 @@ namespace dxvk { HRESULT D3D11Device::CreateSamplerState( const D3D11_SAMPLER_DESC* pSamplerDesc, ID3D11SamplerState** ppSamplerState) { - Logger::err("D3D11Device::CreateSamplerState: Not implemented"); - return E_NOTIMPL; + 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(pSamplerDesc->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; + + // 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; + + 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) + Logger::warn("D3D11: Border color not supported yet"); + + // Create sampler object if the application requests it + if (ppSamplerState == nullptr) + return S_OK; + + try { + *ppSamplerState = ref(new D3D11SamplerState(this, + *pSamplerDesc, m_dxvkDevice->createSampler(info))); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return S_OK; + } } @@ -1327,4 +1374,63 @@ namespace dxvk { return memoryFlags; } + + 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; + } + } + + + VkCompareOp D3D11Device::DecodeCompareOp( + D3D11_COMPARISON_FUNC mode) const { + switch (mode) { + case D3D11_COMPARISON_NEVER: + return VK_COMPARE_OP_NEVER; + + case D3D11_COMPARISON_LESS: + return VK_COMPARE_OP_LESS; + + case D3D11_COMPARISON_EQUAL: + return VK_COMPARE_OP_EQUAL; + + case D3D11_COMPARISON_LESS_EQUAL: + return VK_COMPARE_OP_LESS_OR_EQUAL; + + case D3D11_COMPARISON_GREATER: + return VK_COMPARE_OP_GREATER; + + case D3D11_COMPARISON_NOT_EQUAL: + return VK_COMPARE_OP_NOT_EQUAL; + + case D3D11_COMPARISON_GREATER_EQUAL: + return VK_COMPARE_OP_GREATER_OR_EQUAL; + + case D3D11_COMPARISON_ALWAYS: + return VK_COMPARE_OP_ALWAYS; + + default: + Logger::err(str::format("D3D11: Unsupported compare op: ", mode)); + return VK_COMPARE_OP_ALWAYS; + } + } + } diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index 674345ec..c60fd1ef 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -288,6 +288,11 @@ namespace dxvk { VkMemoryPropertyFlags GetMemoryFlagsForUsage( D3D11_USAGE usage) const; + VkSamplerAddressMode DecodeAddressMode( + D3D11_TEXTURE_ADDRESS_MODE mode) const; + + VkCompareOp DecodeCompareOp( + D3D11_COMPARISON_FUNC mode) const; }; diff --git a/src/d3d11/d3d11_sampler.cpp b/src/d3d11/d3d11_sampler.cpp new file mode 100644 index 00000000..2e216f81 --- /dev/null +++ b/src/d3d11/d3d11_sampler.cpp @@ -0,0 +1,41 @@ +#include "d3d11_device.h" +#include "d3d11_sampler.h" + +namespace dxvk { + + D3D11SamplerState::D3D11SamplerState( + D3D11Device* device, + const D3D11_SAMPLER_DESC& desc, + const Rc& sampler) + : m_device(device), + m_desc(desc), + m_sampler(sampler) { + + } + + + D3D11SamplerState::~D3D11SamplerState() { + + } + + + HRESULT D3D11SamplerState::QueryInterface(REFIID riid, void** ppvObject) { + COM_QUERY_IFACE(riid, ppvObject, IUnknown); + COM_QUERY_IFACE(riid, ppvObject, ID3D11DeviceChild); + COM_QUERY_IFACE(riid, ppvObject, ID3D11SamplerState); + + Logger::warn("D3D11SamplerState::QueryInterface: Unknown interface query"); + return E_NOINTERFACE; + } + + + void D3D11SamplerState::GetDevice(ID3D11Device** ppDevice) { + *ppDevice = m_device.ref(); + } + + + void D3D11SamplerState::GetDesc(D3D11_SAMPLER_DESC* pDesc) { + *pDesc = m_desc; + } + +} diff --git a/src/d3d11/d3d11_sampler.h b/src/d3d11/d3d11_sampler.h new file mode 100644 index 00000000..aab44390 --- /dev/null +++ b/src/d3d11/d3d11_sampler.h @@ -0,0 +1,43 @@ +#pragma once + +#include + +#include "d3d11_device_child.h" + +namespace dxvk { + + class D3D11Device; + + class D3D11SamplerState : public D3D11DeviceChild { + + public: + + D3D11SamplerState( + D3D11Device* device, + const D3D11_SAMPLER_DESC& desc, + const Rc& sampler); + ~D3D11SamplerState(); + + HRESULT QueryInterface( + REFIID riid, + void** ppvObject) final; + + void GetDevice( + ID3D11Device **ppDevice) final; + + void GetDesc( + D3D11_SAMPLER_DESC* pDesc) final; + + Rc GetDXVKSampler() const { + return m_sampler; + } + + private: + + Com m_device; + D3D11_SAMPLER_DESC m_desc; + Rc m_sampler; + + }; + +} diff --git a/src/d3d11/d3d11_state_rs.cpp b/src/d3d11/d3d11_state_rs.cpp index ebed7e64..da2d3c04 100644 --- a/src/d3d11/d3d11_state_rs.cpp +++ b/src/d3d11/d3d11_state_rs.cpp @@ -78,7 +78,7 @@ namespace dxvk { void D3D11RasterizerState::GetDevice(ID3D11Device** ppDevice) { - *ppDevice = ref(m_device); + *ppDevice = m_device.ref(); } diff --git a/src/d3d11/d3d11_state_rs.h b/src/d3d11/d3d11_state_rs.h index 20912a3b..356cfba3 100644 --- a/src/d3d11/d3d11_state_rs.h +++ b/src/d3d11/d3d11_state_rs.h @@ -35,7 +35,7 @@ namespace dxvk { private: - D3D11Device* const m_device; + Com m_device; D3D11_RASTERIZER_DESC m_desc; DxvkRasterizerState m_state; diff --git a/src/d3d11/meson.build b/src/d3d11/meson.build index 644d62e1..80bc99e1 100644 --- a/src/d3d11/meson.build +++ b/src/d3d11/meson.build @@ -6,6 +6,7 @@ d3d11_src = [ 'd3d11_input_layout.cpp', 'd3d11_main.cpp', 'd3d11_present.cpp', + 'd3d11_sampler.cpp', 'd3d11_shader.cpp', 'd3d11_state.cpp', 'd3d11_state_rs.cpp',