From 75596c07e0fc1462c2a19484e168f4944c33d3d3 Mon Sep 17 00:00:00 2001 From: Feng Chen Date: Fri, 4 Nov 2022 14:39:42 +0800 Subject: video_core: Fix SNORM texture buffer emulating error (#9001) --- src/video_core/shader_environment.cpp | 89 +++++++++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 10 deletions(-) (limited to 'src/video_core/shader_environment.cpp') diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index 63bcf9337..37bb76b72 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp @@ -19,6 +19,7 @@ #include "video_core/engines/kepler_compute.h" #include "video_core/memory_manager.h" #include "video_core/shader_environment.h" +#include "video_core/texture_cache/format_lookup_table.h" #include "video_core/textures/texture.h" namespace VideoCommon { @@ -33,7 +34,7 @@ static u64 MakeCbufKey(u32 index, u32 offset) { return (static_cast(index) << 32) | offset; } -static Shader::TextureType ConvertType(const Tegra::Texture::TICEntry& entry) { +static Shader::TextureType ConvertTextureType(const Tegra::Texture::TICEntry& entry) { switch (entry.texture_type) { case Tegra::Texture::TextureType::Texture1D: return Shader::TextureType::Color1D; @@ -59,6 +60,26 @@ static Shader::TextureType ConvertType(const Tegra::Texture::TICEntry& entry) { } } +static Shader::TexturePixelFormat ConvertTexturePixelFormat(const Tegra::Texture::TICEntry& entry) { + switch (PixelFormatFromTextureInfo(entry.format, entry.r_type, entry.g_type, entry.b_type, + entry.a_type, entry.srgb_conversion)) { + case VideoCore::Surface::PixelFormat::A8B8G8R8_SNORM: + return Shader::TexturePixelFormat::A8B8G8R8_SNORM; + case VideoCore::Surface::PixelFormat::R8_SNORM: + return Shader::TexturePixelFormat::R8_SNORM; + case VideoCore::Surface::PixelFormat::R8G8_SNORM: + return Shader::TexturePixelFormat::R8G8_SNORM; + case VideoCore::Surface::PixelFormat::R16G16B16A16_SNORM: + return Shader::TexturePixelFormat::R16G16B16A16_SNORM; + case VideoCore::Surface::PixelFormat::R16G16_SNORM: + return Shader::TexturePixelFormat::R16G16_SNORM; + case VideoCore::Surface::PixelFormat::R16_SNORM: + return Shader::TexturePixelFormat::R16_SNORM; + default: + return Shader::TexturePixelFormat::OTHER; + } +} + static std::string_view StageToPrefix(Shader::Stage stage) { switch (stage) { case Shader::Stage::VertexB: @@ -178,10 +199,13 @@ void GenericEnvironment::Dump(u64 hash) { void GenericEnvironment::Serialize(std::ofstream& file) const { const u64 code_size{static_cast(CachedSize())}; const u64 num_texture_types{static_cast(texture_types.size())}; + const u64 num_texture_pixel_formats{static_cast(texture_pixel_formats.size())}; const u64 num_cbuf_values{static_cast(cbuf_values.size())}; file.write(reinterpret_cast(&code_size), sizeof(code_size)) .write(reinterpret_cast(&num_texture_types), sizeof(num_texture_types)) + .write(reinterpret_cast(&num_texture_pixel_formats), + sizeof(num_texture_pixel_formats)) .write(reinterpret_cast(&num_cbuf_values), sizeof(num_cbuf_values)) .write(reinterpret_cast(&local_memory_size), sizeof(local_memory_size)) .write(reinterpret_cast(&texture_bound), sizeof(texture_bound)) @@ -196,6 +220,10 @@ void GenericEnvironment::Serialize(std::ofstream& file) const { file.write(reinterpret_cast(&key), sizeof(key)) .write(reinterpret_cast(&type), sizeof(type)); } + for (const auto& [key, format] : texture_pixel_formats) { + file.write(reinterpret_cast(&key), sizeof(key)) + .write(reinterpret_cast(&format), sizeof(format)); + } for (const auto& [key, type] : cbuf_values) { file.write(reinterpret_cast(&key), sizeof(key)) .write(reinterpret_cast(&type), sizeof(type)); @@ -239,15 +267,13 @@ std::optional GenericEnvironment::TryFindSize() { return std::nullopt; } -Shader::TextureType GenericEnvironment::ReadTextureTypeImpl(GPUVAddr tic_addr, u32 tic_limit, - bool via_header_index, u32 raw) { +Tegra::Texture::TICEntry GenericEnvironment::ReadTextureInfo(GPUVAddr tic_addr, u32 tic_limit, + bool via_header_index, u32 raw) { const auto handle{Tegra::Texture::TexturePair(raw, via_header_index)}; const GPUVAddr descriptor_addr{tic_addr + handle.first * sizeof(Tegra::Texture::TICEntry)}; Tegra::Texture::TICEntry entry; gpu_memory->ReadBlock(descriptor_addr, &entry, sizeof(entry)); - const Shader::TextureType result{ConvertType(entry)}; - texture_types.emplace(raw, result); - return result; + return entry; } GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_, @@ -307,13 +333,26 @@ u32 GraphicsEnvironment::ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) { Shader::TextureType GraphicsEnvironment::ReadTextureType(u32 handle) { const auto& regs{maxwell3d->regs}; const bool via_header_index{regs.sampler_binding == Maxwell::SamplerBinding::ViaHeaderBinding}; - return ReadTextureTypeImpl(regs.tex_header.Address(), regs.tex_header.limit, via_header_index, - handle); + auto entry = + ReadTextureInfo(regs.tex_header.Address(), regs.tex_header.limit, via_header_index, handle); + const Shader::TextureType result{ConvertTextureType(entry)}; + texture_types.emplace(handle, result); + return result; +} + +Shader::TexturePixelFormat GraphicsEnvironment::ReadTexturePixelFormat(u32 handle) { + const auto& regs{maxwell3d->regs}; + const bool via_header_index{regs.sampler_binding == Maxwell::SamplerBinding::ViaHeaderBinding}; + auto entry = + ReadTextureInfo(regs.tex_header.Address(), regs.tex_header.limit, via_header_index, handle); + const Shader::TexturePixelFormat result(ConvertTexturePixelFormat(entry)); + texture_pixel_formats.emplace(handle, result); + return result; } u32 GraphicsEnvironment::ReadViewportTransformState() { const auto& regs{maxwell3d->regs}; - viewport_transform_state = regs.viewport_transform_enabled; + viewport_transform_state = regs.viewport_scale_offset_enbled; return viewport_transform_state; } @@ -345,7 +384,19 @@ u32 ComputeEnvironment::ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) { Shader::TextureType ComputeEnvironment::ReadTextureType(u32 handle) { const auto& regs{kepler_compute->regs}; const auto& qmd{kepler_compute->launch_description}; - return ReadTextureTypeImpl(regs.tic.Address(), regs.tic.limit, qmd.linked_tsc != 0, handle); + auto entry = ReadTextureInfo(regs.tic.Address(), regs.tic.limit, qmd.linked_tsc != 0, handle); + const Shader::TextureType result{ConvertTextureType(entry)}; + texture_types.emplace(handle, result); + return result; +} + +Shader::TexturePixelFormat ComputeEnvironment::ReadTexturePixelFormat(u32 handle) { + const auto& regs{kepler_compute->regs}; + const auto& qmd{kepler_compute->launch_description}; + auto entry = ReadTextureInfo(regs.tic.Address(), regs.tic.limit, qmd.linked_tsc != 0, handle); + const Shader::TexturePixelFormat result(ConvertTexturePixelFormat(entry)); + texture_pixel_formats.emplace(handle, result); + return result; } u32 ComputeEnvironment::ReadViewportTransformState() { @@ -355,9 +406,12 @@ u32 ComputeEnvironment::ReadViewportTransformState() { void FileEnvironment::Deserialize(std::ifstream& file) { u64 code_size{}; u64 num_texture_types{}; + u64 num_texture_pixel_formats{}; u64 num_cbuf_values{}; file.read(reinterpret_cast(&code_size), sizeof(code_size)) .read(reinterpret_cast(&num_texture_types), sizeof(num_texture_types)) + .read(reinterpret_cast(&num_texture_pixel_formats), + sizeof(num_texture_pixel_formats)) .read(reinterpret_cast(&num_cbuf_values), sizeof(num_cbuf_values)) .read(reinterpret_cast(&local_memory_size), sizeof(local_memory_size)) .read(reinterpret_cast(&texture_bound), sizeof(texture_bound)) @@ -375,6 +429,13 @@ void FileEnvironment::Deserialize(std::ifstream& file) { .read(reinterpret_cast(&type), sizeof(type)); texture_types.emplace(key, type); } + for (size_t i = 0; i < num_texture_pixel_formats; ++i) { + u32 key; + Shader::TexturePixelFormat format; + file.read(reinterpret_cast(&key), sizeof(key)) + .read(reinterpret_cast(&format), sizeof(format)); + texture_pixel_formats.emplace(key, format); + } for (size_t i = 0; i < num_cbuf_values; ++i) { u64 key; u32 value; @@ -422,6 +483,14 @@ Shader::TextureType FileEnvironment::ReadTextureType(u32 handle) { return it->second; } +Shader::TexturePixelFormat FileEnvironment::ReadTexturePixelFormat(u32 handle) { + const auto it{texture_pixel_formats.find(handle)}; + if (it == texture_pixel_formats.end()) { + throw Shader::LogicError("Uncached read texture pixel format"); + } + return it->second; +} + u32 FileEnvironment::ReadViewportTransformState() { return viewport_transform_state; } -- cgit v1.2.3