diff options
Diffstat (limited to 'src/video_core/renderer_opengl')
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 9 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 18 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 55 |
3 files changed, 70 insertions, 12 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 3f385484f..86682d7cb 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -167,6 +167,7 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form {GL_RG8, GL_RG, GL_BYTE, ComponentType::SNorm, false}, // RG8S {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // RG32UI {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // R32UI + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8 // Depth formats {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F @@ -213,6 +214,7 @@ static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType static bool IsPixelFormatASTC(PixelFormat format) { switch (format) { case PixelFormat::ASTC_2D_4X4: + case PixelFormat::ASTC_2D_8X8: return true; default: return false; @@ -223,6 +225,8 @@ static std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) { switch (format) { case PixelFormat::ASTC_2D_4X4: return {4, 4}; + case PixelFormat::ASTC_2D_8X8: + return {8, 8}; default: LOG_CRITICAL(HW_GPU, "Unhandled format: {}", static_cast<u32>(format)); UNREACHABLE(); @@ -327,6 +331,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, std::size_t, VAddr), MortonCopy<true, PixelFormat::RG8S>, MortonCopy<true, PixelFormat::RG32UI>, MortonCopy<true, PixelFormat::R32UI>, + MortonCopy<true, PixelFormat::ASTC_2D_8X8>, MortonCopy<true, PixelFormat::Z32F>, MortonCopy<true, PixelFormat::Z16>, MortonCopy<true, PixelFormat::Z24S8>, @@ -386,6 +391,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, std::size_t, VAddr), MortonCopy<false, PixelFormat::RG8S>, MortonCopy<false, PixelFormat::RG32UI>, MortonCopy<false, PixelFormat::R32UI>, + nullptr, MortonCopy<false, PixelFormat::Z32F>, MortonCopy<false, PixelFormat::Z16>, MortonCopy<false, PixelFormat::Z24S8>, @@ -544,7 +550,8 @@ static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) { static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelFormat pixel_format, u32 width, u32 height) { switch (pixel_format) { - case PixelFormat::ASTC_2D_4X4: { + case PixelFormat::ASTC_2D_4X4: + case PixelFormat::ASTC_2D_8X8: { // Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC. u32 block_width{}; u32 block_height{}; diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index aafac9a20..d7a4bc37f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -70,19 +70,20 @@ struct SurfaceParams { RG8S = 42, RG32UI = 43, R32UI = 44, + ASTC_2D_8X8 = 45, MaxColorFormat, // Depth formats - Z32F = 45, - Z16 = 46, + Z32F = 46, + Z16 = 47, MaxDepthFormat, // DepthStencil formats - Z24S8 = 47, - S8Z24 = 48, - Z32FS8 = 49, + Z24S8 = 48, + S8Z24 = 49, + Z32FS8 = 50, MaxDepthStencilFormat, @@ -192,6 +193,7 @@ struct SurfaceParams { 1, // RG8S 1, // RG32UI 1, // R32UI + 4, // ASTC_2D_8X8 1, // Z32F 1, // Z16 1, // Z24S8 @@ -253,6 +255,7 @@ struct SurfaceParams { 16, // RG8S 64, // RG32UI 32, // R32UI + 16, // ASTC_2D_8X8 32, // Z32F 16, // Z16 32, // Z24S8 @@ -316,6 +319,8 @@ struct SurfaceParams { return PixelFormat::R11FG11FB10F; case Tegra::RenderTargetFormat::B5G6R5_UNORM: return PixelFormat::B5G6R5U; + case Tegra::RenderTargetFormat::BGR5A1_UNORM: + return PixelFormat::A1B5G5R5U; case Tegra::RenderTargetFormat::RGBA32_UINT: return PixelFormat::RGBA32UI; case Tegra::RenderTargetFormat::R8_UNORM: @@ -522,6 +527,8 @@ struct SurfaceParams { return PixelFormat::BC6H_SF16; case Tegra::Texture::TextureFormat::ASTC_2D_4X4: return PixelFormat::ASTC_2D_4X4; + case Tegra::Texture::TextureFormat::ASTC_2D_8X8: + return PixelFormat::ASTC_2D_8X8; case Tegra::Texture::TextureFormat::R16_G16: switch (component_type) { case Tegra::Texture::ComponentType::FLOAT: @@ -576,6 +583,7 @@ struct SurfaceParams { case Tegra::RenderTargetFormat::RG16_UNORM: case Tegra::RenderTargetFormat::R16_UNORM: case Tegra::RenderTargetFormat::B5G6R5_UNORM: + case Tegra::RenderTargetFormat::BGR5A1_UNORM: case Tegra::RenderTargetFormat::RG8_UNORM: case Tegra::RenderTargetFormat::RGBA16_UNORM: return ComponentType::UNorm; diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index d58a65935..15f628acd 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -1772,13 +1772,34 @@ private: case OpCode::Type::Memory: { switch (opcode->GetId()) { case OpCode::Id::LD_A: { - ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested"); // Note: Shouldn't this be interp mode flat? As in no interpolation made. + ASSERT_MSG(instr.gpr8.Value() == Register::ZeroIndex, + "Indirect attribute loads are not supported"); + ASSERT_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) == 0, + "Unaligned attribute loads are not supported"); Tegra::Shader::IpaMode input_mode{Tegra::Shader::IpaInterpMode::Perspective, Tegra::Shader::IpaSampleMode::Default}; - regs.SetRegisterToInputAttibute(instr.gpr0, instr.attribute.fmt20.element, - instr.attribute.fmt20.index, input_mode); + + u32 next_element = instr.attribute.fmt20.element; + u32 next_index = static_cast<u32>(instr.attribute.fmt20.index.Value()); + + const auto LoadNextElement = [&](u32 reg_offset) { + regs.SetRegisterToInputAttibute(instr.gpr0.Value() + reg_offset, next_element, + static_cast<Attribute::Index>(next_index), + input_mode); + + // Load the next attribute element into the following register. If the element + // to load goes beyond the vec4 size, load the first element of the next + // attribute. + next_element = (next_element + 1) % 4; + next_index = next_index + (next_element == 0 ? 1 : 0); + }; + + const u32 num_words = static_cast<u32>(instr.attribute.fmt20.size.Value()) + 1; + for (u32 reg_offset = 0; reg_offset < num_words; ++reg_offset) { + LoadNextElement(reg_offset); + } break; } case OpCode::Id::LD_C: { @@ -1820,9 +1841,31 @@ private: break; } case OpCode::Id::ST_A: { - ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested"); - regs.SetOutputAttributeToRegister(instr.attribute.fmt20.index, - instr.attribute.fmt20.element, instr.gpr0); + ASSERT_MSG(instr.gpr8.Value() == Register::ZeroIndex, + "Indirect attribute loads are not supported"); + ASSERT_MSG((instr.attribute.fmt20.immediate.Value() % sizeof(u32)) == 0, + "Unaligned attribute loads are not supported"); + + u32 next_element = instr.attribute.fmt20.element; + u32 next_index = static_cast<u32>(instr.attribute.fmt20.index.Value()); + + const auto StoreNextElement = [&](u32 reg_offset) { + regs.SetOutputAttributeToRegister(static_cast<Attribute::Index>(next_index), + next_element, + instr.gpr0.Value() + reg_offset); + + // Load the next attribute element into the following register. If the element + // to load goes beyond the vec4 size, load the first element of the next + // attribute. + next_element = (next_element + 1) % 4; + next_index = next_index + (next_element == 0 ? 1 : 0); + }; + + const u32 num_words = static_cast<u32>(instr.attribute.fmt20.size.Value()) + 1; + for (u32 reg_offset = 0; reg_offset < num_words; ++reg_offset) { + StoreNextElement(reg_offset); + } + break; } case OpCode::Id::TEX: { |