diff options
Diffstat (limited to 'src/video_core/renderer_opengl')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 65 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 92 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 13 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/maxwell_to_gl.h | 21 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 1 |
7 files changed, 123 insertions, 83 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index e7fbc703a..0bd235218 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -682,6 +682,14 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, GLuint program, Surface surface = res_cache.GetTextureSurface(texture); if (surface != nullptr) { state.texture_units[current_bindpoint].texture_2d = surface->texture.handle; + state.texture_units[current_bindpoint].swizzle.r = + MaxwellToGL::SwizzleSource(texture.tic.x_source); + state.texture_units[current_bindpoint].swizzle.g = + MaxwellToGL::SwizzleSource(texture.tic.y_source); + state.texture_units[current_bindpoint].swizzle.b = + MaxwellToGL::SwizzleSource(texture.tic.z_source); + state.texture_units[current_bindpoint].swizzle.a = + MaxwellToGL::SwizzleSource(texture.tic.w_source); } else { // Can occur when texture addr is null or its memory is unmapped/invalid state.texture_units[current_bindpoint].texture_2d = 0; diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 9164d7f34..df2474ea2 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -169,60 +169,10 @@ static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tup static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, GLuint dst_tex, const MathUtil::Rectangle<u32>& dst_rect, SurfaceType type, GLuint read_fb_handle, GLuint draw_fb_handle) { - OpenGLState state = OpenGLState::GetCurState(); - - OpenGLState prev_state = state; - SCOPE_EXIT({ prev_state.Apply(); }); - - // Make sure textures aren't bound to texture units, since going to bind them to framebuffer - // components - state.ResetTexture(src_tex); - state.ResetTexture(dst_tex); - - state.draw.read_framebuffer = read_fb_handle; - state.draw.draw_framebuffer = draw_fb_handle; - state.Apply(); - - u32 buffers = 0; - - if (type == SurfaceType::ColorTexture) { - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_tex, - 0); - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, - 0); - - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_tex, - 0); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, - 0); - - buffers = GL_COLOR_BUFFER_BIT; - } else if (type == SurfaceType::Depth) { - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, src_tex, 0); - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); - - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, dst_tex, 0); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); - - buffers = GL_DEPTH_BUFFER_BIT; - } else if (type == SurfaceType::DepthStencil) { - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, - src_tex, 0); - - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, - dst_tex, 0); - - buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; - } - - glBlitFramebuffer(src_rect.left, src_rect.bottom, src_rect.right, src_rect.top, dst_rect.left, - dst_rect.bottom, dst_rect.right, dst_rect.top, buffers, - buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); + glCopyImageSubData(src_tex, GL_TEXTURE_2D, 0, src_rect.left, src_rect.bottom, 0, dst_tex, + GL_TEXTURE_2D, 0, dst_rect.left, dst_rect.bottom, 0, src_rect.GetWidth(), + src_rect.GetHeight(), 0); return true; } @@ -1102,16 +1052,19 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu params.UpdateParams(); - if (config.tic.Width() % 8 != 0 || config.tic.Height() % 8 != 0 || + if (params.GetActualWidth() % 8 != 0 || params.GetActualHeight() % 8 != 0 || params.stride != params.width) { Surface src_surface; MathUtil::Rectangle<u32> rect; std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); + rect = rect.Scale(params.GetCompresssionFactor()); + params.res_scale = src_surface->res_scale; Surface tmp_surface = CreateSurface(params); - BlitTextures(src_surface->texture.handle, rect, tmp_surface->texture.handle, - tmp_surface->GetScaledRect(), + + auto dst_rect = tmp_surface->GetScaledRect().Scale(params.GetCompresssionFactor()); + BlitTextures(src_surface->texture.handle, rect, tmp_surface->texture.handle, dst_rect, SurfaceParams::GetFormatType(params.pixel_format), read_framebuffer.handle, draw_framebuffer.handle); diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 3067ce3b3..94c6bc4b2 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -888,8 +888,33 @@ private: } break; } + case OpCode::Type::Bfe: { + ASSERT_MSG(!instr.bfe.negate_b, "Unimplemented"); + + std::string op_a = instr.bfe.negate_a ? "-" : ""; + op_a += regs.GetRegisterAsInteger(instr.gpr8); + + switch (opcode->GetId()) { + case OpCode::Id::BFE_IMM: { + std::string inner_shift = + '(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')'; + std::string outer_shift = + '(' + inner_shift + " >> " + + std::to_string(instr.bfe.GetLeftShiftValue() + instr.bfe.shift_position) + ')'; + + regs.SetRegisterToInteger(instr.gpr0, true, 0, outer_shift, 1, 1); + break; + } + default: { + NGLOG_CRITICAL(HW_GPU, "Unhandled BFE instruction: {}", opcode->GetName()); + UNREACHABLE(); + } + } + + break; + } case OpCode::Type::Logic: { - std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, false); + std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, true); if (instr.alu.lop.invert_a) op_a = "~(" + op_a + ')'; @@ -903,17 +928,17 @@ private: switch (instr.alu.lop.operation) { case Tegra::Shader::LogicOperation::And: { - regs.SetRegisterToInteger(instr.gpr0, false, 0, + regs.SetRegisterToInteger(instr.gpr0, true, 0, '(' + op_a + " & " + std::to_string(imm) + ')', 1, 1); break; } case Tegra::Shader::LogicOperation::Or: { - regs.SetRegisterToInteger(instr.gpr0, false, 0, + regs.SetRegisterToInteger(instr.gpr0, true, 0, '(' + op_a + " | " + std::to_string(imm) + ')', 1, 1); break; } case Tegra::Shader::LogicOperation::Xor: { - regs.SetRegisterToInteger(instr.gpr0, false, 0, + regs.SetRegisterToInteger(instr.gpr0, true, 0, '(' + op_a + " ^ " + std::to_string(imm) + ')', 1, 1); break; } @@ -1056,10 +1081,27 @@ private: break; } case OpCode::Id::F2F_R: { - // TODO(Subv): Implement rounding operations. - ASSERT_MSG(instr.conversion.f2f.rounding == 0, "Unimplemented rounding operation"); std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); + switch (instr.conversion.f2f.rounding) { + case Tegra::Shader::F2fRoundingOp::None: + break; + case Tegra::Shader::F2fRoundingOp::Floor: + op_a = "floor(" + op_a + ')'; + break; + case Tegra::Shader::F2fRoundingOp::Ceil: + op_a = "ceil(" + op_a + ')'; + break; + case Tegra::Shader::F2fRoundingOp::Trunc: + op_a = "trunc(" + op_a + ')'; + break; + default: + NGLOG_CRITICAL(HW_GPU, "Unimplemented f2f rounding mode {}", + static_cast<u32>(instr.conversion.f2f.rounding.Value())); + UNREACHABLE(); + break; + } + if (instr.conversion.abs_a) { op_a = "abs(" + op_a + ')'; } @@ -1074,17 +1116,16 @@ private: op_a = "abs(" + op_a + ')'; } - using Tegra::Shader::FloatRoundingOp; switch (instr.conversion.f2i.rounding) { - case FloatRoundingOp::None: + case Tegra::Shader::F2iRoundingOp::None: break; - case FloatRoundingOp::Floor: + case Tegra::Shader::F2iRoundingOp::Floor: op_a = "floor(" + op_a + ')'; break; - case FloatRoundingOp::Ceil: + case Tegra::Shader::F2iRoundingOp::Ceil: op_a = "ceil(" + op_a + ')'; break; - case FloatRoundingOp::Trunc: + case Tegra::Shader::F2iRoundingOp::Trunc: op_a = "trunc(" + op_a + ')'; break; default: @@ -1112,13 +1153,11 @@ private: break; } case OpCode::Type::Memory: { - const Attribute::Index attribute = instr.attribute.fmt20.index; - switch (opcode->GetId()) { case OpCode::Id::LD_A: { ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested"); regs.SetRegisterToInputAttibute(instr.gpr0, instr.attribute.fmt20.element, - attribute); + instr.attribute.fmt20.index); break; } case OpCode::Id::LD_C: { @@ -1150,12 +1189,11 @@ private: } case OpCode::Id::ST_A: { ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested"); - regs.SetOutputAttributeToRegister(attribute, instr.attribute.fmt20.element, - instr.gpr0); + regs.SetOutputAttributeToRegister(instr.attribute.fmt20.index, + instr.attribute.fmt20.element, instr.gpr0); break; } case OpCode::Id::TEX: { - ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested"); 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); @@ -1168,7 +1206,7 @@ private: const std::string texture = "texture(" + sampler + ", coords)"; size_t dest_elem{}; - for (size_t elem = 0; elem < instr.attribute.fmt20.size; ++elem) { + for (size_t elem = 0; elem < 4; ++elem) { if (!instr.tex.IsComponentEnabled(elem)) { // Skip disabled components continue; @@ -1181,7 +1219,6 @@ private: break; } case OpCode::Id::TEXS: { - ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested"); 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); @@ -1278,16 +1315,17 @@ private: } case OpCode::Type::IntegerSetPredicate: { std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.isetp.is_signed); + std::string op_b; - std::string op_b{}; - - ASSERT_MSG(!instr.is_b_imm, "ISETP_IMM not implemented"); - - if (instr.is_b_gpr) { - op_b += regs.GetRegisterAsInteger(instr.gpr20, 0, instr.isetp.is_signed); + if (instr.is_b_imm) { + op_b += '(' + std::to_string(instr.alu.GetSignedImm20_20()) + ')'; } else { - op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset, - GLSLRegister::Type::Integer); + if (instr.is_b_gpr) { + op_b += regs.GetRegisterAsInteger(instr.gpr20, 0, instr.isetp.is_signed); + } else { + op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset, + GLSLRegister::Type::Integer); + } } using Tegra::Shader::Pred; diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index f91dfe36a..44f0c8a01 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -50,6 +50,10 @@ OpenGLState::OpenGLState() { for (auto& texture_unit : texture_units) { texture_unit.texture_2d = 0; texture_unit.sampler = 0; + texture_unit.swizzle.r = GL_RED; + texture_unit.swizzle.g = GL_GREEN; + texture_unit.swizzle.b = GL_BLUE; + texture_unit.swizzle.a = GL_ALPHA; } lighting_lut.texture_buffer = 0; @@ -200,6 +204,15 @@ void OpenGLState::Apply() const { if (texture_units[i].sampler != cur_state.texture_units[i].sampler) { glBindSampler(i, texture_units[i].sampler); } + // Update the texture swizzle + if (texture_units[i].swizzle.r != cur_state.texture_units[i].swizzle.r || + texture_units[i].swizzle.g != cur_state.texture_units[i].swizzle.g || + texture_units[i].swizzle.b != cur_state.texture_units[i].swizzle.b || + texture_units[i].swizzle.a != cur_state.texture_units[i].swizzle.a) { + std::array<GLint, 4> mask = {texture_units[i].swizzle.r, texture_units[i].swizzle.g, + texture_units[i].swizzle.b, texture_units[i].swizzle.a}; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask.data()); + } } // Constbuffers diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 75c08e645..839e50e93 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -85,6 +85,12 @@ public: struct { GLuint texture_2d; // GL_TEXTURE_BINDING_2D GLuint sampler; // GL_SAMPLER_BINDING + struct { + GLint r; // GL_TEXTURE_SWIZZLE_R + GLint g; // GL_TEXTURE_SWIZZLE_G + GLint b; // GL_TEXTURE_SWIZZLE_B + GLint a; // GL_TEXTURE_SWIZZLE_A + } swizzle; } texture_units[32]; struct { diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index cf11983cf..2155fb019 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h @@ -180,4 +180,25 @@ inline GLenum BlendFunc(Maxwell::Blend::Factor factor) { return {}; } +inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) { + switch (source) { + case Tegra::Texture::SwizzleSource::Zero: + return GL_ZERO; + case Tegra::Texture::SwizzleSource::R: + return GL_RED; + case Tegra::Texture::SwizzleSource::G: + return GL_GREEN; + case Tegra::Texture::SwizzleSource::B: + return GL_BLUE; + case Tegra::Texture::SwizzleSource::A: + return GL_ALPHA; + case Tegra::Texture::SwizzleSource::OneInt: + case Tegra::Texture::SwizzleSource::OneFloat: + return GL_ONE; + } + NGLOG_CRITICAL(Render_OpenGL, "Unimplemented swizzle source={}", static_cast<u32>(source)); + UNREACHABLE(); + return {}; +} + } // namespace MaxwellToGL diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 3440d2190..f33766bfd 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -316,6 +316,7 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, }}; state.texture_units[0].texture_2d = screen_info.display_texture; + state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; state.Apply(); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data()); |
