mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Merge pull request #2071 from ReinUsesLisp/dsa-texture
gl_rasterizer: Use DSA for textures and move swizzling to texture state
This commit is contained in:
		
						commit
						40ac058557
					
				| @ -1019,11 +1019,8 @@ 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); | ||||
|             surface->UpdateSwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source, | ||||
|                                    texture.tic.w_source); | ||||
|         } else { | ||||
|             // Can occur when texture addr is null or its memory is unmapped/invalid
 | ||||
|             unit.texture = 0; | ||||
|  | ||||
| @ -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<GLsizei>(params.MipWidth(0)); | ||||
|     const auto height = static_cast<GLsizei>(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()); | ||||
|         glTextureStorage1D(texture.handle, params.max_mip_level, format_tuple.internal_format, | ||||
|                            width); | ||||
|         break; | ||||
|     case SurfaceTarget::Texture2D: | ||||
|     case SurfaceTarget::TextureCubemap: | ||||
|             glTexStorage2D(SurfaceTargetToGL(params.target), params.max_mip_level, | ||||
|                            format_tuple.internal_format, rect.GetWidth(), rect.GetHeight()); | ||||
|         glTextureStorage2D(texture.handle, params.max_mip_level, format_tuple.internal_format, | ||||
|                            width, height); | ||||
|         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); | ||||
|         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<u32>(params.target)); | ||||
|         UNREACHABLE(); | ||||
|             glTexStorage2D(GL_TEXTURE_2D, params.max_mip_level, format_tuple.internal_format, | ||||
|                            rect.GetWidth(), rect.GetHeight()); | ||||
|         } | ||||
|         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()); | ||||
| 
 | ||||
| @ -751,62 +736,49 @@ 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<GLint>(rect.left); | ||||
|     const GLint y0 = static_cast<GLint>(rect.bottom); | ||||
|     std::size_t buffer_offset = | ||||
|     const auto x0 = static_cast<GLint>(rect.left); | ||||
|     const auto y0 = static_cast<GLint>(rect.bottom); | ||||
|     auto buffer_offset = | ||||
|         static_cast<std::size_t>(static_cast<std::size_t>(y0) * params.MipWidth(mip_map) + | ||||
|                                  static_cast<std::size_t>(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<GLint>(params.MipWidth(mip_map))); | ||||
| 
 | ||||
|     GLsizei image_size = static_cast<GLsizei>(params.GetMipmapSizeGL(mip_map, false)); | ||||
|     glActiveTexture(GL_TEXTURE0); | ||||
|     const auto image_size = static_cast<GLsizei>(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<GLsizei>(params.MipWidth(mip_map)), | ||||
|                                    static_cast<GLsizei>(params.MipHeight(mip_map)), 0, image_size, | ||||
|             glCompressedTextureSubImage2D( | ||||
|                 texture.handle, mip_map, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)), | ||||
|                 static_cast<GLsizei>(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<GLsizei>(params.MipWidth(mip_map)), | ||||
|             glCompressedTextureSubImage3D( | ||||
|                 texture.handle, mip_map, 0, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)), | ||||
|                 static_cast<GLsizei>(params.MipHeight(mip_map)), | ||||
|                                    static_cast<GLsizei>(params.MipDepth(mip_map)), 0, image_size, | ||||
|                 static_cast<GLsizei>(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<GLsizei>(params.MipWidth(mip_map)), | ||||
|                                    static_cast<GLsizei>(params.MipHeight(mip_map)), | ||||
|                                    static_cast<GLsizei>(params.depth), 0, image_size, | ||||
|                                    &gl_buffer[mip_map][buffer_offset]); | ||||
|             glCompressedTextureSubImage3D( | ||||
|                 texture.handle, mip_map, 0, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)), | ||||
|                 static_cast<GLsizei>(params.MipHeight(mip_map)), static_cast<GLsizei>(params.depth), | ||||
|                 tuple.internal_format, image_size, &gl_buffer[mip_map][buffer_offset]); | ||||
|             break; | ||||
|         case SurfaceTarget::TextureCubemap: { | ||||
|             GLsizei layer_size = static_cast<GLsizei>(params.LayerSizeGL(mip_map)); | ||||
|             const auto layer_size = static_cast<GLsizei>(params.LayerSizeGL(mip_map)); | ||||
|             for (std::size_t face = 0; face < params.depth; ++face) { | ||||
|                 glCompressedTexImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), | ||||
|                                        mip_map, tuple.internal_format, | ||||
|                 glCompressedTextureSubImage3D( | ||||
|                     texture.handle, mip_map, 0, 0, static_cast<GLint>(face), | ||||
|                     static_cast<GLsizei>(params.MipWidth(mip_map)), | ||||
|                                        static_cast<GLsizei>(params.MipHeight(mip_map)), 0, | ||||
|                     static_cast<GLsizei>(params.MipHeight(mip_map)), 1, tuple.internal_format, | ||||
|                     layer_size, &gl_buffer[mip_map][buffer_offset]); | ||||
|                 buffer_offset += layer_size; | ||||
|             } | ||||
| @ -816,35 +788,32 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, | ||||
|             LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", | ||||
|                          static_cast<u32>(params.target)); | ||||
|             UNREACHABLE(); | ||||
|             glCompressedTexImage2D(GL_TEXTURE_2D, mip_map, tuple.internal_format, | ||||
|                                    static_cast<GLsizei>(params.MipWidth(mip_map)), | ||||
|                                    static_cast<GLsizei>(params.MipHeight(mip_map)), 0, | ||||
|                                    static_cast<GLsizei>(params.size_in_bytes_gl), | ||||
|                                    &gl_buffer[mip_map][buffer_offset]); | ||||
|             glCompressedTextureSubImage2D( | ||||
|                 texture.handle, mip_map, 0, 0, static_cast<GLsizei>(params.MipWidth(mip_map)), | ||||
|                 static_cast<GLsizei>(params.MipHeight(mip_map)), tuple.internal_format, | ||||
|                 static_cast<GLsizei>(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<GLsizei>(rect.GetWidth()), tuple.format, tuple.type, | ||||
|                             &gl_buffer[mip_map][buffer_offset]); | ||||
|             glTextureSubImage1D(texture.handle, mip_map, x0, static_cast<GLsizei>(rect.GetWidth()), | ||||
|                                 tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]); | ||||
|             break; | ||||
|         case SurfaceTarget::Texture2D: | ||||
|             glTexSubImage2D(SurfaceTargetToGL(params.target), mip_map, x0, y0, | ||||
|             glTextureSubImage2D(texture.handle, mip_map, x0, y0, | ||||
|                                 static_cast<GLsizei>(rect.GetWidth()), | ||||
|                                 static_cast<GLsizei>(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, | ||||
|             glTextureSubImage3D(texture.handle, mip_map, x0, y0, 0, | ||||
|                                 static_cast<GLsizei>(rect.GetWidth()), | ||||
|                                 static_cast<GLsizei>(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, | ||||
|             glTextureSubImage3D(texture.handle, mip_map, x0, y0, 0, | ||||
|                                 static_cast<GLsizei>(rect.GetWidth()), | ||||
|                                 static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format, | ||||
|                                 tuple.type, &gl_buffer[mip_map][buffer_offset]); | ||||
| @ -852,10 +821,10 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, | ||||
|         case SurfaceTarget::TextureCubemap: { | ||||
|             std::size_t start = buffer_offset; | ||||
|             for (std::size_t face = 0; face < params.depth; ++face) { | ||||
|                 glTexSubImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), mip_map, | ||||
|                                 x0, y0, static_cast<GLsizei>(rect.GetWidth()), | ||||
|                                 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, | ||||
|                                 &gl_buffer[mip_map][buffer_offset]); | ||||
|                 glTextureSubImage3D(texture.handle, mip_map, x0, y0, static_cast<GLint>(face), | ||||
|                                     static_cast<GLsizei>(rect.GetWidth()), | ||||
|                                     static_cast<GLsizei>(rect.GetHeight()), 1, tuple.format, | ||||
|                                     tuple.type, &gl_buffer[mip_map][buffer_offset]); | ||||
|                 buffer_offset += params.LayerSizeGL(mip_map); | ||||
|             } | ||||
|             break; | ||||
| @ -864,7 +833,8 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, | ||||
|             LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", | ||||
|                          static_cast<u32>(params.target)); | ||||
|             UNREACHABLE(); | ||||
|             glTexSubImage2D(GL_TEXTURE_2D, mip_map, x0, y0, static_cast<GLsizei>(rect.GetWidth()), | ||||
|             glTextureSubImage2D(texture.handle, mip_map, x0, y0, | ||||
|                                 static_cast<GLsizei>(rect.GetWidth()), | ||||
|                                 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, | ||||
|                                 &gl_buffer[mip_map][buffer_offset]); | ||||
|         } | ||||
| @ -876,29 +846,18 @@ 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); | ||||
|     glTextureParameteriv(texture_view.handle, GL_TEXTURE_SWIZZLE_RGBA, | ||||
|                          reinterpret_cast<const GLint*>(swizzle.data())); | ||||
| } | ||||
| 
 | ||||
| MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); | ||||
| @ -909,6 +868,25 @@ 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) { | ||||
|         return; | ||||
|     } | ||||
|     swizzle = {new_x, new_y, new_z, new_w}; | ||||
|     const auto swizzle_data = reinterpret_cast<const GLint*>(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(); | ||||
|  | ||||
| @ -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); | ||||
| 
 | ||||
| @ -393,8 +398,8 @@ private: | ||||
|     SurfaceParams params{}; | ||||
|     GLenum gl_target{}; | ||||
|     GLenum gl_internal_format{}; | ||||
|     bool gl_is_compressed{}; | ||||
|     std::size_t cached_size_in_bytes{}; | ||||
|     std::array<GLenum, 4> swizzle{GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; | ||||
| }; | ||||
| 
 | ||||
| class RasterizerCacheOpenGL final : public RasterizerCache<Surface> { | ||||
|  | ||||
| @ -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() { | ||||
|  | ||||
| @ -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(); | ||||
|  | ||||
| @ -462,29 +462,35 @@ void OpenGLState::ApplyPolygonOffset() const { | ||||
| } | ||||
| 
 | ||||
| void OpenGLState::ApplyTextures() const { | ||||
|     bool has_delta{}; | ||||
|     std::size_t first{}; | ||||
|     std::size_t last{}; | ||||
|     std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> 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<int>(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; | ||||
|             } | ||||
|         // 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) { | ||||
|             std::array<GLint, 4> 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()); | ||||
|             last = i; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (has_delta) { | ||||
|         glBindTextures(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1), | ||||
|                        textures.data()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void OpenGLState::ApplySamplers() const { | ||||
|     bool has_delta{}; | ||||
|     std::size_t first{}, last{}; | ||||
|     std::size_t first{}; | ||||
|     std::size_t last{}; | ||||
|     std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers; | ||||
|     for (std::size_t i = 0; i < std::size(samplers); ++i) { | ||||
|         samplers[i] = texture_units[i].sampler; | ||||
|  | ||||
| @ -126,26 +126,14 @@ public: | ||||
|     struct TextureUnit { | ||||
|         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() { | ||||
|             Unbind(); | ||||
|             sampler = 0; | ||||
|             target = GL_TEXTURE_2D; | ||||
|         } | ||||
|     }; | ||||
|     std::array<TextureUnit, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_units; | ||||
|  | ||||
| @ -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<GLint>(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, | ||||
| @ -356,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(); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei