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:
parent
42f7c11021
commit
27ddbeb01c
3 changed files with 42 additions and 32 deletions
|
@ -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{};
|
||||||
|
|
Loading…
Reference in a new issue