summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp106
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.h50
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
15namespace GLShader { 16namespace 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
74public: 75public:
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
110struct ShaderEntries { 148struct ShaderEntries {