mirror of
https://github.com/skyline-emu/skyline.git
synced 2025-01-01 07:15:28 +03:00
Introduce pipeline shader stage state
Simple state that generates a hash that can be used in the packed state and spans over the binary for pipeline creation.
This commit is contained in:
parent
a6bb716123
commit
0c6fa22c6b
@ -211,6 +211,44 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
view = ctx.executor.AcquireTextureManager().FindOrCreate(guest, ctx.executor.tag);
|
view = ctx.executor.AcquireTextureManager().FindOrCreate(guest, ctx.executor.tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pipeline Stages */
|
||||||
|
void PipelineStageState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
|
||||||
|
manager.Bind(handle, pipeline, programRegion);
|
||||||
|
}
|
||||||
|
|
||||||
|
PipelineStageState::PipelineStageState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine, u8 shaderType)
|
||||||
|
: engine{manager, dirtyHandle, engine},
|
||||||
|
shaderType{static_cast<engine::Pipeline::Shader::Type>(shaderType)} {}
|
||||||
|
|
||||||
|
void PipelineStageState::Flush(InterconnectContext &ctx) {
|
||||||
|
if (engine->pipeline.shader.type != 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) {
|
||||||
|
hash = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
binary.binary = ctx.channelCtx.asCtx->gmmu.ReadTill(shaderBacking, engine->programRegion + engine->pipeline.programOffset, [](span<u8> data) -> std::optional<size_t> {
|
||||||
|
// We attempt to find the shader size by looking for "BRA $" (Infinite Loop) which is used as padding at the end of the shader
|
||||||
|
// UAM Shader Compiler Reference: https://github.com/devkitPro/uam/blob/5a5afc2bae8b55409ab36ba45be63fcb73f68993/source/compiler_iface.cpp#L319-L351
|
||||||
|
constexpr u64 BraSelf1{0xE2400FFFFF87000F}, BraSelf2{0xE2400FFFFF07000F};
|
||||||
|
|
||||||
|
span<u64> shaderInstructions{data.cast<u64, std::dynamic_extent, true>()};
|
||||||
|
for (auto it{shaderInstructions.begin()}; it != shaderInstructions.end(); it++) {
|
||||||
|
auto instruction{*it};
|
||||||
|
if (instruction == BraSelf1 || instruction == BraSelf2) [[unlikely]]
|
||||||
|
// It is far more likely that the instruction doesn't match so this is an unlikely case
|
||||||
|
return static_cast<size_t>(std::distance(shaderInstructions.begin(), it)) * sizeof(u64);
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
});
|
||||||
|
|
||||||
|
binary.baseOffset = engine->pipeline.programOffset;
|
||||||
|
|
||||||
|
hash = XXH64(binary.binary.data(), binary.binary.size_bytes(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Vertex Input State */
|
/* Vertex Input State */
|
||||||
// TODO: check if better individually
|
// TODO: check if better individually
|
||||||
void VertexInputState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
|
void VertexInputState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
|
||||||
@ -502,7 +540,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
|
|
||||||
PipelineState::PipelineState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine)
|
PipelineState::PipelineState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine)
|
||||||
: engine{manager, dirtyHandle, engine},
|
: engine{manager, dirtyHandle, engine},
|
||||||
shaders{util::MergeInto<dirty::ManualDirtyState<IndividualShaderState>, engine::PipelineCount>(manager, engine.shadersRegisters, util::IncrementingT<u8>{})},
|
pipelineStages{util::MergeInto<dirty::ManualDirtyState<PipelineStageState>, engine::PipelineCount>(manager, engine.pipelineStageRegisters, util::IncrementingT<u8>{})},
|
||||||
colorRenderTargets{util::MergeInto<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount>(manager, engine.colorRenderTargetsRegisters, util::IncrementingT<size_t>{})},
|
colorRenderTargets{util::MergeInto<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount>(manager, engine.colorRenderTargetsRegisters, util::IncrementingT<size_t>{})},
|
||||||
depthRenderTarget{manager, engine.depthRenderTargetRegisters},
|
depthRenderTarget{manager, engine.depthRenderTargetRegisters},
|
||||||
vertexInput{manager, engine.vertexInputRegisters},
|
vertexInput{manager, engine.vertexInputRegisters},
|
||||||
@ -514,6 +552,13 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
globalShaderConfig{engine.globalShaderConfigRegisters} {}
|
globalShaderConfig{engine.globalShaderConfigRegisters} {}
|
||||||
|
|
||||||
void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) {
|
void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) {
|
||||||
|
std::array<ShaderBinary, engine::PipelineCount> shaderBinaries;
|
||||||
|
for (size_t i{}; i < engine::PipelineCount; i++) {
|
||||||
|
const auto &stage{pipelineStages[i].UpdateGet(ctx)};
|
||||||
|
packedState.shaderHashes[i] = stage.hash;
|
||||||
|
shaderBinaries[i] = stage.binary;
|
||||||
|
}
|
||||||
|
|
||||||
boost::container::static_vector<TextureView *, engine::ColorTargetCount> colorAttachments;
|
boost::container::static_vector<TextureView *, engine::ColorTargetCount> colorAttachments;
|
||||||
for (auto &colorRenderTarget : colorRenderTargets)
|
for (auto &colorRenderTarget : colorRenderTargets)
|
||||||
if (auto view{colorRenderTarget.UpdateGet(ctx, packedState).view}; view)
|
if (auto view{colorRenderTarget.UpdateGet(ctx, packedState).view}; view)
|
||||||
|
@ -56,6 +56,32 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
void Flush(InterconnectContext &ctx, PackedPipelineState &packedState);
|
void Flush(InterconnectContext &ctx, PackedPipelineState &packedState);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PipelineStageState : dirty::ManualDirty {
|
||||||
|
public:
|
||||||
|
struct EngineRegisters {
|
||||||
|
const engine::Pipeline &pipeline;
|
||||||
|
const soc::gm20b::engine::Address &programRegion;
|
||||||
|
|
||||||
|
void DirtyBind(DirtyManager &manager, dirty::Handle handle) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
dirty::BoundSubresource<EngineRegisters> engine;
|
||||||
|
engine::Pipeline::Shader::Type shaderType;
|
||||||
|
|
||||||
|
constexpr static size_t MaxShaderBytecodeSize{1 * 1024 * 1024}; //!< The largest shader binary that we support (1 MiB)
|
||||||
|
|
||||||
|
std::array<u8, MaxShaderBytecodeSize> shaderBacking;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ShaderBinary binary;
|
||||||
|
u64 hash;
|
||||||
|
|
||||||
|
PipelineStageState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine, u8 shaderType);
|
||||||
|
|
||||||
|
void Flush(InterconnectContext &ctx);
|
||||||
|
};
|
||||||
|
|
||||||
class VertexInputState : dirty::ManualDirty {
|
class VertexInputState : dirty::ManualDirty {
|
||||||
public:
|
public:
|
||||||
struct EngineRegisters {
|
struct EngineRegisters {
|
||||||
@ -223,7 +249,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
class PipelineState : dirty::ManualDirty {
|
class PipelineState : dirty::ManualDirty {
|
||||||
public:
|
public:
|
||||||
struct EngineRegisters {
|
struct EngineRegisters {
|
||||||
std::array<IndividualShaderState::EngineRegisters, engine::PipelineCount> shadersRegisters;
|
std::array<PipelineStageState::EngineRegisters, engine::PipelineCount> pipelineStageRegisters;
|
||||||
std::array<ColorRenderTargetState::EngineRegisters, engine::ColorTargetCount> colorRenderTargetsRegisters;
|
std::array<ColorRenderTargetState::EngineRegisters, engine::ColorTargetCount> colorRenderTargetsRegisters;
|
||||||
DepthRenderTargetState::EngineRegisters depthRenderTargetRegisters;
|
DepthRenderTargetState::EngineRegisters depthRenderTargetRegisters;
|
||||||
VertexInputState::EngineRegisters vertexInputRegisters;
|
VertexInputState::EngineRegisters vertexInputRegisters;
|
||||||
@ -238,11 +264,14 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
PipelineManager pipelineManager{};
|
||||||
|
Pipeline *pipeline{};
|
||||||
|
|
||||||
PackedPipelineState packedState{};
|
PackedPipelineState packedState{};
|
||||||
|
|
||||||
dirty::BoundSubresource<EngineRegisters> engine;
|
dirty::BoundSubresource<EngineRegisters> engine;
|
||||||
|
|
||||||
std::array<dirty::ManualDirtyState<IndividualShaderState>, engine::PipelineCount> shaders;
|
std::array<dirty::ManualDirtyState<PipelineStageState>, engine::PipelineCount> pipelineStages;
|
||||||
std::array<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount> colorRenderTargets;
|
std::array<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount> colorRenderTargets;
|
||||||
dirty::ManualDirtyState<DepthRenderTargetState> depthRenderTarget;
|
dirty::ManualDirtyState<DepthRenderTargetState> depthRenderTarget;
|
||||||
dirty::ManualDirtyState<VertexInputState> vertexInput;
|
dirty::ManualDirtyState<VertexInputState> vertexInput;
|
||||||
|
@ -14,7 +14,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
|
|
||||||
static gpu::interconnect::maxwell3d::PipelineState::EngineRegisters MakePipelineStateRegisters(const Maxwell3D::Registers ®isters) {
|
static gpu::interconnect::maxwell3d::PipelineState::EngineRegisters MakePipelineStateRegisters(const Maxwell3D::Registers ®isters) {
|
||||||
return {
|
return {
|
||||||
.shadersRegisters = util::MergeInto<REGTYPE(IndividualShaderState), type::PipelineCount>(*registers.pipelines, *registers.programRegion),
|
.pipelineStageRegisters = util::MergeInto<REGTYPE(PipelineStageState), type::PipelineCount>(*registers.pipelines, *registers.programRegion),
|
||||||
.colorRenderTargetsRegisters = util::MergeInto<REGTYPE(ColorRenderTargetState), type::ColorTargetCount>(*registers.colorTargets),
|
.colorRenderTargetsRegisters = util::MergeInto<REGTYPE(ColorRenderTargetState), type::ColorTargetCount>(*registers.colorTargets),
|
||||||
.depthRenderTargetRegisters = {*registers.ztSize, *registers.ztOffset, *registers.ztFormat, *registers.ztBlockSize, *registers.ztArrayPitch, *registers.ztSelect, *registers.ztLayer},
|
.depthRenderTargetRegisters = {*registers.ztSize, *registers.ztOffset, *registers.ztFormat, *registers.ztBlockSize, *registers.ztArrayPitch, *registers.ztSelect, *registers.ztLayer},
|
||||||
.vertexInputRegisters = {*registers.vertexStreams, *registers.vertexStreamInstance, *registers.vertexAttributes},
|
.vertexInputRegisters = {*registers.vertexStreams, *registers.vertexStreamInstance, *registers.vertexAttributes},
|
||||||
|
Loading…
Reference in New Issue
Block a user