mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
graphics: compact shader keys and hash packed pipeline state
This commit is contained in:
@@ -165,6 +165,32 @@ bool ValidateShaderSpirv(const char* label, uint64_t shader_hash,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
std::size_t PipelineCache::GraphicsPipelineKeyHash::operator()(const GraphicsPipelineKey& key) const {
|
||||||
|
std::size_t hash = 0;
|
||||||
|
PipelineKeyHash::Mix(hash, key.rendering.color_count);
|
||||||
|
for (uint32_t i = 0; i < key.rendering.color_count; i++) {
|
||||||
|
PipelineKeyHash::Mix(hash, static_cast<uint32_t>(key.rendering.color_formats[i]));
|
||||||
|
}
|
||||||
|
PipelineKeyHash::Mix(hash, static_cast<uint32_t>(key.rendering.depth_format));
|
||||||
|
PipelineKeyHash::Mix(hash, static_cast<uint32_t>(key.rendering.stencil_format));
|
||||||
|
for (const auto id: key.vertex_shader_ids) {
|
||||||
|
PipelineKeyHash::Mix(hash, id);
|
||||||
|
}
|
||||||
|
PipelineKeyHash::Mix(hash, key.ps_shader_id);
|
||||||
|
PipelineKeyHash::Mix(hash, key.vertex_input.binding_count);
|
||||||
|
for (uint32_t i = 0; i < key.vertex_input.binding_count; i++) {
|
||||||
|
PipelineKeyHash::Mix(hash, key.vertex_input.bindings[i].stride);
|
||||||
|
PipelineKeyHash::Mix(hash, key.vertex_input.bindings[i].instance);
|
||||||
|
}
|
||||||
|
PipelineKeyHash::Mix(hash, key.vertex_input.attribute_count);
|
||||||
|
for (uint32_t i = 0; i < key.vertex_input.attribute_count; i++) {
|
||||||
|
PipelineKeyHash::Mix(hash, key.vertex_input.attributes[i].offset);
|
||||||
|
PipelineKeyHash::Mix(hash, key.vertex_input.attributes[i].binding);
|
||||||
|
}
|
||||||
|
PipelineKeyHash::Mix(hash, XXH3_64bits(&key.static_params, sizeof(key.static_params)));
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
struct PipelineCache::ProgramCache {
|
struct PipelineCache::ProgramCache {
|
||||||
struct ProgramKey {
|
struct ProgramKey {
|
||||||
ShaderType stage = ShaderType::Unknown;
|
ShaderType stage = ShaderType::Unknown;
|
||||||
@@ -206,12 +232,12 @@ struct PipelineCache::ProgramCache {
|
|||||||
PipelineKeyHash::Mix(hash, key.code_size);
|
PipelineKeyHash::Mix(hash, key.code_size);
|
||||||
PipelineKeyHash::Mix(hash, key.static_state.size());
|
PipelineKeyHash::Mix(hash, key.static_state.size());
|
||||||
// Bucket same-shape static variants by source. ProgramKey equality performs the one
|
// Bucket same-shape static variants by source. ProgramKey equality performs the one
|
||||||
// exact state comparison needed on a stable hit without hashing up to 429 words first.
|
// exact state comparison needed on a stable hit without hashing the full state first.
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr std::size_t MaxStaticKeyWords = 13 + ShaderVertexInputInfo::RES_MAX * 13;
|
static constexpr std::size_t MaxStaticKeyWords = 32 + ShaderVertexInputInfo::RES_MAX * 6;
|
||||||
|
|
||||||
Permutation CompilePermutation(const char* stage_name,
|
Permutation CompilePermutation(const char* stage_name,
|
||||||
const ShaderRecompiler::CompileOptions& options,
|
const ShaderRecompiler::CompileOptions& options,
|
||||||
|
|||||||
@@ -166,45 +166,10 @@ private:
|
|||||||
hash ^= value + static_cast<std::size_t>(0x9e3779b97f4a7c15ull) + (hash << 6u) +
|
hash ^= value + static_cast<std::size_t>(0x9e3779b97f4a7c15ull) + (hash << 6u) +
|
||||||
(hash >> 2u);
|
(hash >> 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MixStaticParams(std::size_t& hash, const PipelineStaticParameters& params) {
|
|
||||||
const auto* bytes = reinterpret_cast<const uint8_t*>(¶ms);
|
|
||||||
for (std::size_t i = 0; i < sizeof(params); i++) {
|
|
||||||
Mix(hash, bytes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void MixRendering(std::size_t& hash, const PipelineRenderingState& rendering) {
|
|
||||||
Mix(hash, rendering.color_count);
|
|
||||||
for (uint32_t i = 0; i < rendering.color_count; i++) {
|
|
||||||
Mix(hash, static_cast<uint32_t>(rendering.color_formats[i]));
|
|
||||||
}
|
|
||||||
Mix(hash, static_cast<uint32_t>(rendering.depth_format));
|
|
||||||
Mix(hash, static_cast<uint32_t>(rendering.stencil_format));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GraphicsPipelineKeyHash {
|
struct GraphicsPipelineKeyHash {
|
||||||
std::size_t operator()(const GraphicsPipelineKey& key) const {
|
std::size_t operator()(const GraphicsPipelineKey& key) const;
|
||||||
std::size_t hash = 0;
|
|
||||||
PipelineKeyHash::MixRendering(hash, key.rendering);
|
|
||||||
for (const auto id: key.vertex_shader_ids) {
|
|
||||||
PipelineKeyHash::Mix(hash, id);
|
|
||||||
}
|
|
||||||
PipelineKeyHash::Mix(hash, key.ps_shader_id);
|
|
||||||
PipelineKeyHash::Mix(hash, key.vertex_input.binding_count);
|
|
||||||
for (uint32_t i = 0; i < key.vertex_input.binding_count; i++) {
|
|
||||||
PipelineKeyHash::Mix(hash, key.vertex_input.bindings[i].stride);
|
|
||||||
PipelineKeyHash::Mix(hash, key.vertex_input.bindings[i].instance);
|
|
||||||
}
|
|
||||||
PipelineKeyHash::Mix(hash, key.vertex_input.attribute_count);
|
|
||||||
for (uint32_t i = 0; i < key.vertex_input.attribute_count; i++) {
|
|
||||||
PipelineKeyHash::Mix(hash, key.vertex_input.attributes[i].offset);
|
|
||||||
PipelineKeyHash::Mix(hash, key.vertex_input.attributes[i].binding);
|
|
||||||
}
|
|
||||||
PipelineKeyHash::MixStaticParams(hash, key.static_params);
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
GraphicContext& m_graphics;
|
GraphicContext& m_graphics;
|
||||||
|
|||||||
@@ -668,15 +668,8 @@ void BuildStageStaticKey(const ShaderVertexInputInfo& info, std::vector<uint32_t
|
|||||||
key.push_back(destination.registers_num);
|
key.push_back(destination.registers_num);
|
||||||
key.push_back(destination.fetch_index);
|
key.push_back(destination.fetch_index);
|
||||||
key.push_back(static_cast<uint32_t>(destination.attr_id));
|
key.push_back(static_cast<uint32_t>(destination.attr_id));
|
||||||
key.push_back(resource.Stride());
|
key.push_back(resource.fields[1] & 0xbfff0000u); // Stride and swizzle enable.
|
||||||
key.push_back(static_cast<uint32_t>(resource.SwizzleEnabled()));
|
key.push_back(resource.fields[3] & 0x3087ffffu); // Channels, format, OOB, and add TID.
|
||||||
key.push_back(resource.DstSelX());
|
|
||||||
key.push_back(resource.DstSelY());
|
|
||||||
key.push_back(resource.DstSelZ());
|
|
||||||
key.push_back(resource.DstSelW());
|
|
||||||
key.push_back(resource.RawFormat());
|
|
||||||
key.push_back(resource.OutOfBounds());
|
|
||||||
key.push_back(static_cast<uint32_t>(resource.AddTid()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10633,6 +10633,24 @@ void TestNewShaderRecompilerClipDisabledPosition() {
|
|||||||
layout_b.resources[0].UpdateAddress48(4);
|
layout_b.resources[0].UpdateAddress48(4);
|
||||||
Check(MakeStageStaticKey(layout_a) == MakeStageStaticKey(layout_b),
|
Check(MakeStageStaticKey(layout_a) == MakeStageStaticKey(layout_b),
|
||||||
"pipeline-only vertex layout fragmented the shader module cache key");
|
"pipeline-only vertex layout fragmented the shader module cache key");
|
||||||
|
|
||||||
|
const auto descriptor_state = [](const ShaderBufferResource &resource) {
|
||||||
|
return std::array<uint32_t, 9>{
|
||||||
|
resource.Stride(), resource.SwizzleEnabled(), resource.DstSelX(),
|
||||||
|
resource.DstSelY(), resource.DstSelZ(), resource.DstSelW(),
|
||||||
|
resource.RawFormat(), resource.OutOfBounds(), resource.AddTid()};
|
||||||
|
};
|
||||||
|
const auto key = MakeStageStaticKey(layout_a);
|
||||||
|
const auto state = descriptor_state(layout_a.resources[0]);
|
||||||
|
for (uint32_t word = 0; word < 4; word++) {
|
||||||
|
for (uint32_t bit = 0; bit < 32; bit++) {
|
||||||
|
auto changed = layout_a;
|
||||||
|
changed.resources[0].fields[word] ^= 1u << bit;
|
||||||
|
Check((MakeStageStaticKey(changed) == key) ==
|
||||||
|
(descriptor_state(changed.resources[0]) == state),
|
||||||
|
"vertex key lost a descriptor field or included runtime-only bits");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestNewShaderRecompilerAuxPositionExports() {
|
void TestNewShaderRecompilerAuxPositionExports() {
|
||||||
|
|||||||
Reference in New Issue
Block a user