diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 76 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 157 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.h | 50 |
3 files changed, 250 insertions, 33 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 9413a81fb..3ba6fe614 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -223,6 +223,13 @@ enum class PredicateResultMode : u64 { | |||
| 223 | NotZero = 0x3, | 223 | NotZero = 0x3, |
| 224 | }; | 224 | }; |
| 225 | 225 | ||
| 226 | enum class TextureType : u64 { | ||
| 227 | Texture1D = 0, | ||
| 228 | Texture2D = 1, | ||
| 229 | Texture3D = 2, | ||
| 230 | TextureCube = 3, | ||
| 231 | }; | ||
| 232 | |||
| 226 | union Instruction { | 233 | union Instruction { |
| 227 | Instruction& operator=(const Instruction& instr) { | 234 | Instruction& operator=(const Instruction& instr) { |
| 228 | value = instr.value; | 235 | value = instr.value; |
| @@ -434,6 +441,8 @@ union Instruction { | |||
| 434 | } conversion; | 441 | } conversion; |
| 435 | 442 | ||
| 436 | union { | 443 | union { |
| 444 | BitField<28, 1, u64> array; | ||
| 445 | BitField<29, 2, TextureType> texture_type; | ||
| 437 | BitField<31, 4, u64> component_mask; | 446 | BitField<31, 4, u64> component_mask; |
| 438 | 447 | ||
| 439 | bool IsComponentEnabled(size_t component) const { | 448 | bool IsComponentEnabled(size_t component) const { |
| @@ -442,9 +451,39 @@ union Instruction { | |||
| 442 | } tex; | 451 | } tex; |
| 443 | 452 | ||
| 444 | union { | 453 | union { |
| 445 | BitField<50, 3, u64> component_mask_selector; | 454 | BitField<28, 1, u64> array; |
| 455 | BitField<29, 2, TextureType> texture_type; | ||
| 456 | BitField<56, 2, u64> component; | ||
| 457 | } tld4; | ||
| 458 | |||
| 459 | union { | ||
| 460 | BitField<52, 2, u64> component; | ||
| 461 | } tld4s; | ||
| 462 | |||
| 463 | union { | ||
| 446 | BitField<0, 8, Register> gpr0; | 464 | BitField<0, 8, Register> gpr0; |
| 447 | BitField<28, 8, Register> gpr28; | 465 | BitField<28, 8, Register> gpr28; |
| 466 | BitField<50, 3, u64> component_mask_selector; | ||
| 467 | BitField<53, 4, u64> texture_info; | ||
| 468 | |||
| 469 | TextureType GetTextureType() const { | ||
| 470 | // The TEXS instruction has a weird encoding for the texture type. | ||
| 471 | if (texture_info == 0) | ||
| 472 | return TextureType::Texture1D; | ||
| 473 | if (texture_info >= 1 && texture_info <= 9) | ||
| 474 | return TextureType::Texture2D; | ||
| 475 | if (texture_info >= 10 && texture_info <= 11) | ||
| 476 | return TextureType::Texture3D; | ||
| 477 | if (texture_info >= 12 && texture_info <= 13) | ||
| 478 | return TextureType::TextureCube; | ||
| 479 | |||
| 480 | UNIMPLEMENTED(); | ||
| 481 | } | ||
| 482 | |||
| 483 | bool IsArrayTexture() const { | ||
| 484 | // TEXS only supports Texture2D arrays. | ||
| 485 | return texture_info >= 7 && texture_info <= 9; | ||
| 486 | } | ||
| 448 | 487 | ||
| 449 | bool HasTwoDestinations() const { | 488 | bool HasTwoDestinations() const { |
| 450 | return gpr28.Value() != Register::ZeroIndex; | 489 | return gpr28.Value() != Register::ZeroIndex; |
| @@ -469,6 +508,31 @@ union Instruction { | |||
| 469 | } texs; | 508 | } texs; |
| 470 | 509 | ||
| 471 | union { | 510 | union { |
| 511 | BitField<53, 4, u64> texture_info; | ||
| 512 | |||
| 513 | TextureType GetTextureType() const { | ||
| 514 | // The TLDS instruction has a weird encoding for the texture type. | ||
| 515 | if (texture_info >= 0 && texture_info <= 1) { | ||
| 516 | return TextureType::Texture1D; | ||
| 517 | } | ||
| 518 | if (texture_info == 2 || texture_info == 8 || texture_info == 12 || | ||
| 519 | texture_info >= 4 && texture_info <= 6) { | ||
| 520 | return TextureType::Texture2D; | ||
| 521 | } | ||
| 522 | if (texture_info == 7) { | ||
| 523 | return TextureType::Texture3D; | ||
| 524 | } | ||
| 525 | |||
| 526 | UNIMPLEMENTED(); | ||
| 527 | } | ||
| 528 | |||
| 529 | bool IsArrayTexture() const { | ||
| 530 | // TEXS only supports Texture2D arrays. | ||
| 531 | return texture_info == 8; | ||
| 532 | } | ||
| 533 | } tlds; | ||
| 534 | |||
| 535 | union { | ||
| 472 | BitField<20, 24, u64> target; | 536 | BitField<20, 24, u64> target; |
| 473 | BitField<5, 1, u64> constant_buffer; | 537 | BitField<5, 1, u64> constant_buffer; |
| 474 | 538 | ||
| @@ -533,9 +597,11 @@ public: | |||
| 533 | LDG, // Load from global memory | 597 | LDG, // Load from global memory |
| 534 | STG, // Store in global memory | 598 | STG, // Store in global memory |
| 535 | TEX, | 599 | TEX, |
| 536 | TEXQ, // Texture Query | 600 | TEXQ, // Texture Query |
| 537 | TEXS, // Texture Fetch with scalar/non-vec4 source/destinations | 601 | TEXS, // Texture Fetch with scalar/non-vec4 source/destinations |
| 538 | TLDS, // Texture Load with scalar/non-vec4 source/destinations | 602 | TLDS, // Texture Load with scalar/non-vec4 source/destinations |
| 603 | TLD4, // Texture Load 4 | ||
| 604 | TLD4S, // Texture Load 4 with scalar / non - vec4 source / destinations | ||
| 539 | EXIT, | 605 | EXIT, |
| 540 | IPA, | 606 | IPA, |
| 541 | FFMA_IMM, // Fused Multiply and Add | 607 | FFMA_IMM, // Fused Multiply and Add |
| @@ -749,6 +815,8 @@ private: | |||
| 749 | INST("1101111101001---", Id::TEXQ, Type::Memory, "TEXQ"), | 815 | INST("1101111101001---", Id::TEXQ, Type::Memory, "TEXQ"), |
| 750 | INST("1101100---------", Id::TEXS, Type::Memory, "TEXS"), | 816 | INST("1101100---------", Id::TEXS, Type::Memory, "TEXS"), |
| 751 | INST("1101101---------", Id::TLDS, Type::Memory, "TLDS"), | 817 | INST("1101101---------", Id::TLDS, Type::Memory, "TLDS"), |
| 818 | INST("110010----111---", Id::TLD4, Type::Memory, "TLD4"), | ||
| 819 | INST("1101111100------", Id::TLD4S, Type::Memory, "TLD4S"), | ||
| 752 | INST("111000110000----", Id::EXIT, Type::Trivial, "EXIT"), | 820 | INST("111000110000----", Id::EXIT, Type::Trivial, "EXIT"), |
| 753 | INST("11100000--------", Id::IPA, Type::Trivial, "IPA"), | 821 | INST("11100000--------", Id::IPA, Type::Trivial, "IPA"), |
| 754 | INST("0011001-1-------", Id::FFMA_IMM, Type::Ffma, "FFMA_IMM"), | 822 | INST("0011001-1-------", Id::FFMA_IMM, Type::Ffma, "FFMA_IMM"), |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 57cf9f213..f3b2d1328 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -439,13 +439,12 @@ public: | |||
| 439 | } | 439 | } |
| 440 | declarations.AddNewLine(); | 440 | declarations.AddNewLine(); |
| 441 | 441 | ||
| 442 | // Append the sampler2D array for the used textures. | 442 | const auto& samplers = GetSamplers(); |
| 443 | size_t num_samplers = GetSamplers().size(); | 443 | for (const auto& sampler : samplers) { |
| 444 | if (num_samplers > 0) { | 444 | declarations.AddLine("uniform " + sampler.GetTypeString() + ' ' + sampler.GetName() + |
| 445 | declarations.AddLine("uniform sampler2D " + SamplerEntry::GetArrayName(stage) + '[' + | 445 | ';'); |
| 446 | std::to_string(num_samplers) + "];"); | ||
| 447 | declarations.AddNewLine(); | ||
| 448 | } | 446 | } |
| 447 | declarations.AddNewLine(); | ||
| 449 | } | 448 | } |
| 450 | 449 | ||
| 451 | /// Returns a list of constant buffer declarations | 450 | /// Returns a list of constant buffer declarations |
| @@ -457,13 +456,14 @@ public: | |||
| 457 | } | 456 | } |
| 458 | 457 | ||
| 459 | /// Returns a list of samplers used in the shader | 458 | /// Returns a list of samplers used in the shader |
| 460 | std::vector<SamplerEntry> GetSamplers() const { | 459 | const std::vector<SamplerEntry>& GetSamplers() const { |
| 461 | return used_samplers; | 460 | return used_samplers; |
| 462 | } | 461 | } |
| 463 | 462 | ||
| 464 | /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if | 463 | /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if |
| 465 | /// necessary. | 464 | /// necessary. |
| 466 | std::string AccessSampler(const Sampler& sampler) { | 465 | std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type, |
| 466 | bool is_array) { | ||
| 467 | size_t offset = static_cast<size_t>(sampler.index.Value()); | 467 | size_t offset = static_cast<size_t>(sampler.index.Value()); |
| 468 | 468 | ||
| 469 | // If this sampler has already been used, return the existing mapping. | 469 | // If this sampler has already been used, return the existing mapping. |
| @@ -472,12 +472,13 @@ public: | |||
| 472 | [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; }); | 472 | [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; }); |
| 473 | 473 | ||
| 474 | if (itr != used_samplers.end()) { | 474 | if (itr != used_samplers.end()) { |
| 475 | ASSERT(itr->GetType() == type && itr->IsArray() == is_array); | ||
| 475 | return itr->GetName(); | 476 | return itr->GetName(); |
| 476 | } | 477 | } |
| 477 | 478 | ||
| 478 | // Otherwise create a new mapping for this sampler | 479 | // Otherwise create a new mapping for this sampler |
| 479 | size_t next_index = used_samplers.size(); | 480 | size_t next_index = used_samplers.size(); |
| 480 | SamplerEntry entry{stage, offset, next_index}; | 481 | SamplerEntry entry{stage, offset, next_index, type, is_array}; |
| 481 | used_samplers.emplace_back(entry); | 482 | used_samplers.emplace_back(entry); |
| 482 | return entry.GetName(); | 483 | return entry.GetName(); |
| 483 | } | 484 | } |
| @@ -638,8 +639,8 @@ private: | |||
| 638 | } | 639 | } |
| 639 | 640 | ||
| 640 | /// Generates code representing a texture sampler. | 641 | /// Generates code representing a texture sampler. |
| 641 | std::string GetSampler(const Sampler& sampler) { | 642 | std::string GetSampler(const Sampler& sampler, Tegra::Shader::TextureType type, bool is_array) { |
| 642 | return regs.AccessSampler(sampler); | 643 | return regs.AccessSampler(sampler, type, is_array); |
| 643 | } | 644 | } |
| 644 | 645 | ||
| 645 | /** | 646 | /** |
| @@ -1507,10 +1508,29 @@ private: | |||
| 1507 | break; | 1508 | break; |
| 1508 | } | 1509 | } |
| 1509 | case OpCode::Id::TEX: { | 1510 | case OpCode::Id::TEX: { |
| 1510 | const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | 1511 | ASSERT_MSG(instr.tex.array == 0, "TEX arrays unimplemented"); |
| 1511 | const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | 1512 | std::string coord{}; |
| 1512 | const std::string sampler = GetSampler(instr.sampler); | 1513 | |
| 1513 | const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; | 1514 | switch (instr.tex.texture_type) { |
| 1515 | case Tegra::Shader::TextureType::Texture2D: { | ||
| 1516 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1517 | std::string y = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 1518 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||
| 1519 | break; | ||
| 1520 | } | ||
| 1521 | case Tegra::Shader::TextureType::Texture3D: { | ||
| 1522 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1523 | std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 1524 | std::string z = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 1525 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; | ||
| 1526 | break; | ||
| 1527 | } | ||
| 1528 | default: | ||
| 1529 | UNIMPLEMENTED(); | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | const std::string sampler = | ||
| 1533 | GetSampler(instr.sampler, instr.tex.texture_type, instr.tex.array); | ||
| 1514 | // Add an extra scope and declare the texture coords inside to prevent | 1534 | // Add an extra scope and declare the texture coords inside to prevent |
| 1515 | // overwriting them in case they are used as outputs of the texs instruction. | 1535 | // overwriting them in case they are used as outputs of the texs instruction. |
| 1516 | shader.AddLine("{"); | 1536 | shader.AddLine("{"); |
| @@ -1532,24 +1552,115 @@ private: | |||
| 1532 | break; | 1552 | break; |
| 1533 | } | 1553 | } |
| 1534 | case OpCode::Id::TEXS: { | 1554 | case OpCode::Id::TEXS: { |
| 1535 | const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | 1555 | std::string coord{}; |
| 1536 | const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); | 1556 | |
| 1537 | const std::string sampler = GetSampler(instr.sampler); | 1557 | switch (instr.texs.GetTextureType()) { |
| 1538 | const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; | 1558 | case Tegra::Shader::TextureType::Texture2D: { |
| 1559 | if (instr.texs.IsArrayTexture()) { | ||
| 1560 | std::string index = regs.GetRegisterAsInteger(instr.gpr8); | ||
| 1561 | std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 1562 | std::string y = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 1563 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");"; | ||
| 1564 | } else { | ||
| 1565 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1566 | std::string y = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 1567 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||
| 1568 | } | ||
| 1569 | break; | ||
| 1570 | } | ||
| 1571 | case Tegra::Shader::TextureType::TextureCube: { | ||
| 1572 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1573 | std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 1574 | std::string z = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 1575 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; | ||
| 1576 | break; | ||
| 1577 | } | ||
| 1578 | default: | ||
| 1579 | UNIMPLEMENTED(); | ||
| 1580 | } | ||
| 1581 | const std::string sampler = GetSampler(instr.sampler, instr.texs.GetTextureType(), | ||
| 1582 | instr.texs.IsArrayTexture()); | ||
| 1539 | 1583 | ||
| 1540 | const std::string texture = "texture(" + sampler + ", coords)"; | 1584 | const std::string texture = "texture(" + sampler + ", coords)"; |
| 1541 | WriteTexsInstruction(instr, coord, texture); | 1585 | WriteTexsInstruction(instr, coord, texture); |
| 1542 | break; | 1586 | break; |
| 1543 | } | 1587 | } |
| 1544 | case OpCode::Id::TLDS: { | 1588 | case OpCode::Id::TLDS: { |
| 1545 | const std::string op_a = regs.GetRegisterAsInteger(instr.gpr8); | 1589 | ASSERT(instr.tlds.GetTextureType() == Tegra::Shader::TextureType::Texture2D); |
| 1546 | const std::string op_b = regs.GetRegisterAsInteger(instr.gpr20); | 1590 | ASSERT(instr.tlds.IsArrayTexture() == false); |
| 1547 | const std::string sampler = GetSampler(instr.sampler); | 1591 | std::string coord{}; |
| 1548 | const std::string coord = "ivec2 coords = ivec2(" + op_a + ", " + op_b + ");"; | 1592 | |
| 1593 | switch (instr.tlds.GetTextureType()) { | ||
| 1594 | case Tegra::Shader::TextureType::Texture2D: { | ||
| 1595 | if (instr.tlds.IsArrayTexture()) { | ||
| 1596 | UNIMPLEMENTED(); | ||
| 1597 | } else { | ||
| 1598 | std::string x = regs.GetRegisterAsInteger(instr.gpr8); | ||
| 1599 | std::string y = regs.GetRegisterAsInteger(instr.gpr20); | ||
| 1600 | coord = "ivec2 coords = ivec2(" + x + ", " + y + ");"; | ||
| 1601 | } | ||
| 1602 | break; | ||
| 1603 | } | ||
| 1604 | default: | ||
| 1605 | UNIMPLEMENTED(); | ||
| 1606 | } | ||
| 1607 | const std::string sampler = GetSampler(instr.sampler, instr.tlds.GetTextureType(), | ||
| 1608 | instr.tlds.IsArrayTexture()); | ||
| 1549 | const std::string texture = "texelFetch(" + sampler + ", coords, 0)"; | 1609 | const std::string texture = "texelFetch(" + sampler + ", coords, 0)"; |
| 1550 | WriteTexsInstruction(instr, coord, texture); | 1610 | WriteTexsInstruction(instr, coord, texture); |
| 1551 | break; | 1611 | break; |
| 1552 | } | 1612 | } |
| 1613 | case OpCode::Id::TLD4: { | ||
| 1614 | ASSERT(instr.tld4.texture_type == Tegra::Shader::TextureType::Texture2D); | ||
| 1615 | ASSERT(instr.tld4.array == 0); | ||
| 1616 | std::string coord{}; | ||
| 1617 | |||
| 1618 | switch (instr.tld4.texture_type) { | ||
| 1619 | case Tegra::Shader::TextureType::Texture2D: { | ||
| 1620 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1621 | std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 1622 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||
| 1623 | break; | ||
| 1624 | } | ||
| 1625 | default: | ||
| 1626 | UNIMPLEMENTED(); | ||
| 1627 | } | ||
| 1628 | |||
| 1629 | const std::string sampler = | ||
| 1630 | GetSampler(instr.sampler, instr.tld4.texture_type, instr.tld4.array); | ||
| 1631 | // Add an extra scope and declare the texture coords inside to prevent | ||
| 1632 | // overwriting them in case they are used as outputs of the texs instruction. | ||
| 1633 | shader.AddLine("{"); | ||
| 1634 | ++shader.scope; | ||
| 1635 | shader.AddLine(coord); | ||
| 1636 | const std::string texture = "textureGather(" + sampler + ", coords, " + | ||
| 1637 | std::to_string(instr.tld4.component) + ')'; | ||
| 1638 | |||
| 1639 | size_t dest_elem{}; | ||
| 1640 | for (size_t elem = 0; elem < 4; ++elem) { | ||
| 1641 | if (!instr.tex.IsComponentEnabled(elem)) { | ||
| 1642 | // Skip disabled components | ||
| 1643 | continue; | ||
| 1644 | } | ||
| 1645 | regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem); | ||
| 1646 | ++dest_elem; | ||
| 1647 | } | ||
| 1648 | --shader.scope; | ||
| 1649 | shader.AddLine("}"); | ||
| 1650 | break; | ||
| 1651 | } | ||
| 1652 | case OpCode::Id::TLD4S: { | ||
| 1653 | const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1654 | const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 1655 | // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. | ||
| 1656 | const std::string sampler = | ||
| 1657 | GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false); | ||
| 1658 | const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; | ||
| 1659 | const std::string texture = "textureGather(" + sampler + ", coords, " + | ||
| 1660 | std::to_string(instr.tld4s.component) + ')'; | ||
| 1661 | WriteTexsInstruction(instr, coord, texture); | ||
| 1662 | break; | ||
| 1663 | } | ||
| 1553 | default: { | 1664 | default: { |
| 1554 | LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {}", opcode->GetName()); | 1665 | LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {}", opcode->GetName()); |
| 1555 | UNREACHABLE(); | 1666 | UNREACHABLE(); |
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h index 4729ce0fc..db48da645 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.h +++ b/src/video_core/renderer_opengl/gl_shader_gen.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <vector> | 11 | #include <vector> |
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "common/hash.h" | 13 | #include "common/hash.h" |
| 14 | #include "video_core/engines/shader_bytecode.h" | ||
| 14 | 15 | ||
| 15 | namespace GLShader { | 16 | namespace GLShader { |
| 16 | 17 | ||
| @@ -72,8 +73,9 @@ class SamplerEntry { | |||
| 72 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 73 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 73 | 74 | ||
| 74 | public: | 75 | public: |
| 75 | SamplerEntry(Maxwell::ShaderStage stage, size_t offset, size_t index) | 76 | SamplerEntry(Maxwell::ShaderStage stage, size_t offset, size_t index, |
| 76 | : offset(offset), stage(stage), sampler_index(index) {} | 77 | Tegra::Shader::TextureType type, bool is_array) |
| 78 | : offset(offset), stage(stage), sampler_index(index), type(type), is_array(is_array) {} | ||
| 77 | 79 | ||
| 78 | size_t GetOffset() const { | 80 | size_t GetOffset() const { |
| 79 | return offset; | 81 | return offset; |
| @@ -88,8 +90,41 @@ public: | |||
| 88 | } | 90 | } |
| 89 | 91 | ||
| 90 | std::string GetName() const { | 92 | std::string GetName() const { |
| 91 | return std::string(TextureSamplerNames[static_cast<size_t>(stage)]) + '[' + | 93 | return std::string(TextureSamplerNames[static_cast<size_t>(stage)]) + '_' + |
| 92 | std::to_string(sampler_index) + ']'; | 94 | std::to_string(sampler_index); |
| 95 | } | ||
| 96 | |||
| 97 | std::string GetTypeString() const { | ||
| 98 | using Tegra::Shader::TextureType; | ||
| 99 | std::string glsl_type; | ||
| 100 | |||
| 101 | switch (type) { | ||
| 102 | case TextureType::Texture1D: | ||
| 103 | glsl_type = "sampler1D"; | ||
| 104 | break; | ||
| 105 | case TextureType::Texture2D: | ||
| 106 | glsl_type = "sampler2D"; | ||
| 107 | break; | ||
| 108 | case TextureType::Texture3D: | ||
| 109 | glsl_type = "sampler3D"; | ||
| 110 | break; | ||
| 111 | case TextureType::TextureCube: | ||
| 112 | glsl_type = "samplerCube"; | ||
| 113 | break; | ||
| 114 | default: | ||
| 115 | UNIMPLEMENTED(); | ||
| 116 | } | ||
| 117 | if (is_array) | ||
| 118 | glsl_type += "Array"; | ||
| 119 | return glsl_type; | ||
| 120 | } | ||
| 121 | |||
| 122 | Tegra::Shader::TextureType GetType() const { | ||
| 123 | return type; | ||
| 124 | } | ||
| 125 | |||
| 126 | bool IsArray() const { | ||
| 127 | return is_array; | ||
| 93 | } | 128 | } |
| 94 | 129 | ||
| 95 | static std::string GetArrayName(Maxwell::ShaderStage stage) { | 130 | static std::string GetArrayName(Maxwell::ShaderStage stage) { |
| @@ -100,11 +135,14 @@ private: | |||
| 100 | static constexpr std::array<const char*, Maxwell::MaxShaderStage> TextureSamplerNames = { | 135 | static constexpr std::array<const char*, Maxwell::MaxShaderStage> TextureSamplerNames = { |
| 101 | "tex_vs", "tex_tessc", "tex_tesse", "tex_gs", "tex_fs", | 136 | "tex_vs", "tex_tessc", "tex_tesse", "tex_gs", "tex_fs", |
| 102 | }; | 137 | }; |
| 138 | |||
| 103 | /// Offset in TSC memory from which to read the sampler object, as specified by the sampling | 139 | /// Offset in TSC memory from which to read the sampler object, as specified by the sampling |
| 104 | /// instruction. | 140 | /// instruction. |
| 105 | size_t offset; | 141 | size_t offset; |
| 106 | Maxwell::ShaderStage stage; ///< Shader stage where this sampler was used. | 142 | Maxwell::ShaderStage stage; ///< Shader stage where this sampler was used. |
| 107 | size_t sampler_index; ///< Value used to index into the generated GLSL sampler array. | 143 | size_t sampler_index; ///< Value used to index into the generated GLSL sampler array. |
| 144 | Tegra::Shader::TextureType type; ///< The type used to sample this texture (Texture2D, etc) | ||
| 145 | bool is_array; ///< Whether the texture is being sampled as an array texture or not. | ||
| 108 | }; | 146 | }; |
| 109 | 147 | ||
| 110 | struct ShaderEntries { | 148 | struct ShaderEntries { |