From 4b676e7786f03a86fd1ecae50eae61098fd3766d Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 6 Jan 2019 18:49:23 -0300 Subject: [PATCH 1/6] gl_rasterizer: Use DSA for textures --- .../renderer_opengl/gl_rasterizer_cache.cpp | 219 +++++++----------- .../renderer_opengl/gl_rasterizer_cache.h | 1 - .../renderer_opengl/gl_resource_manager.cpp | 4 +- .../renderer_opengl/gl_resource_manager.h | 2 +- .../renderer_opengl/renderer_opengl.cpp | 62 ++--- 5 files changed, 104 insertions(+), 184 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 2b9c4628f..a3c782972 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -18,7 +18,6 @@ #include "video_core/morton.h" #include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_rasterizer_cache.h" -#include "video_core/renderer_opengl/gl_state.h" #include "video_core/renderer_opengl/utils.h" #include "video_core/surface.h" #include "video_core/textures/astc.h" @@ -44,14 +43,14 @@ struct FormatTuple { bool compressed; }; -static void ApplyTextureDefaults(GLenum target, u32 max_mip_level) { - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1); +static void ApplyTextureDefaults(GLuint texture, u32 max_mip_level) { + glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTextureParameteri(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTextureParameteri(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTextureParameteri(texture, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1); if (max_mip_level == 1) { - glTexParameterf(target, GL_TEXTURE_LOD_BIAS, 1000.0); + glTextureParameterf(texture, GL_TEXTURE_LOD_BIAS, 1000.0); } } @@ -529,55 +528,41 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface, CachedSurface::CachedSurface(const SurfaceParams& params) : params(params), gl_target(SurfaceTargetToGL(params.target)), cached_size_in_bytes(params.size_in_bytes) { - texture.Create(); - const auto& rect{params.GetRect()}; + texture.Create(gl_target); - // Keep track of previous texture bindings - OpenGLState cur_state = OpenGLState::GetCurState(); - const auto& old_tex = cur_state.texture_units[0]; - SCOPE_EXIT({ - cur_state.texture_units[0] = old_tex; - cur_state.Apply(); - }); - - cur_state.texture_units[0].texture = texture.handle; - cur_state.texture_units[0].target = SurfaceTargetToGL(params.target); - cur_state.Apply(); - glActiveTexture(GL_TEXTURE0); + // TODO(Rodrigo): Using params.GetRect() returns a different size than using its Mip*(0) + // alternatives. This signals a bug on those functions. + const auto width = static_cast(params.MipWidth(0)); + const auto height = static_cast(params.MipHeight(0)); const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type); gl_internal_format = format_tuple.internal_format; - gl_is_compressed = format_tuple.compressed; - if (!format_tuple.compressed) { - // Only pre-create the texture for non-compressed textures. - switch (params.target) { - case SurfaceTarget::Texture1D: - glTexStorage1D(SurfaceTargetToGL(params.target), params.max_mip_level, - format_tuple.internal_format, rect.GetWidth()); - break; - case SurfaceTarget::Texture2D: - case SurfaceTarget::TextureCubemap: - glTexStorage2D(SurfaceTargetToGL(params.target), params.max_mip_level, - format_tuple.internal_format, rect.GetWidth(), rect.GetHeight()); - break; - case SurfaceTarget::Texture3D: - case SurfaceTarget::Texture2DArray: - case SurfaceTarget::TextureCubeArray: - glTexStorage3D(SurfaceTargetToGL(params.target), params.max_mip_level, - format_tuple.internal_format, rect.GetWidth(), rect.GetHeight(), - params.depth); - break; - default: - LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", - static_cast(params.target)); - UNREACHABLE(); - glTexStorage2D(GL_TEXTURE_2D, params.max_mip_level, format_tuple.internal_format, - rect.GetWidth(), rect.GetHeight()); - } + switch (params.target) { + case SurfaceTarget::Texture1D: + glTextureStorage1D(texture.handle, params.max_mip_level, format_tuple.internal_format, + width); + break; + case SurfaceTarget::Texture2D: + case SurfaceTarget::TextureCubemap: + glTextureStorage2D(texture.handle, params.max_mip_level, format_tuple.internal_format, + width, height); + break; + case SurfaceTarget::Texture3D: + case SurfaceTarget::Texture2DArray: + case SurfaceTarget::TextureCubeArray: + glTextureStorage3D(texture.handle, params.max_mip_level, format_tuple.internal_format, + width, height, params.depth); + break; + default: + LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", + static_cast(params.target)); + UNREACHABLE(); + glTextureStorage2D(texture.handle, params.max_mip_level, format_tuple.internal_format, + width, height); } - ApplyTextureDefaults(SurfaceTargetToGL(params.target), params.max_mip_level); + ApplyTextureDefaults(texture.handle, params.max_mip_level); OpenGL::LabelGLObject(GL_TEXTURE, texture.handle, params.addr, params.IdentityString()); @@ -752,63 +737,50 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, const auto& rect{params.GetRect(mip_map)}; // Load data from memory to the surface - const GLint x0 = static_cast(rect.left); - const GLint y0 = static_cast(rect.bottom); - std::size_t buffer_offset = + const auto x0 = static_cast(rect.left); + const auto y0 = static_cast(rect.bottom); + auto buffer_offset = static_cast(static_cast(y0) * params.MipWidth(mip_map) + static_cast(x0)) * GetBytesPerPixel(params.pixel_format); const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); - const GLuint target_tex = texture.handle; - OpenGLState cur_state = OpenGLState::GetCurState(); - - const auto& old_tex = cur_state.texture_units[0]; - SCOPE_EXIT({ - cur_state.texture_units[0] = old_tex; - cur_state.Apply(); - }); - cur_state.texture_units[0].texture = target_tex; - cur_state.texture_units[0].target = SurfaceTargetToGL(params.target); - cur_state.Apply(); // Ensure no bad interactions with GL_UNPACK_ALIGNMENT ASSERT(params.MipWidth(mip_map) * GetBytesPerPixel(params.pixel_format) % 4 == 0); glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast(params.MipWidth(mip_map))); - GLsizei image_size = static_cast(params.GetMipmapSizeGL(mip_map, false)); - glActiveTexture(GL_TEXTURE0); + const auto image_size = static_cast(params.GetMipmapSizeGL(mip_map, false)); if (tuple.compressed) { switch (params.target) { case SurfaceTarget::Texture2D: - glCompressedTexImage2D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, - static_cast(params.MipWidth(mip_map)), - static_cast(params.MipHeight(mip_map)), 0, image_size, - &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage2D( + texture.handle, mip_map, 0, 0, static_cast(params.MipWidth(mip_map)), + static_cast(params.MipHeight(mip_map)), tuple.internal_format, image_size, + &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture3D: - glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, - static_cast(params.MipWidth(mip_map)), - static_cast(params.MipHeight(mip_map)), - static_cast(params.MipDepth(mip_map)), 0, image_size, - &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage3D( + texture.handle, mip_map, 0, 0, 0, static_cast(params.MipWidth(mip_map)), + static_cast(params.MipHeight(mip_map)), + static_cast(params.MipDepth(mip_map)), tuple.internal_format, image_size, + &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture2DArray: case SurfaceTarget::TextureCubeArray: - glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format, - static_cast(params.MipWidth(mip_map)), - static_cast(params.MipHeight(mip_map)), - static_cast(params.depth), 0, image_size, - &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage3D( + texture.handle, mip_map, 0, 0, 0, static_cast(params.MipWidth(mip_map)), + static_cast(params.MipHeight(mip_map)), static_cast(params.depth), + tuple.internal_format, image_size, &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::TextureCubemap: { - GLsizei layer_size = static_cast(params.LayerSizeGL(mip_map)); + const auto layer_size = static_cast(params.LayerSizeGL(mip_map)); for (std::size_t face = 0; face < params.depth; ++face) { - glCompressedTexImage2D(static_cast(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), - mip_map, tuple.internal_format, - static_cast(params.MipWidth(mip_map)), - static_cast(params.MipHeight(mip_map)), 0, - layer_size, &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage3D( + texture.handle, mip_map, 0, 0, static_cast(face), + static_cast(params.MipWidth(mip_map)), + static_cast(params.MipHeight(mip_map)), 1, tuple.internal_format, + layer_size, &gl_buffer[mip_map][buffer_offset]); buffer_offset += layer_size; } break; @@ -817,46 +789,43 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", static_cast(params.target)); UNREACHABLE(); - glCompressedTexImage2D(GL_TEXTURE_2D, mip_map, tuple.internal_format, - static_cast(params.MipWidth(mip_map)), - static_cast(params.MipHeight(mip_map)), 0, - static_cast(params.size_in_bytes_gl), - &gl_buffer[mip_map][buffer_offset]); + glCompressedTextureSubImage2D( + texture.handle, mip_map, 0, 0, static_cast(params.MipWidth(mip_map)), + static_cast(params.MipHeight(mip_map)), tuple.internal_format, + static_cast(params.size_in_bytes_gl), &gl_buffer[mip_map][buffer_offset]); } } else { - switch (params.target) { case SurfaceTarget::Texture1D: - glTexSubImage1D(SurfaceTargetToGL(params.target), mip_map, x0, - static_cast(rect.GetWidth()), tuple.format, tuple.type, - &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage1D(texture.handle, mip_map, x0, static_cast(rect.GetWidth()), + tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture2D: - glTexSubImage2D(SurfaceTargetToGL(params.target), mip_map, x0, y0, - static_cast(rect.GetWidth()), - static_cast(rect.GetHeight()), tuple.format, tuple.type, - &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage2D(texture.handle, mip_map, x0, y0, + static_cast(rect.GetWidth()), + static_cast(rect.GetHeight()), tuple.format, tuple.type, + &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture3D: - glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, - static_cast(rect.GetWidth()), - static_cast(rect.GetHeight()), params.MipDepth(mip_map), - tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage3D(texture.handle, mip_map, x0, y0, 0, + static_cast(rect.GetWidth()), + static_cast(rect.GetHeight()), params.MipDepth(mip_map), + tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::Texture2DArray: case SurfaceTarget::TextureCubeArray: - glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0, - static_cast(rect.GetWidth()), - static_cast(rect.GetHeight()), params.depth, tuple.format, - tuple.type, &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage3D(texture.handle, mip_map, x0, y0, 0, + static_cast(rect.GetWidth()), + static_cast(rect.GetHeight()), params.depth, tuple.format, + tuple.type, &gl_buffer[mip_map][buffer_offset]); break; case SurfaceTarget::TextureCubemap: { std::size_t start = buffer_offset; for (std::size_t face = 0; face < params.depth; ++face) { - glTexSubImage2D(static_cast(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), mip_map, - x0, y0, static_cast(rect.GetWidth()), - static_cast(rect.GetHeight()), tuple.format, tuple.type, - &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage3D(texture.handle, mip_map, x0, y0, static_cast(face), + static_cast(rect.GetWidth()), + static_cast(rect.GetHeight()), 1, tuple.format, + tuple.type, &gl_buffer[mip_map][buffer_offset]); buffer_offset += params.LayerSizeGL(mip_map); } break; @@ -865,9 +834,10 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", static_cast(params.target)); UNREACHABLE(); - glTexSubImage2D(GL_TEXTURE_2D, mip_map, x0, y0, static_cast(rect.GetWidth()), - static_cast(rect.GetHeight()), tuple.format, tuple.type, - &gl_buffer[mip_map][buffer_offset]); + glTextureSubImage2D(texture.handle, mip_map, x0, y0, + static_cast(rect.GetWidth()), + static_cast(rect.GetHeight()), tuple.format, tuple.type, + &gl_buffer[mip_map][buffer_offset]); } } @@ -877,29 +847,16 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, void CachedSurface::EnsureTextureView() { if (texture_view.handle != 0) return; - // Compressed texture are not being created with immutable storage - UNIMPLEMENTED_IF(gl_is_compressed); const GLenum target{TargetLayer()}; const GLuint num_layers{target == GL_TEXTURE_CUBE_MAP_ARRAY ? 6u : 1u}; constexpr GLuint min_layer = 0; constexpr GLuint min_level = 0; - texture_view.Create(); - glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, min_level, - params.max_mip_level, min_layer, num_layers); - - OpenGLState cur_state = OpenGLState::GetCurState(); - const auto& old_tex = cur_state.texture_units[0]; - SCOPE_EXIT({ - cur_state.texture_units[0] = old_tex; - cur_state.Apply(); - }); - cur_state.texture_units[0].texture = texture_view.handle; - cur_state.texture_units[0].target = target; - cur_state.Apply(); - - ApplyTextureDefaults(target, params.max_mip_level); + glGenTextures(1, &texture_view.handle); + glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, 0, + params.max_mip_level, 0, 1); + ApplyTextureDefaults(texture_view.handle, params.max_mip_level); } MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 8d7d6722c..9ee6f3f65 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -393,7 +393,6 @@ private: SurfaceParams params{}; GLenum gl_target{}; GLenum gl_internal_format{}; - bool gl_is_compressed{}; std::size_t cached_size_in_bytes{}; }; diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp index 1da744158..4170cbd3c 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp @@ -15,12 +15,12 @@ MICROPROFILE_DEFINE(OpenGL_ResourceDeletion, "OpenGL", "Resource Deletion", MP_R namespace OpenGL { -void OGLTexture::Create() { +void OGLTexture::Create(GLenum target) { if (handle != 0) return; MICROPROFILE_SCOPE(OpenGL_ResourceCreation); - glGenTextures(1, &handle); + glCreateTextures(target, 1, &handle); } void OGLTexture::Release() { diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index e33f1e973..df76cbc4b 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h @@ -28,7 +28,7 @@ public: } /// Creates a new internal OpenGL resource and stores the handle - void Create(); + void Create(GLenum target); /// Deletes the internal OpenGL resource void Release(); diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index e37b65b38..761dd6be3 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -171,10 +171,6 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf Memory::GetPointer(framebuffer_addr), gl_framebuffer_data.data(), true); - state.texture_units[0].texture = screen_info.texture.resource.handle; - state.Apply(); - - glActiveTexture(GL_TEXTURE0); glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast(framebuffer.stride)); // Update existing texture @@ -182,14 +178,11 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf // they differ from the LCD resolution. // TODO: Applications could theoretically crash yuzu here by specifying too large // framebuffer sizes. We should make sure that this cannot happen. - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer.width, framebuffer.height, - screen_info.texture.gl_format, screen_info.texture.gl_type, - gl_framebuffer_data.data()); + glTextureSubImage2D(screen_info.texture.resource.handle, 0, 0, 0, framebuffer.width, + framebuffer.height, screen_info.texture.gl_format, + screen_info.texture.gl_type, gl_framebuffer_data.data()); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - - state.texture_units[0].texture = 0; - state.Apply(); } } @@ -199,17 +192,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf */ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, const TextureInfo& texture) { - state.texture_units[0].texture = texture.resource.handle; - state.Apply(); - - glActiveTexture(GL_TEXTURE0); - u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r}; - - // Update existing texture - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); - - state.texture_units[0].texture = 0; - state.Apply(); + const u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r}; + glClearTexImage(texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); } /** @@ -249,26 +233,13 @@ void RendererOpenGL::InitOpenGLObjects() { sizeof(ScreenRectVertex)); // Allocate textures for the screen - screen_info.texture.resource.Create(); + screen_info.texture.resource.Create(GL_TEXTURE_2D); - // Allocation of storage is deferred until the first frame, when we - // know the framebuffer size. - - state.texture_units[0].texture = screen_info.texture.resource.handle; - state.Apply(); - - glActiveTexture(GL_TEXTURE0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + const GLuint texture = screen_info.texture.resource.handle; + glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1); screen_info.display_texture = screen_info.texture.resource.handle; - state.texture_units[0].texture = 0; - state.Apply(); - // Clear screen to black LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); } @@ -284,20 +255,19 @@ void RendererOpenGL::CreateRasterizer() { void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, const Tegra::FramebufferConfig& framebuffer) { - texture.width = framebuffer.width; texture.height = framebuffer.height; GLint internal_format; switch (framebuffer.pixel_format) { case Tegra::FramebufferConfig::PixelFormat::ABGR8: - internal_format = GL_RGBA; + internal_format = GL_RGBA8; texture.gl_format = GL_RGBA; texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; gl_framebuffer_data.resize(texture.width * texture.height * 4); break; default: - internal_format = GL_RGBA; + internal_format = GL_RGBA8; texture.gl_format = GL_RGBA; texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; gl_framebuffer_data.resize(texture.width * texture.height * 4); @@ -306,15 +276,9 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, UNREACHABLE(); } - state.texture_units[0].texture = texture.resource.handle; - state.Apply(); - - glActiveTexture(GL_TEXTURE0); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, texture.width, texture.height, 0, - texture.gl_format, texture.gl_type, nullptr); - - state.texture_units[0].texture = 0; - state.Apply(); + texture.resource.Release(); + texture.resource.Create(GL_TEXTURE_2D); + glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height); } void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, float y, float w, From 3bbaa98c78da8a45227fcd7abd82532f6f49851b Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 6 Jan 2019 22:36:51 -0300 Subject: [PATCH 2/6] gl_state: Use DSA and multi bind to update texture bindings --- src/video_core/renderer_opengl/gl_state.cpp | 30 +++++++++++++++------ 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index b7ba59350..997325efc 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -462,24 +462,38 @@ void OpenGLState::ApplyPolygonOffset() const { } void OpenGLState::ApplyTextures() const { + bool has_delta{}; + std::size_t first{}, last{}; + std::array textures; + for (std::size_t i = 0; i < std::size(texture_units); ++i) { const auto& texture_unit = texture_units[i]; const auto& cur_state_texture_unit = cur_state.texture_units[i]; + textures[i] = texture_unit.texture; - if (texture_unit.texture != cur_state_texture_unit.texture) { - glActiveTexture(TextureUnits::MaxwellTexture(static_cast(i)).Enum()); - glBindTexture(texture_unit.target, texture_unit.texture); + if (textures[i] != cur_state_texture_unit.texture) { + if (!has_delta) { + first = i; + has_delta = true; + } + last = i; } + // Update the texture swizzle - if (texture_unit.swizzle.r != cur_state_texture_unit.swizzle.r || - texture_unit.swizzle.g != cur_state_texture_unit.swizzle.g || - texture_unit.swizzle.b != cur_state_texture_unit.swizzle.b || - texture_unit.swizzle.a != cur_state_texture_unit.swizzle.a) { + if (textures[i] != 0 && (texture_unit.swizzle.r != cur_state_texture_unit.swizzle.r || + texture_unit.swizzle.g != cur_state_texture_unit.swizzle.g || + texture_unit.swizzle.b != cur_state_texture_unit.swizzle.b || + texture_unit.swizzle.a != cur_state_texture_unit.swizzle.a)) { std::array mask = {texture_unit.swizzle.r, texture_unit.swizzle.g, texture_unit.swizzle.b, texture_unit.swizzle.a}; - glTexParameteriv(texture_unit.target, GL_TEXTURE_SWIZZLE_RGBA, mask.data()); + glTextureParameteriv(texture_unit.texture, GL_TEXTURE_SWIZZLE_RGBA, mask.data()); } } + + if (has_delta) { + glBindTextures(static_cast(first), static_cast(last - first + 1), + textures.data()); + } } void OpenGLState::ApplySamplers() const { From 704744bb72972f99fa992e286b3de5967b48af37 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 6 Jan 2019 23:02:27 -0300 Subject: [PATCH 3/6] gl_rasterizer_cache: Move swizzling to textures instead of state --- .../renderer_opengl/gl_rasterizer.cpp | 10 +++++----- .../renderer_opengl/gl_rasterizer_cache.cpp | 20 +++++++++++++++++++ .../renderer_opengl/gl_rasterizer_cache.h | 6 ++++++ src/video_core/renderer_opengl/gl_state.cpp | 16 ++++----------- src/video_core/renderer_opengl/gl_state.h | 10 ---------- .../renderer_opengl/renderer_opengl.cpp | 1 - 6 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index ee313cb2f..79d16d1f3 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -1022,11 +1022,11 @@ void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& s if (surface != nullptr) { unit.texture = entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle; - unit.target = entry.IsArray() ? surface->TargetLayer() : surface->Target(); - unit.swizzle.r = MaxwellToGL::SwizzleSource(texture.tic.x_source); - unit.swizzle.g = MaxwellToGL::SwizzleSource(texture.tic.y_source); - unit.swizzle.b = MaxwellToGL::SwizzleSource(texture.tic.z_source); - unit.swizzle.a = MaxwellToGL::SwizzleSource(texture.tic.w_source); + const GLenum target = entry.IsArray() ? surface->TargetLayer() : surface->Target(); + surface->UpdateSwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source, + texture.tic.w_source); + unit.texture = handle; + unit.target = target; } else { // Can occur when texture addr is null or its memory is unmapped/invalid unit.texture = 0; diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index a3c782972..0dc4857e8 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -857,6 +857,8 @@ void CachedSurface::EnsureTextureView() { glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, 0, params.max_mip_level, 0, 1); ApplyTextureDefaults(texture_view.handle, params.max_mip_level); + glTextureParameteriv(texture_view.handle, GL_TEXTURE_SWIZZLE_RGBA, + reinterpret_cast(swizzle.data())); } MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); @@ -870,6 +872,24 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle UploadGLMipmapTexture(i, read_fb_handle, draw_fb_handle); } +void CachedSurface::UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x, + Tegra::Texture::SwizzleSource swizzle_y, + Tegra::Texture::SwizzleSource swizzle_z, + Tegra::Texture::SwizzleSource swizzle_w) { + const GLenum new_x = MaxwellToGL::SwizzleSource(swizzle_x); + const GLenum new_y = MaxwellToGL::SwizzleSource(swizzle_y); + const GLenum new_z = MaxwellToGL::SwizzleSource(swizzle_z); + const GLenum new_w = MaxwellToGL::SwizzleSource(swizzle_w); + if (swizzle[0] != new_x || swizzle[1] != new_y || swizzle[2] != new_z || swizzle[3] != new_w) { + swizzle = {new_x, new_y, new_z, new_w}; + const auto swizzle_data = reinterpret_cast(swizzle.data()); + glTextureParameteriv(texture.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data); + if (texture_view.handle != 0) { + glTextureParameteriv(texture_view.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data); + } + } +} + RasterizerCacheOpenGL::RasterizerCacheOpenGL(RasterizerOpenGL& rasterizer) : RasterizerCache{rasterizer} { read_framebuffer.Create(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 9ee6f3f65..490b8252e 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -382,6 +382,11 @@ public: // Upload data in gl_buffer to this surface's texture void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle); + void UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x, + Tegra::Texture::SwizzleSource swizzle_y, + Tegra::Texture::SwizzleSource swizzle_z, + Tegra::Texture::SwizzleSource swizzle_w); + private: void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle); @@ -394,6 +399,7 @@ private: GLenum gl_target{}; GLenum gl_internal_format{}; std::size_t cached_size_in_bytes{}; + std::array swizzle{GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; }; class RasterizerCacheOpenGL final : public RasterizerCache { diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 997325efc..81af803bc 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -463,7 +463,8 @@ void OpenGLState::ApplyPolygonOffset() const { void OpenGLState::ApplyTextures() const { bool has_delta{}; - std::size_t first{}, last{}; + std::size_t first{}; + std::size_t last{}; std::array textures; for (std::size_t i = 0; i < std::size(texture_units); ++i) { @@ -478,16 +479,6 @@ void OpenGLState::ApplyTextures() const { } last = i; } - - // Update the texture swizzle - if (textures[i] != 0 && (texture_unit.swizzle.r != cur_state_texture_unit.swizzle.r || - texture_unit.swizzle.g != cur_state_texture_unit.swizzle.g || - texture_unit.swizzle.b != cur_state_texture_unit.swizzle.b || - texture_unit.swizzle.a != cur_state_texture_unit.swizzle.a)) { - std::array mask = {texture_unit.swizzle.r, texture_unit.swizzle.g, - texture_unit.swizzle.b, texture_unit.swizzle.a}; - glTextureParameteriv(texture_unit.texture, GL_TEXTURE_SWIZZLE_RGBA, mask.data()); - } } if (has_delta) { @@ -498,7 +489,8 @@ void OpenGLState::ApplyTextures() const { void OpenGLState::ApplySamplers() const { bool has_delta{}; - std::size_t first{}, last{}; + std::size_t first{}; + std::size_t last{}; std::array samplers; for (std::size_t i = 0; i < std::size(samplers); ++i) { samplers[i] = texture_units[i].sampler; diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index a5a7c0920..ced602bf6 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -127,19 +127,9 @@ public: GLuint texture; // GL_TEXTURE_BINDING_2D GLuint sampler; // GL_SAMPLER_BINDING GLenum target; - 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; void Unbind() { texture = 0; - swizzle.r = GL_RED; - swizzle.g = GL_GREEN; - swizzle.b = GL_BLUE; - swizzle.a = GL_ALPHA; } void Reset() { diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 761dd6be3..5b09c38ea 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -320,7 +320,6 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, }}; state.texture_units[0].texture = screen_info.display_texture; - state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; // Workaround brigthness problems in SMO by enabling sRGB in the final output // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987 state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed(); From 220df45b7dfc3654fe0fb4cb6b6eb65c1bfce8e3 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 9 Jan 2019 17:42:27 -0300 Subject: [PATCH 4/6] gl_state: Remove texture target tracking --- src/video_core/renderer_opengl/gl_rasterizer.cpp | 3 --- src/video_core/renderer_opengl/gl_state.h | 2 -- 2 files changed, 5 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 79d16d1f3..7831bc8cc 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -1022,11 +1022,8 @@ void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& s if (surface != nullptr) { unit.texture = entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle; - const GLenum target = entry.IsArray() ? surface->TargetLayer() : surface->Target(); surface->UpdateSwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source, texture.tic.w_source); - unit.texture = handle; - unit.target = target; } else { // Can occur when texture addr is null or its memory is unmapped/invalid unit.texture = 0; diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index ced602bf6..9e1eda5b1 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -126,7 +126,6 @@ public: struct TextureUnit { GLuint texture; // GL_TEXTURE_BINDING_2D GLuint sampler; // GL_SAMPLER_BINDING - GLenum target; void Unbind() { texture = 0; @@ -135,7 +134,6 @@ public: void Reset() { Unbind(); sampler = 0; - target = GL_TEXTURE_2D; } }; std::array texture_units; From 911587fb8d4fbd6917c427ce7c500fef7f1274d7 Mon Sep 17 00:00:00 2001 From: Mat M Date: Tue, 29 Jan 2019 22:01:04 -0300 Subject: [PATCH 5/6] gl_rasterizer_cache: Guard clause swizzle testing Co-Authored-By: ReinUsesLisp --- src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 0dc4857e8..d453ddbce 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -880,7 +880,9 @@ void CachedSurface::UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x, const GLenum new_y = MaxwellToGL::SwizzleSource(swizzle_y); const GLenum new_z = MaxwellToGL::SwizzleSource(swizzle_z); const GLenum new_w = MaxwellToGL::SwizzleSource(swizzle_w); - if (swizzle[0] != new_x || swizzle[1] != new_y || swizzle[2] != new_z || swizzle[3] != new_w) { + if (swizzle[0] == new_x && swizzle[1] == new_y && swizzle[2] == new_z && swizzle[3] == new_w) { + return; + } swizzle = {new_x, new_y, new_z, new_w}; const auto swizzle_data = reinterpret_cast(swizzle.data()); glTextureParameteriv(texture.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data); From 3e80b0894494c0a25f84e97e3e320e606028c206 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 29 Jan 2019 22:08:03 -0300 Subject: [PATCH 6/6] gl_rasterizer_cache: Fixup test clause --- .../renderer_opengl/gl_rasterizer_cache.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index d453ddbce..42e4e7aa1 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -883,12 +883,11 @@ void CachedSurface::UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x, if (swizzle[0] == new_x && swizzle[1] == new_y && swizzle[2] == new_z && swizzle[3] == new_w) { return; } - swizzle = {new_x, new_y, new_z, new_w}; - const auto swizzle_data = reinterpret_cast(swizzle.data()); - glTextureParameteriv(texture.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data); - if (texture_view.handle != 0) { - glTextureParameteriv(texture_view.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data); - } + swizzle = {new_x, new_y, new_z, new_w}; + const auto swizzle_data = reinterpret_cast(swizzle.data()); + glTextureParameteriv(texture.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data); + if (texture_view.handle != 0) { + glTextureParameteriv(texture_view.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data); } }