diff options
| author | 2018-08-19 12:54:19 -0500 | |
|---|---|---|
| committer | 2018-08-19 12:57:54 -0500 | |
| commit | 3ef4b3d4b445960576f10d1ba6521580d03e3da8 (patch) | |
| tree | 095841351b74f05ec43dd63754b9aa342e261b4c /src | |
| parent | Shader: Added bitfields for the texture type of the various sampling instruct... (diff) | |
| download | yuzu-3ef4b3d4b445960576f10d1ba6521580d03e3da8.tar.gz yuzu-3ef4b3d4b445960576f10d1ba6521580d03e3da8.tar.xz yuzu-3ef4b3d4b445960576f10d1ba6521580d03e3da8.zip | |
Shader: Use the right sampler type in the TEX, TEXS and TLDS instructions.
Different sampler types have their parameters in different registers.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 106 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.h | 50 |
2 files changed, 127 insertions, 29 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 4007ecc02..6562be102 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 | /** |
| @@ -1464,10 +1465,29 @@ private: | |||
| 1464 | break; | 1465 | break; |
| 1465 | } | 1466 | } |
| 1466 | case OpCode::Id::TEX: { | 1467 | case OpCode::Id::TEX: { |
| 1467 | const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | 1468 | ASSERT_MSG(instr.tex.array == 0, "TEX arrays unimplemented"); |
| 1468 | const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | 1469 | std::string coord{}; |
| 1469 | const std::string sampler = GetSampler(instr.sampler); | 1470 | |
| 1470 | const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; | 1471 | switch (instr.tex.texture_type) { |
| 1472 | case Tegra::Shader::TextureType::Texture2D: { | ||
| 1473 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1474 | std::string y = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 1475 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||
| 1476 | break; | ||
| 1477 | } | ||
| 1478 | case Tegra::Shader::TextureType::Texture3D: { | ||
| 1479 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1480 | std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 1481 | std::string z = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 1482 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; | ||
| 1483 | break; | ||
| 1484 | } | ||
| 1485 | default: | ||
| 1486 | UNIMPLEMENTED(); | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | const std::string sampler = | ||
| 1490 | GetSampler(instr.sampler, instr.tex.texture_type, instr.tex.array); | ||
| 1471 | // Add an extra scope and declare the texture coords inside to prevent | 1491 | // Add an extra scope and declare the texture coords inside to prevent |
| 1472 | // overwriting them in case they are used as outputs of the texs instruction. | 1492 | // overwriting them in case they are used as outputs of the texs instruction. |
| 1473 | shader.AddLine("{"); | 1493 | shader.AddLine("{"); |
| @@ -1489,20 +1509,60 @@ private: | |||
| 1489 | break; | 1509 | break; |
| 1490 | } | 1510 | } |
| 1491 | case OpCode::Id::TEXS: { | 1511 | case OpCode::Id::TEXS: { |
| 1492 | const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | 1512 | std::string coord{}; |
| 1493 | const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); | 1513 | |
| 1494 | const std::string sampler = GetSampler(instr.sampler); | 1514 | switch (instr.texs.GetTextureType()) { |
| 1495 | const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; | 1515 | case Tegra::Shader::TextureType::Texture2D: { |
| 1516 | if (instr.texs.IsArrayTexture()) { | ||
| 1517 | std::string index = regs.GetRegisterAsInteger(instr.gpr8); | ||
| 1518 | std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 1519 | std::string y = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 1520 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");"; | ||
| 1521 | } else { | ||
| 1522 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1523 | std::string y = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 1524 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||
| 1525 | } | ||
| 1526 | break; | ||
| 1527 | } | ||
| 1528 | case Tegra::Shader::TextureType::TextureCube: { | ||
| 1529 | std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 1530 | std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 1531 | std::string z = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 1532 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; | ||
| 1533 | break; | ||
| 1534 | } | ||
| 1535 | default: | ||
| 1536 | UNIMPLEMENTED(); | ||
| 1537 | } | ||
| 1538 | const std::string sampler = GetSampler(instr.sampler, instr.texs.GetTextureType(), | ||
| 1539 | instr.texs.IsArrayTexture()); | ||
| 1496 | 1540 | ||
| 1497 | const std::string texture = "texture(" + sampler + ", coords)"; | 1541 | const std::string texture = "texture(" + sampler + ", coords)"; |
| 1498 | WriteTexsInstruction(instr, coord, texture); | 1542 | WriteTexsInstruction(instr, coord, texture); |
| 1499 | break; | 1543 | break; |
| 1500 | } | 1544 | } |
| 1501 | case OpCode::Id::TLDS: { | 1545 | case OpCode::Id::TLDS: { |
| 1502 | const std::string op_a = regs.GetRegisterAsInteger(instr.gpr8); | 1546 | ASSERT(instr.tlds.GetTextureType() == Tegra::Shader::TextureType::Texture2D); |
| 1503 | const std::string op_b = regs.GetRegisterAsInteger(instr.gpr20); | 1547 | ASSERT(instr.tlds.IsArrayTexture() == false); |
| 1504 | const std::string sampler = GetSampler(instr.sampler); | 1548 | std::string coord{}; |
| 1505 | const std::string coord = "ivec2 coords = ivec2(" + op_a + ", " + op_b + ");"; | 1549 | |
| 1550 | switch (instr.tlds.GetTextureType()) { | ||
| 1551 | case Tegra::Shader::TextureType::Texture2D: { | ||
| 1552 | if (instr.tlds.IsArrayTexture()) { | ||
| 1553 | UNIMPLEMENTED(); | ||
| 1554 | } else { | ||
| 1555 | std::string x = regs.GetRegisterAsInteger(instr.gpr8); | ||
| 1556 | std::string y = regs.GetRegisterAsInteger(instr.gpr20); | ||
| 1557 | coord = "ivec2 coords = ivec2(" + x + ", " + y + ");"; | ||
| 1558 | } | ||
| 1559 | break; | ||
| 1560 | } | ||
| 1561 | default: | ||
| 1562 | UNIMPLEMENTED(); | ||
| 1563 | } | ||
| 1564 | const std::string sampler = GetSampler(instr.sampler, instr.tlds.GetTextureType(), | ||
| 1565 | instr.tlds.IsArrayTexture()); | ||
| 1506 | const std::string texture = "texelFetch(" + sampler + ", coords, 0)"; | 1566 | const std::string texture = "texelFetch(" + sampler + ", coords, 0)"; |
| 1507 | WriteTexsInstruction(instr, coord, texture); | 1567 | WriteTexsInstruction(instr, coord, texture); |
| 1508 | break; | 1568 | break; |
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 { |