summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-10-06 23:14:27 -0400
committerGravatar GitHub2018-10-06 23:14:27 -0400
commit1cc5e6e9bc8c62fe8084d45041b14d0bb86e6890 (patch)
treec446422e9a7f44977dae87b9774acd7bf2a9721a /src
parentMerge pull request #1453 from FearlessTobi/port-4311 (diff)
parentImplemented Depth Compare and Shadow Samplers (diff)
downloadyuzu-1cc5e6e9bc8c62fe8084d45041b14d0bb86e6890.tar.gz
yuzu-1cc5e6e9bc8c62fe8084d45041b14d0bb86e6890.tar.xz
yuzu-1cc5e6e9bc8c62fe8084d45041b14d0bb86e6890.zip
Merge pull request #1437 from FernandoS27/tex-mode2
Implemented Depth Compare, Shadow Samplers and Texture Processing Modes for TEXS and TLDS
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp18
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp262
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.h14
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h25
-rw-r--r--src/video_core/textures/texture.h13
6 files changed, 265 insertions, 69 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index a91bc6dee..edcd5e451 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -662,10 +662,13 @@ void RasterizerOpenGL::SamplerInfo::Create() {
662 sampler.Create(); 662 sampler.Create();
663 mag_filter = min_filter = Tegra::Texture::TextureFilter::Linear; 663 mag_filter = min_filter = Tegra::Texture::TextureFilter::Linear;
664 wrap_u = wrap_v = wrap_p = Tegra::Texture::WrapMode::Wrap; 664 wrap_u = wrap_v = wrap_p = Tegra::Texture::WrapMode::Wrap;
665 uses_depth_compare = false;
666 depth_compare_func = Tegra::Texture::DepthCompareFunc::Never;
665 667
666 // default is GL_LINEAR_MIPMAP_LINEAR 668 // default is GL_LINEAR_MIPMAP_LINEAR
667 glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 669 glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
668 // Other attributes have correct defaults 670 // Other attributes have correct defaults
671 glSamplerParameteri(sampler.handle, GL_TEXTURE_COMPARE_FUNC, GL_NEVER);
669} 672}
670 673
671void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntry& config) { 674void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntry& config) {
@@ -693,6 +696,21 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr
693 glSamplerParameteri(s, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(wrap_p)); 696 glSamplerParameteri(s, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(wrap_p));
694 } 697 }
695 698
699 if (uses_depth_compare != (config.depth_compare_enabled == 1)) {
700 uses_depth_compare = (config.depth_compare_enabled == 1);
701 if (uses_depth_compare) {
702 glSamplerParameteri(s, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
703 } else {
704 glSamplerParameteri(s, GL_TEXTURE_COMPARE_MODE, GL_NONE);
705 }
706 }
707
708 if (depth_compare_func != config.depth_compare_func) {
709 depth_compare_func = config.depth_compare_func;
710 glSamplerParameteri(s, GL_TEXTURE_COMPARE_FUNC,
711 MaxwellToGL::DepthCompareFunc(depth_compare_func));
712 }
713
696 if (wrap_u == Tegra::Texture::WrapMode::Border || wrap_v == Tegra::Texture::WrapMode::Border || 714 if (wrap_u == Tegra::Texture::WrapMode::Border || wrap_v == Tegra::Texture::WrapMode::Border ||
697 wrap_p == Tegra::Texture::WrapMode::Border) { 715 wrap_p == Tegra::Texture::WrapMode::Border) {
698 const GLvec4 new_border_color = {{config.border_color_r, config.border_color_g, 716 const GLvec4 new_border_color = {{config.border_color_r, config.border_color_g,
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index bf954bb5d..dc31a2dbc 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -96,6 +96,8 @@ private:
96 Tegra::Texture::WrapMode wrap_u; 96 Tegra::Texture::WrapMode wrap_u;
97 Tegra::Texture::WrapMode wrap_v; 97 Tegra::Texture::WrapMode wrap_v;
98 Tegra::Texture::WrapMode wrap_p; 98 Tegra::Texture::WrapMode wrap_p;
99 bool uses_depth_compare;
100 Tegra::Texture::DepthCompareFunc depth_compare_func;
99 GLvec4 border_color; 101 GLvec4 border_color;
100 }; 102 };
101 103
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 579a78702..7e57de78a 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -508,7 +508,7 @@ public:
508 /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if 508 /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if
509 /// necessary. 509 /// necessary.
510 std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type, 510 std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type,
511 bool is_array) { 511 bool is_array, bool is_shadow) {
512 const std::size_t offset = static_cast<std::size_t>(sampler.index.Value()); 512 const std::size_t offset = static_cast<std::size_t>(sampler.index.Value());
513 513
514 // If this sampler has already been used, return the existing mapping. 514 // If this sampler has already been used, return the existing mapping.
@@ -517,13 +517,14 @@ public:
517 [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; }); 517 [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; });
518 518
519 if (itr != used_samplers.end()) { 519 if (itr != used_samplers.end()) {
520 ASSERT(itr->GetType() == type && itr->IsArray() == is_array); 520 ASSERT(itr->GetType() == type && itr->IsArray() == is_array &&
521 itr->IsShadow() == is_shadow);
521 return itr->GetName(); 522 return itr->GetName();
522 } 523 }
523 524
524 // Otherwise create a new mapping for this sampler 525 // Otherwise create a new mapping for this sampler
525 const std::size_t next_index = used_samplers.size(); 526 const std::size_t next_index = used_samplers.size();
526 const SamplerEntry entry{stage, offset, next_index, type, is_array}; 527 const SamplerEntry entry{stage, offset, next_index, type, is_array, is_shadow};
527 used_samplers.emplace_back(entry); 528 used_samplers.emplace_back(entry);
528 return entry.GetName(); 529 return entry.GetName();
529 } 530 }
@@ -747,8 +748,9 @@ private:
747 } 748 }
748 749
749 /// Generates code representing a texture sampler. 750 /// Generates code representing a texture sampler.
750 std::string GetSampler(const Sampler& sampler, Tegra::Shader::TextureType type, bool is_array) { 751 std::string GetSampler(const Sampler& sampler, Tegra::Shader::TextureType type, bool is_array,
751 return regs.AccessSampler(sampler, type, is_array); 752 bool is_shadow) {
753 return regs.AccessSampler(sampler, type, is_array, is_shadow);
752 } 754 }
753 755
754 /** 756 /**
@@ -1002,6 +1004,24 @@ private:
1002 shader.AddLine('}'); 1004 shader.AddLine('}');
1003 } 1005 }
1004 1006
1007 static u32 TextureCoordinates(Tegra::Shader::TextureType texture_type) {
1008 switch (texture_type) {
1009 case Tegra::Shader::TextureType::Texture1D: {
1010 return 1;
1011 }
1012 case Tegra::Shader::TextureType::Texture2D: {
1013 return 2;
1014 }
1015 case Tegra::Shader::TextureType::TextureCube: {
1016 return 3;
1017 }
1018 default:
1019 LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", static_cast<u32>(texture_type));
1020 UNREACHABLE();
1021 return 0;
1022 }
1023 }
1024
1005 /* 1025 /*
1006 * Emits code to push the input target address to the SSY address stack, incrementing the stack 1026 * Emits code to push the input target address to the SSY address stack, incrementing the stack
1007 * top. 1027 * top.
@@ -1896,24 +1916,35 @@ private:
1896 "NODEP is not implemented"); 1916 "NODEP is not implemented");
1897 ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), 1917 ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
1898 "AOFFI is not implemented"); 1918 "AOFFI is not implemented");
1899 ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC),
1900 "DC is not implemented");
1901 1919
1902 switch (texture_type) { 1920 const bool depth_compare =
1903 case Tegra::Shader::TextureType::Texture1D: { 1921 instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
1922 u32 num_coordinates = TextureCoordinates(texture_type);
1923 if (depth_compare)
1924 num_coordinates += 1;
1925
1926 switch (num_coordinates) {
1927 case 1: {
1904 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 1928 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1905 coord = "float coords = " + x + ';'; 1929 coord = "float coords = " + x + ';';
1906 break; 1930 break;
1907 } 1931 }
1908 case Tegra::Shader::TextureType::Texture2D: { 1932 case 2: {
1909 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 1933 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1910 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 1934 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
1911 coord = "vec2 coords = vec2(" + x + ", " + y + ");"; 1935 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1912 break; 1936 break;
1913 } 1937 }
1938 case 3: {
1939 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1940 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
1941 const std::string z = regs.GetRegisterAsFloat(instr.gpr20);
1942 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");";
1943 break;
1944 }
1914 default: 1945 default:
1915 LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", 1946 LOG_CRITICAL(HW_GPU, "Unhandled coordinates number {}",
1916 static_cast<u32>(texture_type)); 1947 static_cast<u32>(num_coordinates));
1917 UNREACHABLE(); 1948 UNREACHABLE();
1918 1949
1919 // Fallback to interpreting as a 2D texture for now 1950 // Fallback to interpreting as a 2D texture for now
@@ -1924,9 +1955,10 @@ private:
1924 } 1955 }
1925 // TODO: make sure coordinates are always indexed to gpr8 and gpr20 is always bias 1956 // TODO: make sure coordinates are always indexed to gpr8 and gpr20 is always bias
1926 // or lod. 1957 // or lod.
1927 const std::string op_c = regs.GetRegisterAsFloat(instr.gpr20); 1958 std::string op_c;
1928 1959
1929 const std::string sampler = GetSampler(instr.sampler, texture_type, false); 1960 const std::string sampler =
1961 GetSampler(instr.sampler, texture_type, false, depth_compare);
1930 // Add an extra scope and declare the texture coords inside to prevent 1962 // Add an extra scope and declare the texture coords inside to prevent
1931 // overwriting them in case they are used as outputs of the texs instruction. 1963 // overwriting them in case they are used as outputs of the texs instruction.
1932 1964
@@ -1935,7 +1967,7 @@ private:
1935 shader.AddLine(coord); 1967 shader.AddLine(coord);
1936 std::string texture; 1968 std::string texture;
1937 1969
1938 switch (instr.tex.process_mode) { 1970 switch (instr.tex.GetTextureProcessMode()) {
1939 case Tegra::Shader::TextureProcessMode::None: { 1971 case Tegra::Shader::TextureProcessMode::None: {
1940 texture = "texture(" + sampler + ", coords)"; 1972 texture = "texture(" + sampler + ", coords)";
1941 break; 1973 break;
@@ -1946,12 +1978,22 @@ private:
1946 } 1978 }
1947 case Tegra::Shader::TextureProcessMode::LB: 1979 case Tegra::Shader::TextureProcessMode::LB:
1948 case Tegra::Shader::TextureProcessMode::LBA: { 1980 case Tegra::Shader::TextureProcessMode::LBA: {
1981 if (num_coordinates <= 2) {
1982 op_c = regs.GetRegisterAsFloat(instr.gpr20);
1983 } else {
1984 op_c = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1);
1985 }
1949 // TODO: Figure if A suffix changes the equation at all. 1986 // TODO: Figure if A suffix changes the equation at all.
1950 texture = "texture(" + sampler + ", coords, " + op_c + ')'; 1987 texture = "texture(" + sampler + ", coords, " + op_c + ')';
1951 break; 1988 break;
1952 } 1989 }
1953 case Tegra::Shader::TextureProcessMode::LL: 1990 case Tegra::Shader::TextureProcessMode::LL:
1954 case Tegra::Shader::TextureProcessMode::LLA: { 1991 case Tegra::Shader::TextureProcessMode::LLA: {
1992 if (num_coordinates <= 2) {
1993 op_c = regs.GetRegisterAsFloat(instr.gpr20);
1994 } else {
1995 op_c = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1);
1996 }
1955 // TODO: Figure if A suffix changes the equation at all. 1997 // TODO: Figure if A suffix changes the equation at all.
1956 texture = "textureLod(" + sampler + ", coords, " + op_c + ')'; 1998 texture = "textureLod(" + sampler + ", coords, " + op_c + ')';
1957 break; 1999 break;
@@ -1959,18 +2001,22 @@ private:
1959 default: { 2001 default: {
1960 texture = "texture(" + sampler + ", coords)"; 2002 texture = "texture(" + sampler + ", coords)";
1961 LOG_CRITICAL(HW_GPU, "Unhandled texture process mode {}", 2003 LOG_CRITICAL(HW_GPU, "Unhandled texture process mode {}",
1962 static_cast<u32>(instr.tex.process_mode.Value())); 2004 static_cast<u32>(instr.tex.GetTextureProcessMode()));
1963 UNREACHABLE(); 2005 UNREACHABLE();
1964 } 2006 }
1965 } 2007 }
1966 std::size_t dest_elem{}; 2008 if (!depth_compare) {
1967 for (std::size_t elem = 0; elem < 4; ++elem) { 2009 std::size_t dest_elem{};
1968 if (!instr.tex.IsComponentEnabled(elem)) { 2010 for (std::size_t elem = 0; elem < 4; ++elem) {
1969 // Skip disabled components 2011 if (!instr.tex.IsComponentEnabled(elem)) {
1970 continue; 2012 // Skip disabled components
2013 continue;
2014 }
2015 regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem);
2016 ++dest_elem;
1971 } 2017 }
1972 regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem); 2018 } else {
1973 ++dest_elem; 2019 regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false);
1974 } 2020 }
1975 --shader.scope; 2021 --shader.scope;
1976 shader.AddLine("}"); 2022 shader.AddLine("}");
@@ -1983,11 +2029,15 @@ private:
1983 2029
1984 ASSERT_MSG(!instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), 2030 ASSERT_MSG(!instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
1985 "NODEP is not implemented"); 2031 "NODEP is not implemented");
1986 ASSERT_MSG(!instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC),
1987 "DC is not implemented");
1988 2032
1989 switch (texture_type) { 2033 const bool depth_compare =
1990 case Tegra::Shader::TextureType::Texture2D: { 2034 instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
2035 u32 num_coordinates = TextureCoordinates(texture_type);
2036 if (depth_compare)
2037 num_coordinates += 1;
2038
2039 switch (num_coordinates) {
2040 case 2: {
1991 if (is_array) { 2041 if (is_array) {
1992 const std::string index = regs.GetRegisterAsInteger(instr.gpr8); 2042 const std::string index = regs.GetRegisterAsInteger(instr.gpr8);
1993 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2043 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
@@ -2000,17 +2050,25 @@ private:
2000 } 2050 }
2001 break; 2051 break;
2002 } 2052 }
2003 case Tegra::Shader::TextureType::TextureCube: { 2053 case 3: {
2004 ASSERT_MSG(!is_array, "Unimplemented"); 2054 if (is_array) {
2005 std::string x = regs.GetRegisterAsFloat(instr.gpr8); 2055 UNIMPLEMENTED_MSG("3-coordinate arrays not fully implemented");
2006 std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2056 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2007 std::string z = regs.GetRegisterAsFloat(instr.gpr20); 2057 const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
2008 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; 2058 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
2059 texture_type = Tegra::Shader::TextureType::Texture2D;
2060 is_array = false;
2061 } else {
2062 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2063 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2064 const std::string z = regs.GetRegisterAsFloat(instr.gpr20);
2065 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");";
2066 }
2009 break; 2067 break;
2010 } 2068 }
2011 default: 2069 default:
2012 LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", 2070 LOG_CRITICAL(HW_GPU, "Unhandled coordinates number {}",
2013 static_cast<u32>(texture_type)); 2071 static_cast<u32>(num_coordinates));
2014 UNREACHABLE(); 2072 UNREACHABLE();
2015 2073
2016 // Fallback to interpreting as a 2D texture for now 2074 // Fallback to interpreting as a 2D texture for now
@@ -2020,9 +2078,35 @@ private:
2020 texture_type = Tegra::Shader::TextureType::Texture2D; 2078 texture_type = Tegra::Shader::TextureType::Texture2D;
2021 is_array = false; 2079 is_array = false;
2022 } 2080 }
2023 const std::string sampler = GetSampler(instr.sampler, texture_type, is_array); 2081 const std::string sampler =
2024 const std::string texture = "texture(" + sampler + ", coords)"; 2082 GetSampler(instr.sampler, texture_type, is_array, depth_compare);
2025 WriteTexsInstruction(instr, coord, texture); 2083 std::string texture;
2084 switch (instr.texs.GetTextureProcessMode()) {
2085 case Tegra::Shader::TextureProcessMode::None: {
2086 texture = "texture(" + sampler + ", coords)";
2087 break;
2088 }
2089 case Tegra::Shader::TextureProcessMode::LZ: {
2090 texture = "textureLod(" + sampler + ", coords, 0.0)";
2091 break;
2092 }
2093 case Tegra::Shader::TextureProcessMode::LL: {
2094 const std::string op_c = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1);
2095 texture = "textureLod(" + sampler + ", coords, " + op_c + ')';
2096 break;
2097 }
2098 default: {
2099 texture = "texture(" + sampler + ", coords)";
2100 LOG_CRITICAL(HW_GPU, "Unhandled texture process mode {}",
2101 static_cast<u32>(instr.texs.GetTextureProcessMode()));
2102 UNREACHABLE();
2103 }
2104 }
2105 if (!depth_compare) {
2106 WriteTexsInstruction(instr, coord, texture);
2107 } else {
2108 WriteTexsInstruction(instr, coord, "vec4(" + texture + ')');
2109 }
2026 break; 2110 break;
2027 } 2111 }
2028 case OpCode::Id::TLDS: { 2112 case OpCode::Id::TLDS: {
@@ -2062,9 +2146,26 @@ private:
2062 static_cast<u32>(texture_type)); 2146 static_cast<u32>(texture_type));
2063 UNREACHABLE(); 2147 UNREACHABLE();
2064 } 2148 }
2065 2149 const std::string sampler =
2066 const std::string sampler = GetSampler(instr.sampler, texture_type, is_array); 2150 GetSampler(instr.sampler, texture_type, is_array, false);
2067 const std::string texture = "texelFetch(" + sampler + ", coords, 0)"; 2151 std::string texture = "texelFetch(" + sampler + ", coords, 0)";
2152 const std::string op_c = regs.GetRegisterAsInteger(instr.gpr20.Value() + 1);
2153 switch (instr.tlds.GetTextureProcessMode()) {
2154 case Tegra::Shader::TextureProcessMode::LZ: {
2155 texture = "texelFetch(" + sampler + ", coords, 0)";
2156 break;
2157 }
2158 case Tegra::Shader::TextureProcessMode::LL: {
2159 texture = "texelFetch(" + sampler + ", coords, " + op_c + ')';
2160 break;
2161 }
2162 default: {
2163 texture = "texelFetch(" + sampler + ", coords, 0)";
2164 LOG_CRITICAL(HW_GPU, "Unhandled texture process mode {}",
2165 static_cast<u32>(instr.tlds.GetTextureProcessMode()));
2166 UNREACHABLE();
2167 }
2168 }
2068 WriteTexsInstruction(instr, coord, texture); 2169 WriteTexsInstruction(instr, coord, texture);
2069 break; 2170 break;
2070 } 2171 }
@@ -2077,28 +2178,43 @@ private:
2077 "NODEP is not implemented"); 2178 "NODEP is not implemented");
2078 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), 2179 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
2079 "AOFFI is not implemented"); 2180 "AOFFI is not implemented");
2080 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC),
2081 "DC is not implemented");
2082 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV), 2181 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV),
2083 "NDV is not implemented"); 2182 "NDV is not implemented");
2084 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::PTP), 2183 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::PTP),
2085 "PTP is not implemented"); 2184 "PTP is not implemented");
2086 2185 const bool depth_compare =
2087 switch (instr.tld4.texture_type) { 2186 instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
2088 case Tegra::Shader::TextureType::Texture2D: { 2187 auto texture_type = instr.tld4.texture_type.Value();
2188 u32 num_coordinates = TextureCoordinates(texture_type);
2189 if (depth_compare)
2190 num_coordinates += 1;
2191
2192 switch (num_coordinates) {
2193 case 2: {
2089 const std::string x = regs.GetRegisterAsFloat(instr.gpr8); 2194 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2090 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2195 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2091 coord = "vec2 coords = vec2(" + x + ", " + y + ");"; 2196 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
2092 break; 2197 break;
2093 } 2198 }
2199 case 3: {
2200 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2201 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2202 const std::string z = regs.GetRegisterAsFloat(instr.gpr8.Value() + 2);
2203 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");";
2204 break;
2205 }
2094 default: 2206 default:
2095 LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", 2207 LOG_CRITICAL(HW_GPU, "Unhandled coordinates number {}",
2096 static_cast<u32>(instr.tld4.texture_type.Value())); 2208 static_cast<u32>(num_coordinates));
2097 UNREACHABLE(); 2209 UNREACHABLE();
2210 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2211 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2212 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
2213 texture_type = Tegra::Shader::TextureType::Texture2D;
2098 } 2214 }
2099 2215
2100 const std::string sampler = 2216 const std::string sampler =
2101 GetSampler(instr.sampler, instr.tld4.texture_type, false); 2217 GetSampler(instr.sampler, texture_type, false, depth_compare);
2102 // Add an extra scope and declare the texture coords inside to prevent 2218 // Add an extra scope and declare the texture coords inside to prevent
2103 // overwriting them in case they are used as outputs of the texs instruction. 2219 // overwriting them in case they are used as outputs of the texs instruction.
2104 shader.AddLine("{"); 2220 shader.AddLine("{");
@@ -2106,15 +2222,18 @@ private:
2106 shader.AddLine(coord); 2222 shader.AddLine(coord);
2107 const std::string texture = "textureGather(" + sampler + ", coords, " + 2223 const std::string texture = "textureGather(" + sampler + ", coords, " +
2108 std::to_string(instr.tld4.component) + ')'; 2224 std::to_string(instr.tld4.component) + ')';
2109 2225 if (!depth_compare) {
2110 std::size_t dest_elem{}; 2226 std::size_t dest_elem{};
2111 for (std::size_t elem = 0; elem < 4; ++elem) { 2227 for (std::size_t elem = 0; elem < 4; ++elem) {
2112 if (!instr.tex.IsComponentEnabled(elem)) { 2228 if (!instr.tex.IsComponentEnabled(elem)) {
2113 // Skip disabled components 2229 // Skip disabled components
2114 continue; 2230 continue;
2231 }
2232 regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem);
2233 ++dest_elem;
2115 } 2234 }
2116 regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem); 2235 } else {
2117 ++dest_elem; 2236 regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false);
2118 } 2237 }
2119 --shader.scope; 2238 --shader.scope;
2120 shader.AddLine("}"); 2239 shader.AddLine("}");
@@ -2125,18 +2244,30 @@ private:
2125 "NODEP is not implemented"); 2244 "NODEP is not implemented");
2126 ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), 2245 ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
2127 "AOFFI is not implemented"); 2246 "AOFFI is not implemented");
2128 ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC),
2129 "DC is not implemented");
2130 2247
2248 const bool depth_compare =
2249 instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
2131 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 2250 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
2132 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); 2251 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);
2133 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. 2252 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction.
2134 const std::string sampler = 2253 const std::string sampler = GetSampler(
2135 GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false); 2254 instr.sampler, Tegra::Shader::TextureType::Texture2D, false, depth_compare);
2136 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; 2255 std::string coord;
2256 if (!depth_compare) {
2257 coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
2258 } else {
2259 // Note: TLD4S coordinate encoding works just like TEXS's
2260 const std::string op_c = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2261 coord = "vec3 coords = vec3(" + op_a + ", " + op_c + ", " + op_b + ");";
2262 }
2137 const std::string texture = "textureGather(" + sampler + ", coords, " + 2263 const std::string texture = "textureGather(" + sampler + ", coords, " +
2138 std::to_string(instr.tld4s.component) + ')'; 2264 std::to_string(instr.tld4s.component) + ')';
2139 WriteTexsInstruction(instr, coord, texture); 2265
2266 if (!depth_compare) {
2267 WriteTexsInstruction(instr, coord, texture);
2268 } else {
2269 WriteTexsInstruction(instr, coord, "vec4(" + texture + ')');
2270 }
2140 break; 2271 break;
2141 } 2272 }
2142 case OpCode::Id::TXQ: { 2273 case OpCode::Id::TXQ: {
@@ -2147,7 +2278,7 @@ private:
2147 // Sadly, not all texture instructions specify the type of texture their sampler 2278 // Sadly, not all texture instructions specify the type of texture their sampler
2148 // uses. This must be fixed at a later instance. 2279 // uses. This must be fixed at a later instance.
2149 const std::string sampler = 2280 const std::string sampler =
2150 GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false); 2281 GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false, false);
2151 switch (instr.txq.query_type) { 2282 switch (instr.txq.query_type) {
2152 case Tegra::Shader::TextureQueryType::Dimension: { 2283 case Tegra::Shader::TextureQueryType::Dimension: {
2153 const std::string texture = "textureQueryLevels(" + sampler + ')'; 2284 const std::string texture = "textureQueryLevels(" + sampler + ')';
@@ -2172,7 +2303,8 @@ private:
2172 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 2303 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2173 const bool is_array = instr.tmml.array != 0; 2304 const bool is_array = instr.tmml.array != 0;
2174 auto texture_type = instr.tmml.texture_type.Value(); 2305 auto texture_type = instr.tmml.texture_type.Value();
2175 const std::string sampler = GetSampler(instr.sampler, texture_type, is_array); 2306 const std::string sampler =
2307 GetSampler(instr.sampler, texture_type, is_array, false);
2176 2308
2177 // TODO: add coordinates for different samplers once other texture types are 2309 // TODO: add coordinates for different samplers once other texture types are
2178 // implemented. 2310 // implemented.
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h
index d53b93ad5..e56f39e78 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.h
+++ b/src/video_core/renderer_opengl/gl_shader_gen.h
@@ -75,8 +75,9 @@ class SamplerEntry {
75 75
76public: 76public:
77 SamplerEntry(Maxwell::ShaderStage stage, std::size_t offset, std::size_t index, 77 SamplerEntry(Maxwell::ShaderStage stage, std::size_t offset, std::size_t index,
78 Tegra::Shader::TextureType type, bool is_array) 78 Tegra::Shader::TextureType type, bool is_array, bool is_shadow)
79 : offset(offset), stage(stage), sampler_index(index), type(type), is_array(is_array) {} 79 : offset(offset), stage(stage), sampler_index(index), type(type), is_array(is_array),
80 is_shadow(is_shadow) {}
80 81
81 std::size_t GetOffset() const { 82 std::size_t GetOffset() const {
82 return offset; 83 return offset;
@@ -117,6 +118,8 @@ public:
117 } 118 }
118 if (is_array) 119 if (is_array)
119 glsl_type += "Array"; 120 glsl_type += "Array";
121 if (is_shadow)
122 glsl_type += "Shadow";
120 return glsl_type; 123 return glsl_type;
121 } 124 }
122 125
@@ -128,6 +131,10 @@ public:
128 return is_array; 131 return is_array;
129 } 132 }
130 133
134 bool IsShadow() const {
135 return is_shadow;
136 }
137
131 u32 GetHash() const { 138 u32 GetHash() const {
132 return (static_cast<u32>(stage) << 16) | static_cast<u32>(sampler_index); 139 return (static_cast<u32>(stage) << 16) | static_cast<u32>(sampler_index);
133 } 140 }
@@ -147,7 +154,8 @@ private:
147 Maxwell::ShaderStage stage; ///< Shader stage where this sampler was used. 154 Maxwell::ShaderStage stage; ///< Shader stage where this sampler was used.
148 std::size_t sampler_index; ///< Value used to index into the generated GLSL sampler array. 155 std::size_t sampler_index; ///< Value used to index into the generated GLSL sampler array.
149 Tegra::Shader::TextureType type; ///< The type used to sample this texture (Texture2D, etc) 156 Tegra::Shader::TextureType type; ///< The type used to sample this texture (Texture2D, etc)
150 bool is_array; ///< Whether the texture is being sampled as an array texture or not. 157 bool is_array; ///< Whether the texture is being sampled as an array texture or not.
158 bool is_shadow; ///< Whether the texture is being sampled as a depth texture or not.
151}; 159};
152 160
153struct ShaderEntries { 161struct ShaderEntries {
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 67273e164..3c3bcaae4 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -159,6 +159,31 @@ inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) {
159 return {}; 159 return {};
160} 160}
161 161
162inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) {
163 switch (func) {
164 case Tegra::Texture::DepthCompareFunc::Never:
165 return GL_NEVER;
166 case Tegra::Texture::DepthCompareFunc::Less:
167 return GL_LESS;
168 case Tegra::Texture::DepthCompareFunc::LessEqual:
169 return GL_LEQUAL;
170 case Tegra::Texture::DepthCompareFunc::Equal:
171 return GL_EQUAL;
172 case Tegra::Texture::DepthCompareFunc::NotEqual:
173 return GL_NOTEQUAL;
174 case Tegra::Texture::DepthCompareFunc::Greater:
175 return GL_GREATER;
176 case Tegra::Texture::DepthCompareFunc::GreaterEqual:
177 return GL_GEQUAL;
178 case Tegra::Texture::DepthCompareFunc::Always:
179 return GL_ALWAYS;
180 }
181 LOG_CRITICAL(Render_OpenGL, "Unimplemented texture depth compare function ={}",
182 static_cast<u32>(func));
183 UNREACHABLE();
184 return {};
185}
186
162inline GLenum BlendEquation(Maxwell::Blend::Equation equation) { 187inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
163 switch (equation) { 188 switch (equation) {
164 case Maxwell::Blend::Equation::Add: 189 case Maxwell::Blend::Equation::Add:
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index 14aea4838..8f31d825a 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -227,6 +227,17 @@ enum class WrapMode : u32 {
227 MirrorOnceClampOGL = 7, 227 MirrorOnceClampOGL = 7,
228}; 228};
229 229
230enum class DepthCompareFunc : u32 {
231 Never = 0,
232 Less = 1,
233 Equal = 2,
234 LessEqual = 3,
235 Greater = 4,
236 NotEqual = 5,
237 GreaterEqual = 6,
238 Always = 7,
239};
240
230enum class TextureFilter : u32 { 241enum class TextureFilter : u32 {
231 Nearest = 1, 242 Nearest = 1,
232 Linear = 2, 243 Linear = 2,
@@ -244,7 +255,7 @@ struct TSCEntry {
244 BitField<3, 3, WrapMode> wrap_v; 255 BitField<3, 3, WrapMode> wrap_v;
245 BitField<6, 3, WrapMode> wrap_p; 256 BitField<6, 3, WrapMode> wrap_p;
246 BitField<9, 1, u32> depth_compare_enabled; 257 BitField<9, 1, u32> depth_compare_enabled;
247 BitField<10, 3, u32> depth_compare_func; 258 BitField<10, 3, DepthCompareFunc> depth_compare_func;
248 }; 259 };
249 union { 260 union {
250 BitField<0, 2, TextureFilter> mag_filter; 261 BitField<0, 2, TextureFilter> mag_filter;