From 030676b95d8f0c0cd6c288f59daf94bbda6c7133 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 1 Sep 2018 02:42:43 -0400 Subject: [PATCH] gl_rasterizer_cache: Keep track of texture type per surface. --- .../renderer_opengl/gl_rasterizer.cpp | 1 + .../renderer_opengl/gl_rasterizer_cache.cpp | 80 ++++++++++++------- .../renderer_opengl/gl_rasterizer_cache.h | 35 +++++++- 3 files changed, 84 insertions(+), 32 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index d5bbfbd1c7..5deee20dd9 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -700,6 +700,7 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader, Surface surface = res_cache.GetTextureSurface(texture); if (surface != nullptr) { state.texture_units[current_bindpoint].texture = surface->Texture().handle; + state.texture_units[current_bindpoint].target = surface->Target(); state.texture_units[current_bindpoint].swizzle.r = MaxwellToGL::SwizzleSource(texture.tic.x_source); state.texture_units[current_bindpoint].swizzle.g = diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 0df1bbf6b3..4d6fd8b8be 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -55,6 +55,7 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) { params.size_in_bytes = params.SizeInBytes(); params.cache_width = Common::AlignUp(params.width, 16); params.cache_height = Common::AlignUp(params.height, 16); + params.target = SurfaceTargetFromTextureType(config.tic.texture_type); return params; } @@ -73,6 +74,7 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) { params.size_in_bytes = params.SizeInBytes(); params.cache_width = Common::AlignUp(params.width, 16); params.cache_height = Common::AlignUp(params.height, 16); + params.target = SurfaceTarget::Texture2D; return params; } @@ -93,6 +95,7 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) { params.size_in_bytes = params.SizeInBytes(); params.cache_width = Common::AlignUp(params.width, 16); params.cache_height = Common::AlignUp(params.height, 16); + params.target = SurfaceTarget::Texture2D; return params; } @@ -166,6 +169,26 @@ static constexpr std::array tex_form ComponentType::Float, false}, // Z32FS8 }}; +static GLenum SurfaceTargetToGL(SurfaceParams::SurfaceTarget target) { + switch (target) { + case SurfaceParams::SurfaceTarget::Texture1D: + return GL_TEXTURE_1D; + case SurfaceParams::SurfaceTarget::Texture2D: + return GL_TEXTURE_2D; + case SurfaceParams::SurfaceTarget::Texture3D: + return GL_TEXTURE_3D; + case SurfaceParams::SurfaceTarget::Texture1DArray: + return GL_TEXTURE_1D_ARRAY; + case SurfaceParams::SurfaceTarget::Texture2DArray: + return GL_TEXTURE_2D_ARRAY; + case SurfaceParams::SurfaceTarget::TextureCubemap: + return GL_TEXTURE_CUBE_MAP; + } + LOG_CRITICAL(Render_OpenGL, "Unimplemented texture target={}", static_cast(target)); + UNREACHABLE(); + return {}; +} + static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) { ASSERT(static_cast(pixel_format) < tex_format_tuples.size()); auto& format = tex_format_tuples[static_cast(pixel_format)]; @@ -357,33 +380,6 @@ static constexpr std::array&, VAddr), // clang-format on }; -// Allocate an uninitialized texture of appropriate size and format for the surface -static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tuple, u32 width, - u32 height) { - OpenGLState cur_state = OpenGLState::GetCurState(); - - // Keep track of previous texture bindings - GLuint old_tex = cur_state.texture_units[0].texture; - cur_state.texture_units[0].texture = texture; - cur_state.Apply(); - glActiveTexture(GL_TEXTURE0); - - if (!format_tuple.compressed) { - // Only pre-create the texture for non-compressed textures. - glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, width, height, 0, - format_tuple.format, format_tuple.type, nullptr); - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - 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); - - // Restore previous texture bindings - cur_state.texture_units[0].texture = old_tex; - cur_state.Apply(); -} - static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle& src_rect, GLuint dst_tex, const MathUtil::Rectangle& dst_rect, SurfaceType type, GLuint read_fb_handle, GLuint draw_fb_handle) { @@ -438,12 +434,34 @@ static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle& src_rec return true; } -CachedSurface::CachedSurface(const SurfaceParams& params) : params(params) { +CachedSurface::CachedSurface(const SurfaceParams& params) + : params(params), gl_target(SurfaceTargetToGL(params.target)) { texture.Create(); const auto& rect{params.GetRect()}; - AllocateSurfaceTexture(texture.handle, - GetFormatTuple(params.pixel_format, params.component_type), - rect.GetWidth(), rect.GetHeight()); + + OpenGLState cur_state = OpenGLState::GetCurState(); + + // Keep track of previous texture bindings + GLuint old_tex = cur_state.texture_units[0].texture; + cur_state.texture_units[0].texture = texture.handle; + cur_state.Apply(); + glActiveTexture(GL_TEXTURE0); + + const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type); + if (!format_tuple.compressed) { + // Only pre-create the texture for non-compressed textures. + glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, rect.GetWidth(), + rect.GetHeight(), 0, format_tuple.format, format_tuple.type, nullptr); + } + + glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL, 0); + glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + // Restore previous texture bindings + cur_state.texture_units[0].texture = old_tex; + cur_state.Apply(); } static void ConvertS8Z24ToZ24S8(std::vector& data, u32 width, u32 height) { diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index b17867f647..6693b5cdaf 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -109,6 +109,33 @@ struct SurfaceParams { Invalid = 4, }; + enum class SurfaceTarget { + Texture1D, + Texture2D, + Texture3D, + Texture1DArray, + Texture2DArray, + TextureCubemap, + }; + + static SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type) { + switch (texture_type) { + case Tegra::Texture::TextureType::Texture1D: + return SurfaceTarget::Texture1D; + case Tegra::Texture::TextureType::Texture2D: + case Tegra::Texture::TextureType::Texture2DNoMipmap: + return SurfaceTarget::Texture2D; + case Tegra::Texture::TextureType::Texture1DArray: + return SurfaceTarget::Texture1DArray; + case Tegra::Texture::TextureType::Texture2DArray: + return SurfaceTarget::Texture2DArray; + default: + LOG_CRITICAL(HW_GPU, "Unimplemented texture_type={}", static_cast(texture_type)); + UNREACHABLE(); + return SurfaceTarget::Texture2D; + } + } + /** * Gets the compression factor for the specified PixelFormat. This applies to just the * "compressed width" and "compressed height", not the overall compression factor of a @@ -666,6 +693,7 @@ struct SurfaceParams { u32 height; u32 unaligned_height; size_t size_in_bytes; + SurfaceTarget target; // Parameters used for caching only u32 cache_width; @@ -709,6 +737,10 @@ public: return texture; } + GLenum Target() const { + return gl_target; + } + static constexpr unsigned int GetGLBytesPerPixel(SurfaceParams::PixelFormat format) { if (format == SurfaceParams::PixelFormat::Invalid) return 0; @@ -724,13 +756,14 @@ public: void LoadGLBuffer(); void FlushGLBuffer(); - // Upload/Download data in gl_buffer in/to this surface's texture + // Upload data in gl_buffer to this surface's texture void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle); private: OGLTexture texture; std::vector gl_buffer; SurfaceParams params; + GLenum gl_target; }; class RasterizerCacheOpenGL final : public RasterizerCache {