aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/renderer_opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_opengl')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp33
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp31
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h5
-rw-r--r--src/video_core/renderer_opengl/gl_shader_util.cpp14
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp13
-rw-r--r--src/video_core/renderer_opengl/gl_state.h3
6 files changed, 40 insertions, 59 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 1b734aaa5..cc7e782a4 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -189,10 +189,6 @@ void RasterizerOpenGL::DrawTriangles() {
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
(has_stencil && depth_surface != nullptr) ? depth_surface->texture.handle : 0, 0);
- if (OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
- return;
- }
-
// Sync the viewport
// These registers hold half-width and half-height, so must be multiplied by 2
GLsizei viewport_width = (GLsizei)Pica::float24::FromRaw(regs.viewport_size_x).ToFloat32() * 2;
@@ -715,7 +711,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);
@@ -736,6 +736,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;
@@ -798,10 +803,6 @@ bool RasterizerOpenGL::AccelerateFill(const GPU::Regs::MemoryFillConfig& config)
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
0);
- if (OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
- return false;
- }
-
GLfloat color_values[4] = {0.0f, 0.0f, 0.0f, 0.0f};
// TODO: Handle additional pixel format and fill value size combinations to accelerate more
@@ -886,10 +887,6 @@ bool RasterizerOpenGL::AccelerateFill(const GPU::Regs::MemoryFillConfig& config)
dst_surface->texture.handle, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
- if (OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
- return false;
- }
-
GLfloat value_float;
if (dst_surface->pixel_format == CachedSurface::PixelFormat::D16) {
value_float = config.value_32bit / 65535.0f; // 2^16 - 1
@@ -905,10 +902,6 @@ bool RasterizerOpenGL::AccelerateFill(const GPU::Regs::MemoryFillConfig& config)
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
dst_surface->texture.handle, 0);
- if (OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
- return false;
- }
-
GLfloat value_float = (config.value_32bit & 0xFFFFFF) / 16777215.0f; // 2^24 - 1
GLint value_int = (config.value_32bit >> 24);
@@ -938,7 +931,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);
@@ -1074,7 +1067,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..0b2e48407 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -103,7 +103,7 @@ static void MortonCopyPixels(CachedSurface::PixelFormat pixel_format, u32 width,
}
}
-bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex,
+void RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex,
CachedSurface::SurfaceType type,
const MathUtil::Rectangle<int>& src_rect,
const MathUtil::Rectangle<int>& dst_rect) {
@@ -158,14 +158,6 @@ 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;
- }
-
- if (OpenGLState::CheckFBStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
- return false;
- }
-
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);
@@ -174,8 +166,6 @@ bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex,
cur_state.draw.read_framebuffer = old_fbs[0];
cur_state.draw.draw_framebuffer = old_fbs[1];
cur_state.Apply();
-
- return true;
}
bool RasterizerCacheOpenGL::TryBlitSurfaces(CachedSurface* src_surface,
@@ -189,9 +179,9 @@ bool RasterizerCacheOpenGL::TryBlitSurfaces(CachedSurface* src_surface,
return false;
}
- return BlitTextures(src_surface->texture.handle, dst_surface->texture.handle,
- CachedSurface::GetFormatType(src_surface->pixel_format), src_rect,
- dst_rect);
+ BlitTextures(src_surface->texture.handle, dst_surface->texture.handle,
+ CachedSurface::GetFormatType(src_surface->pixel_format), src_rect, dst_rect);
+ return true;
}
static void AllocateSurfaceTexture(GLuint texture, CachedSurface::PixelFormat pixel_format,
@@ -291,6 +281,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 +292,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 +318,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 +385,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 +694,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 +744,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..b50e8292b 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;
@@ -186,7 +187,7 @@ public:
~RasterizerCacheOpenGL();
/// Blits one texture to another
- bool BlitTextures(GLuint src_tex, GLuint dst_tex, CachedSurface::SurfaceType type,
+ void BlitTextures(GLuint src_tex, GLuint dst_tex, CachedSurface::SurfaceType type,
const MathUtil::Rectangle<int>& src_rect,
const MathUtil::Rectangle<int>& dst_rect);
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);
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 2a731f483..3c03b424a 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -232,19 +232,6 @@ void OpenGLState::Apply() const {
cur_state = *this;
}
-GLenum OpenGLState::CheckFBStatus(GLenum target) {
- GLenum fb_status = glCheckFramebufferStatus(target);
- if (fb_status != GL_FRAMEBUFFER_COMPLETE) {
- const char* fb_description =
- (target == GL_READ_FRAMEBUFFER ? "READ"
- : (target == GL_DRAW_FRAMEBUFFER ? "DRAW" : "UNK"));
- LOG_CRITICAL(Render_OpenGL, "OpenGL %s framebuffer check failed, status %X", fb_description,
- fb_status);
- }
-
- return fb_status;
-}
-
void OpenGLState::ResetTexture(GLuint handle) {
for (auto& unit : cur_state.texture_units) {
if (unit.texture_2d == handle) {
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 01dead883..aee3c2946 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -90,9 +90,6 @@ public:
/// Apply this state as the current OpenGL state
void Apply() const;
- /// Check the status of the current OpenGL read or draw framebuffer configuration
- static GLenum CheckFBStatus(GLenum target);
-
/// Resets and unbinds any references to the given resource in the current OpenGL state
static void ResetTexture(GLuint handle);
static void ResetSampler(GLuint handle);