From 030676b95d8f0c0cd6c288f59daf94bbda6c7133 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
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<FormatTuple, SurfaceParams::MaxPixelFormat> 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<u32>(target));
+    UNREACHABLE();
+    return {};
+}
+
 static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
     ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size());
     auto& format = tex_format_tuples[static_cast<unsigned int>(pixel_format)];
@@ -357,33 +380,6 @@ static constexpr std::array<void (*)(u32, u32, u32, std::vector<u8>&, 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<u32>& src_rect, GLuint dst_tex,
                          const MathUtil::Rectangle<u32>& 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<u32>& 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<u8>& 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<u32>(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<u8> gl_buffer;
     SurfaceParams params;
+    GLenum gl_target;
 };
 
 class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {
-- 
GitLab