gl_rasterizer_cache: Create texture views for array discrepancies
When a texture is sampled in a shader with a different array mode than the cached state, create a texture view and bind that to the shader instead.
This commit is contained in:
		@@ -1012,10 +1012,9 @@ void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& s
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc);
 | 
					        texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Surface surface = res_cache.GetTextureSurface(texture, entry);
 | 
					        if (Surface surface = res_cache.GetTextureSurface(texture, entry); surface) {
 | 
				
			||||||
        if (surface != nullptr) {
 | 
					 | 
				
			||||||
            state.texture_units[current_bindpoint].texture =
 | 
					            state.texture_units[current_bindpoint].texture =
 | 
				
			||||||
                entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle;
 | 
					                surface->Texture(entry.IsArray()).handle;
 | 
				
			||||||
            surface->UpdateSwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source,
 | 
					            surface->UpdateSwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source,
 | 
				
			||||||
                                   texture.tic.w_source);
 | 
					                                   texture.tic.w_source);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -399,6 +399,27 @@ static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType
 | 
				
			|||||||
    return format;
 | 
					    return format;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Returns the discrepant array target
 | 
				
			||||||
 | 
					constexpr GLenum GetArrayDiscrepantTarget(SurfaceTarget target) {
 | 
				
			||||||
 | 
					    switch (target) {
 | 
				
			||||||
 | 
					    case SurfaceTarget::Texture1D:
 | 
				
			||||||
 | 
					        return GL_TEXTURE_1D_ARRAY;
 | 
				
			||||||
 | 
					    case SurfaceTarget::Texture2D:
 | 
				
			||||||
 | 
					        return GL_TEXTURE_2D_ARRAY;
 | 
				
			||||||
 | 
					    case SurfaceTarget::Texture3D:
 | 
				
			||||||
 | 
					        return GL_NONE;
 | 
				
			||||||
 | 
					    case SurfaceTarget::Texture1DArray:
 | 
				
			||||||
 | 
					        return GL_TEXTURE_1D;
 | 
				
			||||||
 | 
					    case SurfaceTarget::Texture2DArray:
 | 
				
			||||||
 | 
					        return GL_TEXTURE_2D;
 | 
				
			||||||
 | 
					    case SurfaceTarget::TextureCubemap:
 | 
				
			||||||
 | 
					        return GL_TEXTURE_CUBE_MAP_ARRAY;
 | 
				
			||||||
 | 
					    case SurfaceTarget::TextureCubeArray:
 | 
				
			||||||
 | 
					        return GL_TEXTURE_CUBE_MAP;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return GL_NONE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Common::Rectangle<u32> SurfaceParams::GetRect(u32 mip_level) const {
 | 
					Common::Rectangle<u32> SurfaceParams::GetRect(u32 mip_level) const {
 | 
				
			||||||
    u32 actual_height{std::max(1U, unaligned_height >> mip_level)};
 | 
					    u32 actual_height{std::max(1U, unaligned_height >> mip_level)};
 | 
				
			||||||
    if (IsPixelFormatASTC(pixel_format)) {
 | 
					    if (IsPixelFormatASTC(pixel_format)) {
 | 
				
			||||||
@@ -881,20 +902,22 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
 | 
				
			|||||||
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
 | 
					    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void CachedSurface::EnsureTextureView() {
 | 
					void CachedSurface::EnsureTextureDiscrepantView() {
 | 
				
			||||||
    if (texture_view.handle != 0)
 | 
					    if (discrepant_view.handle != 0)
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const GLenum target{TargetLayer()};
 | 
					    const GLenum target{GetArrayDiscrepantTarget(params.target)};
 | 
				
			||||||
 | 
					    ASSERT(target != GL_NONE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const GLuint num_layers{target == GL_TEXTURE_CUBE_MAP_ARRAY ? 6u : 1u};
 | 
					    const GLuint num_layers{target == GL_TEXTURE_CUBE_MAP_ARRAY ? 6u : 1u};
 | 
				
			||||||
    constexpr GLuint min_layer = 0;
 | 
					    constexpr GLuint min_layer = 0;
 | 
				
			||||||
    constexpr GLuint min_level = 0;
 | 
					    constexpr GLuint min_level = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glGenTextures(1, &texture_view.handle);
 | 
					    glGenTextures(1, &discrepant_view.handle);
 | 
				
			||||||
    glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, min_level,
 | 
					    glTextureView(discrepant_view.handle, target, texture.handle, gl_internal_format, min_level,
 | 
				
			||||||
                  params.max_mip_level, min_layer, num_layers);
 | 
					                  params.max_mip_level, min_layer, num_layers);
 | 
				
			||||||
    ApplyTextureDefaults(texture_view.handle, params.max_mip_level);
 | 
					    ApplyTextureDefaults(discrepant_view.handle, params.max_mip_level);
 | 
				
			||||||
    glTextureParameteriv(texture_view.handle, GL_TEXTURE_SWIZZLE_RGBA,
 | 
					    glTextureParameteriv(discrepant_view.handle, GL_TEXTURE_SWIZZLE_RGBA,
 | 
				
			||||||
                         reinterpret_cast<const GLint*>(swizzle.data()));
 | 
					                         reinterpret_cast<const GLint*>(swizzle.data()));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -920,8 +943,8 @@ void CachedSurface::UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x,
 | 
				
			|||||||
    swizzle = {new_x, new_y, new_z, new_w};
 | 
					    swizzle = {new_x, new_y, new_z, new_w};
 | 
				
			||||||
    const auto swizzle_data = reinterpret_cast<const GLint*>(swizzle.data());
 | 
					    const auto swizzle_data = reinterpret_cast<const GLint*>(swizzle.data());
 | 
				
			||||||
    glTextureParameteriv(texture.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data);
 | 
					    glTextureParameteriv(texture.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data);
 | 
				
			||||||
    if (texture_view.handle != 0) {
 | 
					    if (discrepant_view.handle != 0) {
 | 
				
			||||||
        glTextureParameteriv(texture_view.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data);
 | 
					        glTextureParameteriv(discrepant_view.handle, GL_TEXTURE_SWIZZLE_RGBA, swizzle_data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -354,31 +354,19 @@ public:
 | 
				
			|||||||
        return texture;
 | 
					        return texture;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const OGLTexture& TextureLayer() {
 | 
					    const OGLTexture& Texture(bool as_array) {
 | 
				
			||||||
        if (params.is_array) {
 | 
					        if (params.is_array == as_array) {
 | 
				
			||||||
            return Texture();
 | 
					            return texture;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            EnsureTextureDiscrepantView();
 | 
				
			||||||
 | 
					            return discrepant_view;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        EnsureTextureView();
 | 
					 | 
				
			||||||
        return texture_view;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GLenum Target() const {
 | 
					    GLenum Target() const {
 | 
				
			||||||
        return gl_target;
 | 
					        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 {
 | 
					    const SurfaceParams& GetSurfaceParams() const {
 | 
				
			||||||
        return params;
 | 
					        return params;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -398,10 +386,10 @@ public:
 | 
				
			|||||||
private:
 | 
					private:
 | 
				
			||||||
    void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle);
 | 
					    void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void EnsureTextureView();
 | 
					    void EnsureTextureDiscrepantView();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    OGLTexture texture;
 | 
					    OGLTexture texture;
 | 
				
			||||||
    OGLTexture texture_view;
 | 
					    OGLTexture discrepant_view;
 | 
				
			||||||
    std::vector<std::vector<u8>> gl_buffer;
 | 
					    std::vector<std::vector<u8>> gl_buffer;
 | 
				
			||||||
    SurfaceParams params{};
 | 
					    SurfaceParams params{};
 | 
				
			||||||
    GLenum gl_target{};
 | 
					    GLenum gl_target{};
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user