|
|
@@ -784,112 +784,119 @@ struct Regs {
|
|
|
INSERT_PADDING_WORDS(0x20);
|
|
|
|
|
|
enum class TriangleTopology : u32 {
|
|
|
- List = 0,
|
|
|
- Strip = 1,
|
|
|
- Fan = 2,
|
|
|
- ListIndexed = 3, // TODO: No idea if this is correct
|
|
|
+ List = 0,
|
|
|
+ Strip = 1,
|
|
|
+ Fan = 2,
|
|
|
+ Shader = 3, // Programmable setup unit implemented in a geometry shader
|
|
|
};
|
|
|
|
|
|
BitField<8, 2, TriangleTopology> triangle_topology;
|
|
|
|
|
|
- INSERT_PADDING_WORDS(0x51);
|
|
|
+ INSERT_PADDING_WORDS(0x21);
|
|
|
|
|
|
- BitField<0, 16, u32> vs_bool_uniforms;
|
|
|
- union {
|
|
|
- BitField< 0, 8, u32> x;
|
|
|
- BitField< 8, 8, u32> y;
|
|
|
- BitField<16, 8, u32> z;
|
|
|
- BitField<24, 8, u32> w;
|
|
|
- } vs_int_uniforms[4];
|
|
|
+ struct ShaderConfig {
|
|
|
+ BitField<0, 16, u32> bool_uniforms;
|
|
|
|
|
|
- INSERT_PADDING_WORDS(0x5);
|
|
|
+ union {
|
|
|
+ BitField< 0, 8, u32> x;
|
|
|
+ BitField< 8, 8, u32> y;
|
|
|
+ BitField<16, 8, u32> z;
|
|
|
+ BitField<24, 8, u32> w;
|
|
|
+ } int_uniforms[4];
|
|
|
|
|
|
- // Offset to shader program entry point (in words)
|
|
|
- BitField<0, 16, u32> vs_main_offset;
|
|
|
+ INSERT_PADDING_WORDS(0x5);
|
|
|
|
|
|
- union {
|
|
|
- BitField< 0, 4, u64> attribute0_register;
|
|
|
- BitField< 4, 4, u64> attribute1_register;
|
|
|
- BitField< 8, 4, u64> attribute2_register;
|
|
|
- BitField<12, 4, u64> attribute3_register;
|
|
|
- BitField<16, 4, u64> attribute4_register;
|
|
|
- BitField<20, 4, u64> attribute5_register;
|
|
|
- BitField<24, 4, u64> attribute6_register;
|
|
|
- BitField<28, 4, u64> attribute7_register;
|
|
|
- BitField<32, 4, u64> attribute8_register;
|
|
|
- BitField<36, 4, u64> attribute9_register;
|
|
|
- BitField<40, 4, u64> attribute10_register;
|
|
|
- BitField<44, 4, u64> attribute11_register;
|
|
|
- BitField<48, 4, u64> attribute12_register;
|
|
|
- BitField<52, 4, u64> attribute13_register;
|
|
|
- BitField<56, 4, u64> attribute14_register;
|
|
|
- BitField<60, 4, u64> attribute15_register;
|
|
|
-
|
|
|
- int GetRegisterForAttribute(int attribute_index) const {
|
|
|
- u64 fields[] = {
|
|
|
- attribute0_register, attribute1_register, attribute2_register, attribute3_register,
|
|
|
- attribute4_register, attribute5_register, attribute6_register, attribute7_register,
|
|
|
- attribute8_register, attribute9_register, attribute10_register, attribute11_register,
|
|
|
- attribute12_register, attribute13_register, attribute14_register, attribute15_register,
|
|
|
+ // Offset to shader program entry point (in words)
|
|
|
+ BitField<0, 16, u32> main_offset;
|
|
|
+
|
|
|
+ union {
|
|
|
+ BitField< 0, 4, u64> attribute0_register;
|
|
|
+ BitField< 4, 4, u64> attribute1_register;
|
|
|
+ BitField< 8, 4, u64> attribute2_register;
|
|
|
+ BitField<12, 4, u64> attribute3_register;
|
|
|
+ BitField<16, 4, u64> attribute4_register;
|
|
|
+ BitField<20, 4, u64> attribute5_register;
|
|
|
+ BitField<24, 4, u64> attribute6_register;
|
|
|
+ BitField<28, 4, u64> attribute7_register;
|
|
|
+ BitField<32, 4, u64> attribute8_register;
|
|
|
+ BitField<36, 4, u64> attribute9_register;
|
|
|
+ BitField<40, 4, u64> attribute10_register;
|
|
|
+ BitField<44, 4, u64> attribute11_register;
|
|
|
+ BitField<48, 4, u64> attribute12_register;
|
|
|
+ BitField<52, 4, u64> attribute13_register;
|
|
|
+ BitField<56, 4, u64> attribute14_register;
|
|
|
+ BitField<60, 4, u64> attribute15_register;
|
|
|
+
|
|
|
+ int GetRegisterForAttribute(int attribute_index) const {
|
|
|
+ u64 fields[] = {
|
|
|
+ attribute0_register, attribute1_register, attribute2_register, attribute3_register,
|
|
|
+ attribute4_register, attribute5_register, attribute6_register, attribute7_register,
|
|
|
+ attribute8_register, attribute9_register, attribute10_register, attribute11_register,
|
|
|
+ attribute12_register, attribute13_register, attribute14_register, attribute15_register,
|
|
|
+ };
|
|
|
+ return (int)fields[attribute_index];
|
|
|
+ }
|
|
|
+ } input_register_map;
|
|
|
+
|
|
|
+ // OUTMAP_MASK, 0x28E, CODETRANSFER_END
|
|
|
+ INSERT_PADDING_WORDS(0x3);
|
|
|
+
|
|
|
+ struct {
|
|
|
+ enum Format : u32
|
|
|
+ {
|
|
|
+ FLOAT24 = 0,
|
|
|
+ FLOAT32 = 1
|
|
|
};
|
|
|
- return (int)fields[attribute_index];
|
|
|
- }
|
|
|
- } vs_input_register_map;
|
|
|
|
|
|
- INSERT_PADDING_WORDS(0x3);
|
|
|
+ bool IsFloat32() const {
|
|
|
+ return format == FLOAT32;
|
|
|
+ }
|
|
|
|
|
|
- struct {
|
|
|
- enum Format : u32
|
|
|
- {
|
|
|
- FLOAT24 = 0,
|
|
|
- FLOAT32 = 1
|
|
|
- };
|
|
|
+ union {
|
|
|
+ // Index of the next uniform to write to
|
|
|
+ // TODO: ctrulib uses 8 bits for this, however that seems to yield lots of invalid indices
|
|
|
+ // TODO: Maybe the uppermost index is for the geometry shader? Investigate!
|
|
|
+ BitField<0, 7, u32> index;
|
|
|
|
|
|
- bool IsFloat32() const {
|
|
|
- return format == FLOAT32;
|
|
|
- }
|
|
|
+ BitField<31, 1, Format> format;
|
|
|
+ };
|
|
|
|
|
|
- union {
|
|
|
- // Index of the next uniform to write to
|
|
|
- // TODO: ctrulib uses 8 bits for this, however that seems to yield lots of invalid indices
|
|
|
- BitField<0, 7, u32> index;
|
|
|
+ // Writing to these registers sets the current uniform.
|
|
|
+ u32 set_value[8];
|
|
|
|
|
|
- BitField<31, 1, Format> format;
|
|
|
- };
|
|
|
+ } uniform_setup;
|
|
|
|
|
|
- // Writing to these registers sets the "current" uniform.
|
|
|
- // TODO: It's not clear how the hardware stores what the "current" uniform is.
|
|
|
- u32 set_value[8];
|
|
|
+ INSERT_PADDING_WORDS(0x2);
|
|
|
|
|
|
- } vs_uniform_setup;
|
|
|
+ struct {
|
|
|
+ // Offset of the next instruction to write code to.
|
|
|
+ // Incremented with each instruction write.
|
|
|
+ u32 offset;
|
|
|
|
|
|
- INSERT_PADDING_WORDS(0x2);
|
|
|
+ // Writing to these registers sets the "current" word in the shader program.
|
|
|
+ u32 set_word[8];
|
|
|
+ } program;
|
|
|
|
|
|
- struct {
|
|
|
- // Offset of the next instruction to write code to.
|
|
|
- // Incremented with each instruction write.
|
|
|
- u32 offset;
|
|
|
+ INSERT_PADDING_WORDS(0x1);
|
|
|
|
|
|
- // Writing to these registers sets the "current" word in the shader program.
|
|
|
- // TODO: It's not clear how the hardware stores what the "current" word is.
|
|
|
- u32 set_word[8];
|
|
|
- } vs_program;
|
|
|
+ // This register group is used to load an internal table of swizzling patterns,
|
|
|
+ // which are indexed by each shader instruction to specify vector component swizzling.
|
|
|
+ struct {
|
|
|
+ // Offset of the next swizzle pattern to write code to.
|
|
|
+ // Incremented with each instruction write.
|
|
|
+ u32 offset;
|
|
|
|
|
|
- INSERT_PADDING_WORDS(0x1);
|
|
|
+ // Writing to these registers sets the current swizzle pattern in the table.
|
|
|
+ u32 set_word[8];
|
|
|
+ } swizzle_patterns;
|
|
|
|
|
|
- // This register group is used to load an internal table of swizzling patterns,
|
|
|
- // which are indexed by each shader instruction to specify vector component swizzling.
|
|
|
- struct {
|
|
|
- // Offset of the next swizzle pattern to write code to.
|
|
|
- // Incremented with each instruction write.
|
|
|
- u32 offset;
|
|
|
+ INSERT_PADDING_WORDS(0x2);
|
|
|
+ };
|
|
|
|
|
|
- // Writing to these registers sets the "current" swizzle pattern in the table.
|
|
|
- // TODO: It's not clear how the hardware stores what the "current" swizzle pattern is.
|
|
|
- u32 set_word[8];
|
|
|
- } vs_swizzle_patterns;
|
|
|
+ ShaderConfig gs;
|
|
|
+ ShaderConfig vs;
|
|
|
|
|
|
- INSERT_PADDING_WORDS(0x22);
|
|
|
+ INSERT_PADDING_WORDS(0x20);
|
|
|
|
|
|
// Map register indices to names readable by humans
|
|
|
// Used for debugging purposes, so performance is not an issue here
|
|
|
@@ -936,13 +943,20 @@ struct Regs {
|
|
|
ADD_FIELD(vs_default_attributes_setup);
|
|
|
ADD_FIELD(command_buffer);
|
|
|
ADD_FIELD(triangle_topology);
|
|
|
- ADD_FIELD(vs_bool_uniforms);
|
|
|
- ADD_FIELD(vs_int_uniforms);
|
|
|
- ADD_FIELD(vs_main_offset);
|
|
|
- ADD_FIELD(vs_input_register_map);
|
|
|
- ADD_FIELD(vs_uniform_setup);
|
|
|
- ADD_FIELD(vs_program);
|
|
|
- ADD_FIELD(vs_swizzle_patterns);
|
|
|
+ ADD_FIELD(gs.bool_uniforms);
|
|
|
+ ADD_FIELD(gs.int_uniforms);
|
|
|
+ ADD_FIELD(gs.main_offset);
|
|
|
+ ADD_FIELD(gs.input_register_map);
|
|
|
+ ADD_FIELD(gs.uniform_setup);
|
|
|
+ ADD_FIELD(gs.program);
|
|
|
+ ADD_FIELD(gs.swizzle_patterns);
|
|
|
+ ADD_FIELD(vs.bool_uniforms);
|
|
|
+ ADD_FIELD(vs.int_uniforms);
|
|
|
+ ADD_FIELD(vs.main_offset);
|
|
|
+ ADD_FIELD(vs.input_register_map);
|
|
|
+ ADD_FIELD(vs.uniform_setup);
|
|
|
+ ADD_FIELD(vs.program);
|
|
|
+ ADD_FIELD(vs.swizzle_patterns);
|
|
|
|
|
|
#undef ADD_FIELD
|
|
|
|
|
|
@@ -1014,17 +1028,14 @@ ASSERT_REG_POSITION(trigger_draw_indexed, 0x22f);
|
|
|
ASSERT_REG_POSITION(vs_default_attributes_setup, 0x232);
|
|
|
ASSERT_REG_POSITION(command_buffer, 0x238);
|
|
|
ASSERT_REG_POSITION(triangle_topology, 0x25e);
|
|
|
-ASSERT_REG_POSITION(vs_bool_uniforms, 0x2b0);
|
|
|
-ASSERT_REG_POSITION(vs_int_uniforms, 0x2b1);
|
|
|
-ASSERT_REG_POSITION(vs_main_offset, 0x2ba);
|
|
|
-ASSERT_REG_POSITION(vs_input_register_map, 0x2bb);
|
|
|
-ASSERT_REG_POSITION(vs_uniform_setup, 0x2c0);
|
|
|
-ASSERT_REG_POSITION(vs_program, 0x2cb);
|
|
|
-ASSERT_REG_POSITION(vs_swizzle_patterns, 0x2d5);
|
|
|
+ASSERT_REG_POSITION(gs, 0x280);
|
|
|
+ASSERT_REG_POSITION(vs, 0x2b0);
|
|
|
|
|
|
#undef ASSERT_REG_POSITION
|
|
|
#endif // !defined(_MSC_VER)
|
|
|
|
|
|
+static_assert(sizeof(Regs::ShaderConfig) == 0x30 * sizeof(u32), "ShaderConfig structure has incorrect size");
|
|
|
+
|
|
|
// The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value anyway.
|
|
|
static_assert(sizeof(Regs) <= 0x300 * sizeof(u32), "Register set structure larger than it should be");
|
|
|
static_assert(sizeof(Regs) >= 0x300 * sizeof(u32), "Register set structure smaller than it should be");
|
|
|
@@ -1134,7 +1145,7 @@ struct State {
|
|
|
Regs regs;
|
|
|
|
|
|
/// Vertex shader memory
|
|
|
- struct {
|
|
|
+ struct ShaderSetup {
|
|
|
struct {
|
|
|
Math::Vec4<float24> f[96];
|
|
|
std::array<bool, 16> b;
|
|
|
@@ -1145,7 +1156,10 @@ struct State {
|
|
|
|
|
|
std::array<u32, 1024> program_code;
|
|
|
std::array<u32, 1024> swizzle_data;
|
|
|
- } vs;
|
|
|
+ };
|
|
|
+
|
|
|
+ ShaderSetup vs;
|
|
|
+ ShaderSetup gs;
|
|
|
|
|
|
/// Current Pica command list
|
|
|
struct {
|