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:
parent
9a22a94a51
commit
97fb6179b9
3 changed files with 74 additions and 14 deletions
|
@ -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> {
|
||||
|
|
Loading…
Reference in a new issue