diff options
Diffstat (limited to '')
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 18 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 3 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 134 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.h | 50 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 20 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 5 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/maxwell_to_gl.h | 42 |
7 files changed, 113 insertions, 159 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index b653bb479..35056d9bd 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -450,6 +450,7 @@ void RasterizerOpenGL::DrawArrays() { SyncDepthTestState(); SyncBlendState(); + SyncLogicOpState(); SyncCullMode(); // TODO(bunnei): Sync framebuffer_scale uniform here @@ -847,6 +848,9 @@ void RasterizerOpenGL::SyncBlendState() { if (!state.blend.enabled) return; + ASSERT_MSG(regs.logic_op.enable == 0, + "Blending and logic op can't be enabled at the same time."); + ASSERT_MSG(regs.independent_blend_enable == 1, "Only independent blending is implemented"); ASSERT_MSG(!regs.independent_blend[0].separate_alpha, "Unimplemented"); state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_rgb); @@ -856,3 +860,17 @@ void RasterizerOpenGL::SyncBlendState() { state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_a); state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_a); } + +void RasterizerOpenGL::SyncLogicOpState() { + const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; + + // TODO(Subv): Support more than just render target 0. + state.logic_op.enabled = regs.logic_op.enable != 0; + + if (!state.logic_op.enabled) + return; + + ASSERT_MSG(regs.blend.enable == 0, "Blending and logic op can't be enabled at the same time."); + + state.logic_op.operation = MaxwellToGL::LogicOp(regs.logic_op.operation); +} diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 394fc59f1..f40e70bf4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -142,6 +142,9 @@ private: /// Syncs the blend state to match the guest state void SyncBlendState(); + /// Syncs the LogicOp state to match the guest state + void SyncLogicOpState(); + bool has_ARB_direct_state_access = false; bool has_ARB_separate_shader_objects = false; bool has_ARB_vertex_attrib_binding = false; diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index aeb908744..5b976b636 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -440,12 +440,13 @@ public: } declarations.AddNewLine(); - const auto& samplers = GetSamplers(); - for (const auto& sampler : samplers) { - declarations.AddLine("uniform " + sampler.GetTypeString() + ' ' + sampler.GetName() + - ';'); + // Append the sampler2D array for the used textures. + size_t num_samplers = GetSamplers().size(); + if (num_samplers > 0) { + declarations.AddLine("uniform sampler2D " + SamplerEntry::GetArrayName(stage) + '[' + + std::to_string(num_samplers) + "];"); + declarations.AddNewLine(); } - declarations.AddNewLine(); } /// Returns a list of constant buffer declarations @@ -457,14 +458,13 @@ public: } /// Returns a list of samplers used in the shader - const std::vector<SamplerEntry>& GetSamplers() const { + std::vector<SamplerEntry> GetSamplers() const { return used_samplers; } /// 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) { + std::string AccessSampler(const Sampler& sampler) { size_t offset = static_cast<size_t>(sampler.index.Value()); // If this sampler has already been used, return the existing mapping. @@ -473,13 +473,12 @@ public: [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; }); if (itr != used_samplers.end()) { - ASSERT(itr->GetType() == type && itr->IsArray() == is_array); return itr->GetName(); } // Otherwise create a new mapping for this sampler size_t next_index = used_samplers.size(); - SamplerEntry entry{stage, offset, next_index, type, is_array}; + SamplerEntry entry{stage, offset, next_index}; used_samplers.emplace_back(entry); return entry.GetName(); } @@ -657,8 +656,8 @@ 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) { + return regs.AccessSampler(sampler); } /** @@ -1556,39 +1555,10 @@ private: break; } case OpCode::Id::TEX: { - ASSERT_MSG(instr.tex.array == 0, "TEX arrays unimplemented"); - std::string coord{}; - - switch (instr.tex.texture_type) { - case Tegra::Shader::TextureType::Texture2D: { - std::string x = regs.GetRegisterAsFloat(instr.gpr8); - std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); - coord = "vec2 coords = vec2(" + x + ", " + y + ");"; - break; - } - case Tegra::Shader::TextureType::Texture3D: { - 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 + ");"; - break; - } - case Tegra::Shader::TextureType::TextureCube: { - std::string x = regs.GetRegisterAsFloat(instr.gpr8); - std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); - std::string z = regs.GetRegisterAsFloat(instr.gpr8.Value() + 2); - ASSERT(instr.gpr20.Value() == Register::ZeroIndex); - coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; - break; - } - default: - LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", - static_cast<u32>(instr.tex.texture_type.Value())); - UNREACHABLE(); - } - - const std::string sampler = - GetSampler(instr.sampler, instr.tex.texture_type, instr.tex.array); + const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); + const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); + const std::string sampler = GetSampler(instr.sampler); + const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; // 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("{"); @@ -1610,72 +1580,20 @@ private: break; } case OpCode::Id::TEXS: { - std::string coord{}; - - switch (instr.texs.GetTextureType()) { - case Tegra::Shader::TextureType::Texture2D: { - if (instr.texs.IsArrayTexture()) { - std::string index = regs.GetRegisterAsInteger(instr.gpr8); - std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); - std::string y = regs.GetRegisterAsFloat(instr.gpr20); - coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");"; - } else { - std::string x = regs.GetRegisterAsFloat(instr.gpr8); - std::string y = regs.GetRegisterAsFloat(instr.gpr20); - coord = "vec2 coords = vec2(" + x + ", " + y + ");"; - } - break; - } - case Tegra::Shader::TextureType::Texture3D: { - std::string x = regs.GetRegisterAsFloat(instr.gpr8); - std::string y = regs.GetRegisterAsFloat(instr.gpr20); - std::string z = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1); - coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; - break; - } - case Tegra::Shader::TextureType::TextureCube: { - 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 + ");"; - break; - } - default: - LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", - static_cast<u32>(instr.texs.GetTextureType())); - UNREACHABLE(); - } - const std::string sampler = GetSampler(instr.sampler, instr.texs.GetTextureType(), - instr.texs.IsArrayTexture()); + const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); + const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); + const std::string sampler = GetSampler(instr.sampler); + const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; const std::string texture = "texture(" + sampler + ", coords)"; WriteTexsInstruction(instr, coord, texture); break; } case OpCode::Id::TLDS: { - ASSERT(instr.tlds.GetTextureType() == Tegra::Shader::TextureType::Texture2D); - ASSERT(instr.tlds.IsArrayTexture() == false); - std::string coord{}; - - switch (instr.tlds.GetTextureType()) { - case Tegra::Shader::TextureType::Texture2D: { - if (instr.tlds.IsArrayTexture()) { - LOG_CRITICAL(HW_GPU, "Unhandled 2d array texture"); - UNREACHABLE(); - } else { - std::string x = regs.GetRegisterAsInteger(instr.gpr8); - std::string y = regs.GetRegisterAsInteger(instr.gpr20); - coord = "ivec2 coords = ivec2(" + x + ", " + y + ");"; - } - break; - } - default: - LOG_CRITICAL(HW_GPU, "Unhandled texture type {}", - static_cast<u32>(instr.tlds.GetTextureType())); - UNREACHABLE(); - } - const std::string sampler = GetSampler(instr.sampler, instr.tlds.GetTextureType(), - instr.tlds.IsArrayTexture()); + const std::string op_a = regs.GetRegisterAsInteger(instr.gpr8); + const std::string op_b = regs.GetRegisterAsInteger(instr.gpr20); + const std::string sampler = GetSampler(instr.sampler); + const std::string coord = "ivec2 coords = ivec2(" + op_a + ", " + op_b + ");"; const std::string texture = "texelFetch(" + sampler + ", coords, 0)"; WriteTexsInstruction(instr, coord, texture); break; @@ -1698,8 +1616,7 @@ private: UNREACHABLE(); } - const std::string sampler = - GetSampler(instr.sampler, instr.tld4.texture_type, instr.tld4.array); + const std::string sampler = GetSampler(instr.sampler); // 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("{"); @@ -1725,8 +1642,7 @@ private: 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 sampler = GetSampler(instr.sampler); const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; const std::string texture = "textureGather(" + sampler + ", coords, " + std::to_string(instr.tld4s.component) + ')'; diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h index db48da645..4729ce0fc 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.h +++ b/src/video_core/renderer_opengl/gl_shader_gen.h @@ -11,7 +11,6 @@ #include <vector> #include "common/common_types.h" #include "common/hash.h" -#include "video_core/engines/shader_bytecode.h" namespace GLShader { @@ -73,9 +72,8 @@ class SamplerEntry { using Maxwell = Tegra::Engines::Maxwell3D::Regs; public: - SamplerEntry(Maxwell::ShaderStage stage, size_t offset, size_t index, - Tegra::Shader::TextureType type, bool is_array) - : offset(offset), stage(stage), sampler_index(index), type(type), is_array(is_array) {} + SamplerEntry(Maxwell::ShaderStage stage, size_t offset, size_t index) + : offset(offset), stage(stage), sampler_index(index) {} size_t GetOffset() const { return offset; @@ -90,41 +88,8 @@ public: } std::string GetName() const { - return std::string(TextureSamplerNames[static_cast<size_t>(stage)]) + '_' + - std::to_string(sampler_index); - } - - std::string GetTypeString() const { - using Tegra::Shader::TextureType; - std::string glsl_type; - - switch (type) { - case TextureType::Texture1D: - glsl_type = "sampler1D"; - break; - case TextureType::Texture2D: - glsl_type = "sampler2D"; - break; - case TextureType::Texture3D: - glsl_type = "sampler3D"; - break; - case TextureType::TextureCube: - glsl_type = "samplerCube"; - break; - default: - UNIMPLEMENTED(); - } - if (is_array) - glsl_type += "Array"; - return glsl_type; - } - - Tegra::Shader::TextureType GetType() const { - return type; - } - - bool IsArray() const { - return is_array; + return std::string(TextureSamplerNames[static_cast<size_t>(stage)]) + '[' + + std::to_string(sampler_index) + ']'; } static std::string GetArrayName(Maxwell::ShaderStage stage) { @@ -135,14 +100,11 @@ private: static constexpr std::array<const char*, Maxwell::MaxShaderStage> TextureSamplerNames = { "tex_vs", "tex_tessc", "tex_tesse", "tex_gs", "tex_fs", }; - /// Offset in TSC memory from which to read the sampler object, as specified by the sampling /// instruction. size_t offset; - Maxwell::ShaderStage stage; ///< Shader stage where this sampler was used. - 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. + Maxwell::ShaderStage stage; ///< Shader stage where this sampler was used. + size_t sampler_index; ///< Value used to index into the generated GLSL sampler array. }; struct ShaderEntries { diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 1d1975179..13399ceb8 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -45,7 +45,8 @@ OpenGLState::OpenGLState() { blend.color.blue = 0.0f; blend.color.alpha = 0.0f; - logic_op = GL_COPY; + logic_op.enabled = false; + logic_op.operation = GL_COPY; for (auto& texture_unit : texture_units) { texture_unit.Reset(); @@ -148,11 +149,10 @@ void OpenGLState::Apply() const { // Blending if (blend.enabled != cur_state.blend.enabled) { if (blend.enabled) { + ASSERT(!logic_op.enabled); glEnable(GL_BLEND); - glDisable(GL_COLOR_LOGIC_OP); } else { glDisable(GL_BLEND); - glEnable(GL_COLOR_LOGIC_OP); } } @@ -176,8 +176,18 @@ void OpenGLState::Apply() const { glBlendEquationSeparate(blend.rgb_equation, blend.a_equation); } - if (logic_op != cur_state.logic_op) { - glLogicOp(logic_op); + // Logic Operation + if (logic_op.enabled != cur_state.logic_op.enabled) { + if (logic_op.enabled) { + ASSERT(!blend.enabled); + glEnable(GL_COLOR_LOGIC_OP); + } else { + glDisable(GL_COLOR_LOGIC_OP); + } + } + + if (logic_op.operation != cur_state.logic_op.operation) { + glLogicOp(logic_op.operation); } // Textures diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index bdb02ba25..219b65a8a 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -83,7 +83,10 @@ public: } color; // GL_BLEND_COLOR } blend; - GLenum logic_op; // GL_LOGIC_OP_MODE + struct { + bool enabled; // GL_LOGIC_OP_MODE + GLenum operation; + } logic_op; // 3 texture units - one for each that is used in PICA fragment shader emulation struct TextureUnit { diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index 5d91a0c2f..0d55b3e17 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h @@ -107,6 +107,8 @@ inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) { switch (topology) { case Maxwell::PrimitiveTopology::Points: return GL_POINTS; + case Maxwell::PrimitiveTopology::Lines: + return GL_LINES; case Maxwell::PrimitiveTopology::LineStrip: return GL_LINE_STRIP; case Maxwell::PrimitiveTopology::Triangles: @@ -317,4 +319,44 @@ inline GLenum CullFace(Maxwell::Cull::CullFace cull_face) { return {}; } +inline GLenum LogicOp(Maxwell::LogicOperation operation) { + switch (operation) { + case Maxwell::LogicOperation::Clear: + return GL_CLEAR; + case Maxwell::LogicOperation::And: + return GL_AND; + case Maxwell::LogicOperation::AndReverse: + return GL_AND_REVERSE; + case Maxwell::LogicOperation::Copy: + return GL_COPY; + case Maxwell::LogicOperation::AndInverted: + return GL_AND_INVERTED; + case Maxwell::LogicOperation::NoOp: + return GL_NOOP; + case Maxwell::LogicOperation::Xor: + return GL_XOR; + case Maxwell::LogicOperation::Or: + return GL_OR; + case Maxwell::LogicOperation::Nor: + return GL_NOR; + case Maxwell::LogicOperation::Equiv: + return GL_EQUIV; + case Maxwell::LogicOperation::Invert: + return GL_INVERT; + case Maxwell::LogicOperation::OrReverse: + return GL_OR_REVERSE; + case Maxwell::LogicOperation::CopyInverted: + return GL_COPY_INVERTED; + case Maxwell::LogicOperation::OrInverted: + return GL_OR_INVERTED; + case Maxwell::LogicOperation::Nand: + return GL_NAND; + case Maxwell::LogicOperation::Set: + return GL_SET; + } + LOG_CRITICAL(Render_OpenGL, "Unimplemented logic operation={}", static_cast<u32>(operation)); + UNREACHABLE(); + return {}; +} + } // namespace MaxwellToGL |