mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 13:26:52 +01: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
|
||||
|
||||
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 ProgramKey {
|
||||
ShaderType stage = ShaderType::Unknown;
|
||||
@@ -206,12 +232,12 @@ struct PipelineCache::ProgramCache {
|
||||
PipelineKeyHash::Mix(hash, key.code_size);
|
||||
PipelineKeyHash::Mix(hash, key.static_state.size());
|
||||
// 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;
|
||||
}
|
||||
};
|
||||
|
||||
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,
|
||||
const ShaderRecompiler::CompileOptions& options,
|
||||
|
||||
@@ -166,45 +166,10 @@ private:
|
||||
hash ^= value + static_cast<std::size_t>(0x9e3779b97f4a7c15ull) + (hash << 6u) +
|
||||
(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 {
|
||||
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;
|
||||
}
|
||||
std::size_t operator()(const GraphicsPipelineKey& key) const;
|
||||
};
|
||||
|
||||
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.fetch_index);
|
||||
key.push_back(static_cast<uint32_t>(destination.attr_id));
|
||||
key.push_back(resource.Stride());
|
||||
key.push_back(static_cast<uint32_t>(resource.SwizzleEnabled()));
|
||||
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()));
|
||||
key.push_back(resource.fields[1] & 0xbfff0000u); // Stride and swizzle enable.
|
||||
key.push_back(resource.fields[3] & 0x3087ffffu); // Channels, format, OOB, and add TID.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10633,6 +10633,24 @@ void TestNewShaderRecompilerClipDisabledPosition() {
|
||||
layout_b.resources[0].UpdateAddress48(4);
|
||||
Check(MakeStageStaticKey(layout_a) == MakeStageStaticKey(layout_b),
|
||||
"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() {
|
||||
|
||||
Reference in New Issue
Block a user