diff --git a/app/src/main/cpp/skyline/gpu/interconnect/common/common.h b/app/src/main/cpp/skyline/gpu/interconnect/common/common.h index 542b374e..98b30499 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/common/common.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/common/common.h @@ -67,7 +67,6 @@ namespace skyline::gpu::interconnect { struct ShaderBinary { span binary; - u64 hash; u32 baseOffset; }; diff --git a/app/src/main/cpp/skyline/gpu/interconnect/common/shader_cache.cpp b/app/src/main/cpp/skyline/gpu/interconnect/common/shader_cache.cpp index 183ce58e..743caaf6 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/common/shader_cache.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/common/shader_cache.cpp @@ -12,7 +12,7 @@ namespace skyline::gpu::interconnect { /* Pipeline Stage */ - ShaderBinary ShaderCache::Lookup(InterconnectContext &ctx, u64 programBase, u32 programOffset) { + std::pair ShaderCache::Lookup(InterconnectContext &ctx, u64 programBase, u32 programOffset) { lastProgramBase = programBase; lastProgramOffset = programOffset; auto[blockMapping, blockOffset]{ctx.channelCtx.asCtx->gmmu.LookupBlock(programBase + programOffset)}; @@ -91,11 +91,11 @@ namespace skyline::gpu::interconnect { }(blockMappingMirror.subspan(blockOffset)); 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) { diff --git a/app/src/main/cpp/skyline/gpu/interconnect/common/shader_cache.h b/app/src/main/cpp/skyline/gpu/interconnect/common/shader_cache.h index 2751df55..ef0a9fca 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/common/shader_cache.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/common/shader_cache.h @@ -7,6 +7,9 @@ #include "common.h" namespace skyline::gpu::interconnect { + /** + * @brief Caches guest shader binaries and their memory locations + */ class ShaderCache { private: /** @@ -14,7 +17,7 @@ namespace skyline::gpu::interconnect { */ struct MirrorEntry { span mirror; - tsl::robin_map cache; + tsl::robin_map> cache; std::optional 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 @@ -34,7 +37,10 @@ namespace skyline::gpu::interconnect { u32 lastProgramOffset{}; public: - ShaderBinary Lookup(InterconnectContext &ctx, u64 programBase, u32 programOffset); + /** + * @brief Returns the shader binary located at the given address + */ + std::pair Lookup(InterconnectContext &ctx, u64 programBase, u32 programOffset); bool Refresh(InterconnectContext &ctx, u64 programBase, u32 programOffset); diff --git a/app/src/main/cpp/skyline/gpu/interconnect/kepler_compute/pipeline_state.cpp b/app/src/main/cpp/skyline/gpu/interconnect/kepler_compute/pipeline_state.cpp index c86ac318..b85a2f6b 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/kepler_compute/pipeline_state.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/kepler_compute/pipeline_state.cpp @@ -14,7 +14,7 @@ namespace skyline::gpu::interconnect::kepler_compute { : engine{manager, dirtyHandle, engine} {} 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) { @@ -32,7 +32,7 @@ namespace skyline::gpu::interconnect::kepler_compute { Pipeline *PipelineState::Update(InterconnectContext &ctx, StateUpdateBuilder &builder, Textures &textures, ConstantBufferSet &constantBuffers, const QMD &qmd) { 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.localMemorySize = qmd.shaderLocalMemoryLowSize + qmd.shaderLocalMemoryHighSize; packedState.sharedMemorySize = qmd.sharedMemorySize; diff --git a/app/src/main/cpp/skyline/gpu/interconnect/kepler_compute/pipeline_state.h b/app/src/main/cpp/skyline/gpu/interconnect/kepler_compute/pipeline_state.h index 9602301b..c3064318 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/kepler_compute/pipeline_state.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/kepler_compute/pipeline_state.h @@ -26,6 +26,7 @@ namespace skyline::gpu::interconnect::kepler_compute { public: ShaderBinary binary; + u64 hash{}; PipelineStageState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine); diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp index 042c7455..527b9616 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp @@ -256,11 +256,11 @@ namespace skyline::gpu::interconnect::maxwell3d { throw exception("Shader type mismatch: {} != {}!", engine->pipeline.shader.type, static_cast(shaderType)); if (!engine->pipeline.shader.enable && shaderType != engine::Pipeline::Shader::Type::Vertex) { - binary.hash = 0; + hash = 0; 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) { @@ -495,7 +495,7 @@ namespace skyline::gpu::interconnect::maxwell3d { std::array shaderBinaries; for (size_t i{}; i < engine::PipelineCount; i++) { const auto &stage{pipelineStages[i].UpdateGet(ctx)}; - packedState.shaderHashes[i] = stage.binary.hash; + packedState.shaderHashes[i] = stage.hash; shaderBinaries[i] = stage.binary; } diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h index a533e829..ba5492e9 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h @@ -75,6 +75,7 @@ namespace skyline::gpu::interconnect::maxwell3d { public: ShaderBinary binary; + u64 hash; PipelineStageState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine, u8 shaderType);