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
|
@ -1014,8 +1014,11 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
|
||||||
texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc);
|
texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc);
|
||||||
Surface surface = res_cache.GetTextureSurface(texture, entry);
|
Surface surface = res_cache.GetTextureSurface(texture, entry);
|
||||||
if (surface != nullptr) {
|
if (surface != nullptr) {
|
||||||
state.texture_units[current_bindpoint].texture = surface->Texture().handle;
|
const GLuint handle =
|
||||||
state.texture_units[current_bindpoint].target = surface->Target();
|
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 =
|
state.texture_units[current_bindpoint].swizzle.r =
|
||||||
MaxwellToGL::SwizzleSource(texture.tic.x_source);
|
MaxwellToGL::SwizzleSource(texture.tic.x_source);
|
||||||
state.texture_units[current_bindpoint].swizzle.g =
|
state.texture_units[current_bindpoint].swizzle.g =
|
||||||
|
|
|
@ -44,6 +44,17 @@ struct FormatTuple {
|
||||||
bool compressed;
|
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_) {
|
void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {
|
||||||
auto& memory_manager{Core::System::GetInstance().GPU().MemoryManager()};
|
auto& memory_manager{Core::System::GetInstance().GPU().MemoryManager()};
|
||||||
const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr_)};
|
const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr_)};
|
||||||
|
@ -532,6 +543,9 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type);
|
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) {
|
if (!format_tuple.compressed) {
|
||||||
// Only pre-create the texture for non-compressed textures.
|
// Only pre-create the texture for non-compressed textures.
|
||||||
switch (params.target) {
|
switch (params.target) {
|
||||||
|
@ -560,15 +574,7 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
ApplyTextureDefaults(SurfaceTargetToGL(params.target), params.max_mip_level);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelGLObject(GL_TEXTURE, texture.handle, params.addr,
|
LabelGLObject(GL_TEXTURE, texture.handle, params.addr,
|
||||||
SurfaceParams::SurfaceTargetName(params.target));
|
SurfaceParams::SurfaceTargetName(params.target));
|
||||||
|
@ -886,6 +892,31 @@ 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() {
|
||||||
|
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));
|
MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64));
|
||||||
void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) {
|
void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) {
|
||||||
if (params.type == SurfaceType::Fill)
|
if (params.type == SurfaceType::Fill)
|
||||||
|
|
|
@ -293,10 +293,31 @@ public:
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const OGLTexture& TextureLayer() {
|
||||||
|
if (params.is_layered) {
|
||||||
|
return Texture();
|
||||||
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
@ -311,11 +332,16 @@ 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();
|
||||||
|
|
||||||
OGLTexture texture;
|
OGLTexture texture;
|
||||||
|
OGLTexture texture_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{};
|
||||||
std::size_t cached_size_in_bytes;
|
GLenum gl_internal_format{};
|
||||||
|
bool gl_is_compressed{};
|
||||||
|
std::size_t cached_size_in_bytes{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {
|
class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {
|
||||||
|
|
Reference in New Issue