mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-22 07:54:15 +01:00
[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:
parent
3f78bde928
commit
c0c1565cba
@ -3710,6 +3710,19 @@ namespace dxvk {
|
|||||||
DWORD oldUsage = oldTexture != nullptr ? oldTexture->Desc()->Usage : 0;
|
DWORD oldUsage = oldTexture != nullptr ? oldTexture->Desc()->Usage : 0;
|
||||||
DWORD newUsage = newTexture != nullptr ? newTexture->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;
|
DWORD combinedUsage = oldUsage | newUsage;
|
||||||
|
|
||||||
TextureChangePrivate(m_state.textures[StateSampler], pTexture);
|
TextureChangePrivate(m_state.textures[StateSampler], pTexture);
|
||||||
@ -5703,6 +5716,7 @@ namespace dxvk {
|
|||||||
key.MipmapLodBias = bit::cast<float>(state[D3DSAMP_MIPMAPLODBIAS]);
|
key.MipmapLodBias = bit::cast<float>(state[D3DSAMP_MIPMAPLODBIAS]);
|
||||||
key.MaxMipLevel = state[D3DSAMP_MAXMIPLEVEL];
|
key.MaxMipLevel = state[D3DSAMP_MAXMIPLEVEL];
|
||||||
key.BorderColor = D3DCOLOR(state[D3DSAMP_BORDERCOLOR]);
|
key.BorderColor = D3DCOLOR(state[D3DSAMP_BORDERCOLOR]);
|
||||||
|
key.Depth = m_depthTextures & (1u << Sampler);
|
||||||
|
|
||||||
if (m_d3d9Options.samplerAnisotropy != -1) {
|
if (m_d3d9Options.samplerAnisotropy != -1) {
|
||||||
if (key.MagFilter == D3DTEXF_LINEAR)
|
if (key.MagFilter == D3DTEXF_LINEAR)
|
||||||
@ -5718,75 +5732,59 @@ namespace dxvk {
|
|||||||
|
|
||||||
auto samplerInfo = RemapStateSamplerShader(Sampler);
|
auto samplerInfo = RemapStateSamplerShader(Sampler);
|
||||||
|
|
||||||
const uint32_t colorSlot = computeResourceSlotId(
|
const uint32_t slot = computeResourceSlotId(
|
||||||
samplerInfo.first, DxsoBindingType::ColorImage,
|
samplerInfo.first, DxsoBindingType::Image,
|
||||||
samplerInfo.second);
|
|
||||||
|
|
||||||
const uint32_t depthSlot = computeResourceSlotId(
|
|
||||||
samplerInfo.first, DxsoBindingType::DepthImage,
|
|
||||||
samplerInfo.second);
|
samplerInfo.second);
|
||||||
|
|
||||||
EmitCs([this,
|
EmitCs([this,
|
||||||
cColorSlot = colorSlot,
|
cSlot = slot,
|
||||||
cDepthSlot = depthSlot,
|
|
||||||
cKey = key
|
cKey = key
|
||||||
] (DxvkContext* ctx) {
|
] (DxvkContext* ctx) {
|
||||||
auto pair = m_samplers.find(cKey);
|
auto pair = m_samplers.find(cKey);
|
||||||
if (pair != m_samplers.end()) {
|
if (pair != m_samplers.end()) {
|
||||||
ctx->bindResourceSampler(cColorSlot, pair->second.color);
|
ctx->bindResourceSampler(cSlot, pair->second);
|
||||||
ctx->bindResourceSampler(cDepthSlot, pair->second.depth);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mipFilter = DecodeMipFilter(cKey.MipFilter);
|
auto mipFilter = DecodeMipFilter(cKey.MipFilter);
|
||||||
|
|
||||||
DxvkSamplerCreateInfo colorInfo;
|
DxvkSamplerCreateInfo info;
|
||||||
colorInfo.addressModeU = DecodeAddressMode(cKey.AddressU);
|
info.addressModeU = DecodeAddressMode(cKey.AddressU);
|
||||||
colorInfo.addressModeV = DecodeAddressMode(cKey.AddressV);
|
info.addressModeV = DecodeAddressMode(cKey.AddressV);
|
||||||
colorInfo.addressModeW = DecodeAddressMode(cKey.AddressW);
|
info.addressModeW = DecodeAddressMode(cKey.AddressW);
|
||||||
colorInfo.compareToDepth = VK_FALSE;
|
info.compareToDepth = cKey.Depth;
|
||||||
colorInfo.compareOp = VK_COMPARE_OP_NEVER;
|
info.compareOp = cKey.Depth ? VK_COMPARE_OP_LESS_OR_EQUAL : VK_COMPARE_OP_NEVER;
|
||||||
colorInfo.magFilter = DecodeFilter(cKey.MagFilter);
|
info.magFilter = DecodeFilter(cKey.MagFilter);
|
||||||
colorInfo.minFilter = DecodeFilter(cKey.MinFilter);
|
info.minFilter = DecodeFilter(cKey.MinFilter);
|
||||||
colorInfo.mipmapMode = mipFilter.MipFilter;
|
info.mipmapMode = mipFilter.MipFilter;
|
||||||
colorInfo.maxAnisotropy = float(cKey.MaxAnisotropy);
|
info.maxAnisotropy = float(cKey.MaxAnisotropy);
|
||||||
colorInfo.useAnisotropy = cKey.MaxAnisotropy > 1;
|
info.useAnisotropy = cKey.MaxAnisotropy > 1;
|
||||||
colorInfo.mipmapLodBias = cKey.MipmapLodBias;
|
info.mipmapLodBias = cKey.MipmapLodBias;
|
||||||
colorInfo.mipmapLodMin = mipFilter.MipsEnabled ? float(cKey.MaxMipLevel) : 0;
|
info.mipmapLodMin = mipFilter.MipsEnabled ? float(cKey.MaxMipLevel) : 0;
|
||||||
colorInfo.mipmapLodMax = mipFilter.MipsEnabled ? FLT_MAX : 0;
|
info.mipmapLodMax = mipFilter.MipsEnabled ? FLT_MAX : 0;
|
||||||
colorInfo.usePixelCoord = VK_FALSE;
|
info.usePixelCoord = VK_FALSE;
|
||||||
|
|
||||||
DecodeD3DCOLOR(cKey.BorderColor, colorInfo.borderColor.float32);
|
DecodeD3DCOLOR(cKey.BorderColor, info.borderColor.float32);
|
||||||
|
|
||||||
if (!m_dxvkDevice->features().extCustomBorderColor.customBorderColorWithoutFormat) {
|
if (!m_dxvkDevice->features().extCustomBorderColor.customBorderColorWithoutFormat) {
|
||||||
// HACK: Let's get OPAQUE_WHITE border color over
|
// HACK: Let's get OPAQUE_WHITE border color over
|
||||||
// TRANSPARENT_BLACK if the border RGB is white.
|
// TRANSPARENT_BLACK if the border RGB is white.
|
||||||
if (colorInfo.borderColor.float32[0] == 1.0f
|
if (info.borderColor.float32[0] == 1.0f
|
||||||
&& colorInfo.borderColor.float32[1] == 1.0f
|
&& info.borderColor.float32[1] == 1.0f
|
||||||
&& colorInfo.borderColor.float32[2] == 1.0f
|
&& info.borderColor.float32[2] == 1.0f
|
||||||
&& !m_dxvkDevice->features().extCustomBorderColor.customBorderColors) {
|
&& !m_dxvkDevice->features().extCustomBorderColor.customBorderColors) {
|
||||||
// Then set the alpha to 1.
|
// 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 {
|
try {
|
||||||
D3D9SamplerPair pair;
|
auto sampler = m_dxvkDevice->createSampler(info);
|
||||||
|
|
||||||
pair.color = m_dxvkDevice->createSampler(colorInfo);
|
m_samplers.insert(std::make_pair(cKey, sampler));
|
||||||
pair.depth = m_dxvkDevice->createSampler(depthInfo);
|
ctx->bindResourceSampler(cSlot, std::move(sampler));
|
||||||
|
|
||||||
m_samplerCount++;
|
m_samplerCount++;
|
||||||
|
|
||||||
m_samplers.insert(std::make_pair(cKey, pair));
|
|
||||||
ctx->bindResourceSampler(cColorSlot, pair.color);
|
|
||||||
ctx->bindResourceSampler(cDepthSlot, pair.depth);
|
|
||||||
}
|
}
|
||||||
catch (const DxvkError& e) {
|
catch (const DxvkError& e) {
|
||||||
Logger::err(e.message());
|
Logger::err(e.message());
|
||||||
@ -5798,11 +5796,8 @@ namespace dxvk {
|
|||||||
void D3D9DeviceEx::BindTexture(DWORD StateSampler) {
|
void D3D9DeviceEx::BindTexture(DWORD StateSampler) {
|
||||||
auto shaderSampler = RemapStateSamplerShader(StateSampler);
|
auto shaderSampler = RemapStateSamplerShader(StateSampler);
|
||||||
|
|
||||||
uint32_t colorSlot = computeResourceSlotId(shaderSampler.first,
|
uint32_t slot = computeResourceSlotId(shaderSampler.first,
|
||||||
DxsoBindingType::ColorImage, uint32_t(shaderSampler.second));
|
DxsoBindingType::Image, uint32_t(shaderSampler.second));
|
||||||
|
|
||||||
uint32_t depthSlot = computeResourceSlotId(shaderSampler.first,
|
|
||||||
DxsoBindingType::DepthImage, uint32_t(shaderSampler.second));
|
|
||||||
|
|
||||||
const bool srgb =
|
const bool srgb =
|
||||||
m_state.samplerStates[StateSampler][D3DSAMP_SRGBTEXTURE] & 0x1;
|
m_state.samplerStates[StateSampler][D3DSAMP_SRGBTEXTURE] & 0x1;
|
||||||
@ -5829,31 +5824,26 @@ namespace dxvk {
|
|||||||
|
|
||||||
if (commonTex != nullptr) {
|
if (commonTex != nullptr) {
|
||||||
EmitCs([
|
EmitCs([
|
||||||
cColorSlot = colorSlot,
|
cSlot = slot,
|
||||||
cDepthSlot = depthSlot,
|
|
||||||
cDepth = commonTex->IsShadow(),
|
|
||||||
cImageView = commonTex->GetSampleView(srgb)
|
cImageView = commonTex->GetSampleView(srgb)
|
||||||
](DxvkContext* ctx) {
|
](DxvkContext* ctx) {
|
||||||
ctx->bindResourceView(cColorSlot, !cDepth ? cImageView : nullptr, nullptr);
|
ctx->bindResourceView(cSlot, cImageView, nullptr);
|
||||||
ctx->bindResourceView(cDepthSlot, cDepth ? cImageView : nullptr, nullptr);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
EmitCs([
|
EmitCs([
|
||||||
cColorSlot = colorSlot,
|
cSlot = slot
|
||||||
cDepthSlot = depthSlot
|
|
||||||
](DxvkContext* ctx) {
|
](DxvkContext* ctx) {
|
||||||
ctx->bindResourceView(cColorSlot, nullptr, nullptr);
|
ctx->bindResourceView(cSlot, nullptr, nullptr);
|
||||||
ctx->bindResourceView(cDepthSlot, nullptr, nullptr);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D9DeviceEx::UndirtySamplers() {
|
void D3D9DeviceEx::UndirtySamplers(uint32_t mask) {
|
||||||
for (uint32_t dirty = m_dirtySamplerStates; dirty; dirty &= dirty - 1)
|
for (uint32_t dirty = mask; dirty; dirty &= dirty - 1)
|
||||||
BindSampler(bit::tzcnt(dirty));
|
BindSampler(bit::tzcnt(dirty));
|
||||||
|
|
||||||
m_dirtySamplerStates = 0;
|
m_dirtySamplerStates &= ~mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5914,15 +5904,13 @@ namespace dxvk {
|
|||||||
FlushBuffer(vbo);
|
FlushBuffer(vbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t texturesToUpload = m_activeTexturesToUpload;
|
const uint32_t usedSamplerMask = m_activeTextures & (m_psShaderMasks.samplerMask | m_vsShaderMasks.samplerMask);
|
||||||
texturesToUpload &= m_psShaderMasks.samplerMask | m_vsShaderMasks.samplerMask;
|
|
||||||
|
|
||||||
|
const uint32_t texturesToUpload = m_activeTexturesToUpload & usedSamplerMask;
|
||||||
if (unlikely(texturesToUpload != 0))
|
if (unlikely(texturesToUpload != 0))
|
||||||
UploadManagedTextures(texturesToUpload);
|
UploadManagedTextures(texturesToUpload);
|
||||||
|
|
||||||
uint32_t texturesToGen = m_activeTexturesToGen;
|
const uint32_t texturesToGen = m_activeTexturesToGen & usedSamplerMask;
|
||||||
texturesToGen &= m_psShaderMasks.samplerMask | m_vsShaderMasks.samplerMask;
|
|
||||||
|
|
||||||
if (unlikely(texturesToGen != 0))
|
if (unlikely(texturesToGen != 0))
|
||||||
GenerateTextureMips(texturesToGen);
|
GenerateTextureMips(texturesToGen);
|
||||||
|
|
||||||
@ -5938,8 +5926,9 @@ namespace dxvk {
|
|||||||
if (m_flags.test(D3D9DeviceFlag::DirtyViewportScissor))
|
if (m_flags.test(D3D9DeviceFlag::DirtyViewportScissor))
|
||||||
BindViewportAndScissor();
|
BindViewportAndScissor();
|
||||||
|
|
||||||
if (m_dirtySamplerStates)
|
const uint32_t activeDirtySamplers = m_dirtySamplerStates & usedSamplerMask;
|
||||||
UndirtySamplers();
|
if (activeDirtySamplers)
|
||||||
|
UndirtySamplers(activeDirtySamplers);
|
||||||
|
|
||||||
if (m_dirtyTextures)
|
if (m_dirtyTextures)
|
||||||
UndirtyTextures();
|
UndirtyTextures();
|
||||||
@ -6030,6 +6019,10 @@ namespace dxvk {
|
|||||||
UpdateFixedFunctionPS();
|
UpdateFixedFunctionPS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint32_t depthTextureMask = m_depthTextures & usedSamplerMask;
|
||||||
|
if (depthTextureMask != m_lastSamplerDepthMode)
|
||||||
|
UpdateSamplerDepthModeSpecConstant(depthTextureMask);
|
||||||
|
|
||||||
if (m_flags.test(D3D9DeviceFlag::DirtySharedPixelShaderData)) {
|
if (m_flags.test(D3D9DeviceFlag::DirtySharedPixelShaderData)) {
|
||||||
m_flags.clr(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(
|
void D3D9DeviceEx::ApplyPrimitiveType(
|
||||||
DxvkContext* pContext,
|
DxvkContext* pContext,
|
||||||
D3DPRIMITIVETYPE PrimType) {
|
D3DPRIMITIVETYPE PrimType) {
|
||||||
@ -7036,24 +7038,21 @@ namespace dxvk {
|
|||||||
for (uint32_t i = 0; i < caps::MaxStreams; i++)
|
for (uint32_t i = 0; i < caps::MaxStreams; i++)
|
||||||
m_state.streamFreq[i] = 1;
|
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);
|
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([
|
EmitCs([
|
||||||
cColorSlot = colorSlot,
|
cSize = m_state.textures.size()
|
||||||
cDepthSlot = depthSlot
|
|
||||||
](DxvkContext* ctx) {
|
](DxvkContext* ctx) {
|
||||||
ctx->bindResourceView(cColorSlot, nullptr, nullptr);
|
for (uint32_t i = 0; i < cSize; i++) {
|
||||||
ctx->bindResourceView(cDepthSlot, nullptr, nullptr);
|
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_dirtyTextures = 0;
|
||||||
|
m_depthTextures = 0;
|
||||||
|
|
||||||
auto& ss = m_state.samplerStates;
|
auto& ss = m_state.samplerStates;
|
||||||
for (uint32_t i = 0; i < ss.size(); i++) {
|
for (uint32_t i = 0; i < ss.size(); i++) {
|
||||||
@ -7088,6 +7087,7 @@ namespace dxvk {
|
|||||||
UpdateSamplerSpecConsant(0u);
|
UpdateSamplerSpecConsant(0u);
|
||||||
UpdateBoolSpecConstantVertex(0u);
|
UpdateBoolSpecConstantVertex(0u);
|
||||||
UpdateBoolSpecConstantPixel(0u);
|
UpdateBoolSpecConstantPixel(0u);
|
||||||
|
UpdateSamplerDepthModeSpecConstant(0u);
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
@ -82,11 +82,6 @@ namespace dxvk {
|
|||||||
uint32_t instanceCount;
|
uint32_t instanceCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct D3D9SamplerPair {
|
|
||||||
Rc<DxvkSampler> color;
|
|
||||||
Rc<DxvkSampler> depth;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct D3D9BufferSlice {
|
struct D3D9BufferSlice {
|
||||||
DxvkBufferSlice slice = {};
|
DxvkBufferSlice slice = {};
|
||||||
void* mapPtr = nullptr;
|
void* mapPtr = nullptr;
|
||||||
@ -840,7 +835,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
void BindTexture(DWORD SamplerSampler);
|
void BindTexture(DWORD SamplerSampler);
|
||||||
|
|
||||||
void UndirtySamplers();
|
void UndirtySamplers(uint32_t mask);
|
||||||
|
|
||||||
void UndirtyTextures();
|
void UndirtyTextures();
|
||||||
|
|
||||||
@ -926,6 +921,9 @@ namespace dxvk {
|
|||||||
D3D9DeviceFlags m_flags;
|
D3D9DeviceFlags m_flags;
|
||||||
uint32_t m_dirtySamplerStates = 0;
|
uint32_t m_dirtySamplerStates = 0;
|
||||||
uint32_t m_dirtyTextures = 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;
|
D3D9Adapter* m_adapter;
|
||||||
Rc<DxvkDevice> m_dxvkDevice;
|
Rc<DxvkDevice> m_dxvkDevice;
|
||||||
@ -1024,7 +1022,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
std::unordered_map<
|
std::unordered_map<
|
||||||
D3D9SamplerKey,
|
D3D9SamplerKey,
|
||||||
D3D9SamplerPair,
|
Rc<DxvkSampler>,
|
||||||
D3D9SamplerKeyHash,
|
D3D9SamplerKeyHash,
|
||||||
D3D9SamplerKeyEq> m_samplers;
|
D3D9SamplerKeyEq> m_samplers;
|
||||||
|
|
||||||
@ -1063,6 +1061,8 @@ namespace dxvk {
|
|||||||
uint32_t m_activeHazardsDS = 0;
|
uint32_t m_activeHazardsDS = 0;
|
||||||
uint32_t m_lastHazardsDS = 0;
|
uint32_t m_lastHazardsDS = 0;
|
||||||
|
|
||||||
|
uint32_t m_lastSamplerDepthMode = 0;
|
||||||
|
|
||||||
D3D9ShaderMasks m_vsShaderMasks = D3D9ShaderMasks();
|
D3D9ShaderMasks m_vsShaderMasks = D3D9ShaderMasks();
|
||||||
D3D9ShaderMasks m_psShaderMasks = FixedFunctionMask;
|
D3D9ShaderMasks m_psShaderMasks = FixedFunctionMask;
|
||||||
|
|
||||||
@ -1241,6 +1241,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
void UpdateFetch4SpecConstant(uint32_t value);
|
void UpdateFetch4SpecConstant(uint32_t value);
|
||||||
|
|
||||||
|
void UpdateSamplerDepthModeSpecConstant(uint32_t value);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2092,7 +2092,7 @@ namespace dxvk {
|
|||||||
m_module.setDebugName(sampler.varId, name.c_str());
|
m_module.setDebugName(sampler.varId, name.c_str());
|
||||||
|
|
||||||
const uint32_t bindingId = computeResourceSlotId(DxsoProgramType::PixelShader,
|
const uint32_t bindingId = computeResourceSlotId(DxsoProgramType::PixelShader,
|
||||||
DxsoBindingType::ColorImage, i);
|
DxsoBindingType::Image, i);
|
||||||
|
|
||||||
sampler.bound = m_module.specConstBool(true);
|
sampler.bound = m_module.specConstBool(true);
|
||||||
m_module.decorateSpecId(sampler.bound, bindingId);
|
m_module.decorateSpecId(sampler.bound, bindingId);
|
||||||
|
@ -9,6 +9,7 @@ namespace dxvk {
|
|||||||
std::hash<D3DTEXTUREADDRESS> tahash;
|
std::hash<D3DTEXTUREADDRESS> tahash;
|
||||||
std::hash<D3DTEXTUREFILTERTYPE> tfhash;
|
std::hash<D3DTEXTUREFILTERTYPE> tfhash;
|
||||||
std::hash<float> fhash;
|
std::hash<float> fhash;
|
||||||
|
std::hash<bool> bhash;
|
||||||
|
|
||||||
state.add(tahash(key.AddressU));
|
state.add(tahash(key.AddressU));
|
||||||
state.add(tahash(key.AddressV));
|
state.add(tahash(key.AddressV));
|
||||||
@ -20,6 +21,7 @@ namespace dxvk {
|
|||||||
state.add(fhash (key.MipmapLodBias));
|
state.add(fhash (key.MipmapLodBias));
|
||||||
state.add(dhash (key.MaxMipLevel));
|
state.add(dhash (key.MaxMipLevel));
|
||||||
state.add(dhash (key.BorderColor));
|
state.add(dhash (key.BorderColor));
|
||||||
|
state.add(bhash (key.Depth));
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@ -35,7 +37,8 @@ namespace dxvk {
|
|||||||
&& a.MaxAnisotropy == b.MaxAnisotropy
|
&& a.MaxAnisotropy == b.MaxAnisotropy
|
||||||
&& a.MipmapLodBias == b.MipmapLodBias
|
&& a.MipmapLodBias == b.MipmapLodBias
|
||||||
&& a.MaxMipLevel == b.MaxMipLevel
|
&& a.MaxMipLevel == b.MaxMipLevel
|
||||||
&& a.BorderColor == b.BorderColor;
|
&& a.BorderColor == b.BorderColor
|
||||||
|
&& a.Depth == b.Depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -21,6 +21,7 @@ namespace dxvk {
|
|||||||
float MipmapLodBias;
|
float MipmapLodBias;
|
||||||
DWORD MaxMipLevel;
|
DWORD MaxMipLevel;
|
||||||
D3DCOLOR BorderColor;
|
D3DCOLOR BorderColor;
|
||||||
|
bool Depth;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct D3D9SamplerKeyHash {
|
struct D3D9SamplerKeyHash {
|
||||||
|
@ -16,7 +16,9 @@ namespace dxvk {
|
|||||||
|
|
||||||
VertexShaderBools = 7,
|
VertexShaderBools = 7,
|
||||||
PixelShaderBools = 8,
|
PixelShaderBools = 8,
|
||||||
Fetch4 = 9
|
Fetch4 = 9,
|
||||||
|
|
||||||
|
SamplerDepthMode = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -362,6 +362,10 @@ namespace dxvk {
|
|||||||
? D3D9SpecConstantId::VertexShaderBools
|
? D3D9SpecConstantId::VertexShaderBools
|
||||||
: D3D9SpecConstantId::PixelShaderBools));
|
: D3D9SpecConstantId::PixelShaderBools));
|
||||||
m_module.setDebugName(m_boolSpecConstant, "boolConstants");
|
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) {
|
DxsoTextureType type) {
|
||||||
m_usedSamplers |= (1u << idx);
|
m_usedSamplers |= (1u << idx);
|
||||||
|
|
||||||
auto DclSampler = [this](
|
VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
|
||||||
|
|
||||||
|
auto DclSampler = [this, &viewType](
|
||||||
uint32_t idx,
|
uint32_t idx,
|
||||||
|
uint32_t bindingId,
|
||||||
DxsoSamplerType type,
|
DxsoSamplerType type,
|
||||||
bool depth,
|
bool depth,
|
||||||
bool implicit) {
|
bool implicit) {
|
||||||
@ -694,7 +701,6 @@ namespace dxvk {
|
|||||||
: m_samplers[idx].depth[type];
|
: m_samplers[idx].depth[type];
|
||||||
|
|
||||||
spv::Dim dimensionality;
|
spv::Dim dimensionality;
|
||||||
VkImageViewType viewType;
|
|
||||||
|
|
||||||
const char* suffix = "_2d";
|
const char* suffix = "_2d";
|
||||||
|
|
||||||
@ -736,31 +742,25 @@ namespace dxvk {
|
|||||||
std::string name = str::format("s", idx, suffix, depth ? "_shadow" : "");
|
std::string name = str::format("s", idx, suffix, depth ? "_shadow" : "");
|
||||||
m_module.setDebugName(sampler.varId, name.c_str());
|
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.decorateDescriptorSet(sampler.varId, 0);
|
||||||
m_module.decorateBinding (sampler.varId, bindingId);
|
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 =
|
DxsoSamplerType samplerType =
|
||||||
SamplerTypeFromTextureType(type);
|
SamplerTypeFromTextureType(type);
|
||||||
|
|
||||||
DclSampler(idx, samplerType, false, false);
|
DclSampler(idx, binding, samplerType, false, implicit);
|
||||||
|
|
||||||
if (samplerType != SamplerTypeTexture3D) {
|
if (samplerType != SamplerTypeTexture3D) {
|
||||||
// We could also be depth compared!
|
// We could also be depth compared!
|
||||||
DclSampler(idx, samplerType, true, false);
|
DclSampler(idx, binding, samplerType, true, implicit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -769,33 +769,27 @@ namespace dxvk {
|
|||||||
for (uint32_t i = 0; i < SamplerTypeCount; i++) {
|
for (uint32_t i = 0; i < SamplerTypeCount; i++) {
|
||||||
auto samplerType = static_cast<DxsoSamplerType>(i);
|
auto samplerType = static_cast<DxsoSamplerType>(i);
|
||||||
|
|
||||||
DclSampler(idx, samplerType, false, true);
|
DclSampler(idx, binding, samplerType, false, implicit);
|
||||||
|
|
||||||
if (samplerType != SamplerTypeTexture3D)
|
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];
|
DxsoSampler& sampler = m_samplers[idx];
|
||||||
|
sampler.boundConst = m_module.specConstBool(true);
|
||||||
sampler.colorSpecConst = m_module.specConstBool(true);
|
|
||||||
sampler.depthSpecConst = m_module.specConstBool(true);
|
|
||||||
sampler.type = type;
|
sampler.type = type;
|
||||||
m_module.decorateSpecId(sampler.colorSpecConst, colorBinding);
|
m_module.decorateSpecId(sampler.boundConst, binding);
|
||||||
m_module.decorateSpecId(sampler.depthSpecConst, depthBinding);
|
m_module.setDebugName(sampler.boundConst,
|
||||||
m_module.setDebugName(sampler.colorSpecConst,
|
str::format("s", idx, "_bound").c_str());
|
||||||
str::format("s", idx, "_useColor").c_str());
|
|
||||||
m_module.setDebugName(sampler.depthSpecConst,
|
// Store descriptor info for the shader interface
|
||||||
str::format("s", idx, "_useShadow").c_str());
|
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 depthLabel = m_module.allocateId();
|
||||||
uint32_t endLabel = 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.opSelectionMerge(endLabel, spv::SelectionControlMaskNone);
|
||||||
m_module.opBranchConditional(sampler.depthSpecConst, depthLabel, colorLabel);
|
m_module.opBranchConditional(isDepth, depthLabel, colorLabel);
|
||||||
|
|
||||||
m_module.opLabel(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.opBranch(endLabel);
|
||||||
|
|
||||||
m_module.opLabel(depthLabel);
|
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.opBranch(endLabel);
|
||||||
|
|
||||||
m_module.opLabel(endLabel);
|
m_module.opLabel(endLabel);
|
||||||
}
|
}
|
||||||
else
|
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) {
|
if (m_programInfo.majorVersion() >= 2 && !m_moduleInfo.options.forceSamplerTypeSpecConstants) {
|
||||||
|
@ -128,8 +128,7 @@ namespace dxvk {
|
|||||||
DxsoSamplerInfo color[SamplerTypeCount];
|
DxsoSamplerInfo color[SamplerTypeCount];
|
||||||
DxsoSamplerInfo depth[SamplerTypeCount];
|
DxsoSamplerInfo depth[SamplerTypeCount];
|
||||||
|
|
||||||
uint32_t colorSpecConst;
|
uint32_t boundConst;
|
||||||
uint32_t depthSpecConst;
|
|
||||||
|
|
||||||
DxsoTextureType type;
|
DxsoTextureType type;
|
||||||
};
|
};
|
||||||
@ -270,6 +269,7 @@ namespace dxvk {
|
|||||||
SpirvModule m_module;
|
SpirvModule m_module;
|
||||||
|
|
||||||
uint32_t m_boolSpecConstant;
|
uint32_t m_boolSpecConstant;
|
||||||
|
uint32_t m_depthSpecConstant;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
// Resource slot description for the shader. This will
|
// Resource slot description for the shader. This will
|
||||||
|
@ -4,39 +4,6 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
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;
|
dxvk::mutex g_linkerSlotMutex;
|
||||||
uint32_t g_linkerSlotCount = 0;
|
uint32_t g_linkerSlotCount = 0;
|
||||||
std::array<DxsoSemantic, 32> g_linkerSlots;
|
std::array<DxsoSemantic, 32> g_linkerSlots;
|
||||||
|
@ -9,8 +9,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
enum class DxsoBindingType : uint32_t {
|
enum class DxsoBindingType : uint32_t {
|
||||||
ConstantBuffer,
|
ConstantBuffer,
|
||||||
ColorImage,
|
Image,
|
||||||
DepthImage // <-- We use whatever one is bound to determine whether an image should be 'shadow' sampled or not.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DxsoConstantBuffers : uint32_t {
|
enum DxsoConstantBuffers : uint32_t {
|
||||||
@ -26,12 +25,22 @@ namespace dxvk {
|
|||||||
PSCount
|
PSCount
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t computeResourceSlotId(
|
constexpr uint32_t computeResourceSlotId(
|
||||||
DxsoProgramType shaderStage,
|
DxsoProgramType shaderStage,
|
||||||
DxsoBindingType bindingType,
|
DxsoBindingType bindingType,
|
||||||
uint32_t bindingIndex);
|
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);
|
uint32_t RegisterLinkerSlot(DxsoSemantic semantic);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user