diff options
| author | 2018-06-15 19:40:34 -0400 | |
|---|---|---|
| committer | 2018-06-15 22:42:02 -0400 | |
| commit | d383043e07e35d374923bc1141344a8881ccc835 (patch) | |
| tree | 80453053e09dcf4f35d9e6048ca7c1a33a113f37 /src | |
| parent | Merge pull request #564 from bunnei/lop32i_passb (diff) | |
| download | yuzu-d383043e07e35d374923bc1141344a8881ccc835.tar.gz yuzu-d383043e07e35d374923bc1141344a8881ccc835.tar.xz yuzu-d383043e07e35d374923bc1141344a8881ccc835.zip | |
gl_shader_decompiler: Implement integer size conversions for I2I/I2F/F2I.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 54 |
2 files changed, 43 insertions, 14 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 29d88192e..ceef8087c 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -343,7 +343,8 @@ union Instruction { | |||
| 343 | } iset; | 343 | } iset; |
| 344 | 344 | ||
| 345 | union { | 345 | union { |
| 346 | BitField<10, 2, Register::Size> size; | 346 | BitField<8, 2, Register::Size> dest_size; |
| 347 | BitField<10, 2, Register::Size> src_size; | ||
| 347 | BitField<12, 1, u64> is_output_signed; | 348 | BitField<12, 1, u64> is_output_signed; |
| 348 | BitField<13, 1, u64> is_input_signed; | 349 | BitField<13, 1, u64> is_input_signed; |
| 349 | BitField<41, 2, u64> selector; | 350 | BitField<41, 2, u64> selector; |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 9093eca32..af68c3bda 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -266,6 +266,27 @@ public: | |||
| 266 | } | 266 | } |
| 267 | 267 | ||
| 268 | /** | 268 | /** |
| 269 | * Returns code that does an integer size conversion for the specified size. | ||
| 270 | * @param value Value to perform integer size conversion on. | ||
| 271 | * @param size Register size to use for conversion instructions. | ||
| 272 | * @returns GLSL string corresponding to the value converted to the specified size. | ||
| 273 | */ | ||
| 274 | static std::string ConvertIntegerSize(const std::string& value, Register::Size size) { | ||
| 275 | switch (size) { | ||
| 276 | case Register::Size::Byte: | ||
| 277 | return "((" + value + " << 24) >> 24)"; | ||
| 278 | case Register::Size::Short: | ||
| 279 | return "((" + value + " << 16) >> 16)"; | ||
| 280 | case Register::Size::Word: | ||
| 281 | // Default - do nothing | ||
| 282 | return value; | ||
| 283 | default: | ||
| 284 | NGLOG_CRITICAL(HW_GPU, "Unimplemented conversion size {}", static_cast<u32>(size)); | ||
| 285 | UNREACHABLE(); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | /** | ||
| 269 | * Gets a register as an float. | 290 | * Gets a register as an float. |
| 270 | * @param reg The register to get. | 291 | * @param reg The register to get. |
| 271 | * @param elem The element to use for the operation. | 292 | * @param elem The element to use for the operation. |
| @@ -281,15 +302,18 @@ public: | |||
| 281 | * @param reg The register to get. | 302 | * @param reg The register to get. |
| 282 | * @param elem The element to use for the operation. | 303 | * @param elem The element to use for the operation. |
| 283 | * @param is_signed Whether to get the register as a signed (or unsigned) integer. | 304 | * @param is_signed Whether to get the register as a signed (or unsigned) integer. |
| 305 | * @param size Register size to use for conversion instructions. | ||
| 284 | * @returns GLSL string corresponding to the register as an integer. | 306 | * @returns GLSL string corresponding to the register as an integer. |
| 285 | */ | 307 | */ |
| 286 | std::string GetRegisterAsInteger(const Register& reg, unsigned elem = 0, | 308 | std::string GetRegisterAsInteger(const Register& reg, unsigned elem = 0, bool is_signed = true, |
| 287 | bool is_signed = true) { | 309 | Register::Size size = Register::Size::Word) { |
| 288 | const std::string func = GetGLSLConversionFunc( | 310 | const std::string func = GetGLSLConversionFunc( |
| 289 | GLSLRegister::Type::Float, | 311 | GLSLRegister::Type::Float, |
| 290 | is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger); | 312 | is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger); |
| 291 | 313 | ||
| 292 | return func + '(' + GetRegister(reg, elem) + ')'; | 314 | std::string value = func + '(' + GetRegister(reg, elem) + ')'; |
| 315 | |||
| 316 | return ConvertIntegerSize(value, size); | ||
| 293 | } | 317 | } |
| 294 | 318 | ||
| 295 | /** | 319 | /** |
| @@ -319,19 +343,20 @@ public: | |||
| 319 | * @param value_num_components Number of components in the value. | 343 | * @param value_num_components Number of components in the value. |
| 320 | * @param is_saturated Optional, when True, saturates the provided value. | 344 | * @param is_saturated Optional, when True, saturates the provided value. |
| 321 | * @param dest_elem Optional, the destination element to use for the operation. | 345 | * @param dest_elem Optional, the destination element to use for the operation. |
| 346 | * @param size Register size to use for conversion instructions. | ||
| 322 | */ | 347 | */ |
| 323 | void SetRegisterToInteger(const Register& reg, bool is_signed, u64 elem, | 348 | void SetRegisterToInteger(const Register& reg, bool is_signed, u64 elem, |
| 324 | const std::string& value, u64 dest_num_components, | 349 | const std::string& value, u64 dest_num_components, |
| 325 | u64 value_num_components, bool is_saturated = false, | 350 | u64 value_num_components, bool is_saturated = false, |
| 326 | u64 dest_elem = 0) { | 351 | u64 dest_elem = 0, Register::Size size = Register::Size::Word) { |
| 327 | ASSERT_MSG(!is_saturated, "Unimplemented"); | 352 | ASSERT_MSG(!is_saturated, "Unimplemented"); |
| 328 | 353 | ||
| 329 | const std::string func = GetGLSLConversionFunc( | 354 | const std::string func = GetGLSLConversionFunc( |
| 330 | is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger, | 355 | is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger, |
| 331 | GLSLRegister::Type::Float); | 356 | GLSLRegister::Type::Float); |
| 332 | 357 | ||
| 333 | SetRegister(reg, elem, func + '(' + value + ')', dest_num_components, value_num_components, | 358 | SetRegister(reg, elem, func + '(' + ConvertIntegerSize(value, size) + ')', |
| 334 | dest_elem); | 359 | dest_num_components, value_num_components, dest_elem); |
| 335 | } | 360 | } |
| 336 | 361 | ||
| 337 | /** | 362 | /** |
| @@ -1114,28 +1139,28 @@ private: | |||
| 1114 | break; | 1139 | break; |
| 1115 | } | 1140 | } |
| 1116 | case OpCode::Type::Conversion: { | 1141 | case OpCode::Type::Conversion: { |
| 1117 | ASSERT_MSG(instr.conversion.size == Register::Size::Word, "Unimplemented"); | ||
| 1118 | ASSERT_MSG(!instr.conversion.negate_a, "Unimplemented"); | 1142 | ASSERT_MSG(!instr.conversion.negate_a, "Unimplemented"); |
| 1119 | 1143 | ||
| 1120 | switch (opcode->GetId()) { | 1144 | switch (opcode->GetId()) { |
| 1121 | case OpCode::Id::I2I_R: { | 1145 | case OpCode::Id::I2I_R: { |
| 1122 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | 1146 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); |
| 1123 | 1147 | ||
| 1124 | std::string op_a = | 1148 | std::string op_a = regs.GetRegisterAsInteger( |
| 1125 | regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed); | 1149 | instr.gpr20, 0, instr.conversion.is_input_signed, instr.conversion.src_size); |
| 1126 | 1150 | ||
| 1127 | if (instr.conversion.abs_a) { | 1151 | if (instr.conversion.abs_a) { |
| 1128 | op_a = "abs(" + op_a + ')'; | 1152 | op_a = "abs(" + op_a + ')'; |
| 1129 | } | 1153 | } |
| 1130 | 1154 | ||
| 1131 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, | 1155 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, |
| 1132 | 1, instr.alu.saturate_d); | 1156 | 1, instr.alu.saturate_d, 0, instr.conversion.dest_size); |
| 1133 | break; | 1157 | break; |
| 1134 | } | 1158 | } |
| 1135 | case OpCode::Id::I2F_R: { | 1159 | case OpCode::Id::I2F_R: { |
| 1160 | ASSERT_MSG(instr.conversion.dest_size == Register::Size::Word, "Unimplemented"); | ||
| 1136 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | 1161 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); |
| 1137 | std::string op_a = | 1162 | std::string op_a = regs.GetRegisterAsInteger( |
| 1138 | regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed); | 1163 | instr.gpr20, 0, instr.conversion.is_input_signed, instr.conversion.src_size); |
| 1139 | 1164 | ||
| 1140 | if (instr.conversion.abs_a) { | 1165 | if (instr.conversion.abs_a) { |
| 1141 | op_a = "abs(" + op_a + ')'; | 1166 | op_a = "abs(" + op_a + ')'; |
| @@ -1145,6 +1170,8 @@ private: | |||
| 1145 | break; | 1170 | break; |
| 1146 | } | 1171 | } |
| 1147 | case OpCode::Id::F2F_R: { | 1172 | case OpCode::Id::F2F_R: { |
| 1173 | ASSERT_MSG(instr.conversion.dest_size == Register::Size::Word, "Unimplemented"); | ||
| 1174 | ASSERT_MSG(instr.conversion.src_size == Register::Size::Word, "Unimplemented"); | ||
| 1148 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | 1175 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); |
| 1149 | 1176 | ||
| 1150 | switch (instr.conversion.f2f.rounding) { | 1177 | switch (instr.conversion.f2f.rounding) { |
| @@ -1174,6 +1201,7 @@ private: | |||
| 1174 | break; | 1201 | break; |
| 1175 | } | 1202 | } |
| 1176 | case OpCode::Id::F2I_R: { | 1203 | case OpCode::Id::F2I_R: { |
| 1204 | ASSERT_MSG(instr.conversion.src_size == Register::Size::Word, "Unimplemented"); | ||
| 1177 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | 1205 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); |
| 1178 | 1206 | ||
| 1179 | if (instr.conversion.abs_a) { | 1207 | if (instr.conversion.abs_a) { |
| @@ -1206,7 +1234,7 @@ private: | |||
| 1206 | } | 1234 | } |
| 1207 | 1235 | ||
| 1208 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, | 1236 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, |
| 1209 | 1); | 1237 | 1, false, 0, instr.conversion.dest_size); |
| 1210 | break; | 1238 | break; |
| 1211 | } | 1239 | } |
| 1212 | default: { | 1240 | default: { |