summaryrefslogtreecommitdiffstats
path: root/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.cpp')
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.cpp147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.cpp b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.cpp
new file mode 100644
index 00000000..397dc47b
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/d3d11/d3d11_sampler.cpp
@@ -0,0 +1,147 @@
+#include "d3d11_device.h"
+#include "d3d11_sampler.h"
+#include "d3d11_util.h"
+
+namespace dxvk {
+
+ D3D11SamplerState::D3D11SamplerState(
+ D3D11Device* device,
+ const D3D11_SAMPLER_DESC& desc)
+ : D3D11StateObject<ID3D11SamplerState>(device),
+ m_desc(desc), m_d3d10(this) {
+ 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 = uint32_t(desc.Filter);
+ info.magFilter = (filterBits & 0x04) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
+ info.minFilter = (filterBits & 0x10) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
+
+ // Set up the remaining properties, which are
+ // stored directly in the sampler description
+ info.mipmapMode = (filterBits & 0x01) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ info.mipmapLodBias = desc.MipLODBias;
+ info.mipmapLodMin = desc.MinLOD;
+ info.mipmapLodMax = desc.MaxLOD;
+
+ info.useAnisotropy = (filterBits & 0x40) ? VK_TRUE : VK_FALSE;
+ info.maxAnisotropy = float(desc.MaxAnisotropy);
+
+ info.addressModeU = DecodeAddressMode(desc.AddressU);
+ info.addressModeV = DecodeAddressMode(desc.AddressV);
+ info.addressModeW = DecodeAddressMode(desc.AddressW);
+
+ info.compareToDepth = (filterBits & 0x80) ? VK_TRUE : VK_FALSE;
+ info.compareOp = DecodeCompareOp(desc.ComparisonFunc);
+
+ for (uint32_t i = 0; i < 4; i++)
+ info.borderColor.float32[i] = desc.BorderColor[i];
+
+ info.usePixelCoord = VK_FALSE; // Not supported in D3D11
+
+ // Make sure to use a valid anisotropy value
+ if (desc.MaxAnisotropy < 1) info.maxAnisotropy = 1.0f;
+ if (desc.MaxAnisotropy > 16) info.maxAnisotropy = 16.0f;
+
+ // Enforce anisotropy specified in the device options
+ int32_t samplerAnisotropyOption = device->GetOptions()->samplerAnisotropy;
+
+ if (samplerAnisotropyOption >= 0) {
+ info.useAnisotropy = samplerAnisotropyOption > 0;
+ info.maxAnisotropy = float(samplerAnisotropyOption);
+ }
+
+ m_sampler = device->GetDXVKDevice()->createSampler(info);
+ }
+
+
+ D3D11SamplerState::~D3D11SamplerState() {
+
+ }
+
+
+ HRESULT STDMETHODCALLTYPE D3D11SamplerState::QueryInterface(REFIID riid, void** ppvObject) {
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (riid == __uuidof(IUnknown)
+ || riid == __uuidof(ID3D11DeviceChild)
+ || riid == __uuidof(ID3D11SamplerState)) {
+ *ppvObject = ref(this);
+ return S_OK;
+ }
+
+ if (riid == __uuidof(ID3D10DeviceChild)
+ || riid == __uuidof(ID3D10SamplerState)) {
+ *ppvObject = ref(&m_d3d10);
+ return S_OK;
+ }
+
+ Logger::warn("D3D11SamplerState::QueryInterface: Unknown interface query");
+ Logger::warn(str::format(riid));
+ return E_NOINTERFACE;
+ }
+
+
+ void STDMETHODCALLTYPE D3D11SamplerState::GetDesc(D3D11_SAMPLER_DESC* pDesc) {
+ *pDesc = m_desc;
+ }
+
+
+ HRESULT D3D11SamplerState::NormalizeDesc(D3D11_SAMPLER_DESC* pDesc) {
+ const uint32_t filterBits = uint32_t(pDesc->Filter);
+
+ if (filterBits & 0xFFFFFF2A) {
+ Logger::err(str::format(
+ "D3D11SamplerState: Unhandled filter: ", filterBits));
+ return E_INVALIDARG;
+ }
+
+ if (pDesc->MaxAnisotropy < 0
+ || pDesc->MaxAnisotropy > 16) {
+ return E_INVALIDARG;
+ } else if ((filterBits & 0x40) == 0 /* not anisotropic */) {
+ // Reset anisotropy if it is not used
+ pDesc->MaxAnisotropy = 0;
+ }
+
+ if (filterBits & 0x80 /* compare-to-depth */) {
+ if (!ValidateComparisonFunc(pDesc->ComparisonFunc))
+ return E_INVALIDARG;
+ } else {
+ // Reset compare func if it is not used
+ pDesc->ComparisonFunc = D3D11_COMPARISON_NEVER;
+ }
+
+ if (!ValidateAddressMode(pDesc->AddressU)
+ || !ValidateAddressMode(pDesc->AddressV)
+ || !ValidateAddressMode(pDesc->AddressW))
+ return E_INVALIDARG;
+
+ // Clear BorderColor to 0 if none of the address
+ // modes are D3D11_TEXTURE_ADDRESS_BORDER
+ if (pDesc->AddressU != D3D11_TEXTURE_ADDRESS_BORDER
+ && pDesc->AddressV != D3D11_TEXTURE_ADDRESS_BORDER
+ && pDesc->AddressW != D3D11_TEXTURE_ADDRESS_BORDER) {
+ for (int i = 0; i < 4; i++)
+ pDesc->BorderColor[i] = 0.0f;
+ }
+
+ return S_OK;
+ }
+
+
+ bool D3D11SamplerState::ValidateAddressMode(D3D11_TEXTURE_ADDRESS_MODE Mode) {
+ return Mode >= D3D11_TEXTURE_ADDRESS_WRAP
+ && Mode <= D3D11_TEXTURE_ADDRESS_MIRROR_ONCE;
+ }
+
+
+ bool D3D11SamplerState::ValidateComparisonFunc(D3D11_COMPARISON_FUNC Comparison) {
+ return Comparison >= D3D11_COMPARISON_NEVER
+ && Comparison <= D3D11_COMPARISON_ALWAYS;
+ }
+
+}