gl_texture_cache: Implement small texture view cache for swizzles
This fixes cases where the texture swizzle was applied twice on the same draw to a texture bound to two different slots.
This commit is contained in:
parent
8bba84a401
commit
b17fe82973
3 changed files with 44 additions and 37 deletions
|
@ -977,16 +977,12 @@ void RasterizerOpenGL::SetupTexture(u32 binding, const Tegra::Texture::FullTextu
|
||||||
glBindTextureUnit(binding, 0);
|
glBindTextureUnit(binding, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
glBindTextureUnit(binding, view->GetTexture());
|
const GLuint handle = view->GetTexture(texture.tic.x_source, texture.tic.y_source,
|
||||||
|
texture.tic.z_source, texture.tic.w_source);
|
||||||
if (view->GetSurfaceParams().IsBuffer()) {
|
glBindTextureUnit(binding, handle);
|
||||||
return;
|
if (!view->GetSurfaceParams().IsBuffer()) {
|
||||||
|
glBindSampler(binding, sampler_cache.GetSampler(texture.tsc));
|
||||||
}
|
}
|
||||||
// Apply swizzle to textures that are not buffers.
|
|
||||||
view->ApplySwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source,
|
|
||||||
texture.tic.w_source);
|
|
||||||
|
|
||||||
glBindSampler(binding, sampler_cache.GetSampler(texture.tsc));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SetupDrawImages(std::size_t stage_index, const Shader& shader) {
|
void RasterizerOpenGL::SetupDrawImages(std::size_t stage_index, const Shader& shader) {
|
||||||
|
@ -1015,14 +1011,11 @@ void RasterizerOpenGL::SetupImage(u32 binding, const Tegra::Texture::TICEntry& t
|
||||||
glBindImageTexture(binding, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8);
|
glBindImageTexture(binding, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!tic.IsBuffer()) {
|
|
||||||
view->ApplySwizzle(tic.x_source, tic.y_source, tic.z_source, tic.w_source);
|
|
||||||
}
|
|
||||||
if (entry.is_written) {
|
if (entry.is_written) {
|
||||||
view->MarkAsModified(texture_cache.Tick());
|
view->MarkAsModified(texture_cache.Tick());
|
||||||
}
|
}
|
||||||
glBindImageTexture(binding, view->GetTexture(), 0, GL_TRUE, 0, GL_READ_WRITE,
|
const GLuint handle = view->GetTexture(tic.x_source, tic.y_source, tic.z_source, tic.w_source);
|
||||||
view->GetFormat());
|
glBindImageTexture(binding, handle, 0, GL_TRUE, 0, GL_READ_WRITE, view->GetFormat());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncViewport() {
|
void RasterizerOpenGL::SyncViewport() {
|
||||||
|
|
|
@ -35,7 +35,7 @@ MICROPROFILE_DEFINE(OpenGL_Texture_Buffer_Copy, "OpenGL", "Texture Buffer Copy",
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct FormatTuple {
|
struct FormatTuple {
|
||||||
GLint internal_format;
|
GLenum internal_format;
|
||||||
GLenum format = GL_NONE;
|
GLenum format = GL_NONE;
|
||||||
GLenum type = GL_NONE;
|
GLenum type = GL_NONE;
|
||||||
};
|
};
|
||||||
|
@ -387,7 +387,7 @@ void CachedSurface::DecorateSurfaceName() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, std::string prefix) {
|
void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, std::string prefix) {
|
||||||
LabelGLObject(GL_TEXTURE, texture_view.handle, gpu_addr, prefix);
|
LabelGLObject(GL_TEXTURE, main_view.handle, gpu_addr, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
View CachedSurface::CreateView(const ViewParams& view_key) {
|
View CachedSurface::CreateView(const ViewParams& view_key) {
|
||||||
|
@ -403,15 +403,13 @@ View CachedSurface::CreateViewInner(const ViewParams& view_key, const bool is_pr
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& params,
|
CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& params,
|
||||||
const bool is_proxy)
|
bool is_proxy)
|
||||||
: VideoCommon::ViewBase(params), surface{surface}, is_proxy{is_proxy} {
|
: VideoCommon::ViewBase(params), surface{surface},
|
||||||
target = GetTextureTarget(params.target);
|
format{GetFormatTuple(surface.GetSurfaceParams().pixel_format).internal_format},
|
||||||
format = GetFormatTuple(surface.GetSurfaceParams().pixel_format).internal_format;
|
target{GetTextureTarget(params.target)}, is_proxy{is_proxy} {
|
||||||
if (!is_proxy) {
|
if (!is_proxy) {
|
||||||
texture_view = CreateTextureView();
|
main_view = CreateTextureView();
|
||||||
}
|
}
|
||||||
current_swizzle =
|
|
||||||
EncodeSwizzle(SwizzleSource::R, SwizzleSource::G, SwizzleSource::B, SwizzleSource::A);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedSurfaceView::~CachedSurfaceView() = default;
|
CachedSurfaceView::~CachedSurfaceView() = default;
|
||||||
|
@ -454,23 +452,34 @@ void CachedSurfaceView::Attach(GLenum attachment, GLenum target) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CachedSurfaceView::ApplySwizzle(SwizzleSource x_source, SwizzleSource y_source,
|
GLuint CachedSurfaceView::GetTexture(SwizzleSource x_source, SwizzleSource y_source,
|
||||||
SwizzleSource z_source, SwizzleSource w_source) {
|
SwizzleSource z_source, SwizzleSource w_source) {
|
||||||
|
if (GetSurfaceParams().IsBuffer()) {
|
||||||
|
return GetTexture();
|
||||||
|
}
|
||||||
const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source);
|
const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source);
|
||||||
if (current_swizzle == new_swizzle) {
|
if (current_swizzle == new_swizzle) {
|
||||||
return;
|
return current_view;
|
||||||
}
|
}
|
||||||
current_swizzle = new_swizzle;
|
current_swizzle = new_swizzle;
|
||||||
|
|
||||||
|
const auto [entry, is_cache_miss] = view_cache.try_emplace(new_swizzle);
|
||||||
|
OGLTextureView& view = entry->second;
|
||||||
|
if (!is_cache_miss) {
|
||||||
|
current_view = view.handle;
|
||||||
|
return view.handle;
|
||||||
|
}
|
||||||
|
view = CreateTextureView();
|
||||||
|
current_view = view.handle;
|
||||||
|
|
||||||
std::array swizzle{x_source, y_source, z_source, w_source};
|
std::array swizzle{x_source, y_source, z_source, w_source};
|
||||||
|
|
||||||
const GLuint handle = GetTexture();
|
switch (const PixelFormat format = GetSurfaceParams().pixel_format) {
|
||||||
switch (const PixelFormat format = surface.GetSurfaceParams().pixel_format) {
|
|
||||||
case PixelFormat::S8Z24:
|
|
||||||
case PixelFormat::Z24S8:
|
case PixelFormat::Z24S8:
|
||||||
case PixelFormat::Z32FS8:
|
case PixelFormat::Z32FS8:
|
||||||
|
case PixelFormat::S8Z24:
|
||||||
UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G);
|
UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G);
|
||||||
glTextureParameteri(handle, GL_DEPTH_STENCIL_TEXTURE_MODE,
|
glTextureParameteri(view.handle, GL_DEPTH_STENCIL_TEXTURE_MODE,
|
||||||
GetComponent(format, x_source == SwizzleSource::R));
|
GetComponent(format, x_source == SwizzleSource::R));
|
||||||
|
|
||||||
// Make sure we sample the first component
|
// Make sure we sample the first component
|
||||||
|
@ -481,10 +490,11 @@ void CachedSurfaceView::ApplySwizzle(SwizzleSource x_source, SwizzleSource y_sou
|
||||||
default: {
|
default: {
|
||||||
const std::array gl_swizzle = {GetSwizzleSource(swizzle[0]), GetSwizzleSource(swizzle[1]),
|
const std::array gl_swizzle = {GetSwizzleSource(swizzle[0]), GetSwizzleSource(swizzle[1]),
|
||||||
GetSwizzleSource(swizzle[2]), GetSwizzleSource(swizzle[3])};
|
GetSwizzleSource(swizzle[2]), GetSwizzleSource(swizzle[3])};
|
||||||
glTextureParameteriv(handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data());
|
glTextureParameteriv(view.handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return view.handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
OGLTextureView CachedSurfaceView::CreateTextureView() const {
|
OGLTextureView CachedSurfaceView::CreateTextureView() const {
|
||||||
|
|
|
@ -83,7 +83,7 @@ public:
|
||||||
/// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER
|
/// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER
|
||||||
void Attach(GLenum attachment, GLenum target) const;
|
void Attach(GLenum attachment, GLenum target) const;
|
||||||
|
|
||||||
void ApplySwizzle(Tegra::Texture::SwizzleSource x_source,
|
GLuint GetTexture(Tegra::Texture::SwizzleSource x_source,
|
||||||
Tegra::Texture::SwizzleSource y_source,
|
Tegra::Texture::SwizzleSource y_source,
|
||||||
Tegra::Texture::SwizzleSource z_source,
|
Tegra::Texture::SwizzleSource z_source,
|
||||||
Tegra::Texture::SwizzleSource w_source);
|
Tegra::Texture::SwizzleSource w_source);
|
||||||
|
@ -98,7 +98,7 @@ public:
|
||||||
if (is_proxy) {
|
if (is_proxy) {
|
||||||
return surface.GetTexture();
|
return surface.GetTexture();
|
||||||
}
|
}
|
||||||
return texture_view.handle;
|
return main_view.handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum GetFormat() const {
|
GLenum GetFormat() const {
|
||||||
|
@ -113,12 +113,16 @@ private:
|
||||||
OGLTextureView CreateTextureView() const;
|
OGLTextureView CreateTextureView() const;
|
||||||
|
|
||||||
CachedSurface& surface;
|
CachedSurface& surface;
|
||||||
GLenum target{};
|
const GLenum format;
|
||||||
GLenum format{};
|
const GLenum target;
|
||||||
|
const bool is_proxy;
|
||||||
|
|
||||||
OGLTextureView texture_view;
|
std::unordered_map<u32, OGLTextureView> view_cache;
|
||||||
u32 current_swizzle{};
|
OGLTextureView main_view;
|
||||||
bool is_proxy{};
|
|
||||||
|
// Use an invalid default so it always fails the comparison test
|
||||||
|
u32 current_swizzle = 0xffffffff;
|
||||||
|
GLuint current_view = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureCacheOpenGL final : public TextureCacheBase {
|
class TextureCacheOpenGL final : public TextureCacheBase {
|
||||||
|
|
Loading…
Reference in a new issue