mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-05 05:15:08 +01:00
Support Dual Vertex Shader Programs
Add support for parsing and combining `VertexA` and `VertexB` programs into a single vertex pipeline program prior to compilation, atomic reparsing and combining is supported to only reparse the stage that was modified and recombine once at most within a single pipeline compilation.
This commit is contained in:
parent
974cf03c18
commit
e1e14e781f
@ -743,7 +743,23 @@ namespace skyline::gpu::interconnect {
|
||||
|
||||
shader.program = gpu.shader.ParseGraphicsShader(shader.data, shader.stage, shader.offset);
|
||||
|
||||
if (shader.stage != ShaderCompiler::Stage::VertexA) {
|
||||
if (shader.stage != ShaderCompiler::Stage::VertexA && shader.stage != ShaderCompiler::Stage::VertexB) {
|
||||
pipelineStage.program.emplace<std::reference_wrapper<ShaderCompiler::IR::Program>>(*shader.program);
|
||||
} else if (shader.stage == ShaderCompiler::Stage::VertexA) {
|
||||
auto &vertexB{shaders[maxwell3d::ShaderStage::VertexB]};
|
||||
|
||||
if (!vertexB.enabled)
|
||||
throw exception("Enabling VertexA without VertexB is not supported");
|
||||
else if (!vertexB.invalidated)
|
||||
// If only VertexA is invalidated, we need to recombine here but we can defer it otherwise
|
||||
pipelineStage.program = gpu.shader.CombineVertexShaders(*shader.program, *vertexB.program, vertexB.data);
|
||||
} else if (shader.stage == ShaderCompiler::Stage::VertexB) {
|
||||
auto &vertexA{shaders[maxwell3d::ShaderStage::VertexA]};
|
||||
|
||||
if (vertexA.enabled)
|
||||
// We need to combine the vertex shader stages if VertexA is enabled
|
||||
pipelineStage.program = gpu.shader.CombineVertexShaders(*vertexA.program, *shader.program, shader.data);
|
||||
else
|
||||
pipelineStage.program.emplace<std::reference_wrapper<ShaderCompiler::IR::Program>>(*shader.program);
|
||||
}
|
||||
|
||||
|
@ -125,6 +125,45 @@ namespace skyline::gpu {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A shader environment for VertexB during combination as it only requires the shader header and no higher level context
|
||||
*/
|
||||
class VertexBEnvironment : public Shader::Environment {
|
||||
public:
|
||||
explicit VertexBEnvironment(span<u8> binary) {
|
||||
sph = *reinterpret_cast<Shader::ProgramHeader *>(binary.data());
|
||||
stage = Shader::Stage::VertexB;
|
||||
}
|
||||
|
||||
[[nodiscard]] u64 ReadInstruction(u32 address) final {
|
||||
throw exception("Not implemented");
|
||||
}
|
||||
|
||||
[[nodiscard]] u32 ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) final {
|
||||
throw exception("Not implemented");
|
||||
}
|
||||
|
||||
[[nodiscard]] Shader::TextureType ReadTextureType(u32 raw_handle) final {
|
||||
throw exception("Not implemented");
|
||||
}
|
||||
|
||||
[[nodiscard]] u32 TextureBoundBuffer() const final {
|
||||
throw exception("Not implemented");
|
||||
}
|
||||
|
||||
[[nodiscard]] u32 LocalMemorySize() const final {
|
||||
return static_cast<u32>(sph.LocalMemorySize()) + sph.common3.shader_local_memory_crs_size;
|
||||
}
|
||||
|
||||
[[nodiscard]] u32 SharedMemorySize() const final {
|
||||
return 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::array<u32, 3> WorkgroupSize() const final {
|
||||
return {0, 0, 0};
|
||||
}
|
||||
};
|
||||
|
||||
Shader::IR::Program ShaderManager::ParseGraphicsShader(span<u8> binary, Shader::Stage stage, u32 baseOffset) {
|
||||
GraphicsEnvironment environment{binary, baseOffset, stage};
|
||||
Shader::Maxwell::Flow::CFG cfg(environment, flowBlockPool, Shader::Maxwell::Location{static_cast<u32>(baseOffset + sizeof(Shader::ProgramHeader))});
|
||||
@ -132,6 +171,11 @@ namespace skyline::gpu {
|
||||
return Shader::Maxwell::TranslateProgram(instPool, blockPool, environment, cfg, hostTranslateInfo);
|
||||
}
|
||||
|
||||
Shader::IR::Program ShaderManager::CombineVertexShaders(Shader::IR::Program &vertexA, Shader::IR::Program &vertexB, span<u8> vertexBBinary) {
|
||||
VertexBEnvironment vertexBEnvironment{vertexBBinary};
|
||||
return Shader::Maxwell::MergeDualVertexPrograms(vertexA, vertexB, vertexBEnvironment);
|
||||
}
|
||||
|
||||
vk::raii::ShaderModule ShaderManager::CompileShader(Shader::RuntimeInfo &runtimeInfo, Shader::IR::Program &program, Shader::Backend::Bindings &bindings) {
|
||||
auto spirv{Shader::Backend::SPIRV::EmitSPIRV(profile, runtimeInfo, program, bindings)};
|
||||
|
||||
|
@ -33,6 +33,11 @@ namespace skyline::gpu {
|
||||
|
||||
Shader::IR::Program ParseGraphicsShader(span<u8> binary, Shader::Stage stage, u32 baseOffset);
|
||||
|
||||
/**
|
||||
* @brief Combines the VertexA and VertexB shader programs into a single program
|
||||
*/
|
||||
static Shader::IR::Program CombineVertexShaders(Shader::IR::Program &vertexA, Shader::IR::Program &vertexB, span<u8> vertexBBinary);
|
||||
|
||||
vk::raii::ShaderModule CompileShader(Shader::RuntimeInfo &runtimeInfo, Shader::IR::Program &program, Shader::Backend::Bindings &bindings);
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user