From c7dab6a442921334ce36db873917b5ef80d0eb3a Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 27 Sep 2024 16:41:54 +0200 Subject: [PATCH] [d3d9] Remove internal sampler pool We have a sampler pool in the backend now, let's use it. --- src/d3d9/d3d9_device.cpp | 117 ++++++++++++++------------------------ src/d3d9/d3d9_device.h | 12 ---- src/d3d9/d3d9_hud.cpp | 3 +- src/d3d9/d3d9_sampler.cpp | 44 -------------- src/d3d9/d3d9_sampler.h | 75 ------------------------ src/d3d9/meson.build | 1 - 6 files changed, 45 insertions(+), 207 deletions(-) delete mode 100644 src/d3d9/d3d9_sampler.cpp delete mode 100644 src/d3d9/d3d9_sampler.h diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index 692603936..4e4f29f67 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -6638,36 +6638,56 @@ namespace dxvk { void D3D9DeviceEx::BindSampler(DWORD Sampler) { auto& state = m_state.samplerStates[Sampler]; - D3D9SamplerKey key; - key.AddressU = D3DTEXTUREADDRESS(state[D3DSAMP_ADDRESSU]); - key.AddressV = D3DTEXTUREADDRESS(state[D3DSAMP_ADDRESSV]); - key.AddressW = D3DTEXTUREADDRESS(state[D3DSAMP_ADDRESSW]); - key.MagFilter = D3DTEXTUREFILTERTYPE(state[D3DSAMP_MAGFILTER]); - key.MinFilter = D3DTEXTUREFILTERTYPE(state[D3DSAMP_MINFILTER]); - key.MipFilter = D3DTEXTUREFILTERTYPE(state[D3DSAMP_MIPFILTER]); - key.MaxAnisotropy = state[D3DSAMP_MAXANISOTROPY]; - key.MipmapLodBias = bit::cast(state[D3DSAMP_MIPMAPLODBIAS]); - key.MaxMipLevel = state[D3DSAMP_MAXMIPLEVEL]; - key.BorderColor = D3DCOLOR(state[D3DSAMP_BORDERCOLOR]); - key.Depth = m_depthTextures & (1u << Sampler); + D3DTEXTUREFILTERTYPE minFilter = D3DTEXTUREFILTERTYPE(state[D3DSAMP_MINFILTER]); + D3DTEXTUREFILTERTYPE magFilter = D3DTEXTUREFILTERTYPE(state[D3DSAMP_MAGFILTER]); + D3DTEXTUREFILTERTYPE mipFilter = D3DTEXTUREFILTERTYPE(state[D3DSAMP_MIPFILTER]); + + DxvkSamplerKey key = { }; + + key.setFilter( + DecodeFilter(minFilter), + DecodeFilter(magFilter), + DecodeMipFilter(mipFilter).MipFilter); if (m_cubeTextures & (1u << Sampler)) { - key.AddressU = D3DTADDRESS_CLAMP; - key.AddressV = D3DTADDRESS_CLAMP; - key.AddressW = D3DTADDRESS_CLAMP; + key.setAddressModes( + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); + + key.setLegacyCubeFilter(!m_d3d9Options.seamlessCubes); + } else { + key.setAddressModes( + DecodeAddressMode(D3DTEXTUREADDRESS(state[D3DSAMP_ADDRESSU])), + DecodeAddressMode(D3DTEXTUREADDRESS(state[D3DSAMP_ADDRESSV])), + DecodeAddressMode(D3DTEXTUREADDRESS(state[D3DSAMP_ADDRESSW]))); } - if (m_d3d9Options.samplerAnisotropy != -1) { - if (key.MagFilter == D3DTEXF_LINEAR) - key.MagFilter = D3DTEXF_ANISOTROPIC; + key.setDepthCompare(m_depthTextures & (1u << Sampler), VK_COMPARE_OP_LESS_OR_EQUAL); - if (key.MinFilter == D3DTEXF_LINEAR) - key.MinFilter = D3DTEXF_ANISOTROPIC; + if (mipFilter != D3DTEXF_NONE) { + // Anisotropic filtering doesn't make any sense with only one mip + uint32_t anisotropy = state[D3DSAMP_MAXANISOTROPY]; - key.MaxAnisotropy = m_d3d9Options.samplerAnisotropy; + if (minFilter != D3DTEXF_ANISOTROPIC) + anisotropy = 0u; + + if (m_d3d9Options.samplerAnisotropy != -1 && minFilter > D3DTEXF_POINT) + anisotropy = m_d3d9Options.samplerAnisotropy; + + key.setAniso(anisotropy); + + float lodBias = bit::cast(state[D3DSAMP_MIPMAPLODBIAS]); + lodBias += m_d3d9Options.samplerLodBias; + + if (m_d3d9Options.clampNegativeLodBias) + lodBias = std::max(lodBias, 0.0f); + + key.setLodRange(float(state[D3DSAMP_MAXMIPLEVEL]), 16.0f, lodBias); } - NormalizeSamplerKey(key); + if (key.u.p.hasBorder) + DecodeD3DCOLOR(D3DCOLOR(state[D3DSAMP_BORDERCOLOR]), key.borderColor.float32); auto samplerInfo = RemapStateSamplerShader(Sampler); @@ -6680,58 +6700,7 @@ namespace dxvk { cKey = key ] (DxvkContext* ctx) { VkShaderStageFlags stage = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; - - auto pair = m_samplers.find(cKey); - if (pair != m_samplers.end()) { - ctx->bindResourceSampler(stage, cSlot, - Rc(pair->second)); - return; - } - - auto mipFilter = DecodeMipFilter(cKey.MipFilter); - - DxvkSamplerKey info = { }; - - info.setFilter( - DecodeFilter(cKey.MinFilter), - DecodeFilter(cKey.MagFilter), - mipFilter.MipFilter); - - info.setAddressModes( - DecodeAddressMode(cKey.AddressU), - DecodeAddressMode(cKey.AddressV), - DecodeAddressMode(cKey.AddressW)); - - info.setDepthCompare(cKey.Depth, - VK_COMPARE_OP_LESS_OR_EQUAL); - - info.setAniso(cKey.MaxAnisotropy); - - float lodBias = cKey.MipmapLodBias + m_d3d9Options.samplerLodBias; - - if (m_d3d9Options.clampNegativeLodBias) - lodBias = std::max(lodBias, 0.0f); - - info.setLodRange( - mipFilter.MipsEnabled ? float(cKey.MaxMipLevel) : 0.0f, - mipFilter.MipsEnabled ? FLT_MAX : 0.0f, - lodBias); - - info.setLegacyCubeFilter(!m_d3d9Options.seamlessCubes); - - DecodeD3DCOLOR(cKey.BorderColor, info.borderColor.float32); - - try { - auto sampler = m_dxvkDevice->createSampler(info); - - m_samplers.insert(std::make_pair(cKey, sampler)); - ctx->bindResourceSampler(stage, cSlot, std::move(sampler)); - - m_samplerCount++; - } - catch (const DxvkError& e) { - Logger::err(e.message()); - } + ctx->bindResourceSampler(stage, cSlot, m_dxvkDevice->createSampler(cKey)); }); } diff --git a/src/d3d9/d3d9_device.h b/src/d3d9/d3d9_device.h index be2ad81c7..5b935c7a0 100644 --- a/src/d3d9/d3d9_device.h +++ b/src/d3d9/d3d9_device.h @@ -22,7 +22,6 @@ #include "../dxso/dxso_options.h" #include "../dxso/dxso_modinfo.h" -#include "d3d9_sampler.h" #include "d3d9_fixed_function.h" #include "d3d9_swvp_emu.h" @@ -979,10 +978,6 @@ namespace dxvk { HRESULT InitialReset(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode); - UINT GetSamplerCount() const { - return m_samplerCount.load(); - } - D3D9MemoryAllocator* GetAllocator() { return &m_memoryAllocator; } @@ -1343,12 +1338,6 @@ namespace dxvk { const D3D9Options m_d3d9Options; DxsoOptions m_dxsoOptions; - std::unordered_map< - D3D9SamplerKey, - Rc, - D3D9SamplerKeyHash, - D3D9SamplerKeyEq> m_samplers; - std::unordered_map< DWORD, Com m_availableMemory = { 0 }; - std::atomic m_samplerCount = { 0 }; D3D9DeviceLostState m_deviceLostState = D3D9DeviceLostState::Ok; HWND m_fullscreenWindow = NULL; diff --git a/src/d3d9/d3d9_hud.cpp b/src/d3d9/d3d9_hud.cpp index d958584b3..d7acdc9fa 100644 --- a/src/d3d9/d3d9_hud.cpp +++ b/src/d3d9/d3d9_hud.cpp @@ -10,7 +10,8 @@ namespace dxvk::hud { void HudSamplerCount::update(dxvk::high_resolution_clock::time_point time) { - m_samplerCount = str::format(m_device->GetSamplerCount()); + DxvkSamplerStats stats = m_device->GetDXVKDevice()->getSamplerStats(); + m_samplerCount = str::format(stats.totalCount); } diff --git a/src/d3d9/d3d9_sampler.cpp b/src/d3d9/d3d9_sampler.cpp deleted file mode 100644 index 6a68f2200..000000000 --- a/src/d3d9/d3d9_sampler.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "d3d9_sampler.h" - -namespace dxvk { - - size_t D3D9SamplerKeyHash::operator () (const D3D9SamplerKey& key) const { - DxvkHashState state; - - std::hash dhash; - std::hash tahash; - std::hash tfhash; - std::hash fhash; - std::hash bhash; - - state.add(tahash(key.AddressU)); - state.add(tahash(key.AddressV)); - state.add(tahash(key.AddressW)); - state.add(tfhash(key.MagFilter)); - state.add(tfhash(key.MinFilter)); - state.add(tfhash(key.MipFilter)); - state.add(dhash (key.MaxAnisotropy)); - state.add(fhash (key.MipmapLodBias)); - state.add(dhash (key.MaxMipLevel)); - state.add(dhash (key.BorderColor)); - state.add(bhash (key.Depth)); - - return state; - } - - - bool D3D9SamplerKeyEq::operator () (const D3D9SamplerKey& a, const D3D9SamplerKey& b) const { - return a.AddressU == b.AddressU - && a.AddressV == b.AddressV - && a.AddressW == b.AddressW - && a.MagFilter == b.MagFilter - && a.MinFilter == b.MinFilter - && a.MipFilter == b.MipFilter - && a.MaxAnisotropy == b.MaxAnisotropy - && a.MipmapLodBias == b.MipmapLodBias - && a.MaxMipLevel == b.MaxMipLevel - && a.BorderColor == b.BorderColor - && a.Depth == b.Depth; - } - -} \ No newline at end of file diff --git a/src/d3d9/d3d9_sampler.h b/src/d3d9/d3d9_sampler.h deleted file mode 100644 index 44471094e..000000000 --- a/src/d3d9/d3d9_sampler.h +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once - -#include "d3d9_include.h" - -#include "d3d9_util.h" - -#include "../dxvk/dxvk_hash.h" - -#include "../util/util_math.h" - -namespace dxvk { - - struct D3D9SamplerKey { - D3DTEXTUREADDRESS AddressU; - D3DTEXTUREADDRESS AddressV; - D3DTEXTUREADDRESS AddressW; - D3DTEXTUREFILTERTYPE MagFilter; - D3DTEXTUREFILTERTYPE MinFilter; - D3DTEXTUREFILTERTYPE MipFilter; - DWORD MaxAnisotropy; - float MipmapLodBias; - DWORD MaxMipLevel; - D3DCOLOR BorderColor; - bool Depth; - }; - - struct D3D9SamplerKeyHash { - size_t operator () (const D3D9SamplerKey& key) const; - }; - - struct D3D9SamplerKeyEq { - bool operator () (const D3D9SamplerKey& a, const D3D9SamplerKey& b) const; - }; - - inline void NormalizeSamplerKey(D3D9SamplerKey& key) { - key.AddressU = std::clamp(key.AddressU, D3DTADDRESS_WRAP, D3DTADDRESS_MIRRORONCE); - key.AddressV = std::clamp(key.AddressV, D3DTADDRESS_WRAP, D3DTADDRESS_MIRRORONCE); - key.AddressW = std::clamp(key.AddressW, D3DTADDRESS_WRAP, D3DTADDRESS_MIRRORONCE); - - bool hasAnisotropy = IsAnisotropic(key.MagFilter) || IsAnisotropic(key.MinFilter); - - key.MagFilter = std::clamp(key.MagFilter, D3DTEXF_NONE, D3DTEXF_LINEAR); - key.MinFilter = std::clamp(key.MinFilter, D3DTEXF_NONE, D3DTEXF_LINEAR); - key.MipFilter = std::clamp(key.MipFilter, D3DTEXF_NONE, D3DTEXF_LINEAR); - - key.MaxAnisotropy = hasAnisotropy - ? std::clamp(key.MaxAnisotropy, 1, 16) - : 1; - - if (key.MipFilter == D3DTEXF_NONE) { - // May as well try and keep slots down. - key.MipmapLodBias = 0; - } - else { - // Games also pass NAN here, this accounts for that. - if (unlikely(key.MipmapLodBias != key.MipmapLodBias)) - key.MipmapLodBias = 0.0f; - - // Clamp between -15.0f and 15.0f, matching mip limits of d3d9. - key.MipmapLodBias = std::clamp(key.MipmapLodBias, -15.0f, 15.0f); - - // Round to the nearest .5 - // Fixes sampler leaks in UE3 games w/ mip streaming - // eg. Borderlands 2 - key.MipmapLodBias = std::round(key.MipmapLodBias * 2.0f) / 2.0f; - } - - if (key.AddressU != D3DTADDRESS_BORDER - && key.AddressV != D3DTADDRESS_BORDER - && key.AddressW != D3DTADDRESS_BORDER) { - key.BorderColor = 0; - } - } - -} \ No newline at end of file diff --git a/src/d3d9/meson.build b/src/d3d9/meson.build index bc3eac428..8a3d78d2f 100644 --- a/src/d3d9/meson.build +++ b/src/d3d9/meson.build @@ -33,7 +33,6 @@ d3d9_src = [ 'd3d9_multithread.cpp', 'd3d9_options.cpp', 'd3d9_stateblock.cpp', - 'd3d9_sampler.cpp', 'd3d9_util.cpp', 'd3d9_initializer.cpp', 'd3d9_fixed_function.cpp',