[d3d9, dxso] Alias color and depth samplers and improve tracking

Takes me from 340 -> 460fps in A Hat in Time's main menu when CPU bound.
This commit is contained in:
Joshua Ashton 2021-08-08 04:52:36 +01:00 committed by Joshie
parent 3f78bde928
commit c0c1565cba
10 changed files with 160 additions and 175 deletions

View File

@ -3710,6 +3710,19 @@ namespace dxvk {
DWORD oldUsage = oldTexture != nullptr ? oldTexture->Desc()->Usage : 0;
DWORD newUsage = newTexture != nullptr ? newTexture->Desc()->Usage : 0;
if (newTexture != nullptr) {
const bool oldDepth = m_depthTextures & (1u << StateSampler);
const bool newDepth = newTexture->IsShadow();
if (oldDepth != newDepth) {
m_depthTextures &= ~(1u << StateSampler);
if (newDepth)
m_depthTextures |= 1u << StateSampler;
m_dirtySamplerStates |= 1u << StateSampler;
}
}
DWORD combinedUsage = oldUsage | newUsage;
TextureChangePrivate(m_state.textures[StateSampler], pTexture);
@ -5703,6 +5716,7 @@ namespace dxvk {
key.MipmapLodBias = bit::cast<float>(state[D3DSAMP_MIPMAPLODBIAS]);
key.MaxMipLevel = state[D3DSAMP_MAXMIPLEVEL];
key.BorderColor = D3DCOLOR(state[D3DSAMP_BORDERCOLOR]);
key.Depth = m_depthTextures & (1u << Sampler);
if (m_d3d9Options.samplerAnisotropy != -1) {
if (key.MagFilter == D3DTEXF_LINEAR)
@ -5718,75 +5732,59 @@ namespace dxvk {
auto samplerInfo = RemapStateSamplerShader(Sampler);
const uint32_t colorSlot = computeResourceSlotId(
samplerInfo.first, DxsoBindingType::ColorImage,
samplerInfo.second);
const uint32_t depthSlot = computeResourceSlotId(
samplerInfo.first, DxsoBindingType::DepthImage,
const uint32_t slot = computeResourceSlotId(
samplerInfo.first, DxsoBindingType::Image,
samplerInfo.second);
EmitCs([this,
cColorSlot = colorSlot,
cDepthSlot = depthSlot,
cKey = key
cSlot = slot,
cKey = key
] (DxvkContext* ctx) {
auto pair = m_samplers.find(cKey);
if (pair != m_samplers.end()) {
ctx->bindResourceSampler(cColorSlot, pair->second.color);
ctx->bindResourceSampler(cDepthSlot, pair->second.depth);
ctx->bindResourceSampler(cSlot, pair->second);
return;
}
auto mipFilter = DecodeMipFilter(cKey.MipFilter);
DxvkSamplerCreateInfo colorInfo;
colorInfo.addressModeU = DecodeAddressMode(cKey.AddressU);
colorInfo.addressModeV = DecodeAddressMode(cKey.AddressV);
colorInfo.addressModeW = DecodeAddressMode(cKey.AddressW);
colorInfo.compareToDepth = VK_FALSE;
colorInfo.compareOp = VK_COMPARE_OP_NEVER;
colorInfo.magFilter = DecodeFilter(cKey.MagFilter);
colorInfo.minFilter = DecodeFilter(cKey.MinFilter);
colorInfo.mipmapMode = mipFilter.MipFilter;
colorInfo.maxAnisotropy = float(cKey.MaxAnisotropy);
colorInfo.useAnisotropy = cKey.MaxAnisotropy > 1;
colorInfo.mipmapLodBias = cKey.MipmapLodBias;
colorInfo.mipmapLodMin = mipFilter.MipsEnabled ? float(cKey.MaxMipLevel) : 0;
colorInfo.mipmapLodMax = mipFilter.MipsEnabled ? FLT_MAX : 0;
colorInfo.usePixelCoord = VK_FALSE;
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;
info.mipmapLodMin = mipFilter.MipsEnabled ? float(cKey.MaxMipLevel) : 0;
info.mipmapLodMax = mipFilter.MipsEnabled ? FLT_MAX : 0;
info.usePixelCoord = VK_FALSE;
DecodeD3DCOLOR(cKey.BorderColor, colorInfo.borderColor.float32);
DecodeD3DCOLOR(cKey.BorderColor, info.borderColor.float32);
if (!m_dxvkDevice->features().extCustomBorderColor.customBorderColorWithoutFormat) {
// HACK: Let's get OPAQUE_WHITE border color over
// TRANSPARENT_BLACK if the border RGB is white.
if (colorInfo.borderColor.float32[0] == 1.0f
&& colorInfo.borderColor.float32[1] == 1.0f
&& colorInfo.borderColor.float32[2] == 1.0f
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.
colorInfo.borderColor.float32[3] = 1.0f;
info.borderColor.float32[3] = 1.0f;
}
}
DxvkSamplerCreateInfo depthInfo = colorInfo;
depthInfo.compareToDepth = VK_TRUE;
depthInfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
depthInfo.magFilter = VK_FILTER_LINEAR;
depthInfo.minFilter = VK_FILTER_LINEAR;
try {
D3D9SamplerPair pair;
auto sampler = m_dxvkDevice->createSampler(info);
pair.color = m_dxvkDevice->createSampler(colorInfo);
pair.depth = m_dxvkDevice->createSampler(depthInfo);
m_samplers.insert(std::make_pair(cKey, sampler));
ctx->bindResourceSampler(cSlot, std::move(sampler));
m_samplerCount++;
m_samplers.insert(std::make_pair(cKey, pair));
ctx->bindResourceSampler(cColorSlot, pair.color);
ctx->bindResourceSampler(cDepthSlot, pair.depth);
}
catch (const DxvkError& e) {
Logger::err(e.message());
@ -5798,11 +5796,8 @@ namespace dxvk {
void D3D9DeviceEx::BindTexture(DWORD StateSampler) {
auto shaderSampler = RemapStateSamplerShader(StateSampler);
uint32_t colorSlot = computeResourceSlotId(shaderSampler.first,
DxsoBindingType::ColorImage, uint32_t(shaderSampler.second));
uint32_t depthSlot = computeResourceSlotId(shaderSampler.first,
DxsoBindingType::DepthImage, uint32_t(shaderSampler.second));
uint32_t slot = computeResourceSlotId(shaderSampler.first,
DxsoBindingType::Image, uint32_t(shaderSampler.second));
const bool srgb =
m_state.samplerStates[StateSampler][D3DSAMP_SRGBTEXTURE] & 0x1;
@ -5829,31 +5824,26 @@ namespace dxvk {
if (commonTex != nullptr) {
EmitCs([
cColorSlot = colorSlot,
cDepthSlot = depthSlot,
cDepth = commonTex->IsShadow(),
cSlot = slot,
cImageView = commonTex->GetSampleView(srgb)
](DxvkContext* ctx) {
ctx->bindResourceView(cColorSlot, !cDepth ? cImageView : nullptr, nullptr);
ctx->bindResourceView(cDepthSlot, cDepth ? cImageView : nullptr, nullptr);
ctx->bindResourceView(cSlot, cImageView, nullptr);
});
} else {
EmitCs([
cColorSlot = colorSlot,
cDepthSlot = depthSlot
cSlot = slot
](DxvkContext* ctx) {
ctx->bindResourceView(cColorSlot, nullptr, nullptr);
ctx->bindResourceView(cDepthSlot, nullptr, nullptr);
ctx->bindResourceView(cSlot, nullptr, nullptr);
});
}
}
void D3D9DeviceEx::UndirtySamplers() {
for (uint32_t dirty = m_dirtySamplerStates; dirty; dirty &= dirty - 1)
void D3D9DeviceEx::UndirtySamplers(uint32_t mask) {
for (uint32_t dirty = mask; dirty; dirty &= dirty - 1)
BindSampler(bit::tzcnt(dirty));
m_dirtySamplerStates = 0;
m_dirtySamplerStates &= ~mask;
}
@ -5914,15 +5904,13 @@ namespace dxvk {
FlushBuffer(vbo);
}
uint32_t texturesToUpload = m_activeTexturesToUpload;
texturesToUpload &= m_psShaderMasks.samplerMask | m_vsShaderMasks.samplerMask;
const uint32_t usedSamplerMask = m_activeTextures & (m_psShaderMasks.samplerMask | m_vsShaderMasks.samplerMask);
const uint32_t texturesToUpload = m_activeTexturesToUpload & usedSamplerMask;
if (unlikely(texturesToUpload != 0))
UploadManagedTextures(texturesToUpload);
uint32_t texturesToGen = m_activeTexturesToGen;
texturesToGen &= m_psShaderMasks.samplerMask | m_vsShaderMasks.samplerMask;
const uint32_t texturesToGen = m_activeTexturesToGen & usedSamplerMask;
if (unlikely(texturesToGen != 0))
GenerateTextureMips(texturesToGen);
@ -5938,8 +5926,9 @@ namespace dxvk {
if (m_flags.test(D3D9DeviceFlag::DirtyViewportScissor))
BindViewportAndScissor();
if (m_dirtySamplerStates)
UndirtySamplers();
const uint32_t activeDirtySamplers = m_dirtySamplerStates & usedSamplerMask;
if (activeDirtySamplers)
UndirtySamplers(activeDirtySamplers);
if (m_dirtyTextures)
UndirtyTextures();
@ -6030,6 +6019,10 @@ namespace dxvk {
UpdateFixedFunctionPS();
}
const uint32_t depthTextureMask = m_depthTextures & usedSamplerMask;
if (depthTextureMask != m_lastSamplerDepthMode)
UpdateSamplerDepthModeSpecConstant(depthTextureMask);
if (m_flags.test(D3D9DeviceFlag::DirtySharedPixelShaderData)) {
m_flags.clr(D3D9DeviceFlag::DirtySharedPixelShaderData);
@ -6720,6 +6713,15 @@ namespace dxvk {
}
void D3D9DeviceEx::UpdateSamplerDepthModeSpecConstant(uint32_t value) {
EmitCs([cBitfield = value](DxvkContext* ctx) {
ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::SamplerDepthMode, cBitfield);
});
m_lastSamplerDepthMode = value;
}
void D3D9DeviceEx::ApplyPrimitiveType(
DxvkContext* pContext,
D3DPRIMITIVETYPE PrimType) {
@ -7036,24 +7038,21 @@ namespace dxvk {
for (uint32_t i = 0; i < caps::MaxStreams; i++)
m_state.streamFreq[i] = 1;
for (uint32_t i = 0; i < m_state.textures.size(); i++) {
for (uint32_t i = 0; i < m_state.textures.size(); i++)
TextureChangePrivate(m_state.textures[i], nullptr);
DWORD sampler = i;
auto samplerInfo = RemapStateSamplerShader(sampler);
uint32_t colorSlot = computeResourceSlotId(samplerInfo.first, DxsoBindingType::ColorImage, uint32_t(samplerInfo.second));
uint32_t depthSlot = computeResourceSlotId(samplerInfo.first, DxsoBindingType::DepthImage, uint32_t(samplerInfo.second));
EmitCs([
cColorSlot = colorSlot,
cDepthSlot = depthSlot
](DxvkContext* ctx) {
ctx->bindResourceView(cColorSlot, nullptr, nullptr);
ctx->bindResourceView(cDepthSlot, nullptr, nullptr);
});
}
EmitCs([
cSize = m_state.textures.size()
](DxvkContext* ctx) {
for (uint32_t i = 0; i < cSize; i++) {
auto samplerInfo = RemapStateSamplerShader(DWORD(i));
uint32_t slot = computeResourceSlotId(samplerInfo.first, DxsoBindingType::Image, uint32_t(samplerInfo.second));
ctx->bindResourceView(slot, nullptr, nullptr);
}
});
m_dirtyTextures = 0;
m_depthTextures = 0;
auto& ss = m_state.samplerStates;
for (uint32_t i = 0; i < ss.size(); i++) {
@ -7088,6 +7087,7 @@ namespace dxvk {
UpdateSamplerSpecConsant(0u);
UpdateBoolSpecConstantVertex(0u);
UpdateBoolSpecConstantPixel(0u);
UpdateSamplerDepthModeSpecConstant(0u);
return D3D_OK;
}

View File

@ -82,11 +82,6 @@ namespace dxvk {
uint32_t instanceCount;
};
struct D3D9SamplerPair {
Rc<DxvkSampler> color;
Rc<DxvkSampler> depth;
};
struct D3D9BufferSlice {
DxvkBufferSlice slice = {};
void* mapPtr = nullptr;
@ -840,7 +835,7 @@ namespace dxvk {
void BindTexture(DWORD SamplerSampler);
void UndirtySamplers();
void UndirtySamplers(uint32_t mask);
void UndirtyTextures();
@ -926,6 +921,9 @@ namespace dxvk {
D3D9DeviceFlags m_flags;
uint32_t m_dirtySamplerStates = 0;
uint32_t m_dirtyTextures = 0;
// Last state of depth textures. Doesn't update when NULL is bound.
// & with m_activeTextures to normalize.
uint32_t m_depthTextures = 0;
D3D9Adapter* m_adapter;
Rc<DxvkDevice> m_dxvkDevice;
@ -1024,7 +1022,7 @@ namespace dxvk {
std::unordered_map<
D3D9SamplerKey,
D3D9SamplerPair,
Rc<DxvkSampler>,
D3D9SamplerKeyHash,
D3D9SamplerKeyEq> m_samplers;
@ -1063,6 +1061,8 @@ namespace dxvk {
uint32_t m_activeHazardsDS = 0;
uint32_t m_lastHazardsDS = 0;
uint32_t m_lastSamplerDepthMode = 0;
D3D9ShaderMasks m_vsShaderMasks = D3D9ShaderMasks();
D3D9ShaderMasks m_psShaderMasks = FixedFunctionMask;
@ -1241,6 +1241,8 @@ namespace dxvk {
void UpdateFetch4SpecConstant(uint32_t value);
void UpdateSamplerDepthModeSpecConstant(uint32_t value);
};
}

View File

@ -2092,7 +2092,7 @@ namespace dxvk {
m_module.setDebugName(sampler.varId, name.c_str());
const uint32_t bindingId = computeResourceSlotId(DxsoProgramType::PixelShader,
DxsoBindingType::ColorImage, i);
DxsoBindingType::Image, i);
sampler.bound = m_module.specConstBool(true);
m_module.decorateSpecId(sampler.bound, bindingId);

View File

@ -9,6 +9,7 @@ namespace dxvk {
std::hash<D3DTEXTUREADDRESS> tahash;
std::hash<D3DTEXTUREFILTERTYPE> tfhash;
std::hash<float> fhash;
std::hash<bool> bhash;
state.add(tahash(key.AddressU));
state.add(tahash(key.AddressV));
@ -20,6 +21,7 @@ namespace dxvk {
state.add(fhash (key.MipmapLodBias));
state.add(dhash (key.MaxMipLevel));
state.add(dhash (key.BorderColor));
state.add(bhash (key.Depth));
return state;
}
@ -35,7 +37,8 @@ namespace dxvk {
&& a.MaxAnisotropy == b.MaxAnisotropy
&& a.MipmapLodBias == b.MipmapLodBias
&& a.MaxMipLevel == b.MaxMipLevel
&& a.BorderColor == b.BorderColor;
&& a.BorderColor == b.BorderColor
&& a.Depth == b.Depth;
}
}

View File

@ -21,6 +21,7 @@ namespace dxvk {
float MipmapLodBias;
DWORD MaxMipLevel;
D3DCOLOR BorderColor;
bool Depth;
};
struct D3D9SamplerKeyHash {

View File

@ -16,7 +16,9 @@ namespace dxvk {
VertexShaderBools = 7,
PixelShaderBools = 8,
Fetch4 = 9
Fetch4 = 9,
SamplerDepthMode = 10,
};
}

View File

@ -362,6 +362,10 @@ namespace dxvk {
? D3D9SpecConstantId::VertexShaderBools
: D3D9SpecConstantId::PixelShaderBools));
m_module.setDebugName(m_boolSpecConstant, "boolConstants");
m_depthSpecConstant = m_module.specConst32(m_module.defIntType(32, 0), 0);
m_module.decorateSpecId(m_depthSpecConstant, getSpecId(D3D9SpecConstantId::SamplerDepthMode));
m_module.setDebugName(m_depthSpecConstant, "depthSamplers");
}
@ -683,8 +687,11 @@ namespace dxvk {
DxsoTextureType type) {
m_usedSamplers |= (1u << idx);
auto DclSampler = [this](
VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
auto DclSampler = [this, &viewType](
uint32_t idx,
uint32_t bindingId,
DxsoSamplerType type,
bool depth,
bool implicit) {
@ -694,7 +701,6 @@ namespace dxvk {
: m_samplers[idx].depth[type];
spv::Dim dimensionality;
VkImageViewType viewType;
const char* suffix = "_2d";
@ -736,31 +742,25 @@ namespace dxvk {
std::string name = str::format("s", idx, suffix, depth ? "_shadow" : "");
m_module.setDebugName(sampler.varId, name.c_str());
const uint32_t bindingId = computeResourceSlotId(m_programInfo.type(),
!depth ? DxsoBindingType::ColorImage : DxsoBindingType::DepthImage,
idx);
m_module.decorateDescriptorSet(sampler.varId, 0);
m_module.decorateBinding (sampler.varId, bindingId);
// Store descriptor info for the shader interface
DxvkResourceSlot resource;
resource.slot = bindingId;
resource.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
resource.view = implicit ? VK_IMAGE_VIEW_TYPE_MAX_ENUM : viewType;
resource.access = VK_ACCESS_SHADER_READ_BIT;
m_resourceSlots.push_back(resource);
};
if (m_programInfo.majorVersion() >= 2 && !m_moduleInfo.options.forceSamplerTypeSpecConstants) {
const uint32_t binding = computeResourceSlotId(m_programInfo.type(),
DxsoBindingType::Image,
idx);
const bool implicit = m_programInfo.majorVersion() < 2 || m_moduleInfo.options.forceSamplerTypeSpecConstants;
if (!implicit) {
DxsoSamplerType samplerType =
SamplerTypeFromTextureType(type);
DclSampler(idx, samplerType, false, false);
DclSampler(idx, binding, samplerType, false, implicit);
if (samplerType != SamplerTypeTexture3D) {
// We could also be depth compared!
DclSampler(idx, samplerType, true, false);
DclSampler(idx, binding, samplerType, true, implicit);
}
}
else {
@ -769,33 +769,27 @@ namespace dxvk {
for (uint32_t i = 0; i < SamplerTypeCount; i++) {
auto samplerType = static_cast<DxsoSamplerType>(i);
DclSampler(idx, samplerType, false, true);
DclSampler(idx, binding, samplerType, false, implicit);
if (samplerType != SamplerTypeTexture3D)
DclSampler(idx, samplerType, true, true);
DclSampler(idx, binding, samplerType, true, implicit);
}
}
// Declare a specialization constant which will
// store whether or not the depth/color views are bound.
const uint32_t colorBinding = computeResourceSlotId(m_programInfo.type(),
DxsoBindingType::ColorImage, idx);
const uint32_t depthBinding = computeResourceSlotId(m_programInfo.type(),
DxsoBindingType::DepthImage, idx);
DxsoSampler& sampler = m_samplers[idx];
sampler.colorSpecConst = m_module.specConstBool(true);
sampler.depthSpecConst = m_module.specConstBool(true);
sampler.boundConst = m_module.specConstBool(true);
sampler.type = type;
m_module.decorateSpecId(sampler.colorSpecConst, colorBinding);
m_module.decorateSpecId(sampler.depthSpecConst, depthBinding);
m_module.setDebugName(sampler.colorSpecConst,
str::format("s", idx, "_useColor").c_str());
m_module.setDebugName(sampler.depthSpecConst,
str::format("s", idx, "_useShadow").c_str());
m_module.decorateSpecId(sampler.boundConst, binding);
m_module.setDebugName(sampler.boundConst,
str::format("s", idx, "_bound").c_str());
// Store descriptor info for the shader interface
DxvkResourceSlot resource;
resource.slot = binding;
resource.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
resource.view = implicit ? VK_IMAGE_VIEW_TYPE_MAX_ENUM : viewType;
resource.access = VK_ACCESS_SHADER_READ_BIT;
m_resourceSlots.push_back(resource);
}
@ -2882,21 +2876,28 @@ void DxsoCompiler::emitControlFlowGenericLoop(
uint32_t depthLabel = m_module.allocateId();
uint32_t endLabel = m_module.allocateId();
uint32_t typeId = m_module.defIntType(32, 0);
uint32_t offset = m_module.consti32(m_programInfo.type() == DxsoProgramTypes::VertexShader ? samplerIdx + 17 : samplerIdx);
uint32_t bitCnt = m_module.consti32(1);
uint32_t isDepth = m_module.opBitFieldUExtract(typeId, m_depthSpecConstant, offset, bitCnt);
isDepth = m_module.opIEqual(m_module.defBoolType(), isDepth, m_module.constu32(1));
m_module.opSelectionMerge(endLabel, spv::SelectionControlMaskNone);
m_module.opBranchConditional(sampler.depthSpecConst, depthLabel, colorLabel);
m_module.opBranchConditional(isDepth, depthLabel, colorLabel);
m_module.opLabel(colorLabel);
SampleImage(texcoordVar, sampler.color[samplerType], false, samplerType, sampler.colorSpecConst);
SampleImage(texcoordVar, sampler.color[samplerType], false, samplerType, sampler.boundConst);
m_module.opBranch(endLabel);
m_module.opLabel(depthLabel);
SampleImage(texcoordVar, sampler.depth[samplerType], true, samplerType, 0); // already specc'ed
// No spec constant as if we are unbound we always fall down the color path.
SampleImage(texcoordVar, sampler.depth[samplerType], true, samplerType, 0);
m_module.opBranch(endLabel);
m_module.opLabel(endLabel);
}
else
SampleImage(texcoordVar, sampler.color[samplerType], false, samplerType, sampler.colorSpecConst);
SampleImage(texcoordVar, sampler.color[samplerType], false, samplerType, sampler.boundConst);
};
if (m_programInfo.majorVersion() >= 2 && !m_moduleInfo.options.forceSamplerTypeSpecConstants) {

View File

@ -128,8 +128,7 @@ namespace dxvk {
DxsoSamplerInfo color[SamplerTypeCount];
DxsoSamplerInfo depth[SamplerTypeCount];
uint32_t colorSpecConst;
uint32_t depthSpecConst;
uint32_t boundConst;
DxsoTextureType type;
};
@ -270,6 +269,7 @@ namespace dxvk {
SpirvModule m_module;
uint32_t m_boolSpecConstant;
uint32_t m_depthSpecConstant;
///////////////////////////////////////////////////////
// Resource slot description for the shader. This will

View File

@ -4,39 +4,6 @@
namespace dxvk {
uint32_t computeResourceSlotId(
DxsoProgramType shaderStage,
DxsoBindingType bindingType,
uint32_t bindingIndex) {
const uint32_t stageOffset = 12 * uint32_t(shaderStage);
if (shaderStage == DxsoProgramTypes::VertexShader) {
switch (bindingType) {
case DxsoBindingType::ConstantBuffer: return bindingIndex + stageOffset + 0; // 0 + 4 = 4
case DxsoBindingType::ColorImage: return bindingIndex + stageOffset + 4; // 4 + 4 = 8
case DxsoBindingType::DepthImage: return bindingIndex + stageOffset + 8; // 8 + 4 = 12
default: Logger::err("computeResourceSlotId: Invalid resource type");
}
}
else { // Pixel Shader
switch (bindingType) {
case DxsoBindingType::ConstantBuffer: return bindingIndex + stageOffset + 0; // 0 + 3 = 3
// The extra sampler here is being reserved for DMAP stuff later on.
case DxsoBindingType::ColorImage: return bindingIndex + stageOffset + 3; // 3 + 17 = 20
case DxsoBindingType::DepthImage: return bindingIndex + stageOffset + 20; // 20 + 17 = 27
default: Logger::err("computeResourceSlotId: Invalid resource type");
}
}
return 0;
}
// TODO: Intergrate into compute resource slot ID/refactor all of this?
uint32_t getSWVPBufferSlot() {
return 39;
}
dxvk::mutex g_linkerSlotMutex;
uint32_t g_linkerSlotCount = 0;
std::array<DxsoSemantic, 32> g_linkerSlots;

View File

@ -9,8 +9,7 @@ namespace dxvk {
enum class DxsoBindingType : uint32_t {
ConstantBuffer,
ColorImage,
DepthImage // <-- We use whatever one is bound to determine whether an image should be 'shadow' sampled or not.
Image,
};
enum DxsoConstantBuffers : uint32_t {
@ -26,12 +25,22 @@ namespace dxvk {
PSCount
};
uint32_t computeResourceSlotId(
DxsoProgramType shaderStage,
DxsoBindingType bindingType,
uint32_t bindingIndex);
constexpr uint32_t computeResourceSlotId(
DxsoProgramType shaderStage,
DxsoBindingType bindingType,
uint32_t bindingIndex) {
const uint32_t stageOffset = 8 * uint32_t(shaderStage);
uint32_t getSWVPBufferSlot();
if (bindingType == DxsoBindingType::ConstantBuffer)
return bindingIndex + stageOffset;
else // if (bindingType == DxsoBindingType::Image)
return bindingIndex + stageOffset + (shaderStage == DxsoProgramType::PixelShader ? PSCount : VSCount);
}
// TODO: Intergrate into compute resource slot ID/refactor all of this?
constexpr uint32_t getSWVPBufferSlot() {
return 27; // From last pixel shader slot, above.
}
uint32_t RegisterLinkerSlot(DxsoSemantic semantic);