Seperate Maxwell3D Stages into Shader/Pipeline

We need this to make the distinction between a shader and pipeline stage in as shader programs are bound at a different rate than that of pipeline stage resources such as UBO.
This commit is contained in:
PixelyIon 2021-12-23 21:21:01 +05:30
parent 492dd47218
commit 055d315048
4 changed files with 46 additions and 14 deletions

View File

@ -568,7 +568,7 @@ namespace skyline::gpu::interconnect {
}; };
IOVA shaderBaseIova{}; //!< The base IOVA that shaders are located at an offset from IOVA shaderBaseIova{}; //!< The base IOVA that shaders are located at an offset from
std::array<Shader, maxwell3d::StageCount> shaders{ std::array<Shader, maxwell3d::ShaderStageCount> shaders{
Shader{ShaderCompiler::Stage::VertexA, vk::ShaderStageFlagBits::eVertex}, Shader{ShaderCompiler::Stage::VertexA, vk::ShaderStageFlagBits::eVertex},
Shader{ShaderCompiler::Stage::VertexB, vk::ShaderStageFlagBits::eVertex}, Shader{ShaderCompiler::Stage::VertexB, vk::ShaderStageFlagBits::eVertex},
Shader{ShaderCompiler::Stage::TessellationControl, vk::ShaderStageFlagBits::eTessellationControl}, Shader{ShaderCompiler::Stage::TessellationControl, vk::ShaderStageFlagBits::eTessellationControl},
@ -662,13 +662,13 @@ namespace skyline::gpu::interconnect {
} }
} }
void SetShaderEnabled(maxwell3d::StageId stage, bool enabled) { void SetShaderEnabled(maxwell3d::ShaderStage stage, bool enabled) {
auto &shader{shaders[static_cast<size_t>(stage)]}; auto &shader{shaders[static_cast<size_t>(stage)]};
shader.enabled = enabled; shader.enabled = enabled;
shader.invalidated = true; shader.invalidated = true;
} }
void SetShaderOffset(maxwell3d::StageId stage, u32 offset) { void SetShaderOffset(maxwell3d::ShaderStage stage, u32 offset) {
auto &shader{shaders[static_cast<size_t>(stage)]}; auto &shader{shaders[static_cast<size_t>(stage)]};
shader.offset = offset; shader.offset = offset;
shader.invalidated = true; shader.invalidated = true;

View File

@ -652,12 +652,43 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
Set = 0x150F, Set = 0x150F,
}; };
constexpr static size_t StageCount{6}; //!< Amount of pipeline stages on Maxwell 3D constexpr static size_t PipelineStageCount{5}; //!< Amount of pipeline stages on Maxwell 3D
/** /**
* @brief All the pipeline stages that Maxwell3D supports for draws * @brief All the pipeline stages that Maxwell3D supports for draws
*/ */
enum class StageId { enum class PipelineStage {
Vertex = 0,
TessellationControl = 1,
TessellationEvaluation = 2,
Geometry = 3,
Fragment = 4,
};
static_assert(static_cast<size_t>(PipelineStage::Fragment) + 1 == PipelineStageCount);
struct Bind {
u32 _pad0_[4];
union {
struct {
u32 valid : 1;
u32 _pad1_ : 3;
u32 index : 5; //!< The index of the constant buffer in the pipeline stage to bind to
};
u32 raw;
} constantBuffer;
u32 _pad2_[3];
};
static_assert(sizeof(Bind) == (sizeof(u32) * 8));
constexpr static size_t PipelineStageConstantBufferCount{18}; //!< Maximum amount of constant buffers that can be bound to a single pipeline stage
constexpr static size_t ShaderStageCount{6}; //!< Amount of shader stages on Maxwell 3D
/**
* @brief All the shader programs stages that Maxwell3D supports for draws
* @note As opposed to pipeline stages, there are two shader programs for the vertex stage
*/
enum class ShaderStage {
VertexA = 0, VertexA = 0,
VertexB = 1, VertexB = 1,
TessellationControl = 2, TessellationControl = 2,
@ -665,7 +696,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
Geometry = 4, Geometry = 4,
Fragment = 5, Fragment = 5,
}; };
static_assert(static_cast<size_t>(StageId::Fragment) + 1 == StageCount); static_assert(static_cast<size_t>(ShaderStage::Fragment) + 1 == ShaderStageCount);
/** /**
* @brief The arguments to set a shader program for a pipeline stage * @brief The arguments to set a shader program for a pipeline stage
@ -674,7 +705,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
struct { struct {
bool enable : 1; bool enable : 1;
u8 _pad0_ : 3; u8 _pad0_ : 3;
StageId stage : 4; ShaderStage stage : 4;
u32 _pad1_ : 24; u32 _pad1_ : 24;
} info; } info;
u32 offset; //!< Offset from the base shader memory IOVA u32 offset; //!< Offset from the base shader memory IOVA

View File

@ -428,7 +428,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
}) })
BOOST_PP_REPEAT(6, SET_SHADER_ENABLE_CALLBACK, 0) BOOST_PP_REPEAT(6, SET_SHADER_ENABLE_CALLBACK, 0)
static_assert(type::StageCount == 6 && type::StageCount < BOOST_PP_LIMIT_REPEAT); static_assert(type::ShaderStageCount == 6 && type::ShaderStageCount < BOOST_PP_LIMIT_REPEAT);
#undef SET_SHADER_ENABLE_CALLBACK #undef SET_SHADER_ENABLE_CALLBACK
MAXWELL3D_CASE(vertexBeginGl, { MAXWELL3D_CASE(vertexBeginGl, {
@ -509,13 +509,14 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
} }
}) })
#define SET_SHADER_OFFSET_CALLBACK(z, index, data) \ #define SHADER_CALLBACKS(z, index, data) \
MAXWELL3D_ARRAY_STRUCT_CASE(setProgram, index, offset, { \ MAXWELL3D_ARRAY_STRUCT_CASE(setProgram, index, offset, { \
context.SetShaderOffset(registers.setProgram[index].info.stage, offset); \ context.SetShaderOffset(static_cast<type::ShaderStage>(index), offset); \
}) })
BOOST_PP_REPEAT(6, SET_SHADER_OFFSET_CALLBACK, 0) BOOST_PP_REPEAT(6, SHADER_CALLBACKS, 0)
static_assert(type::StageCount == 6 && type::StageCount < BOOST_PP_LIMIT_REPEAT); static_assert(type::ShaderStageCount == 6 && type::ShaderStageCount < BOOST_PP_LIMIT_REPEAT);
#undef SHADER_CALLBACKS
MAXWELL3D_ARRAY_CASE(firmwareCall, 4, { MAXWELL3D_ARRAY_CASE(firmwareCall, 4, {
registers.raw[0xD00] = 1; registers.raw[0xD00] = 1;

View File

@ -278,7 +278,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x7C0, std::array<type::Address, type::VertexBufferCount>> vertexBufferLimits; //!< A per-VBO IOVA denoting the end of the vertex buffer Register<0x7C0, std::array<type::Address, type::VertexBufferCount>> vertexBufferLimits; //!< A per-VBO IOVA denoting the end of the vertex buffer
Register<0x800, std::array<type::SetProgramInfo, type::StageCount>> setProgram; Register<0x800, std::array<type::SetProgramInfo, type::ShaderStageCount>> setProgram;
Register<0x8C0, u32[0x20]> firmwareCall; Register<0x8C0, u32[0x20]> firmwareCall;