diff options
Diffstat (limited to 'src/video_core/renderer_opengl')
4 files changed, 50 insertions, 26 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index d4d5903ce..ba65db419 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -213,12 +213,16 @@ void RasterizerOpenGL::DrawTriangles() { // Scissor checks are window-, not viewport-relative, which means that if the cached texture // sub-rect changes, the scissor bounds also need to be updated. - GLint scissor_x1 = rect.left + regs.scissor_test.x1 * color_surface->res_scale_width; - GLint scissor_y1 = rect.bottom + regs.scissor_test.y1 * color_surface->res_scale_height; + GLint scissor_x1 = + static_cast<GLint>(rect.left + regs.scissor_test.x1 * color_surface->res_scale_width); + GLint scissor_y1 = + static_cast<GLint>(rect.bottom + regs.scissor_test.y1 * color_surface->res_scale_height); // x2, y2 have +1 added to cover the entire pixel area, otherwise you might get cracks when // scaling or doing multisampling. - GLint scissor_x2 = rect.left + (regs.scissor_test.x2 + 1) * color_surface->res_scale_width; - GLint scissor_y2 = rect.bottom + (regs.scissor_test.y2 + 1) * color_surface->res_scale_height; + GLint scissor_x2 = + static_cast<GLint>(rect.left + (regs.scissor_test.x2 + 1) * color_surface->res_scale_width); + GLint scissor_y2 = static_cast<GLint>( + rect.bottom + (regs.scissor_test.y2 + 1) * color_surface->res_scale_height); if (uniform_block_data.data.scissor_x1 != scissor_x1 || uniform_block_data.data.scissor_x2 != scissor_x2 || @@ -711,7 +715,11 @@ bool RasterizerOpenGL::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransfe CachedSurface src_params; src_params.addr = config.GetPhysicalInputAddress(); - src_params.width = config.output_width; + // It's important to use the correct source input width to properly skip over parts of the input + // image which will be cropped from the output but still affect the stride of the input image. + src_params.width = config.input_width; + // Using the output's height is fine because we don't read or skip over the remaining part of + // the image, and it allows for smaller texture cache lookup rectangles. src_params.height = config.output_height; src_params.is_tiled = !config.input_linear; src_params.pixel_format = CachedSurface::PixelFormatFromGPUPixelFormat(config.input_format); @@ -732,6 +740,11 @@ bool RasterizerOpenGL::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransfe return false; } + // Adjust the source rectangle to take into account parts of the input lines being cropped + if (config.input_width > config.output_width) { + src_rect.right -= (config.input_width - config.output_width) * src_surface->res_scale_width; + } + // Require destination surface to have same resolution scale as source to preserve scaling dst_params.res_scale_width = src_surface->res_scale_width; dst_params.res_scale_height = src_surface->res_scale_height; @@ -934,7 +947,7 @@ bool RasterizerOpenGL::AccelerateDisplay(const GPU::Regs::FramebufferConfig& con src_params.addr = framebuffer_addr; src_params.width = config.width; src_params.height = config.height; - src_params.stride = pixel_stride; + src_params.pixel_stride = pixel_stride; src_params.is_tiled = false; src_params.pixel_format = CachedSurface::PixelFormatFromGPUPixelFormat(config.color_format); @@ -1070,7 +1083,9 @@ void RasterizerOpenGL::SetShader() { GLint block_size; glGetActiveUniformBlockiv(current_shader->shader.handle, block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &block_size); - ASSERT_MSG(block_size == sizeof(UniformData), "Uniform block size did not match!"); + ASSERT_MSG(block_size == sizeof(UniformData), + "Uniform block size did not match! Got %d, expected %zu", + static_cast<int>(block_size), sizeof(UniformData)); glUniformBlockBinding(current_shader->shader.handle, block_index, 0); // Update uniforms diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 5cbad9b43..61f6e767f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -158,24 +158,21 @@ bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex, buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; } - if (OpenGLState::CheckFBStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - return false; - } + bool can_blit = OpenGLState::CheckFBStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE && + OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE; - if (OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - return false; + if (can_blit) { + glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, + dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, buffers, + buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); } - glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, dst_rect.left, - dst_rect.top, dst_rect.right, dst_rect.bottom, buffers, - buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); - // Restore previous framebuffer bindings cur_state.draw.read_framebuffer = old_fbs[0]; cur_state.draw.draw_framebuffer = old_fbs[1]; cur_state.Apply(); - return true; + return can_blit; } bool RasterizerCacheOpenGL::TryBlitSurfaces(CachedSurface* src_surface, @@ -291,6 +288,9 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo MICROPROFILE_SCOPE(OpenGL_SurfaceUpload); + // Stride only applies to linear images. + ASSERT(params.pixel_stride == 0 || !params.is_tiled); + std::shared_ptr<CachedSurface> new_surface = std::make_shared<CachedSurface>(); new_surface->addr = params.addr; @@ -299,7 +299,7 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo new_surface->texture.Create(); new_surface->width = params.width; new_surface->height = params.height; - new_surface->stride = params.stride; + new_surface->pixel_stride = params.pixel_stride; new_surface->res_scale_width = params.res_scale_width; new_surface->res_scale_height = params.res_scale_height; @@ -325,14 +325,15 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo cur_state.Apply(); glActiveTexture(GL_TEXTURE0); - glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)new_surface->stride); if (!new_surface->is_tiled) { // TODO: Ensure this will always be a color format, not a depth or other format ASSERT((size_t)new_surface->pixel_format < fb_format_tuples.size()); const FormatTuple& tuple = fb_format_tuples[(unsigned int)params.pixel_format]; + glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)new_surface->pixel_stride); glTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format, params.width, params.height, 0, tuple.format, tuple.type, texture_src_data); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } else { SurfaceType type = CachedSurface::GetFormatType(new_surface->pixel_format); if (type != SurfaceType::Depth && type != SurfaceType::DepthStencil) { @@ -391,7 +392,6 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo 0, tuple.format, tuple.type, temp_fb_depth_buffer.data()); } } - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); // If not 1x scale, blit 1x texture to a new scaled texture and replace texture in surface if (new_surface->res_scale_width != 1.f || new_surface->res_scale_height != 1.f) { @@ -701,13 +701,14 @@ void RasterizerCacheOpenGL::FlushSurface(CachedSurface* surface) { cur_state.Apply(); glActiveTexture(GL_TEXTURE0); - glPixelStorei(GL_PACK_ROW_LENGTH, (GLint)surface->stride); if (!surface->is_tiled) { // TODO: Ensure this will always be a color format, not a depth or other format ASSERT((size_t)surface->pixel_format < fb_format_tuples.size()); const FormatTuple& tuple = fb_format_tuples[(unsigned int)surface->pixel_format]; + glPixelStorei(GL_PACK_ROW_LENGTH, (GLint)surface->pixel_stride); glGetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type, dst_buffer); + glPixelStorei(GL_PACK_ROW_LENGTH, 0); } else { SurfaceType type = CachedSurface::GetFormatType(surface->pixel_format); if (type != SurfaceType::Depth && type != SurfaceType::DepthStencil) { @@ -750,7 +751,6 @@ void RasterizerCacheOpenGL::FlushSurface(CachedSurface* surface) { false); } } - glPixelStorei(GL_PACK_ROW_LENGTH, 0); surface->dirty = false; diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 849530d86..32abfbaf5 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -171,7 +171,8 @@ struct CachedSurface { OGLTexture texture; u32 width; u32 height; - u32 stride = 0; + /// Stride between lines, in pixels. Only valid for images in linear format. + u32 pixel_stride = 0; float res_scale_width = 1.f; float res_scale_height = 1.f; diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp index fe07aa6eb..4da241d83 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.cpp +++ b/src/video_core/renderer_opengl/gl_shader_util.cpp @@ -4,6 +4,7 @@ #include <vector> #include <glad/glad.h> +#include "common/assert.h" #include "common/logging/log.h" #include "video_core/renderer_opengl/gl_shader_util.h" @@ -31,7 +32,7 @@ GLuint LoadProgram(const char* vertex_shader, const char* fragment_shader) { if (info_log_length > 1) { std::vector<char> vertex_shader_error(info_log_length); glGetShaderInfoLog(vertex_shader_id, info_log_length, nullptr, &vertex_shader_error[0]); - if (result) { + if (result == GL_TRUE) { LOG_DEBUG(Render_OpenGL, "%s", &vertex_shader_error[0]); } else { LOG_ERROR(Render_OpenGL, "Error compiling vertex shader:\n%s", &vertex_shader_error[0]); @@ -51,7 +52,7 @@ GLuint LoadProgram(const char* vertex_shader, const char* fragment_shader) { if (info_log_length > 1) { std::vector<char> fragment_shader_error(info_log_length); glGetShaderInfoLog(fragment_shader_id, info_log_length, nullptr, &fragment_shader_error[0]); - if (result) { + if (result == GL_TRUE) { LOG_DEBUG(Render_OpenGL, "%s", &fragment_shader_error[0]); } else { LOG_ERROR(Render_OpenGL, "Error compiling fragment shader:\n%s", @@ -75,13 +76,20 @@ GLuint LoadProgram(const char* vertex_shader, const char* fragment_shader) { if (info_log_length > 1) { std::vector<char> program_error(info_log_length); glGetProgramInfoLog(program_id, info_log_length, nullptr, &program_error[0]); - if (result) { + if (result == GL_TRUE) { LOG_DEBUG(Render_OpenGL, "%s", &program_error[0]); } else { LOG_ERROR(Render_OpenGL, "Error linking shader:\n%s", &program_error[0]); } } + // If the program linking failed at least one of the shaders was probably bad + if (result == GL_FALSE) { + LOG_ERROR(Render_OpenGL, "Vertex shader:\n%s", vertex_shader); + LOG_ERROR(Render_OpenGL, "Fragment shader:\n%s", fragment_shader); + } + ASSERT_MSG(result == GL_TRUE, "Shader not linked"); + glDeleteShader(vertex_shader_id); glDeleteShader(fragment_shader_id); |