Split-out hash from ShaderBinary struct

This isn't necessary for pipeline creation and creates some difficulty with pipeline caching.
This commit is contained in:
Billy Laws 2022-12-03 14:25:35 +00:00
parent de10ab1219
commit bc7e1eb380
7 changed files with 19 additions and 12 deletions

View File

@ -67,7 +67,6 @@ namespace skyline::gpu::interconnect {
struct ShaderBinary { struct ShaderBinary {
span<u8> binary; span<u8> binary;
u64 hash;
u32 baseOffset; u32 baseOffset;
}; };

View File

@ -12,7 +12,7 @@
namespace skyline::gpu::interconnect { namespace skyline::gpu::interconnect {
/* Pipeline Stage */ /* Pipeline Stage */
ShaderBinary ShaderCache::Lookup(InterconnectContext &ctx, u64 programBase, u32 programOffset) { std::pair<ShaderBinary, u64> ShaderCache::Lookup(InterconnectContext &ctx, u64 programBase, u32 programOffset) {
lastProgramBase = programBase; lastProgramBase = programBase;
lastProgramOffset = programOffset; lastProgramOffset = programOffset;
auto[blockMapping, blockOffset]{ctx.channelCtx.asCtx->gmmu.LookupBlock(programBase + programOffset)}; auto[blockMapping, blockOffset]{ctx.channelCtx.asCtx->gmmu.LookupBlock(programBase + programOffset)};
@ -91,11 +91,11 @@ namespace skyline::gpu::interconnect {
}(blockMappingMirror.subspan(blockOffset)); }(blockMappingMirror.subspan(blockOffset));
binary.baseOffset = programOffset; binary.baseOffset = programOffset;
binary.hash = XXH64(binary.binary.data(), binary.binary.size_bytes(), 0);
entry->cache.insert({blockMapping.data() + blockOffset, binary}); u64 hash{XXH64(binary.binary.data(), binary.binary.size_bytes(), 0)};
entry->cache.insert({blockMapping.data() + blockOffset, {binary, hash}});
return binary; return {binary, hash};
} }
bool ShaderCache::Refresh(InterconnectContext &ctx, u64 programBase, u32 programOffset) { bool ShaderCache::Refresh(InterconnectContext &ctx, u64 programBase, u32 programOffset) {

View File

@ -7,6 +7,9 @@
#include "common.h" #include "common.h"
namespace skyline::gpu::interconnect { namespace skyline::gpu::interconnect {
/**
* @brief Caches guest shader binaries and their memory locations
*/
class ShaderCache { class ShaderCache {
private: private:
/** /**
@ -14,7 +17,7 @@ namespace skyline::gpu::interconnect {
*/ */
struct MirrorEntry { struct MirrorEntry {
span<u8> mirror; span<u8> mirror;
tsl::robin_map<u8 *, ShaderBinary> cache; tsl::robin_map<u8 *, std::pair<ShaderBinary, u64>> cache;
std::optional<nce::NCE::TrapHandle> trap; std::optional<nce::NCE::TrapHandle> trap;
static constexpr u32 SkipTrapThreshold{20}; //!< Threshold for the number of times a mirror trap needs to be hit before we fallback to always hashing static constexpr u32 SkipTrapThreshold{20}; //!< Threshold for the number of times a mirror trap needs to be hit before we fallback to always hashing
@ -34,7 +37,10 @@ namespace skyline::gpu::interconnect {
u32 lastProgramOffset{}; u32 lastProgramOffset{};
public: public:
ShaderBinary Lookup(InterconnectContext &ctx, u64 programBase, u32 programOffset); /**
* @brief Returns the shader binary located at the given address
*/
std::pair<ShaderBinary, u64> Lookup(InterconnectContext &ctx, u64 programBase, u32 programOffset);
bool Refresh(InterconnectContext &ctx, u64 programBase, u32 programOffset); bool Refresh(InterconnectContext &ctx, u64 programBase, u32 programOffset);

View File

@ -14,7 +14,7 @@ namespace skyline::gpu::interconnect::kepler_compute {
: engine{manager, dirtyHandle, engine} {} : engine{manager, dirtyHandle, engine} {}
void PipelineStageState::Flush(InterconnectContext &ctx, u32 programOffset) { void PipelineStageState::Flush(InterconnectContext &ctx, u32 programOffset) {
binary = cache.Lookup(ctx, engine->programRegion, programOffset); std::tie(binary, hash) = cache.Lookup(ctx, engine->programRegion, programOffset);
} }
bool PipelineStageState::Refresh(InterconnectContext &ctx, u32 programOffset) { bool PipelineStageState::Refresh(InterconnectContext &ctx, u32 programOffset) {
@ -32,7 +32,7 @@ namespace skyline::gpu::interconnect::kepler_compute {
Pipeline *PipelineState::Update(InterconnectContext &ctx, StateUpdateBuilder &builder, Textures &textures, ConstantBufferSet &constantBuffers, const QMD &qmd) { Pipeline *PipelineState::Update(InterconnectContext &ctx, StateUpdateBuilder &builder, Textures &textures, ConstantBufferSet &constantBuffers, const QMD &qmd) {
const auto &stage{pipelineStage.UpdateGet(ctx, qmd.programOffset)}; const auto &stage{pipelineStage.UpdateGet(ctx, qmd.programOffset)};
packedState.shaderHash = stage.binary.hash; packedState.shaderHash = stage.hash;
packedState.dimensions = {qmd.ctaThreadDimension0, qmd.ctaThreadDimension1, qmd.ctaThreadDimension2}; packedState.dimensions = {qmd.ctaThreadDimension0, qmd.ctaThreadDimension1, qmd.ctaThreadDimension2};
packedState.localMemorySize = qmd.shaderLocalMemoryLowSize + qmd.shaderLocalMemoryHighSize; packedState.localMemorySize = qmd.shaderLocalMemoryLowSize + qmd.shaderLocalMemoryHighSize;
packedState.sharedMemorySize = qmd.sharedMemorySize; packedState.sharedMemorySize = qmd.sharedMemorySize;

View File

@ -26,6 +26,7 @@ namespace skyline::gpu::interconnect::kepler_compute {
public: public:
ShaderBinary binary; ShaderBinary binary;
u64 hash{};
PipelineStageState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine); PipelineStageState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine);

View File

@ -256,11 +256,11 @@ namespace skyline::gpu::interconnect::maxwell3d {
throw exception("Shader type mismatch: {} != {}!", engine->pipeline.shader.type, static_cast<u8>(shaderType)); throw exception("Shader type mismatch: {} != {}!", engine->pipeline.shader.type, static_cast<u8>(shaderType));
if (!engine->pipeline.shader.enable && shaderType != engine::Pipeline::Shader::Type::Vertex) { if (!engine->pipeline.shader.enable && shaderType != engine::Pipeline::Shader::Type::Vertex) {
binary.hash = 0; hash = 0;
return; return;
} }
binary = cache.Lookup(ctx, engine->programRegion, engine->pipeline.programOffset); std::tie(binary, hash) = cache.Lookup(ctx, engine->programRegion, engine->pipeline.programOffset);
} }
bool PipelineStageState::Refresh(InterconnectContext &ctx) { bool PipelineStageState::Refresh(InterconnectContext &ctx) {
@ -495,7 +495,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
std::array<ShaderBinary, engine::PipelineCount> shaderBinaries; std::array<ShaderBinary, engine::PipelineCount> shaderBinaries;
for (size_t i{}; i < engine::PipelineCount; i++) { for (size_t i{}; i < engine::PipelineCount; i++) {
const auto &stage{pipelineStages[i].UpdateGet(ctx)}; const auto &stage{pipelineStages[i].UpdateGet(ctx)};
packedState.shaderHashes[i] = stage.binary.hash; packedState.shaderHashes[i] = stage.hash;
shaderBinaries[i] = stage.binary; shaderBinaries[i] = stage.binary;
} }

View File

@ -75,6 +75,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
public: public:
ShaderBinary binary; ShaderBinary binary;
u64 hash;
PipelineStageState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine, u8 shaderType); PipelineStageState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine, u8 shaderType);