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:
ReinUsesLisp 2019-02-21 01:11:49 -03:00
parent 42f7c11021
commit 27ddbeb01c
3 changed files with 42 additions and 32 deletions

View file

@ -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 {

View file

@ -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);
} }
} }

View file

@ -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{};