|
|
|
@ -785,112 +785,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 |
|
|
|
@ -937,13 +944,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 |
|
|
|
|
|
|
|
@ -1015,17 +1029,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"); |
|
|
|
@ -1135,7 +1146,7 @@ struct State { |
|
|
|
Regs regs; |
|
|
|
|
|
|
|
/// Vertex shader memory |
|
|
|
struct { |
|
|
|
struct ShaderSetup { |
|
|
|
struct { |
|
|
|
Math::Vec4<float24> f[96]; |
|
|
|
std::array<bool, 16> b; |
|
|
|
@ -1146,7 +1157,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 { |
|
|
|
|