Skip to content

Commit

Permalink
[dxvk] Implement sampler pool
Browse files Browse the repository at this point in the history
Deduplicates redundant sampler objects and makes sampler creation
as well as lifetime tracking a bit more efficient.
  • Loading branch information
doitsujin committed Sep 27, 2024
1 parent a4ecb30 commit aa95f07
Show file tree
Hide file tree
Showing 15 changed files with 521 additions and 223 deletions.
78 changes: 38 additions & 40 deletions src/d3d11/d3d11_sampler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,63 +9,61 @@ namespace dxvk {
const D3D11_SAMPLER_DESC& desc)
: D3D11StateObject<ID3D11SamplerState>(device),
m_desc(desc), m_d3d10(this) {
DxvkSamplerCreateInfo info;
DxvkSamplerKey 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 & 0x180) == 0x80 ? VK_TRUE : VK_FALSE;
info.compareOp = DecodeCompareOp(desc.ComparisonFunc);

info.reductionMode = DecodeReductionMode(filterBits);
VkFilter minFilter = (filterBits & 0x10) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
VkFilter magFilter = (filterBits & 0x04) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;

info.setFilter(minFilter, magFilter,
(filterBits & 0x01) ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST);

for (uint32_t i = 0; i < 4; i++)
info.borderColor.float32[i] = desc.BorderColor[i];

info.usePixelCoord = VK_FALSE; // Not supported in D3D11
info.nonSeamless = VK_FALSE;

// 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 LOD bias specified in the device options
if (info.minFilter == VK_FILTER_LINEAR && info.magFilter == VK_FILTER_LINEAR) {
info.mipmapLodBias += device->GetOptions()->samplerLodBias;
float lodBias = desc.MipLODBias;

if (minFilter == VK_FILTER_LINEAR && magFilter == VK_FILTER_LINEAR) {
lodBias += device->GetOptions()->samplerLodBias;

if (device->GetOptions()->clampNegativeLodBias)
info.mipmapLodBias = std::max(info.mipmapLodBias, 0.0f);
lodBias = std::max(lodBias, 0.0f);
}

info.setLodRange(desc.MinLOD, desc.MaxLOD, lodBias);

// Enforce anisotropy specified in the device options
uint32_t anisotropy = (filterBits & 0x40) ? desc.MaxAnisotropy : 0u;
int32_t samplerAnisotropyOption = device->GetOptions()->samplerAnisotropy;

if (samplerAnisotropyOption >= 0 && info.minFilter == VK_FILTER_LINEAR) {
info.useAnisotropy = samplerAnisotropyOption > 0;
info.maxAnisotropy = float(samplerAnisotropyOption);
if (samplerAnisotropyOption >= 0 && minFilter == VK_FILTER_LINEAR) {
anisotropy = samplerAnisotropyOption > 0
? uint32_t(samplerAnisotropyOption)
: 0u;
}

info.setAniso(anisotropy);

// Set up the remaining properties, which are
// stored directly in the sampler description
info.setAddressModes(
DecodeAddressMode(desc.AddressU),
DecodeAddressMode(desc.AddressV),
DecodeAddressMode(desc.AddressW));

info.setDepthCompare((filterBits & 0x180) == 0x80,
DecodeCompareOp(desc.ComparisonFunc));

info.setReduction(DecodeReductionMode(filterBits));

for (uint32_t i = 0; i < 4; i++)
info.borderColor.float32[i] = desc.BorderColor[i];

m_sampler = device->GetDXVKDevice()->createSampler(info);
}


D3D11SamplerState::~D3D11SamplerState() {

}
Expand Down
57 changes: 26 additions & 31 deletions src/d3d9/d3d9_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6689,41 +6689,36 @@ namespace dxvk {

auto mipFilter = DecodeMipFilter(cKey.MipFilter);

DxvkSamplerCreateInfo info;
info.addressModeU = DecodeAddressMode(cKey.AddressU);
info.addressModeV = DecodeAddressMode(cKey.AddressV);
info.addressModeW = DecodeAddressMode(cKey.AddressW);
info.compareToDepth = cKey.Depth;
info.compareOp = cKey.Depth ? VK_COMPARE_OP_LESS_OR_EQUAL : VK_COMPARE_OP_NEVER;
info.magFilter = DecodeFilter(cKey.MagFilter);
info.minFilter = DecodeFilter(cKey.MinFilter);
info.mipmapMode = mipFilter.MipFilter;
info.maxAnisotropy = float(cKey.MaxAnisotropy);
info.useAnisotropy = cKey.MaxAnisotropy > 1;

info.mipmapLodBias = cKey.MipmapLodBias + m_d3d9Options.samplerLodBias;
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)
info.mipmapLodBias = std::max(info.mipmapLodBias, 0.0f);
lodBias = std::max(lodBias, 0.0f);

info.mipmapLodMin = mipFilter.MipsEnabled ? float(cKey.MaxMipLevel) : 0;
info.mipmapLodMax = mipFilter.MipsEnabled ? FLT_MAX : 0;
info.reductionMode = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE;
info.usePixelCoord = VK_FALSE;
info.nonSeamless = m_dxvkDevice->features().extNonSeamlessCubeMap.nonSeamlessCubeMap && !m_d3d9Options.seamlessCubes;
info.setLodRange(
mipFilter.MipsEnabled ? float(cKey.MaxMipLevel) : 0.0f,
mipFilter.MipsEnabled ? FLT_MAX : 0.0f,
lodBias);

DecodeD3DCOLOR(cKey.BorderColor, info.borderColor.float32);
info.setLegacyCubeFilter(!m_d3d9Options.seamlessCubes);

if (!m_dxvkDevice->features().extCustomBorderColor.customBorderColorWithoutFormat) {
// HACK: Let's get OPAQUE_WHITE border color over
// TRANSPARENT_BLACK if the border RGB is white.
if (info.borderColor.float32[0] == 1.0f
&& info.borderColor.float32[1] == 1.0f
&& info.borderColor.float32[2] == 1.0f
&& !m_dxvkDevice->features().extCustomBorderColor.customBorderColors) {
// Then set the alpha to 1.
info.borderColor.float32[3] = 1.0f;
}
}
DecodeD3DCOLOR(cKey.BorderColor, info.borderColor.float32);

try {
auto sampler = m_dxvkDevice->createSampler(info);
Expand Down
4 changes: 4 additions & 0 deletions src/dxvk/dxvk_cmdlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ namespace dxvk {
m_resources.trackResource(DxvkLifetime<DxvkResource>(rc, Access));
}

void trackSampler(const Rc<DxvkSampler>& sampler) {
m_resources.trackSampler(sampler);
}

/**
* \brief Tracks a GPU event
*
Expand Down
4 changes: 2 additions & 2 deletions src/dxvk/dxvk_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5260,7 +5260,7 @@ namespace dxvk {
descriptorInfo.image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;

if (m_rcTracked.set(binding.resourceBinding))
m_cmd->trackResource<DxvkAccess::None>(res.sampler);
m_cmd->trackSampler(res.sampler);
} else {
descriptorInfo.image.sampler = m_common->dummyResources().samplerHandle();
descriptorInfo.image.imageView = VK_NULL_HANDLE;
Expand Down Expand Up @@ -5312,7 +5312,7 @@ namespace dxvk {
descriptorInfo.image.imageLayout = res.imageView->image()->info().layout;

if (m_rcTracked.set(binding.resourceBinding)) {
m_cmd->trackResource<DxvkAccess::None>(res.sampler);
m_cmd->trackSampler(res.sampler);
m_cmd->trackResource<DxvkAccess::Read>(res.imageView->image());
}
} else {
Expand Down
4 changes: 2 additions & 2 deletions src/dxvk/dxvk_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ namespace dxvk {


Rc<DxvkSampler> DxvkDevice::createSampler(
const DxvkSamplerCreateInfo& createInfo) {
return new DxvkSampler(this, createInfo);
const DxvkSamplerKey& createInfo) {
return m_objects.samplerPool().createSampler(createInfo);
}


Expand Down
2 changes: 1 addition & 1 deletion src/dxvk/dxvk_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ namespace dxvk {
* \returns Newly created sampler object
*/
Rc<DxvkSampler> createSampler(
const DxvkSamplerCreateInfo& createInfo);
const DxvkSamplerKey& createInfo);

/**
* \brief Creates local allocation cache
Expand Down
1 change: 1 addition & 0 deletions src/dxvk/dxvk_lifetime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace dxvk {
void DxvkLifetimeTracker::reset() {
m_resources.clear();
m_allocations.clear();
m_samplers.clear();
}

}
12 changes: 12 additions & 0 deletions src/dxvk/dxvk_lifetime.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#pragma once

#include <unordered_set>
#include <vector>

#include "dxvk_resource.h"
#include "dxvk_sampler.h"

namespace dxvk {

Expand Down Expand Up @@ -106,6 +108,14 @@ namespace dxvk {
DxvkLifetimeTracker();
~DxvkLifetimeTracker();

/**
* \brief Adds a sampler to track
* \param [in] res The sampler to track
*/
void trackSampler(const Rc<DxvkSampler>& res) {
m_samplers.insert(res);
}

/**
* \brief Adds a resource to track
* \param [in] res The resource to track
Expand All @@ -132,6 +142,8 @@ namespace dxvk {

private:

std::unordered_set<Rc<DxvkSampler>, RcHash> m_samplers;

std::vector<DxvkLifetime<DxvkResource>> m_resources;
std::vector<DxvkLifetime<DxvkResourceAllocation>> m_allocations;

Expand Down
7 changes: 7 additions & 0 deletions src/dxvk/dxvk_objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "dxvk_meta_resolve.h"
#include "dxvk_pipemanager.h"
#include "dxvk_renderpass.h"
#include "dxvk_sampler.h"
#include "dxvk_unbound.h"

#include "../util/util_lazy.h"
Expand All @@ -25,6 +26,7 @@ namespace dxvk {
: m_device (device),
m_memoryManager (device),
m_pipelineManager (device),
m_samplerPool (device),
m_eventPool (device),
m_queryPool (device),
m_dummyResources (device) {
Expand All @@ -39,6 +41,10 @@ namespace dxvk {
return m_pipelineManager;
}

DxvkSamplerPool& samplerPool() {
return m_samplerPool;
}

DxvkGpuEventPool& eventPool() {
return m_eventPool;
}
Expand Down Expand Up @@ -78,6 +84,7 @@ namespace dxvk {
DxvkMemoryAllocator m_memoryManager;
DxvkPipelineManager m_pipelineManager;

DxvkSamplerPool m_samplerPool;
DxvkGpuEventPool m_eventPool;
DxvkGpuQueryPool m_queryPool;

Expand Down
Loading

0 comments on commit aa95f07

Please sign in to comment.