mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-19 05:52:11 +01:00
[d3d11] Use existing MD5 hash to look up shader objects
Skips the expensive SHA-1 pass.
This commit is contained in:
parent
ae9024492b
commit
800f71c4f5
@ -791,13 +791,8 @@ namespace dxvk {
|
||||
moduleInfo.tess = nullptr;
|
||||
moduleInfo.xfb = nullptr;
|
||||
|
||||
Sha1Hash hash = Sha1Hash::compute(
|
||||
pShaderBytecode, BytecodeLength);
|
||||
|
||||
HRESULT hr = CreateShaderModule(&module,
|
||||
DxvkShaderKey(VK_SHADER_STAGE_VERTEX_BIT, hash),
|
||||
pShaderBytecode, BytecodeLength, pClassLinkage,
|
||||
&moduleInfo);
|
||||
HRESULT hr = CreateShaderModule(&module, VK_SHADER_STAGE_VERTEX_BIT,
|
||||
pShaderBytecode, BytecodeLength, pClassLinkage, &moduleInfo);
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
@ -823,13 +818,8 @@ namespace dxvk {
|
||||
moduleInfo.tess = nullptr;
|
||||
moduleInfo.xfb = nullptr;
|
||||
|
||||
Sha1Hash hash = Sha1Hash::compute(
|
||||
pShaderBytecode, BytecodeLength);
|
||||
|
||||
HRESULT hr = CreateShaderModule(&module,
|
||||
DxvkShaderKey(VK_SHADER_STAGE_GEOMETRY_BIT, hash),
|
||||
pShaderBytecode, BytecodeLength, pClassLinkage,
|
||||
&moduleInfo);
|
||||
HRESULT hr = CreateShaderModule(&module, VK_SHADER_STAGE_GEOMETRY_BIT,
|
||||
pShaderBytecode, BytecodeLength, pClassLinkage, &moduleInfo);
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
@ -898,36 +888,14 @@ namespace dxvk {
|
||||
if (RasterizedStream != D3D11_SO_NO_RASTERIZED_STREAM)
|
||||
Logger::err("D3D11: CreateGeometryShaderWithStreamOutput: Rasterized stream not supported");
|
||||
|
||||
// Compute hash from both the xfb info and the source
|
||||
// code, because both influence the generated code
|
||||
DxbcXfbInfo hashXfb = xfb;
|
||||
|
||||
std::vector<Sha1Data> chunks = {{
|
||||
{ pShaderBytecode, BytecodeLength },
|
||||
{ &hashXfb, sizeof(hashXfb) },
|
||||
}};
|
||||
|
||||
for (uint32_t i = 0; i < hashXfb.entryCount; i++) {
|
||||
const char* semantic = hashXfb.entries[i].semanticName;
|
||||
|
||||
if (semantic) {
|
||||
chunks.push_back({ semantic, std::strlen(semantic) });
|
||||
hashXfb.entries[i].semanticName = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Sha1Hash hash = Sha1Hash::compute(chunks.size(), chunks.data());
|
||||
|
||||
// Create the actual shader module
|
||||
DxbcModuleInfo moduleInfo;
|
||||
moduleInfo.options = m_dxbcOptions;
|
||||
moduleInfo.tess = nullptr;
|
||||
moduleInfo.xfb = &xfb;
|
||||
|
||||
HRESULT hr = CreateShaderModule(&module,
|
||||
DxvkShaderKey(VK_SHADER_STAGE_GEOMETRY_BIT, hash),
|
||||
pShaderBytecode, BytecodeLength, pClassLinkage,
|
||||
&moduleInfo);
|
||||
HRESULT hr = CreateShaderModule(&module, VK_SHADER_STAGE_GEOMETRY_BIT,
|
||||
pShaderBytecode, BytecodeLength, pClassLinkage, &moduleInfo);
|
||||
|
||||
if (FAILED(hr))
|
||||
return E_INVALIDARG;
|
||||
@ -953,14 +921,8 @@ namespace dxvk {
|
||||
moduleInfo.tess = nullptr;
|
||||
moduleInfo.xfb = nullptr;
|
||||
|
||||
Sha1Hash hash = Sha1Hash::compute(
|
||||
pShaderBytecode, BytecodeLength);
|
||||
|
||||
|
||||
HRESULT hr = CreateShaderModule(&module,
|
||||
DxvkShaderKey(VK_SHADER_STAGE_FRAGMENT_BIT, hash),
|
||||
pShaderBytecode, BytecodeLength, pClassLinkage,
|
||||
&moduleInfo);
|
||||
HRESULT hr = CreateShaderModule(&module, VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
pShaderBytecode, BytecodeLength, pClassLinkage, &moduleInfo);
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
@ -992,11 +954,7 @@ namespace dxvk {
|
||||
if (tessInfo.maxTessFactor >= 8.0f)
|
||||
moduleInfo.tess = &tessInfo;
|
||||
|
||||
Sha1Hash hash = Sha1Hash::compute(
|
||||
pShaderBytecode, BytecodeLength);
|
||||
|
||||
HRESULT hr = CreateShaderModule(&module,
|
||||
DxvkShaderKey(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, hash),
|
||||
HRESULT hr = CreateShaderModule(&module, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
|
||||
pShaderBytecode, BytecodeLength, pClassLinkage, &moduleInfo);
|
||||
|
||||
if (FAILED(hr))
|
||||
@ -1023,11 +981,7 @@ namespace dxvk {
|
||||
moduleInfo.tess = nullptr;
|
||||
moduleInfo.xfb = nullptr;
|
||||
|
||||
Sha1Hash hash = Sha1Hash::compute(
|
||||
pShaderBytecode, BytecodeLength);
|
||||
|
||||
HRESULT hr = CreateShaderModule(&module,
|
||||
DxvkShaderKey(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, hash),
|
||||
HRESULT hr = CreateShaderModule(&module, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
|
||||
pShaderBytecode, BytecodeLength, pClassLinkage, &moduleInfo);
|
||||
|
||||
if (FAILED(hr))
|
||||
@ -1054,13 +1008,8 @@ namespace dxvk {
|
||||
moduleInfo.tess = nullptr;
|
||||
moduleInfo.xfb = nullptr;
|
||||
|
||||
Sha1Hash hash = Sha1Hash::compute(
|
||||
pShaderBytecode, BytecodeLength);
|
||||
|
||||
HRESULT hr = CreateShaderModule(&module,
|
||||
DxvkShaderKey(VK_SHADER_STAGE_COMPUTE_BIT, hash),
|
||||
pShaderBytecode, BytecodeLength, pClassLinkage,
|
||||
&moduleInfo);
|
||||
HRESULT hr = CreateShaderModule(&module, VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
pShaderBytecode, BytecodeLength, pClassLinkage, &moduleInfo);
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
@ -2010,9 +1959,65 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
DxvkShaderKey D3D11Device::ComputeShaderKey(
|
||||
VkShaderStageFlagBits ShaderStage,
|
||||
const void* pShaderBytecode,
|
||||
size_t BytecodeLength,
|
||||
const DxbcModuleInfo* pModuleInfo) {
|
||||
constexpr static uint32_t Md5Size = 16;
|
||||
|
||||
// DXBC shaders store an MD5 hash within their header, so just
|
||||
// use that instead of running SHA-1 over the entire binary.
|
||||
Sha1Digest digest = { };
|
||||
|
||||
if (BytecodeLength >= Md5Size + 4u)
|
||||
std::memcpy(&digest[0], reinterpret_cast<const char*>(pShaderBytecode) + 4, Md5Size);
|
||||
|
||||
uint32_t metadata = uint32_t(ShaderStage) | (uint32_t(BytecodeLength) << 8u);
|
||||
std::memcpy(&digest[Md5Size], &metadata, sizeof(metadata));
|
||||
|
||||
// If transform feedback is enabled, hash that state too since it
|
||||
// affects the generated shader code, and factor it into the key.
|
||||
if (pModuleInfo && pModuleInfo->xfb) {
|
||||
std::vector<unsigned char> serialized;
|
||||
|
||||
serialized.push_back(pModuleInfo->xfb->entryCount);
|
||||
|
||||
for (uint32_t i = 0; i < pModuleInfo->xfb->entryCount; i++) {
|
||||
if (pModuleInfo->xfb->entries[i].semanticName) {
|
||||
for (uint32_t j = 0; pModuleInfo->xfb->entries[i].semanticName[j]; j++)
|
||||
serialized.push_back(pModuleInfo->xfb->entries[i].semanticName[j]);
|
||||
}
|
||||
|
||||
serialized.push_back(pModuleInfo->xfb->entries[i].semanticIndex);
|
||||
serialized.push_back(pModuleInfo->xfb->entries[i].componentIndex);
|
||||
serialized.push_back(pModuleInfo->xfb->entries[i].componentCount);
|
||||
serialized.push_back(pModuleInfo->xfb->entries[i].streamId);
|
||||
serialized.push_back(pModuleInfo->xfb->entries[i].bufferId);
|
||||
serialized.push_back(pModuleInfo->xfb->entries[i].offset);
|
||||
serialized.push_back(pModuleInfo->xfb->entries[i].offset >> 8u);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < 4u; i++) {
|
||||
serialized.push_back(pModuleInfo->xfb->strides[i]);
|
||||
serialized.push_back(pModuleInfo->xfb->strides[i] >> 8u);
|
||||
}
|
||||
|
||||
serialized.push_back(pModuleInfo->xfb->rasterizedStream);
|
||||
|
||||
Sha1Digest xfbDigest = Sha1Hash::compute(serialized.data(), serialized.size()).digest();
|
||||
|
||||
for (size_t i = 0; i < xfbDigest.size(); i++)
|
||||
digest[i] ^= xfbDigest[i];
|
||||
}
|
||||
|
||||
return DxvkShaderKey(ShaderStage, Sha1Hash(digest));
|
||||
}
|
||||
|
||||
|
||||
HRESULT D3D11Device::CreateShaderModule(
|
||||
D3D11CommonShader* pShaderModule,
|
||||
DxvkShaderKey ShaderKey,
|
||||
VkShaderStageFlagBits ShaderStage,
|
||||
const void* pShaderBytecode,
|
||||
size_t BytecodeLength,
|
||||
ID3D11ClassLinkage* pClassLinkage,
|
||||
@ -2020,10 +2025,12 @@ namespace dxvk {
|
||||
if (pClassLinkage != nullptr)
|
||||
Logger::warn("D3D11Device::CreateShaderModule: Class linkage not supported");
|
||||
|
||||
DxvkShaderKey shaderKey = ComputeShaderKey(ShaderStage, pShaderBytecode, BytecodeLength, pModuleInfo);
|
||||
|
||||
D3D11CommonShader commonShader;
|
||||
|
||||
HRESULT hr = m_shaderModules.GetShaderModule(this,
|
||||
&ShaderKey, pModuleInfo, pShaderBytecode, BytecodeLength,
|
||||
&shaderKey, pModuleInfo, pShaderBytecode, BytecodeLength,
|
||||
&commonShader);
|
||||
|
||||
if (FAILED(hr))
|
||||
|
@ -511,9 +511,15 @@ namespace dxvk {
|
||||
D3D_FEATURE_LEVEL m_maxFeatureLevel;
|
||||
D3D11DeviceFeatures m_deviceFeatures;
|
||||
|
||||
DxvkShaderKey ComputeShaderKey(
|
||||
VkShaderStageFlagBits ShaderStage,
|
||||
const void* pShaderBytecode,
|
||||
size_t BytecodeLength,
|
||||
const DxbcModuleInfo* pModuleInfo);
|
||||
|
||||
HRESULT CreateShaderModule(
|
||||
D3D11CommonShader* pShaderModule,
|
||||
DxvkShaderKey ShaderKey,
|
||||
VkShaderStageFlagBits ShaderStage,
|
||||
const void* pShaderBytecode,
|
||||
size_t BytecodeLength,
|
||||
ID3D11ClassLinkage* pClassLinkage,
|
||||
|
@ -30,6 +30,10 @@ namespace dxvk {
|
||||
| uint32_t(m_digest[4 * id + 3]) << 24;
|
||||
}
|
||||
|
||||
Sha1Digest digest() const {
|
||||
return m_digest;
|
||||
}
|
||||
|
||||
bool operator == (const Sha1Hash& other) const {
|
||||
return !std::memcmp(
|
||||
this->m_digest.data(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user