diff options
| author | 2018-04-29 12:56:16 -0400 | |
|---|---|---|
| committer | 2018-04-29 12:56:16 -0400 | |
| commit | 6c464a2a4a50ec531cd2c5c20fa03f1579eced88 (patch) | |
| tree | 49eb4e1010af58ab7c14fe906aba1b0bcf842bfe /src | |
| parent | Merge pull request #417 from bunnei/lang-codes (diff) | |
| parent | gl_shader_decompiler: Partially implement I2I_R, and I2F_R. (diff) | |
| download | yuzu-6c464a2a4a50ec531cd2c5c20fa03f1579eced88.tar.gz yuzu-6c464a2a4a50ec531cd2c5c20fa03f1579eced88.tar.xz yuzu-6c464a2a4a50ec531cd2c5c20fa03f1579eced88.zip | |
Merge pull request #416 from bunnei/shader-ints-p3
gl_shader_decompiler: Implement MOV32I, partially implement I2I, I2F
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 33 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 287 |
2 files changed, 206 insertions, 114 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index f3ca30cfa..f20c2cd41 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -25,6 +25,13 @@ struct Register { | |||
| 25 | /// Register 255 is special cased to always be 0 | 25 | /// Register 255 is special cased to always be 0 |
| 26 | static constexpr size_t ZeroIndex = 255; | 26 | static constexpr size_t ZeroIndex = 255; |
| 27 | 27 | ||
| 28 | enum class Size : u64 { | ||
| 29 | Byte = 0, | ||
| 30 | Short = 1, | ||
| 31 | Word = 2, | ||
| 32 | Long = 3, | ||
| 33 | }; | ||
| 34 | |||
| 28 | constexpr Register() = default; | 35 | constexpr Register() = default; |
| 29 | 36 | ||
| 30 | constexpr Register(u64 value) : value(value) {} | 37 | constexpr Register(u64 value) : value(value) {} |
| @@ -236,6 +243,15 @@ union Instruction { | |||
| 236 | BitField<56, 1, u64> neg_imm; | 243 | BitField<56, 1, u64> neg_imm; |
| 237 | } fset; | 244 | } fset; |
| 238 | 245 | ||
| 246 | union { | ||
| 247 | BitField<10, 2, Register::Size> size; | ||
| 248 | BitField<13, 1, u64> is_signed; | ||
| 249 | BitField<41, 2, u64> selector; | ||
| 250 | BitField<45, 1, u64> negate_a; | ||
| 251 | BitField<49, 1, u64> abs_a; | ||
| 252 | BitField<50, 1, u64> saturate_a; | ||
| 253 | } conversion; | ||
| 254 | |||
| 239 | BitField<61, 1, u64> is_b_imm; | 255 | BitField<61, 1, u64> is_b_imm; |
| 240 | BitField<60, 1, u64> is_b_gpr; | 256 | BitField<60, 1, u64> is_b_gpr; |
| 241 | BitField<59, 1, u64> is_c_gpr; | 257 | BitField<59, 1, u64> is_c_gpr; |
| @@ -290,7 +306,7 @@ public: | |||
| 290 | MOV_C, | 306 | MOV_C, |
| 291 | MOV_R, | 307 | MOV_R, |
| 292 | MOV_IMM, | 308 | MOV_IMM, |
| 293 | MOV32I, | 309 | MOV32_IMM, |
| 294 | SHR_C, | 310 | SHR_C, |
| 295 | SHR_R, | 311 | SHR_R, |
| 296 | SHR_IMM, | 312 | SHR_IMM, |
| @@ -314,6 +330,7 @@ public: | |||
| 314 | FloatSet, | 330 | FloatSet, |
| 315 | FloatSetPredicate, | 331 | FloatSetPredicate, |
| 316 | IntegerSetPredicate, | 332 | IntegerSetPredicate, |
| 333 | Conversion, | ||
| 317 | Unknown, | 334 | Unknown, |
| 318 | }; | 335 | }; |
| 319 | 336 | ||
| @@ -435,20 +452,20 @@ private: | |||
| 435 | INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), | 452 | INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), |
| 436 | INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), | 453 | INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), |
| 437 | INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), | 454 | INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), |
| 438 | INST("0100110010111---", Id::I2F_C, Type::Arithmetic, "I2F_C"), | ||
| 439 | INST("0101110010111---", Id::I2F_R, Type::Arithmetic, "I2F_R"), | ||
| 440 | INST("0011100-10111---", Id::I2F_IMM, Type::Arithmetic, "I2F_IMM"), | ||
| 441 | INST("0100110011100---", Id::I2I_C, Type::Arithmetic, "I2I_C"), | ||
| 442 | INST("0101110011100---", Id::I2I_R, Type::Arithmetic, "I2I_R"), | ||
| 443 | INST("01110001-1000---", Id::I2I_IMM, Type::Arithmetic, "I2I_IMM"), | ||
| 444 | INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"), | 455 | INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"), |
| 445 | INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), | 456 | INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), |
| 446 | INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), | 457 | INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), |
| 447 | INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), | 458 | INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), |
| 448 | INST("000000010000----", Id::MOV32I, Type::Arithmetic, "MOV32I"), | 459 | INST("000000010000----", Id::MOV32_IMM, Type::Arithmetic, "MOV32_IMM"), |
| 449 | INST("0100110000101---", Id::SHR_C, Type::Arithmetic, "SHR_C"), | 460 | INST("0100110000101---", Id::SHR_C, Type::Arithmetic, "SHR_C"), |
| 450 | INST("0101110000101---", Id::SHR_R, Type::Arithmetic, "SHR_R"), | 461 | INST("0101110000101---", Id::SHR_R, Type::Arithmetic, "SHR_R"), |
| 451 | INST("0011100-00101---", Id::SHR_IMM, Type::Arithmetic, "SHR_IMM"), | 462 | INST("0011100-00101---", Id::SHR_IMM, Type::Arithmetic, "SHR_IMM"), |
| 463 | INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), | ||
| 464 | INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), | ||
| 465 | INST("01110001-1000---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), | ||
| 466 | INST("0100110010111---", Id::I2F_C, Type::Conversion, "I2F_C"), | ||
| 467 | INST("0101110010111---", Id::I2F_R, Type::Conversion, "I2F_R"), | ||
| 468 | INST("0011100-10111---", Id::I2F_IMM, Type::Conversion, "I2F_IMM"), | ||
| 452 | INST("01011000--------", Id::FSET_R, Type::FloatSet, "FSET_R"), | 469 | INST("01011000--------", Id::FSET_R, Type::FloatSet, "FSET_R"), |
| 453 | INST("0100100---------", Id::FSET_C, Type::FloatSet, "FSET_C"), | 470 | INST("0100100---------", Id::FSET_C, Type::FloatSet, "FSET_C"), |
| 454 | INST("0011000---------", Id::FSET_IMM, Type::FloatSet, "FSET_IMM"), | 471 | INST("0011000---------", Id::FSET_IMM, Type::FloatSet, "FSET_IMM"), |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 8b235e252..27190cc45 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -153,85 +153,61 @@ private: | |||
| 153 | */ | 153 | */ |
| 154 | class GLSLRegister { | 154 | class GLSLRegister { |
| 155 | public: | 155 | public: |
| 156 | GLSLRegister(size_t index, ShaderWriter& shader) | 156 | enum class Type { |
| 157 | : index{index}, shader{shader}, float_str{"freg_" + std::to_string(index)}, | 157 | Float, |
| 158 | integer_str{"ireg_" + std::to_string(index)} {} | 158 | Integer, |
| 159 | UnsignedInteger, | ||
| 160 | }; | ||
| 159 | 161 | ||
| 160 | /// Returns a GLSL string representing the current state of the register | 162 | GLSLRegister(size_t index, ShaderWriter& shader) : index{index}, shader{shader} {} |
| 161 | const std::string& GetActiveString() { | ||
| 162 | declr_type.insert(active_type); | ||
| 163 | 163 | ||
| 164 | switch (active_type) { | 164 | /// Gets the GLSL type string for a register |
| 165 | static std::string GetTypeString(Type type) { | ||
| 166 | switch (type) { | ||
| 165 | case Type::Float: | 167 | case Type::Float: |
| 166 | return float_str; | 168 | return "float"; |
| 167 | case Type::Integer: | 169 | case Type::Integer: |
| 168 | return integer_str; | 170 | return "int"; |
| 171 | case Type::UnsignedInteger: | ||
| 172 | return "uint"; | ||
| 169 | } | 173 | } |
| 170 | 174 | ||
| 171 | UNREACHABLE(); | 175 | UNREACHABLE(); |
| 172 | return float_str; | 176 | return {}; |
| 173 | } | ||
| 174 | |||
| 175 | /// Returns a GLSL string representing the register as a float | ||
| 176 | const std::string& GetFloatString() const { | ||
| 177 | ASSERT(IsFloatUsed()); | ||
| 178 | return float_str; | ||
| 179 | } | ||
| 180 | |||
| 181 | /// Returns a GLSL string representing the register as an integer | ||
| 182 | const std::string& GetIntegerString() const { | ||
| 183 | ASSERT(IsIntegerUsed()); | ||
| 184 | return integer_str; | ||
| 185 | } | ||
| 186 | |||
| 187 | /// Convert the current register state from float to integer | ||
| 188 | void FloatToInteger() { | ||
| 189 | ASSERT(active_type == Type::Float); | ||
| 190 | |||
| 191 | const std::string src = GetActiveString(); | ||
| 192 | active_type = Type::Integer; | ||
| 193 | const std::string dest = GetActiveString(); | ||
| 194 | |||
| 195 | shader.AddLine(dest + " = floatBitsToInt(" + src + ");"); | ||
| 196 | } | ||
| 197 | |||
| 198 | /// Convert the current register state from integer to float | ||
| 199 | void IntegerToFloat() { | ||
| 200 | ASSERT(active_type == Type::Integer); | ||
| 201 | |||
| 202 | const std::string src = GetActiveString(); | ||
| 203 | active_type = Type::Float; | ||
| 204 | const std::string dest = GetActiveString(); | ||
| 205 | |||
| 206 | shader.AddLine(dest + " = intBitsToFloat(" + src + ");"); | ||
| 207 | } | 177 | } |
| 208 | 178 | ||
| 209 | /// Returns true if the register was ever used as a float, used for register declarations | 179 | /// Gets the GLSL register prefix string, used for declarations and referencing |
| 210 | bool IsFloatUsed() const { | 180 | static std::string GetPrefixString(Type type) { |
| 211 | return declr_type.find(Type::Float) != declr_type.end(); | 181 | return "reg_" + GetTypeString(type) + '_'; |
| 212 | } | 182 | } |
| 213 | 183 | ||
| 214 | /// Returns true if the register was ever used as an integer, used for register declarations | 184 | /// Returns a GLSL string representing the current state of the register |
| 215 | bool IsIntegerUsed() const { | 185 | const std::string GetActiveString() { |
| 216 | return declr_type.find(Type::Integer) != declr_type.end(); | 186 | declr_type.insert(active_type); |
| 187 | return GetPrefixString(active_type) + std::to_string(index); | ||
| 217 | } | 188 | } |
| 218 | 189 | ||
| 219 | /// Returns true if the active type is float | 190 | /// Returns true if the active type is a float |
| 220 | bool IsFloat() const { | 191 | bool IsFloat() const { |
| 221 | return active_type == Type::Float; | 192 | return active_type == Type::Float; |
| 222 | } | 193 | } |
| 223 | 194 | ||
| 224 | /// Returns true if the active type is integer | 195 | /// Returns true if the active type is an integer |
| 225 | bool IsInteger() const { | 196 | bool IsInteger() const { |
| 226 | return active_type == Type::Integer; | 197 | return active_type == Type::Integer; |
| 227 | } | 198 | } |
| 228 | 199 | ||
| 229 | private: | 200 | /// Returns the index of the register |
| 230 | enum class Type { | 201 | size_t GetIndex() const { |
| 231 | Float, | 202 | return index; |
| 232 | Integer, | 203 | } |
| 233 | }; | ||
| 234 | 204 | ||
| 205 | /// Returns a set of the declared types of the register | ||
| 206 | const std::set<Type>& DeclaredTypes() const { | ||
| 207 | return declr_type; | ||
| 208 | } | ||
| 209 | |||
| 210 | private: | ||
| 235 | const size_t index; | 211 | const size_t index; |
| 236 | const std::string float_str; | 212 | const std::string float_str; |
| 237 | const std::string integer_str; | 213 | const std::string integer_str; |
| @@ -254,18 +230,35 @@ public: | |||
| 254 | BuildRegisterList(); | 230 | BuildRegisterList(); |
| 255 | } | 231 | } |
| 256 | 232 | ||
| 257 | /// Generates code representing a temporary (GPR) register. | 233 | /** |
| 258 | std::string GetRegister(const Register& reg, unsigned elem = 0) { | 234 | * Gets a register as an float. |
| 259 | if (reg == Register::ZeroIndex) { | 235 | * @param reg The register to get. |
| 260 | return "0"; | 236 | * @param elem The element to use for the operation. |
| 261 | } | 237 | * @returns GLSL string corresponding to the register as a float. |
| 238 | */ | ||
| 239 | std::string GetRegisterAsFloat(const Register& reg, unsigned elem = 0) { | ||
| 240 | ASSERT(regs[reg].IsFloat()); | ||
| 241 | return GetRegister(reg, elem); | ||
| 242 | } | ||
| 262 | 243 | ||
| 263 | return regs[reg.GetSwizzledIndex(elem)].GetActiveString(); | 244 | /** |
| 245 | * Gets a register as an integer. | ||
| 246 | * @param reg The register to get. | ||
| 247 | * @param elem The element to use for the operation. | ||
| 248 | * @param is_signed Whether to get the register as a signed (or unsigned) integer. | ||
| 249 | * @returns GLSL string corresponding to the register as an integer. | ||
| 250 | */ | ||
| 251 | std::string GetRegisterAsInteger(const Register& reg, unsigned elem = 0, | ||
| 252 | bool is_signed = true) { | ||
| 253 | const std::string func = GetGLSLConversionFunc( | ||
| 254 | GLSLRegister::Type::Float, | ||
| 255 | is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger); | ||
| 256 | |||
| 257 | return func + '(' + GetRegister(reg, elem) + ')'; | ||
| 264 | } | 258 | } |
| 265 | 259 | ||
| 266 | /** | 260 | /** |
| 267 | * Writes code that does a register assignment to float value operation. Should only be used | 261 | * Writes code that does a register assignment to float value operation. |
| 268 | * with shader instructions that deal with floats. | ||
| 269 | * @param reg The destination register to use. | 262 | * @param reg The destination register to use. |
| 270 | * @param elem The element to use for the operation. | 263 | * @param elem The element to use for the operation. |
| 271 | * @param value The code representing the value to assign. | 264 | * @param value The code representing the value to assign. |
| @@ -277,21 +270,28 @@ public: | |||
| 277 | void SetRegisterToFloat(const Register& reg, u64 elem, const std::string& value, | 270 | void SetRegisterToFloat(const Register& reg, u64 elem, const std::string& value, |
| 278 | u64 dest_num_components, u64 value_num_components, bool is_abs = false, | 271 | u64 dest_num_components, u64 value_num_components, bool is_abs = false, |
| 279 | u64 dest_elem = 0) { | 272 | u64 dest_elem = 0) { |
| 280 | ASSERT(regs[reg].IsFloat()); | 273 | SetRegister(reg, elem, value, dest_num_components, value_num_components, is_abs, dest_elem); |
| 281 | 274 | } | |
| 282 | std::string dest = GetRegister(reg, dest_elem); | ||
| 283 | if (dest_num_components > 1) { | ||
| 284 | dest += GetSwizzle(elem); | ||
| 285 | } | ||
| 286 | |||
| 287 | std::string src = '(' + value + ')'; | ||
| 288 | if (value_num_components > 1) { | ||
| 289 | src += GetSwizzle(elem); | ||
| 290 | } | ||
| 291 | |||
| 292 | src = is_abs ? "abs(" + src + ')' : src; | ||
| 293 | 275 | ||
| 294 | shader.AddLine(dest + " = " + src + ';'); | 276 | /** |
| 277 | * Writes code that does a register assignment to integer value operation. | ||
| 278 | * @param reg The destination register to use. | ||
| 279 | * @param elem The element to use for the operation. | ||
| 280 | * @param value The code representing the value to assign. | ||
| 281 | * @param dest_num_components Number of components in the destination. | ||
| 282 | * @param value_num_components Number of components in the value. | ||
| 283 | * @param is_abs Optional, when True, applies absolute value to output. | ||
| 284 | * @param dest_elem Optional, the destination element to use for the operation. | ||
| 285 | */ | ||
| 286 | void SetRegisterToInteger(const Register& reg, bool is_signed, u64 elem, | ||
| 287 | const std::string& value, u64 dest_num_components, | ||
| 288 | u64 value_num_components, bool is_abs = false, u64 dest_elem = 0) { | ||
| 289 | const std::string func = GetGLSLConversionFunc( | ||
| 290 | is_signed ? GLSLRegister::Type::Integer : GLSLRegister::Type::UnsignedInteger, | ||
| 291 | GLSLRegister::Type::Float); | ||
| 292 | |||
| 293 | SetRegister(reg, elem, func + '(' + value + ')', dest_num_components, value_num_components, | ||
| 294 | is_abs, dest_elem); | ||
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | /** | 297 | /** |
| @@ -302,7 +302,7 @@ public: | |||
| 302 | * @param attribute The input attibute to use as the source value. | 302 | * @param attribute The input attibute to use as the source value. |
| 303 | */ | 303 | */ |
| 304 | void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute) { | 304 | void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute) { |
| 305 | std::string dest = GetRegister(reg); | 305 | std::string dest = GetRegisterAsFloat(reg); |
| 306 | std::string src = GetInputAttribute(attribute) + GetSwizzle(elem); | 306 | std::string src = GetInputAttribute(attribute) + GetSwizzle(elem); |
| 307 | 307 | ||
| 308 | if (regs[reg].IsFloat()) { | 308 | if (regs[reg].IsFloat()) { |
| @@ -323,7 +323,7 @@ public: | |||
| 323 | */ | 323 | */ |
| 324 | void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) { | 324 | void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) { |
| 325 | std::string dest = GetOutputAttribute(attribute) + GetSwizzle(elem); | 325 | std::string dest = GetOutputAttribute(attribute) + GetSwizzle(elem); |
| 326 | std::string src = GetRegister(reg); | 326 | std::string src = GetRegisterAsFloat(reg); |
| 327 | ASSERT_MSG(regs[reg].IsFloat(), "Output attributes must be set to a float"); | 327 | ASSERT_MSG(regs[reg].IsFloat(), "Output attributes must be set to a float"); |
| 328 | shader.AddLine(dest + " = " + src + ';'); | 328 | shader.AddLine(dest + " = " + src + ';'); |
| 329 | } | 329 | } |
| @@ -347,11 +347,10 @@ public: | |||
| 347 | /// Add declarations for registers | 347 | /// Add declarations for registers |
| 348 | void GenerateDeclarations() { | 348 | void GenerateDeclarations() { |
| 349 | for (const auto& reg : regs) { | 349 | for (const auto& reg : regs) { |
| 350 | if (reg.IsFloatUsed()) { | 350 | for (const auto& type : reg.DeclaredTypes()) { |
| 351 | declarations.AddLine("float " + reg.GetFloatString() + " = 0.0;"); | 351 | declarations.AddLine(GLSLRegister::GetTypeString(type) + ' ' + |
| 352 | } | 352 | GLSLRegister::GetPrefixString(type) + |
| 353 | if (reg.IsIntegerUsed()) { | 353 | std::to_string(reg.GetIndex()) + " = 0;"); |
| 354 | declarations.AddLine("int " + reg.GetIntegerString() + " = 0;"); | ||
| 355 | } | 354 | } |
| 356 | } | 355 | } |
| 357 | declarations.AddNewLine(); | 356 | declarations.AddNewLine(); |
| @@ -395,6 +394,51 @@ public: | |||
| 395 | } | 394 | } |
| 396 | 395 | ||
| 397 | private: | 396 | private: |
| 397 | /// Build GLSL conversion function, e.g. floatBitsToInt, intBitsToFloat, etc. | ||
| 398 | const std::string GetGLSLConversionFunc(GLSLRegister::Type src, GLSLRegister::Type dest) const { | ||
| 399 | const std::string src_type = GLSLRegister::GetTypeString(src); | ||
| 400 | std::string dest_type = GLSLRegister::GetTypeString(dest); | ||
| 401 | dest_type[0] = toupper(dest_type[0]); | ||
| 402 | return src_type + "BitsTo" + dest_type; | ||
| 403 | } | ||
| 404 | |||
| 405 | /// Generates code representing a temporary (GPR) register. | ||
| 406 | std::string GetRegister(const Register& reg, unsigned elem) { | ||
| 407 | if (reg == Register::ZeroIndex) { | ||
| 408 | return "0"; | ||
| 409 | } | ||
| 410 | |||
| 411 | return regs[reg.GetSwizzledIndex(elem)].GetActiveString(); | ||
| 412 | } | ||
| 413 | |||
| 414 | /** | ||
| 415 | * Writes code that does a register assignment to value operation. | ||
| 416 | * @param reg The destination register to use. | ||
| 417 | * @param elem The element to use for the operation. | ||
| 418 | * @param value The code representing the value to assign. | ||
| 419 | * @param dest_num_components Number of components in the destination. | ||
| 420 | * @param value_num_components Number of components in the value. | ||
| 421 | * @param is_abs Optional, when True, applies absolute value to output. | ||
| 422 | * @param dest_elem Optional, the destination element to use for the operation. | ||
| 423 | */ | ||
| 424 | void SetRegister(const Register& reg, u64 elem, const std::string& value, | ||
| 425 | u64 dest_num_components, u64 value_num_components, bool is_abs, | ||
| 426 | u64 dest_elem) { | ||
| 427 | std::string dest = GetRegister(reg, dest_elem); | ||
| 428 | if (dest_num_components > 1) { | ||
| 429 | dest += GetSwizzle(elem); | ||
| 430 | } | ||
| 431 | |||
| 432 | std::string src = '(' + value + ')'; | ||
| 433 | if (value_num_components > 1) { | ||
| 434 | src += GetSwizzle(elem); | ||
| 435 | } | ||
| 436 | |||
| 437 | src = is_abs ? "abs(" + src + ')' : src; | ||
| 438 | |||
| 439 | shader.AddLine(dest + " = " + src + ';'); | ||
| 440 | } | ||
| 441 | |||
| 398 | /// Build the GLSL register list. | 442 | /// Build the GLSL register list. |
| 399 | void BuildRegisterList() { | 443 | void BuildRegisterList() { |
| 400 | for (size_t index = 0; index < Register::NumRegisters; ++index) { | 444 | for (size_t index = 0; index < Register::NumRegisters; ++index) { |
| @@ -598,7 +642,7 @@ private: | |||
| 598 | switch (opcode->GetType()) { | 642 | switch (opcode->GetType()) { |
| 599 | case OpCode::Type::Arithmetic: { | 643 | case OpCode::Type::Arithmetic: { |
| 600 | std::string op_a = instr.alu.negate_a ? "-" : ""; | 644 | std::string op_a = instr.alu.negate_a ? "-" : ""; |
| 601 | op_a += regs.GetRegister(instr.gpr8); | 645 | op_a += regs.GetRegisterAsFloat(instr.gpr8); |
| 602 | if (instr.alu.abs_a) { | 646 | if (instr.alu.abs_a) { |
| 603 | op_a = "abs(" + op_a + ')'; | 647 | op_a = "abs(" + op_a + ')'; |
| 604 | } | 648 | } |
| @@ -609,7 +653,7 @@ private: | |||
| 609 | op_b += GetImmediate19(instr); | 653 | op_b += GetImmediate19(instr); |
| 610 | } else { | 654 | } else { |
| 611 | if (instr.is_b_gpr) { | 655 | if (instr.is_b_gpr) { |
| 612 | op_b += regs.GetRegister(instr.gpr20); | 656 | op_b += regs.GetRegisterAsFloat(instr.gpr20); |
| 613 | } else { | 657 | } else { |
| 614 | op_b += regs.GetUniform(instr.uniform, instr.gpr0); | 658 | op_b += regs.GetUniform(instr.uniform, instr.gpr0); |
| 615 | } | 659 | } |
| @@ -620,6 +664,11 @@ private: | |||
| 620 | } | 664 | } |
| 621 | 665 | ||
| 622 | switch (opcode->GetId()) { | 666 | switch (opcode->GetId()) { |
| 667 | case OpCode::Id::MOV32_IMM: { | ||
| 668 | // mov32i doesn't have abs or neg bits. | ||
| 669 | regs.SetRegisterToFloat(instr.gpr0, 0, GetImmediate32(instr), 1, 1); | ||
| 670 | break; | ||
| 671 | } | ||
| 623 | case OpCode::Id::FMUL_C: | 672 | case OpCode::Id::FMUL_C: |
| 624 | case OpCode::Id::FMUL_R: | 673 | case OpCode::Id::FMUL_R: |
| 625 | case OpCode::Id::FMUL_IMM: { | 674 | case OpCode::Id::FMUL_IMM: { |
| @@ -629,8 +678,8 @@ private: | |||
| 629 | case OpCode::Id::FMUL32_IMM: { | 678 | case OpCode::Id::FMUL32_IMM: { |
| 630 | // fmul32i doesn't have abs or neg bits. | 679 | // fmul32i doesn't have abs or neg bits. |
| 631 | regs.SetRegisterToFloat( | 680 | regs.SetRegisterToFloat( |
| 632 | instr.gpr0, 0, regs.GetRegister(instr.gpr8) + " * " + GetImmediate32(instr), 1, | 681 | instr.gpr0, 0, |
| 633 | 1); | 682 | regs.GetRegisterAsFloat(instr.gpr8) + " * " + GetImmediate32(instr), 1, 1); |
| 634 | break; | 683 | break; |
| 635 | } | 684 | } |
| 636 | case OpCode::Id::FADD_C: | 685 | case OpCode::Id::FADD_C: |
| @@ -687,29 +736,29 @@ private: | |||
| 687 | break; | 736 | break; |
| 688 | } | 737 | } |
| 689 | case OpCode::Type::Ffma: { | 738 | case OpCode::Type::Ffma: { |
| 690 | std::string op_a = regs.GetRegister(instr.gpr8); | 739 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); |
| 691 | std::string op_b = instr.ffma.negate_b ? "-" : ""; | 740 | std::string op_b = instr.ffma.negate_b ? "-" : ""; |
| 692 | std::string op_c = instr.ffma.negate_c ? "-" : ""; | 741 | std::string op_c = instr.ffma.negate_c ? "-" : ""; |
| 693 | 742 | ||
| 694 | switch (opcode->GetId()) { | 743 | switch (opcode->GetId()) { |
| 695 | case OpCode::Id::FFMA_CR: { | 744 | case OpCode::Id::FFMA_CR: { |
| 696 | op_b += regs.GetUniform(instr.uniform, instr.gpr0); | 745 | op_b += regs.GetUniform(instr.uniform, instr.gpr0); |
| 697 | op_c += regs.GetRegister(instr.gpr39); | 746 | op_c += regs.GetRegisterAsFloat(instr.gpr39); |
| 698 | break; | 747 | break; |
| 699 | } | 748 | } |
| 700 | case OpCode::Id::FFMA_RR: { | 749 | case OpCode::Id::FFMA_RR: { |
| 701 | op_b += regs.GetRegister(instr.gpr20); | 750 | op_b += regs.GetRegisterAsFloat(instr.gpr20); |
| 702 | op_c += regs.GetRegister(instr.gpr39); | 751 | op_c += regs.GetRegisterAsFloat(instr.gpr39); |
| 703 | break; | 752 | break; |
| 704 | } | 753 | } |
| 705 | case OpCode::Id::FFMA_RC: { | 754 | case OpCode::Id::FFMA_RC: { |
| 706 | op_b += regs.GetRegister(instr.gpr39); | 755 | op_b += regs.GetRegisterAsFloat(instr.gpr39); |
| 707 | op_c += regs.GetUniform(instr.uniform, instr.gpr0); | 756 | op_c += regs.GetUniform(instr.uniform, instr.gpr0); |
| 708 | break; | 757 | break; |
| 709 | } | 758 | } |
| 710 | case OpCode::Id::FFMA_IMM: { | 759 | case OpCode::Id::FFMA_IMM: { |
| 711 | op_b += GetImmediate19(instr); | 760 | op_b += GetImmediate19(instr); |
| 712 | op_c += regs.GetRegister(instr.gpr39); | 761 | op_c += regs.GetRegisterAsFloat(instr.gpr39); |
| 713 | break; | 762 | break; |
| 714 | } | 763 | } |
| 715 | default: { | 764 | default: { |
| @@ -721,6 +770,32 @@ private: | |||
| 721 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b + " + " + op_c, 1, 1); | 770 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b + " + " + op_c, 1, 1); |
| 722 | break; | 771 | break; |
| 723 | } | 772 | } |
| 773 | case OpCode::Type::Conversion: { | ||
| 774 | ASSERT_MSG(instr.conversion.size == Register::Size::Word, "Unimplemented"); | ||
| 775 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | ||
| 776 | ASSERT_MSG(!instr.conversion.negate_a, "Unimplemented"); | ||
| 777 | ASSERT_MSG(!instr.conversion.saturate_a, "Unimplemented"); | ||
| 778 | |||
| 779 | switch (opcode->GetId()) { | ||
| 780 | case OpCode::Id::I2I_R: | ||
| 781 | case OpCode::Id::I2F_R: { | ||
| 782 | std::string op_a = | ||
| 783 | regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); | ||
| 784 | |||
| 785 | if (instr.conversion.abs_a) { | ||
| 786 | op_a = "abs(" + op_a + ')'; | ||
| 787 | } | ||
| 788 | |||
| 789 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_signed, 0, op_a, 1, 1); | ||
| 790 | break; | ||
| 791 | } | ||
| 792 | default: { | ||
| 793 | NGLOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", opcode->GetName()); | ||
| 794 | UNREACHABLE(); | ||
| 795 | } | ||
| 796 | } | ||
| 797 | break; | ||
| 798 | } | ||
| 724 | case OpCode::Type::Memory: { | 799 | case OpCode::Type::Memory: { |
| 725 | const Attribute::Index attribute = instr.attribute.fmt20.index; | 800 | const Attribute::Index attribute = instr.attribute.fmt20.index; |
| 726 | 801 | ||
| @@ -739,8 +814,8 @@ private: | |||
| 739 | } | 814 | } |
| 740 | case OpCode::Id::TEXS: { | 815 | case OpCode::Id::TEXS: { |
| 741 | ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested"); | 816 | ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested"); |
| 742 | const std::string op_a = regs.GetRegister(instr.gpr8); | 817 | const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); |
| 743 | const std::string op_b = regs.GetRegister(instr.gpr20); | 818 | const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); |
| 744 | const std::string sampler = GetSampler(instr.sampler); | 819 | const std::string sampler = GetSampler(instr.sampler); |
| 745 | const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; | 820 | const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; |
| 746 | // Add an extra scope and declare the texture coords inside to prevent overwriting | 821 | // Add an extra scope and declare the texture coords inside to prevent overwriting |
| @@ -765,7 +840,7 @@ private: | |||
| 765 | } | 840 | } |
| 766 | case OpCode::Type::FloatSetPredicate: { | 841 | case OpCode::Type::FloatSetPredicate: { |
| 767 | std::string op_a = instr.fsetp.neg_a ? "-" : ""; | 842 | std::string op_a = instr.fsetp.neg_a ? "-" : ""; |
| 768 | op_a += regs.GetRegister(instr.gpr8); | 843 | op_a += regs.GetRegisterAsFloat(instr.gpr8); |
| 769 | 844 | ||
| 770 | if (instr.fsetp.abs_a) { | 845 | if (instr.fsetp.abs_a) { |
| 771 | op_a = "abs(" + op_a + ')'; | 846 | op_a = "abs(" + op_a + ')'; |
| @@ -781,7 +856,7 @@ private: | |||
| 781 | op_b += '(' + GetImmediate19(instr) + ')'; | 856 | op_b += '(' + GetImmediate19(instr) + ')'; |
| 782 | } else { | 857 | } else { |
| 783 | if (instr.is_b_gpr) { | 858 | if (instr.is_b_gpr) { |
| 784 | op_b += regs.GetRegister(instr.gpr20); | 859 | op_b += regs.GetRegisterAsFloat(instr.gpr20); |
| 785 | } else { | 860 | } else { |
| 786 | op_b += regs.GetUniform(instr.uniform, instr.gpr0); | 861 | op_b += regs.GetUniform(instr.uniform, instr.gpr0); |
| 787 | } | 862 | } |
| @@ -816,7 +891,7 @@ private: | |||
| 816 | } | 891 | } |
| 817 | case OpCode::Type::FloatSet: { | 892 | case OpCode::Type::FloatSet: { |
| 818 | std::string op_a = instr.fset.neg_a ? "-" : ""; | 893 | std::string op_a = instr.fset.neg_a ? "-" : ""; |
| 819 | op_a += regs.GetRegister(instr.gpr8); | 894 | op_a += regs.GetRegisterAsFloat(instr.gpr8); |
| 820 | 895 | ||
| 821 | if (instr.fset.abs_a) { | 896 | if (instr.fset.abs_a) { |
| 822 | op_a = "abs(" + op_a + ')'; | 897 | op_a = "abs(" + op_a + ')'; |
| @@ -832,7 +907,7 @@ private: | |||
| 832 | op_b += imm; | 907 | op_b += imm; |
| 833 | } else { | 908 | } else { |
| 834 | if (instr.is_b_gpr) { | 909 | if (instr.is_b_gpr) { |
| 835 | op_b += regs.GetRegister(instr.gpr20); | 910 | op_b += regs.GetRegisterAsFloat(instr.gpr20); |
| 836 | } else { | 911 | } else { |
| 837 | op_b += regs.GetUniform(instr.uniform, instr.gpr0); | 912 | op_b += regs.GetUniform(instr.uniform, instr.gpr0); |
| 838 | } | 913 | } |
| @@ -877,10 +952,10 @@ private: | |||
| 877 | 952 | ||
| 878 | // Final color output is currently hardcoded to GPR0-3 for fragment shaders | 953 | // Final color output is currently hardcoded to GPR0-3 for fragment shaders |
| 879 | if (stage == Maxwell3D::Regs::ShaderStage::Fragment) { | 954 | if (stage == Maxwell3D::Regs::ShaderStage::Fragment) { |
| 880 | shader.AddLine("color.r = " + regs.GetRegister(0) + ';'); | 955 | shader.AddLine("color.r = " + regs.GetRegisterAsFloat(0) + ';'); |
| 881 | shader.AddLine("color.g = " + regs.GetRegister(1) + ';'); | 956 | shader.AddLine("color.g = " + regs.GetRegisterAsFloat(1) + ';'); |
| 882 | shader.AddLine("color.b = " + regs.GetRegister(2) + ';'); | 957 | shader.AddLine("color.b = " + regs.GetRegisterAsFloat(2) + ';'); |
| 883 | shader.AddLine("color.a = " + regs.GetRegister(3) + ';'); | 958 | shader.AddLine("color.a = " + regs.GetRegisterAsFloat(3) + ';'); |
| 884 | } | 959 | } |
| 885 | 960 | ||
| 886 | shader.AddLine("return true;"); | 961 | shader.AddLine("return true;"); |