diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/vertex_shader.cpp | 28 | ||||
| -rw-r--r-- | src/video_core/vertex_shader.h | 78 |
2 files changed, 92 insertions, 14 deletions
diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp index 8df14b51f..cdecbff3c 100644 --- a/src/video_core/vertex_shader.cpp +++ b/src/video_core/vertex_shader.cpp | |||
| @@ -65,26 +65,32 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 65 | const Instruction& instr = *(const Instruction*)state.program_counter; | 65 | const Instruction& instr = *(const Instruction*)state.program_counter; |
| 66 | state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + (state.program_counter - shader_memory)); | 66 | state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + (state.program_counter - shader_memory)); |
| 67 | 67 | ||
| 68 | const float24* src1_ = (instr.common.src1 < 0x10) ? state.input_register_table[instr.common.src1] | 68 | const float24* src1_ = (instr.common.src1 < 0x10) ? state.input_register_table[instr.common.src1.GetIndex()] |
| 69 | : (instr.common.src1 < 0x20) ? &state.temporary_registers[instr.common.src1-0x10].x | 69 | : (instr.common.src1 < 0x20) ? &state.temporary_registers[instr.common.src1.GetIndex()].x |
| 70 | : (instr.common.src1 < 0x80) ? &shader_uniforms.f[instr.common.src1-0x20].x | 70 | : (instr.common.src1 < 0x80) ? &shader_uniforms.f[instr.common.src1.GetIndex()].x |
| 71 | : nullptr; | ||
| 72 | const float24* src2_ = (instr.common.src2 < 0x10) ? state.input_register_table[instr.common.src2] | ||
| 73 | : &state.temporary_registers[instr.common.src2-0x10].x; | ||
| 74 | // TODO: Unsure about the limit values | ||
| 75 | float24* dest = (instr.common.dest <= 0x1C) ? state.output_register_table[instr.common.dest] | ||
| 76 | : (instr.common.dest <= 0x3C) ? nullptr | ||
| 77 | : (instr.common.dest <= 0x7C) ? &state.temporary_registers[(instr.common.dest-0x40)/4][instr.common.dest%4] | ||
| 78 | : nullptr; | 71 | : nullptr; |
| 72 | const float24* src2_ = (instr.common.src2 < 0x10) ? state.input_register_table[instr.common.src2.GetIndex()] | ||
| 73 | : &state.temporary_registers[instr.common.src2.GetIndex()].x; | ||
| 74 | float24* dest = (instr.common.dest < 0x08) ? state.output_register_table[4*instr.common.dest.GetIndex()] | ||
| 75 | : (instr.common.dest < 0x10) ? nullptr | ||
| 76 | : (instr.common.dest < 0x20) ? &state.temporary_registers[instr.common.dest.GetIndex()][0] | ||
| 77 | : nullptr; | ||
| 79 | 78 | ||
| 80 | const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.common.operand_desc_id]; | 79 | const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.common.operand_desc_id]; |
| 80 | const bool negate_src1 = swizzle.negate; | ||
| 81 | 81 | ||
| 82 | const float24 src1[4] = { | 82 | float24 src1[4] = { |
| 83 | src1_[(int)swizzle.GetSelectorSrc1(0)], | 83 | src1_[(int)swizzle.GetSelectorSrc1(0)], |
| 84 | src1_[(int)swizzle.GetSelectorSrc1(1)], | 84 | src1_[(int)swizzle.GetSelectorSrc1(1)], |
| 85 | src1_[(int)swizzle.GetSelectorSrc1(2)], | 85 | src1_[(int)swizzle.GetSelectorSrc1(2)], |
| 86 | src1_[(int)swizzle.GetSelectorSrc1(3)], | 86 | src1_[(int)swizzle.GetSelectorSrc1(3)], |
| 87 | }; | 87 | }; |
| 88 | if (negate_src1) { | ||
| 89 | src1[0] = src1[0] * float24::FromFloat32(-1); | ||
| 90 | src1[1] = src1[1] * float24::FromFloat32(-1); | ||
| 91 | src1[2] = src1[2] * float24::FromFloat32(-1); | ||
| 92 | src1[3] = src1[3] * float24::FromFloat32(-1); | ||
| 93 | } | ||
| 88 | const float24 src2[4] = { | 94 | const float24 src2[4] = { |
| 89 | src2_[(int)swizzle.GetSelectorSrc2(0)], | 95 | src2_[(int)swizzle.GetSelectorSrc2(0)], |
| 90 | src2_[(int)swizzle.GetSelectorSrc2(1)], | 96 | src2_[(int)swizzle.GetSelectorSrc2(1)], |
diff --git a/src/video_core/vertex_shader.h b/src/video_core/vertex_shader.h index 1b71e367b..f0a8a5b60 100644 --- a/src/video_core/vertex_shader.h +++ b/src/video_core/vertex_shader.h | |||
| @@ -117,9 +117,78 @@ union Instruction { | |||
| 117 | // while "dest" addresses individual floats. | 117 | // while "dest" addresses individual floats. |
| 118 | union { | 118 | union { |
| 119 | BitField<0x00, 0x5, u32> operand_desc_id; | 119 | BitField<0x00, 0x5, u32> operand_desc_id; |
| 120 | BitField<0x07, 0x5, u32> src2; | 120 | |
| 121 | BitField<0x0c, 0x7, u32> src1; | 121 | template<class BitFieldType> |
| 122 | BitField<0x13, 0x7, u32> dest; | 122 | struct SourceRegister : BitFieldType { |
| 123 | enum RegisterType { | ||
| 124 | Input, | ||
| 125 | Temporary, | ||
| 126 | FloatUniform | ||
| 127 | }; | ||
| 128 | |||
| 129 | RegisterType GetRegisterType() const { | ||
| 130 | if (BitFieldType::Value() < 0x10) | ||
| 131 | return Input; | ||
| 132 | else if (BitFieldType::Value() < 0x20) | ||
| 133 | return Temporary; | ||
| 134 | else | ||
| 135 | return FloatUniform; | ||
| 136 | } | ||
| 137 | |||
| 138 | int GetIndex() const { | ||
| 139 | if (GetRegisterType() == Input) | ||
| 140 | return BitFieldType::Value(); | ||
| 141 | else if (GetRegisterType() == Temporary) | ||
| 142 | return BitFieldType::Value() - 0x10; | ||
| 143 | else if (GetRegisterType() == FloatUniform) | ||
| 144 | return BitFieldType::Value() - 0x20; | ||
| 145 | } | ||
| 146 | |||
| 147 | std::string GetRegisterName() const { | ||
| 148 | std::map<RegisterType, std::string> type = { | ||
| 149 | { Input, "i" }, | ||
| 150 | { Temporary, "t" }, | ||
| 151 | { FloatUniform, "f" }, | ||
| 152 | }; | ||
| 153 | return type[GetRegisterType()] + std::to_string(GetIndex()); | ||
| 154 | } | ||
| 155 | }; | ||
| 156 | |||
| 157 | SourceRegister<BitField<0x07, 0x5, u32>> src2; | ||
| 158 | SourceRegister<BitField<0x0c, 0x7, u32>> src1; | ||
| 159 | |||
| 160 | struct : BitField<0x15, 0x5, u32> | ||
| 161 | { | ||
| 162 | enum RegisterType { | ||
| 163 | Output, | ||
| 164 | Temporary, | ||
| 165 | Unknown | ||
| 166 | }; | ||
| 167 | RegisterType GetRegisterType() const { | ||
| 168 | if (Value() < 0x8) | ||
| 169 | return Output; | ||
| 170 | else if (Value() < 0x10) | ||
| 171 | return Unknown; | ||
| 172 | else | ||
| 173 | return Temporary; | ||
| 174 | } | ||
| 175 | int GetIndex() const { | ||
| 176 | if (GetRegisterType() == Output) | ||
| 177 | return Value(); | ||
| 178 | else if (GetRegisterType() == Temporary) | ||
| 179 | return Value() - 0x10; | ||
| 180 | else | ||
| 181 | return Value(); | ||
| 182 | } | ||
| 183 | std::string GetRegisterName() const { | ||
| 184 | std::map<RegisterType, std::string> type = { | ||
| 185 | { Output, "o" }, | ||
| 186 | { Temporary, "t" }, | ||
| 187 | { Unknown, "u" } | ||
| 188 | }; | ||
| 189 | return type[GetRegisterType()] + std::to_string(GetIndex()); | ||
| 190 | } | ||
| 191 | } dest; | ||
| 123 | } common; | 192 | } common; |
| 124 | 193 | ||
| 125 | // Format used for flow control instructions ("if") | 194 | // Format used for flow control instructions ("if") |
| @@ -128,6 +197,7 @@ union Instruction { | |||
| 128 | BitField<0x0a, 0xc, u32> offset_words; | 197 | BitField<0x0a, 0xc, u32> offset_words; |
| 129 | } flow_control; | 198 | } flow_control; |
| 130 | }; | 199 | }; |
| 200 | static_assert(std::is_standard_layout<Instruction>::value, "Structure is not using standard layout!"); | ||
| 131 | 201 | ||
| 132 | union SwizzlePattern { | 202 | union SwizzlePattern { |
| 133 | u32 hex; | 203 | u32 hex; |
| @@ -185,6 +255,8 @@ union SwizzlePattern { | |||
| 185 | // Components of "dest" that should be written to: LSB=dest.w, MSB=dest.x | 255 | // Components of "dest" that should be written to: LSB=dest.w, MSB=dest.x |
| 186 | BitField< 0, 4, u32> dest_mask; | 256 | BitField< 0, 4, u32> dest_mask; |
| 187 | 257 | ||
| 258 | BitField< 4, 1, u32> negate; // negates src1 | ||
| 259 | |||
| 188 | BitField< 5, 2, Selector> src1_selector_3; | 260 | BitField< 5, 2, Selector> src1_selector_3; |
| 189 | BitField< 7, 2, Selector> src1_selector_2; | 261 | BitField< 7, 2, Selector> src1_selector_2; |
| 190 | BitField< 9, 2, Selector> src1_selector_1; | 262 | BitField< 9, 2, Selector> src1_selector_1; |