Merge pull request #3991 from ReinUsesLisp/depth-sampling

texture_cache: Implement depth stencil texture swizzles
merge-requests/60/head
bunnei 2020-05-28 23:33:38 +07:00 committed by GitHub
commit 1bb3122c1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 83 additions and 68 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;
}; };
@ -238,6 +238,12 @@ OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum inte
return texture; return texture;
} }
constexpr u32 EncodeSwizzle(SwizzleSource x_source, SwizzleSource y_source, SwizzleSource z_source,
SwizzleSource w_source) {
return (static_cast<u32>(x_source) << 24) | (static_cast<u32>(y_source) << 16) |
(static_cast<u32>(z_source) << 8) | static_cast<u32>(w_source);
}
} // Anonymous namespace } // Anonymous namespace
CachedSurface::CachedSurface(const GPUVAddr gpu_addr, const SurfaceParams& params, CachedSurface::CachedSurface(const GPUVAddr gpu_addr, const SurfaceParams& params,
@ -381,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) {
@ -397,14 +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();
} }
swizzle = EncodeSwizzle(SwizzleSource::R, SwizzleSource::G, SwizzleSource::B, SwizzleSource::A);
} }
CachedSurfaceView::~CachedSurfaceView() = default; CachedSurfaceView::~CachedSurfaceView() = default;
@ -447,27 +452,49 @@ 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) {
u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source); if (GetSurfaceParams().IsBuffer()) {
if (new_swizzle == swizzle) return GetTexture();
return; }
swizzle = new_swizzle; const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source);
const std::array gl_swizzle = {GetSwizzleSource(x_source), GetSwizzleSource(y_source), if (current_swizzle == new_swizzle) {
GetSwizzleSource(z_source), GetSwizzleSource(w_source)}; return current_view;
const GLuint handle = GetTexture(); }
const PixelFormat format = surface.GetSurfaceParams().pixel_format; current_swizzle = new_swizzle;
switch (format) {
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};
switch (const PixelFormat format = GetSurfaceParams().pixel_format) {
case PixelFormat::Z24S8: case PixelFormat::Z24S8:
case PixelFormat::Z32FS8: case PixelFormat::Z32FS8:
case PixelFormat::S8Z24: case PixelFormat::S8Z24:
glTextureParameteri(handle, GL_DEPTH_STENCIL_TEXTURE_MODE, UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G);
glTextureParameteri(view.handle, GL_DEPTH_STENCIL_TEXTURE_MODE,
GetComponent(format, x_source == SwizzleSource::R)); GetComponent(format, x_source == SwizzleSource::R));
break;
default: // Make sure we sample the first component
glTextureParameteriv(handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data()); std::transform(swizzle.begin(), swizzle.end(), swizzle.begin(), [](SwizzleSource value) {
return value == SwizzleSource::G ? SwizzleSource::R : value;
});
[[fallthrough]];
default: {
const std::array gl_swizzle = {GetSwizzleSource(swizzle[0]), GetSwizzleSource(swizzle[1]),
GetSwizzleSource(swizzle[2]), GetSwizzleSource(swizzle[3])};
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 {
@ -110,23 +110,19 @@ public:
} }
private: private:
u32 EncodeSwizzle(Tegra::Texture::SwizzleSource x_source,
Tegra::Texture::SwizzleSource y_source,
Tegra::Texture::SwizzleSource z_source,
Tegra::Texture::SwizzleSource w_source) const {
return (static_cast<u32>(x_source) << 24) | (static_cast<u32>(y_source) << 16) |
(static_cast<u32>(z_source) << 8) | static_cast<u32>(w_source);
}
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 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 {

@ -354,26 +354,23 @@ CachedSurfaceView::~CachedSurfaceView() = default;
VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y_source, VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y_source,
SwizzleSource z_source, SwizzleSource w_source) { SwizzleSource z_source, SwizzleSource w_source) {
const u32 swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source); const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source);
if (last_image_view && last_swizzle == swizzle) { if (last_image_view && last_swizzle == new_swizzle) {
return last_image_view; return last_image_view;
} }
last_swizzle = swizzle; last_swizzle = new_swizzle;
const auto [entry, is_cache_miss] = view_cache.try_emplace(swizzle); const auto [entry, is_cache_miss] = view_cache.try_emplace(new_swizzle);
auto& image_view = entry->second; auto& image_view = entry->second;
if (!is_cache_miss) { if (!is_cache_miss) {
return last_image_view = *image_view; return last_image_view = *image_view;
} }
auto swizzle_x = MaxwellToVK::SwizzleSource(x_source); std::array swizzle{MaxwellToVK::SwizzleSource(x_source), MaxwellToVK::SwizzleSource(y_source),
auto swizzle_y = MaxwellToVK::SwizzleSource(y_source); MaxwellToVK::SwizzleSource(z_source), MaxwellToVK::SwizzleSource(w_source)};
auto swizzle_z = MaxwellToVK::SwizzleSource(z_source);
auto swizzle_w = MaxwellToVK::SwizzleSource(w_source);
if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5U) { if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5U) {
// A1B5G5R5 is implemented as A1R5G5B5, we have to change the swizzle here. // A1B5G5R5 is implemented as A1R5G5B5, we have to change the swizzle here.
std::swap(swizzle_x, swizzle_z); std::swap(swizzle[0], swizzle[2]);
} }
// Games can sample depth or stencil values on textures. This is decided by the swizzle value on // Games can sample depth or stencil values on textures. This is decided by the swizzle value on
@ -395,11 +392,11 @@ VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
// Vulkan doesn't seem to understand swizzling of a depth stencil image, use identity // Make sure we sample the first component
swizzle_x = VK_COMPONENT_SWIZZLE_R; std::transform(
swizzle_y = VK_COMPONENT_SWIZZLE_G; swizzle.begin(), swizzle.end(), swizzle.begin(), [](VkComponentSwizzle component) {
swizzle_z = VK_COMPONENT_SWIZZLE_B; return component == VK_COMPONENT_SWIZZLE_G ? VK_COMPONENT_SWIZZLE_R : component;
swizzle_w = VK_COMPONENT_SWIZZLE_A; });
} }
VkImageViewCreateInfo ci; VkImageViewCreateInfo ci;
@ -409,7 +406,7 @@ VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y
ci.image = surface.GetImageHandle(); ci.image = surface.GetImageHandle();
ci.viewType = image_view_type; ci.viewType = image_view_type;
ci.format = surface.GetImage().GetFormat(); ci.format = surface.GetImage().GetFormat();
ci.components = {swizzle_x, swizzle_y, swizzle_z, swizzle_w}; ci.components = {swizzle[0], swizzle[1], swizzle[2], swizzle[3]};
ci.subresourceRange.aspectMask = aspect; ci.subresourceRange.aspectMask = aspect;
ci.subresourceRange.baseMipLevel = base_level; ci.subresourceRange.baseMipLevel = base_level;
ci.subresourceRange.levelCount = num_levels; ci.subresourceRange.levelCount = num_levels;

@ -991,7 +991,9 @@ private:
params.target = target; params.target = target;
params.is_tiled = false; params.is_tiled = false;
params.srgb_conversion = false; params.srgb_conversion = false;
params.is_layered = false; params.is_layered =
target == SurfaceTarget::Texture1DArray || target == SurfaceTarget::Texture2DArray ||
target == SurfaceTarget::TextureCubemap || target == SurfaceTarget::TextureCubeArray;
params.block_width = 0; params.block_width = 0;
params.block_height = 0; params.block_height = 0;
params.block_depth = 0; params.block_depth = 0;