gl_rasterizer_cache: Texture view if shader samples array but OGL is not
When a shader samples a texture array but that texture in OpenGL is created without layers, use a texture view to increase the texture hierarchy. For example, instead of binding a GL_TEXTURE_2D bind a GL_TEXTURE_2D_ARRAY view.
This commit is contained in:
		| @@ -1014,8 +1014,11 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader, | ||||
|         texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc); | ||||
|         Surface surface = res_cache.GetTextureSurface(texture, entry); | ||||
|         if (surface != nullptr) { | ||||
|             state.texture_units[current_bindpoint].texture = surface->Texture().handle; | ||||
|             state.texture_units[current_bindpoint].target = surface->Target(); | ||||
|             const GLuint handle = | ||||
|                 entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle; | ||||
|             const GLenum target = entry.IsArray() ? surface->TargetLayer() : surface->Target(); | ||||
|             state.texture_units[current_bindpoint].texture = handle; | ||||
|             state.texture_units[current_bindpoint].target = target; | ||||
|             state.texture_units[current_bindpoint].swizzle.r = | ||||
|                 MaxwellToGL::SwizzleSource(texture.tic.x_source); | ||||
|             state.texture_units[current_bindpoint].swizzle.g = | ||||
|   | ||||
| @@ -44,6 +44,17 @@ 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); | ||||
|     if (max_mip_level == 1) { | ||||
|         glTexParameterf(target, GL_TEXTURE_LOD_BIAS, 1000.0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) { | ||||
|     auto& memory_manager{Core::System::GetInstance().GPU().MemoryManager()}; | ||||
|     const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr_)}; | ||||
| @@ -532,6 +543,9 @@ CachedSurface::CachedSurface(const SurfaceParams& params) | ||||
|     glActiveTexture(GL_TEXTURE0); | ||||
|  | ||||
|     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) { | ||||
| @@ -560,15 +574,7 @@ CachedSurface::CachedSurface(const SurfaceParams& params) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||
|     glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAG_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); | ||||
|     glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL, | ||||
|                     params.max_mip_level - 1); | ||||
|     if (params.max_mip_level == 1) { | ||||
|         glTexParameterf(SurfaceTargetToGL(params.target), GL_TEXTURE_LOD_BIAS, 1000.0); | ||||
|     } | ||||
|     ApplyTextureDefaults(SurfaceTargetToGL(params.target), params.max_mip_level); | ||||
|  | ||||
|     LabelGLObject(GL_TEXTURE, texture.handle, params.addr, | ||||
|                   SurfaceParams::SurfaceTargetName(params.target)); | ||||
| @@ -886,6 +892,31 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, | ||||
|     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | ||||
| } | ||||
|  | ||||
| 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()}; | ||||
|  | ||||
|     texture_view.Create(); | ||||
|     glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, 0, | ||||
|                   params.max_mip_level, 0, 1); | ||||
|  | ||||
|     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); | ||||
| } | ||||
|  | ||||
| MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); | ||||
| void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) { | ||||
|     if (params.type == SurfaceType::Fill) | ||||
|   | ||||
| @@ -293,10 +293,31 @@ public: | ||||
|         return texture; | ||||
|     } | ||||
|  | ||||
|     const OGLTexture& TextureLayer() { | ||||
|         if (params.is_layered) { | ||||
|             return Texture(); | ||||
|         } | ||||
|         EnsureTextureView(); | ||||
|         return texture_view; | ||||
|     } | ||||
|  | ||||
|     GLenum Target() const { | ||||
|         return gl_target; | ||||
|     } | ||||
|  | ||||
|     GLenum TargetLayer() const { | ||||
|         using VideoCore::Surface::SurfaceTarget; | ||||
|         switch (params.target) { | ||||
|         case SurfaceTarget::Texture1D: | ||||
|             return GL_TEXTURE_1D_ARRAY; | ||||
|         case SurfaceTarget::Texture2D: | ||||
|             return GL_TEXTURE_2D_ARRAY; | ||||
|         case SurfaceTarget::TextureCubemap: | ||||
|             return GL_TEXTURE_CUBE_MAP_ARRAY; | ||||
|         } | ||||
|         return Target(); | ||||
|     } | ||||
|  | ||||
|     const SurfaceParams& GetSurfaceParams() const { | ||||
|         return params; | ||||
|     } | ||||
| @@ -311,11 +332,16 @@ public: | ||||
| private: | ||||
|     void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle); | ||||
|  | ||||
|     void EnsureTextureView(); | ||||
|  | ||||
|     OGLTexture texture; | ||||
|     OGLTexture texture_view; | ||||
|     std::vector<std::vector<u8>> gl_buffer; | ||||
|     SurfaceParams params; | ||||
|     GLenum gl_target; | ||||
|     std::size_t cached_size_in_bytes; | ||||
|     SurfaceParams params{}; | ||||
|     GLenum gl_target{}; | ||||
|     GLenum gl_internal_format{}; | ||||
|     bool gl_is_compressed{}; | ||||
|     std::size_t cached_size_in_bytes{}; | ||||
| }; | ||||
|  | ||||
| class RasterizerCacheOpenGL final : public RasterizerCache<Surface> { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ReinUsesLisp
					ReinUsesLisp