From bea863efff092a855445b055ec32f1f9893c4e8a Mon Sep 17 00:00:00 2001 From: GPUCode <47210458+GPUCode@users.noreply.github.com> Date: Wed, 24 Jan 2024 19:22:10 +0200 Subject: [PATCH] general: Fixes for Tales of the Abyss (#7381) * geometry_pipeline: Remove unneeded assert * Has been hw-tested that gs works correctly even when not in exclusive mode * pica_core: Propagate output_mask to gs * Has been hw-tested to occur under the same conditions that other uniforms are shared * regs_shader: Intialize GPUREG_SH_INPUTBUFFER_CONFIG to default value * Default value verified on hw. Tales of Abyss does not update the number of vertex attributes for the geometry unit and expects it to be 2 * texture_codec: Align buffer sizes to bpp * Prevents out of bounds texture reads when launching TOA from the HOME menu * pica_core: Make default value more clear --- src/video_core/pica/geometry_pipeline.cpp | 1 - src/video_core/pica/pica_core.cpp | 16 ++++++++++++++-- src/video_core/pica/pica_core.h | 2 +- src/video_core/pica/regs_shader.h | 1 + src/video_core/rasterizer_cache/texture_codec.h | 7 +++++-- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/video_core/pica/geometry_pipeline.cpp b/src/video_core/pica/geometry_pipeline.cpp index fa7d5d8a7..8b2d8d697 100644 --- a/src/video_core/pica/geometry_pipeline.cpp +++ b/src/video_core/pica/geometry_pipeline.cpp @@ -337,7 +337,6 @@ void GeometryPipeline::Reconfigure() { // The following assumes that when geometry shader is in use, the shader unit 3 is configured as // a geometry shader unit. // TODO: what happens if this is not true? - ASSERT(regs.pipeline.gs_unit_exclusive_configuration == 1); ASSERT(regs.gs.shader_mode == ShaderRegs::ShaderMode::GS); ASSERT(regs.pipeline.use_gs == PipelineRegs::UseGS::Yes); diff --git a/src/video_core/pica/pica_core.cpp b/src/video_core/pica/pica_core.cpp index 1c9304090..6450e669b 100644 --- a/src/video_core/pica/pica_core.cpp +++ b/src/video_core/pica/pica_core.cpp @@ -35,7 +35,7 @@ PicaCore::PicaCore(Memory::MemorySystem& memory_, std::shared_ptr gs_unit, gs_setup}, shader_engine{CreateEngine(Settings::values.use_shader_jit.GetValue())} { - SetFramebufferDefaults(); + InitializeRegs(); const auto submit_vertex = [this](const AttributeBuffer& buffer) { const auto add_triangle = [this](const OutputVertex& v0, const OutputVertex& v1, @@ -54,7 +54,7 @@ PicaCore::PicaCore(Memory::MemorySystem& memory_, std::shared_ptr PicaCore::~PicaCore() = default; -void PicaCore::SetFramebufferDefaults() { +void PicaCore::InitializeRegs() { auto& framebuffer_top = regs.framebuffer_config[0]; auto& framebuffer_sub = regs.framebuffer_config[1]; @@ -77,6 +77,11 @@ void PicaCore::SetFramebufferDefaults() { framebuffer_sub.stride = 3 * 240; framebuffer_sub.color_format.Assign(PixelFormat::RGB8); framebuffer_sub.active_fb = 0; + + // Tales of Abyss expects this register to have the following default values. + auto& gs = regs.internal.gs; + gs.max_input_attribute_index.Assign(1); + gs.shader_mode.Assign(ShaderRegs::ShaderMode::VS); } void PicaCore::BindRasterizer(VideoCore::RasterizerInterface* rasterizer) { @@ -254,6 +259,13 @@ void PicaCore::WriteInternalReg(u32 id, u32 value, u32 mask) { break; } + case PICA_REG_INDEX(vs.output_mask): + if (!regs.internal.pipeline.gs_unit_exclusive_configuration && + regs.internal.pipeline.use_gs == PipelineRegs::UseGS::No) { + regs.internal.gs.output_mask.Assign(value); + } + break; + case PICA_REG_INDEX(vs.bool_uniforms): vs_setup.WriteUniformBoolReg(regs.internal.vs.bool_uniforms.Value()); if (!regs.internal.pipeline.gs_unit_exclusive_configuration && diff --git a/src/video_core/pica/pica_core.h b/src/video_core/pica/pica_core.h index b35ec7b08..cfd43f5a6 100644 --- a/src/video_core/pica/pica_core.h +++ b/src/video_core/pica/pica_core.h @@ -39,7 +39,7 @@ public: void ProcessCmdList(PAddr list, u32 size); private: - void SetFramebufferDefaults(); + void InitializeRegs(); void WriteInternalReg(u32 id, u32 value, u32 mask); diff --git a/src/video_core/pica/regs_shader.h b/src/video_core/pica/regs_shader.h index f9e47d6d1..3e49e00a3 100644 --- a/src/video_core/pica/regs_shader.h +++ b/src/video_core/pica/regs_shader.h @@ -35,6 +35,7 @@ struct ShaderRegs { union { // Number of input attributes to shader unit - 1 + u32 input_buffer_config; BitField<0, 4, u32> max_input_attribute_index; BitField<8, 8, u32> input_to_uniform; BitField<24, 8, ShaderMode> shader_mode; diff --git a/src/video_core/rasterizer_cache/texture_codec.h b/src/video_core/rasterizer_cache/texture_codec.h index 01e90f461..76ac6d996 100644 --- a/src/video_core/rasterizer_cache/texture_codec.h +++ b/src/video_core/rasterizer_cache/texture_codec.h @@ -341,8 +341,8 @@ static constexpr void MortonCopy(u32 width, u32 height, u32 start_offset, u32 en */ template static constexpr void LinearCopy(std::span src_buffer, std::span dst_buffer) { - const std::size_t src_size = src_buffer.size(); - const std::size_t dst_size = dst_buffer.size(); + std::size_t src_size = src_buffer.size(); + std::size_t dst_size = dst_buffer.size(); if constexpr (converted) { constexpr u32 encoded_bytes_per_pixel = GetFormatBpp(format) / 8; @@ -352,6 +352,9 @@ static constexpr void LinearCopy(std::span src_buffer, std::span dst_buf constexpr u32 dst_bytes_per_pixel = decode ? decoded_bytes_per_pixel : encoded_bytes_per_pixel; + src_size = Common::AlignDown(src_size, src_bytes_per_pixel); + dst_size = Common::AlignDown(dst_size, dst_bytes_per_pixel); + for (std::size_t src_index = 0, dst_index = 0; src_index < src_size && dst_index < dst_size; src_index += src_bytes_per_pixel, dst_index += dst_bytes_per_pixel) { const auto src_pixel = src_buffer.subspan(src_index, src_bytes_per_pixel);