Implemented Depth Compare and Shadow Samplers
This commit is contained in:
		| @@ -601,10 +601,13 @@ void RasterizerOpenGL::SamplerInfo::Create() { | ||||
|     sampler.Create(); | ||||
|     mag_filter = min_filter = Tegra::Texture::TextureFilter::Linear; | ||||
|     wrap_u = wrap_v = wrap_p = Tegra::Texture::WrapMode::Wrap; | ||||
|     uses_depth_compare = false; | ||||
|     depth_compare_func = Tegra::Texture::DepthCompareFunc::Never; | ||||
|  | ||||
|     // default is GL_LINEAR_MIPMAP_LINEAR | ||||
|     glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||
|     // Other attributes have correct defaults | ||||
|     glSamplerParameteri(sampler.handle, GL_TEXTURE_COMPARE_FUNC, GL_NEVER); | ||||
| } | ||||
|  | ||||
| void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntry& config) { | ||||
| @@ -632,6 +635,21 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr | ||||
|         glSamplerParameteri(s, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(wrap_p)); | ||||
|     } | ||||
|  | ||||
|     if (uses_depth_compare != (config.depth_compare_enabled == 1)) { | ||||
|         uses_depth_compare = (config.depth_compare_enabled == 1); | ||||
|         if (uses_depth_compare) { | ||||
|             glSamplerParameteri(s, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); | ||||
|         } else { | ||||
|             glSamplerParameteri(s, GL_TEXTURE_COMPARE_MODE, GL_NONE); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (depth_compare_func != config.depth_compare_func) { | ||||
|         depth_compare_func = config.depth_compare_func; | ||||
|         glSamplerParameteri(s, GL_TEXTURE_COMPARE_FUNC, | ||||
|                             MaxwellToGL::DepthCompareFunc(depth_compare_func)); | ||||
|     } | ||||
|  | ||||
|     if (wrap_u == Tegra::Texture::WrapMode::Border || wrap_v == Tegra::Texture::WrapMode::Border || | ||||
|         wrap_p == Tegra::Texture::WrapMode::Border) { | ||||
|         const GLvec4 new_border_color = {{config.border_color_r, config.border_color_g, | ||||
|   | ||||
| @@ -94,6 +94,8 @@ private: | ||||
|         Tegra::Texture::WrapMode wrap_u; | ||||
|         Tegra::Texture::WrapMode wrap_v; | ||||
|         Tegra::Texture::WrapMode wrap_p; | ||||
|         bool uses_depth_compare; | ||||
|         Tegra::Texture::DepthCompareFunc depth_compare_func; | ||||
|         GLvec4 border_color; | ||||
|     }; | ||||
|  | ||||
|   | ||||
| @@ -508,7 +508,7 @@ public: | ||||
|     /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if | ||||
|     /// necessary. | ||||
|     std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type, | ||||
|                               bool is_array) { | ||||
|                               bool is_array, bool is_shadow) { | ||||
|         const std::size_t offset = static_cast<std::size_t>(sampler.index.Value()); | ||||
|  | ||||
|         // If this sampler has already been used, return the existing mapping. | ||||
| @@ -517,13 +517,14 @@ public: | ||||
|                          [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; }); | ||||
|  | ||||
|         if (itr != used_samplers.end()) { | ||||
|             ASSERT(itr->GetType() == type && itr->IsArray() == is_array); | ||||
|             ASSERT(itr->GetType() == type && itr->IsArray() == is_array && | ||||
|                    itr->IsShadow() == is_shadow); | ||||
|             return itr->GetName(); | ||||
|         } | ||||
|  | ||||
|         // Otherwise create a new mapping for this sampler | ||||
|         const std::size_t next_index = used_samplers.size(); | ||||
|         const SamplerEntry entry{stage, offset, next_index, type, is_array}; | ||||
|         const SamplerEntry entry{stage, offset, next_index, type, is_array, is_shadow}; | ||||
|         used_samplers.emplace_back(entry); | ||||
|         return entry.GetName(); | ||||
|     } | ||||
| @@ -747,8 +748,9 @@ private: | ||||
|     } | ||||
|  | ||||
|     /// Generates code representing a texture sampler. | ||||
|     std::string GetSampler(const Sampler& sampler, Tegra::Shader::TextureType type, bool is_array) { | ||||
|         return regs.AccessSampler(sampler, type, is_array); | ||||
|     std::string GetSampler(const Sampler& sampler, Tegra::Shader::TextureType type, bool is_array, | ||||
|                            bool is_shadow) { | ||||
|         return regs.AccessSampler(sampler, type, is_array, is_shadow); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -1002,6 +1004,24 @@ private: | ||||
|         shader.AddLine('}'); | ||||
|     } | ||||
|  | ||||
|     static u32 TextureCoordinates(Tegra::Shader::TextureType texture_type) { | ||||
|         switch (texture_type) { | ||||
|         case Tegra::Shader::TextureType::Texture1D: { | ||||
|             return 1; | ||||
|         } | ||||
|         case Tegra::Shader::TextureType::Texture2D: { | ||||
|             return 2; | ||||
|         } | ||||
|         case Tegra::Shader::TextureType::TextureCube: { | ||||
|             return 3; | ||||
|         } | ||||
|         default: | ||||
|             LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", static_cast<u32>(texture_type)); | ||||
|             UNREACHABLE(); | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * Emits code to push the input target address to the SSY address stack, incrementing the stack | ||||
|      * top. | ||||
| @@ -1896,24 +1916,35 @@ private: | ||||
|                            "NODEP is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | ||||
|                            "AOFFI is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC), | ||||
|                            "DC is not implemented"); | ||||
|  | ||||
|                 switch (texture_type) { | ||||
|                 case Tegra::Shader::TextureType::Texture1D: { | ||||
|                 const bool depth_compare = | ||||
|                     instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); | ||||
|                 u32 num_coordinates = TextureCoordinates(texture_type); | ||||
|                 if (depth_compare) | ||||
|                     num_coordinates += 1; | ||||
|  | ||||
|                 switch (num_coordinates) { | ||||
|                 case 1: { | ||||
|                     const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|                     coord = "float coords = " + x + ';'; | ||||
|                     break; | ||||
|                 } | ||||
|                 case Tegra::Shader::TextureType::Texture2D: { | ||||
|                 case 2: { | ||||
|                     const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|                     const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||||
|                     coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||||
|                     break; | ||||
|                 } | ||||
|                 case 3: { | ||||
|                     const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|                     const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||||
|                     const std::string z = regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                     coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; | ||||
|                     break; | ||||
|                 } | ||||
|                 default: | ||||
|                     LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", | ||||
|                                  static_cast<u32>(texture_type)); | ||||
|                     LOG_CRITICAL(HW_GPU, "Unhandled coordinates number {}", | ||||
|                                  static_cast<u32>(num_coordinates)); | ||||
|                     UNREACHABLE(); | ||||
|  | ||||
|                     // Fallback to interpreting as a 2D texture for now | ||||
| @@ -1924,9 +1955,10 @@ private: | ||||
|                 } | ||||
|                 // TODO: make sure coordinates are always indexed to gpr8 and gpr20 is always bias | ||||
|                 // or lod. | ||||
|                 const std::string op_c = regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                 std::string op_c; | ||||
|  | ||||
|                 const std::string sampler = GetSampler(instr.sampler, texture_type, false); | ||||
|                 const std::string sampler = | ||||
|                     GetSampler(instr.sampler, texture_type, false, depth_compare); | ||||
|                 // Add an extra scope and declare the texture coords inside to prevent | ||||
|                 // overwriting them in case they are used as outputs of the texs instruction. | ||||
|  | ||||
| @@ -1946,12 +1978,22 @@ private: | ||||
|                 } | ||||
|                 case Tegra::Shader::TextureProcessMode::LB: | ||||
|                 case Tegra::Shader::TextureProcessMode::LBA: { | ||||
|                     if (num_coordinates <= 2) { | ||||
|                         op_c = regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                     } else { | ||||
|                         op_c = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1); | ||||
|                     } | ||||
|                     // TODO: Figure if A suffix changes the equation at all. | ||||
|                     texture = "texture(" + sampler + ", coords, " + op_c + ')'; | ||||
|                     break; | ||||
|                 } | ||||
|                 case Tegra::Shader::TextureProcessMode::LL: | ||||
|                 case Tegra::Shader::TextureProcessMode::LLA: { | ||||
|                     if (num_coordinates <= 2) { | ||||
|                         op_c = regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                     } else { | ||||
|                         op_c = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1); | ||||
|                     } | ||||
|                     // TODO: Figure if A suffix changes the equation at all. | ||||
|                     texture = "textureLod(" + sampler + ", coords, " + op_c + ')'; | ||||
|                     break; | ||||
| @@ -1963,14 +2005,18 @@ private: | ||||
|                     UNREACHABLE(); | ||||
|                 } | ||||
|                 } | ||||
|                 std::size_t dest_elem{}; | ||||
|                 for (std::size_t elem = 0; elem < 4; ++elem) { | ||||
|                     if (!instr.tex.IsComponentEnabled(elem)) { | ||||
|                         // Skip disabled components | ||||
|                         continue; | ||||
|                 if (!depth_compare) { | ||||
|                     std::size_t dest_elem{}; | ||||
|                     for (std::size_t elem = 0; elem < 4; ++elem) { | ||||
|                         if (!instr.tex.IsComponentEnabled(elem)) { | ||||
|                             // Skip disabled components | ||||
|                             continue; | ||||
|                         } | ||||
|                         regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem); | ||||
|                         ++dest_elem; | ||||
|                     } | ||||
|                     regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem); | ||||
|                     ++dest_elem; | ||||
|                 } else { | ||||
|                     regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false); | ||||
|                 } | ||||
|                 --shader.scope; | ||||
|                 shader.AddLine("}"); | ||||
| @@ -1983,11 +2029,15 @@ private: | ||||
|  | ||||
|                 ASSERT_MSG(!instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | ||||
|                            "NODEP is not implemented"); | ||||
|                 ASSERT_MSG(!instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC), | ||||
|                            "DC is not implemented"); | ||||
|  | ||||
|                 switch (texture_type) { | ||||
|                 case Tegra::Shader::TextureType::Texture2D: { | ||||
|                 const bool depth_compare = | ||||
|                     instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); | ||||
|                 u32 num_coordinates = TextureCoordinates(texture_type); | ||||
|                 if (depth_compare) | ||||
|                     num_coordinates += 1; | ||||
|  | ||||
|                 switch (num_coordinates) { | ||||
|                 case 2: { | ||||
|                     if (is_array) { | ||||
|                         const std::string index = regs.GetRegisterAsInteger(instr.gpr8); | ||||
|                         const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||||
| @@ -2000,17 +2050,25 @@ private: | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|                 case Tegra::Shader::TextureType::TextureCube: { | ||||
|                     ASSERT_MSG(!is_array, "Unimplemented"); | ||||
|                     std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|                     std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||||
|                     std::string z = regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                     coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; | ||||
|                 case 3: { | ||||
|                     if (is_array) { | ||||
|                         UNIMPLEMENTED_MSG("3-coordinate arrays not fully implemented"); | ||||
|                         const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|                         const std::string y = regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                         coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||||
|                         texture_type = Tegra::Shader::TextureType::Texture2D; | ||||
|                         is_array = false; | ||||
|                     } else { | ||||
|                         const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|                         const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||||
|                         const std::string z = regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                         coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|                 default: | ||||
|                     LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", | ||||
|                                  static_cast<u32>(texture_type)); | ||||
|                     LOG_CRITICAL(HW_GPU, "Unhandled coordinates number {}", | ||||
|                                  static_cast<u32>(num_coordinates)); | ||||
|                     UNREACHABLE(); | ||||
|  | ||||
|                     // Fallback to interpreting as a 2D texture for now | ||||
| @@ -2020,9 +2078,9 @@ private: | ||||
|                     texture_type = Tegra::Shader::TextureType::Texture2D; | ||||
|                     is_array = false; | ||||
|                 } | ||||
|                 const std::string sampler = GetSampler(instr.sampler, texture_type, is_array); | ||||
|                 const std::string sampler = | ||||
|                     GetSampler(instr.sampler, texture_type, is_array, depth_compare); | ||||
|                 std::string texture; | ||||
|                 const std::string op_c = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1); | ||||
|                 switch (instr.texs.GetTextureProcessMode()) { | ||||
|                 case Tegra::Shader::TextureProcessMode::None: { | ||||
|                     texture = "texture(" + sampler + ", coords)"; | ||||
| @@ -2033,6 +2091,7 @@ private: | ||||
|                     break; | ||||
|                 } | ||||
|                 case Tegra::Shader::TextureProcessMode::LL: { | ||||
|                     const std::string op_c = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1); | ||||
|                     texture = "textureLod(" + sampler + ", coords, " + op_c + ')'; | ||||
|                     break; | ||||
|                 } | ||||
| @@ -2043,7 +2102,11 @@ private: | ||||
|                     UNREACHABLE(); | ||||
|                 } | ||||
|                 } | ||||
|                 WriteTexsInstruction(instr, coord, texture); | ||||
|                 if (!depth_compare) { | ||||
|                     WriteTexsInstruction(instr, coord, texture); | ||||
|                 } else { | ||||
|                     WriteTexsInstruction(instr, coord, "vec4(" + texture + ')'); | ||||
|                 } | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::TLDS: { | ||||
| @@ -2083,7 +2146,8 @@ private: | ||||
|                                  static_cast<u32>(texture_type)); | ||||
|                     UNREACHABLE(); | ||||
|                 } | ||||
|                 const std::string sampler = GetSampler(instr.sampler, texture_type, is_array); | ||||
|                 const std::string sampler = | ||||
|                     GetSampler(instr.sampler, texture_type, is_array, false); | ||||
|                 std::string texture = "texelFetch(" + sampler + ", coords, 0)"; | ||||
|                 const std::string op_c = regs.GetRegisterAsInteger(instr.gpr20.Value() + 1); | ||||
|                 switch (instr.tlds.GetTextureProcessMode()) { | ||||
| @@ -2114,28 +2178,43 @@ private: | ||||
|                            "NODEP is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | ||||
|                            "AOFFI is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC), | ||||
|                            "DC is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV), | ||||
|                            "NDV is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::PTP), | ||||
|                            "PTP is not implemented"); | ||||
|                 const bool depth_compare = | ||||
|                     instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); | ||||
|                 auto texture_type = instr.tld4.texture_type.Value(); | ||||
|                 u32 num_coordinates = TextureCoordinates(texture_type); | ||||
|                 if (depth_compare) | ||||
|                     num_coordinates += 1; | ||||
|  | ||||
|                 switch (instr.tld4.texture_type) { | ||||
|                 case Tegra::Shader::TextureType::Texture2D: { | ||||
|                 switch (num_coordinates) { | ||||
|                 case 2: { | ||||
|                     const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|                     const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||||
|                     coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||||
|                     break; | ||||
|                 } | ||||
|                 case 3: { | ||||
|                     const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|                     const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||||
|                     const std::string z = regs.GetRegisterAsFloat(instr.gpr8.Value() + 2); | ||||
|                     coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; | ||||
|                     break; | ||||
|                 } | ||||
|                 default: | ||||
|                     LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", | ||||
|                                  static_cast<u32>(instr.tld4.texture_type.Value())); | ||||
|                     LOG_CRITICAL(HW_GPU, "Unhandled coordinates number {}", | ||||
|                                  static_cast<u32>(num_coordinates)); | ||||
|                     UNREACHABLE(); | ||||
|                     const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|                     const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||||
|                     coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||||
|                     texture_type = Tegra::Shader::TextureType::Texture2D; | ||||
|                 } | ||||
|  | ||||
|                 const std::string sampler = | ||||
|                     GetSampler(instr.sampler, instr.tld4.texture_type, false); | ||||
|                     GetSampler(instr.sampler, texture_type, false, depth_compare); | ||||
|                 // Add an extra scope and declare the texture coords inside to prevent | ||||
|                 // overwriting them in case they are used as outputs of the texs instruction. | ||||
|                 shader.AddLine("{"); | ||||
| @@ -2143,15 +2222,18 @@ private: | ||||
|                 shader.AddLine(coord); | ||||
|                 const std::string texture = "textureGather(" + sampler + ", coords, " + | ||||
|                                             std::to_string(instr.tld4.component) + ')'; | ||||
|  | ||||
|                 std::size_t dest_elem{}; | ||||
|                 for (std::size_t elem = 0; elem < 4; ++elem) { | ||||
|                     if (!instr.tex.IsComponentEnabled(elem)) { | ||||
|                         // Skip disabled components | ||||
|                         continue; | ||||
|                 if (!depth_compare) { | ||||
|                     std::size_t dest_elem{}; | ||||
|                     for (std::size_t elem = 0; elem < 4; ++elem) { | ||||
|                         if (!instr.tex.IsComponentEnabled(elem)) { | ||||
|                             // Skip disabled components | ||||
|                             continue; | ||||
|                         } | ||||
|                         regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem); | ||||
|                         ++dest_elem; | ||||
|                     } | ||||
|                     regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem); | ||||
|                     ++dest_elem; | ||||
|                 } else { | ||||
|                     regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false); | ||||
|                 } | ||||
|                 --shader.scope; | ||||
|                 shader.AddLine("}"); | ||||
| @@ -2162,18 +2244,30 @@ private: | ||||
|                            "NODEP is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | ||||
|                            "AOFFI is not implemented"); | ||||
|                 ASSERT_MSG(!instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC), | ||||
|                            "DC is not implemented"); | ||||
|  | ||||
|                 const bool depth_compare = | ||||
|                     instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); | ||||
|                 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|                 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); | ||||
|                 // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. | ||||
|                 const std::string sampler = | ||||
|                     GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false); | ||||
|                 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; | ||||
|                 const std::string sampler = GetSampler( | ||||
|                     instr.sampler, Tegra::Shader::TextureType::Texture2D, false, depth_compare); | ||||
|                 std::string coord; | ||||
|                 if (!depth_compare) { | ||||
|                     coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; | ||||
|                 } else { | ||||
|                     // Note: TLD4S coordinate encoding works just like TEXS's | ||||
|                     const std::string op_c = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||||
|                     coord = "vec3 coords = vec3(" + op_a + ", " + op_c + ", " + op_b + ");"; | ||||
|                 } | ||||
|                 const std::string texture = "textureGather(" + sampler + ", coords, " + | ||||
|                                             std::to_string(instr.tld4s.component) + ')'; | ||||
|                 WriteTexsInstruction(instr, coord, texture); | ||||
|  | ||||
|                 if (!depth_compare) { | ||||
|                     WriteTexsInstruction(instr, coord, texture); | ||||
|                 } else { | ||||
|                     WriteTexsInstruction(instr, coord, "vec4(" + texture + ')'); | ||||
|                 } | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::TXQ: { | ||||
| @@ -2184,7 +2278,7 @@ private: | ||||
|                 // Sadly, not all texture instructions specify the type of texture their sampler | ||||
|                 // uses. This must be fixed at a later instance. | ||||
|                 const std::string sampler = | ||||
|                     GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false); | ||||
|                     GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false, false); | ||||
|                 switch (instr.txq.query_type) { | ||||
|                 case Tegra::Shader::TextureQueryType::Dimension: { | ||||
|                     const std::string texture = "textureQueryLevels(" + sampler + ')'; | ||||
| @@ -2209,7 +2303,8 @@ private: | ||||
|                 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||||
|                 const bool is_array = instr.tmml.array != 0; | ||||
|                 auto texture_type = instr.tmml.texture_type.Value(); | ||||
|                 const std::string sampler = GetSampler(instr.sampler, texture_type, is_array); | ||||
|                 const std::string sampler = | ||||
|                     GetSampler(instr.sampler, texture_type, is_array, false); | ||||
|  | ||||
|                 // TODO: add coordinates for different samplers once other texture types are | ||||
|                 // implemented. | ||||
|   | ||||
| @@ -75,8 +75,9 @@ class SamplerEntry { | ||||
|  | ||||
| public: | ||||
|     SamplerEntry(Maxwell::ShaderStage stage, std::size_t offset, std::size_t index, | ||||
|                  Tegra::Shader::TextureType type, bool is_array) | ||||
|         : offset(offset), stage(stage), sampler_index(index), type(type), is_array(is_array) {} | ||||
|                  Tegra::Shader::TextureType type, bool is_array, bool is_shadow) | ||||
|         : offset(offset), stage(stage), sampler_index(index), type(type), is_array(is_array), | ||||
|           is_shadow(is_shadow) {} | ||||
|  | ||||
|     std::size_t GetOffset() const { | ||||
|         return offset; | ||||
| @@ -117,6 +118,8 @@ public: | ||||
|         } | ||||
|         if (is_array) | ||||
|             glsl_type += "Array"; | ||||
|         if (is_shadow) | ||||
|             glsl_type += "Shadow"; | ||||
|         return glsl_type; | ||||
|     } | ||||
|  | ||||
| @@ -128,6 +131,10 @@ public: | ||||
|         return is_array; | ||||
|     } | ||||
|  | ||||
|     bool IsShadow() const { | ||||
|         return is_shadow; | ||||
|     } | ||||
|  | ||||
|     u32 GetHash() const { | ||||
|         return (static_cast<u32>(stage) << 16) | static_cast<u32>(sampler_index); | ||||
|     } | ||||
| @@ -147,7 +154,8 @@ private: | ||||
|     Maxwell::ShaderStage stage;      ///< Shader stage where this sampler was used. | ||||
|     std::size_t sampler_index;       ///< Value used to index into the generated GLSL sampler array. | ||||
|     Tegra::Shader::TextureType type; ///< The type used to sample this texture (Texture2D, etc) | ||||
|     bool is_array; ///< Whether the texture is being sampled as an array texture or not. | ||||
|     bool is_array;  ///< Whether the texture is being sampled as an array texture or not. | ||||
|     bool is_shadow; ///< Whether the texture is being sampled as a depth texture or not. | ||||
| }; | ||||
|  | ||||
| struct ShaderEntries { | ||||
|   | ||||
| @@ -159,6 +159,31 @@ inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) { | ||||
|     return {}; | ||||
| } | ||||
|  | ||||
| inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) { | ||||
|     switch (func) { | ||||
|     case Tegra::Texture::DepthCompareFunc::Never: | ||||
|         return GL_NEVER; | ||||
|     case Tegra::Texture::DepthCompareFunc::Less: | ||||
|         return GL_LESS; | ||||
|     case Tegra::Texture::DepthCompareFunc::LessEqual: | ||||
|         return GL_LEQUAL; | ||||
|     case Tegra::Texture::DepthCompareFunc::Equal: | ||||
|         return GL_EQUAL; | ||||
|     case Tegra::Texture::DepthCompareFunc::NotEqual: | ||||
|         return GL_NOTEQUAL; | ||||
|     case Tegra::Texture::DepthCompareFunc::Greater: | ||||
|         return GL_GREATER; | ||||
|     case Tegra::Texture::DepthCompareFunc::GreaterEqual: | ||||
|         return GL_GEQUAL; | ||||
|     case Tegra::Texture::DepthCompareFunc::Always: | ||||
|         return GL_ALWAYS; | ||||
|     } | ||||
|     LOG_CRITICAL(Render_OpenGL, "Unimplemented texture depth compare function ={}", | ||||
|                  static_cast<u32>(func)); | ||||
|     UNREACHABLE(); | ||||
|     return {}; | ||||
| } | ||||
|  | ||||
| inline GLenum BlendEquation(Maxwell::Blend::Equation equation) { | ||||
|     switch (equation) { | ||||
|     case Maxwell::Blend::Equation::Add: | ||||
|   | ||||
| @@ -227,6 +227,17 @@ enum class WrapMode : u32 { | ||||
|     MirrorOnceClampOGL = 7, | ||||
| }; | ||||
|  | ||||
| enum class DepthCompareFunc : u32 { | ||||
|     Never = 0, | ||||
|     Less = 1, | ||||
|     Equal = 2, | ||||
|     LessEqual = 3, | ||||
|     Greater = 4, | ||||
|     NotEqual = 5, | ||||
|     GreaterEqual = 6, | ||||
|     Always = 7, | ||||
| }; | ||||
|  | ||||
| enum class TextureFilter : u32 { | ||||
|     Nearest = 1, | ||||
|     Linear = 2, | ||||
| @@ -244,7 +255,7 @@ struct TSCEntry { | ||||
|         BitField<3, 3, WrapMode> wrap_v; | ||||
|         BitField<6, 3, WrapMode> wrap_p; | ||||
|         BitField<9, 1, u32> depth_compare_enabled; | ||||
|         BitField<10, 3, u32> depth_compare_func; | ||||
|         BitField<10, 3, DepthCompareFunc> depth_compare_func; | ||||
|     }; | ||||
|     union { | ||||
|         BitField<0, 2, TextureFilter> mag_filter; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user