mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	renderer_software: Fix screen rendering (#6664)
This commit is contained in:
		
							parent
							
								
									cf9bb90ae3
								
							
						
					
					
						commit
						80033b84cb
					
				
					 4 changed files with 28 additions and 34 deletions
				
			
		|  | @ -23,10 +23,8 @@ void RendererSoftware::SwapBuffers() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RendererSoftware::PrepareRenderTarget() { | void RendererSoftware::PrepareRenderTarget() { | ||||||
|     for (int i : {0, 1, 2}) { |     for (u32 i = 0; i < 3; i++) { | ||||||
|         const int fb_id = i == 2 ? 1 : 0; |         const int fb_id = i == 2 ? 1 : 0; | ||||||
|         const auto& framebuffer = GPU::g_regs.framebuffer_config[fb_id]; |  | ||||||
|         auto& info = screen_infos[i]; |  | ||||||
| 
 | 
 | ||||||
|         u32 lcd_color_addr = |         u32 lcd_color_addr = | ||||||
|             (fb_id == 0) ? LCD_REG_INDEX(color_fill_top) : LCD_REG_INDEX(color_fill_bottom); |             (fb_id == 0) ? LCD_REG_INDEX(color_fill_top) : LCD_REG_INDEX(color_fill_bottom); | ||||||
|  | @ -35,33 +33,29 @@ void RendererSoftware::PrepareRenderTarget() { | ||||||
|         LCD::Read(color_fill.raw, lcd_color_addr); |         LCD::Read(color_fill.raw, lcd_color_addr); | ||||||
| 
 | 
 | ||||||
|         if (!color_fill.is_enabled) { |         if (!color_fill.is_enabled) { | ||||||
|             const u32 old_width = std::exchange(info.width, framebuffer.width); |             LoadFBToScreenInfo(i); | ||||||
|             const u32 old_height = std::exchange(info.height, framebuffer.height); |  | ||||||
|             if (framebuffer.width != old_width || framebuffer.height != old_height) [[unlikely]] { |  | ||||||
|                 info.pixels.resize(framebuffer.width * framebuffer.height * 4); |  | ||||||
|             } |  | ||||||
|             CopyPixels(i); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RendererSoftware::CopyPixels(int i) { | void RendererSoftware::LoadFBToScreenInfo(int i) { | ||||||
|     const u32 fb_id = i == 2 ? 1 : 0; |     const u32 fb_id = i == 2 ? 1 : 0; | ||||||
|     const auto& framebuffer = GPU::g_regs.framebuffer_config[fb_id]; |     const auto& framebuffer = GPU::g_regs.framebuffer_config[fb_id]; | ||||||
|  |     auto& info = screen_infos[i]; | ||||||
| 
 | 
 | ||||||
|     const PAddr framebuffer_addr = |     const PAddr framebuffer_addr = | ||||||
|         framebuffer.active_fb == 0 ? framebuffer.address_left1 : framebuffer.address_left2; |         framebuffer.active_fb == 0 ? framebuffer.address_left1 : framebuffer.address_left2; | ||||||
|     const s32 bpp = GPU::Regs::BytesPerPixel(framebuffer.color_format); |     const s32 bpp = GPU::Regs::BytesPerPixel(framebuffer.color_format); | ||||||
|     const u8* framebuffer_data = memory.GetPhysicalPointer(framebuffer_addr); |     const u8* framebuffer_data = memory.GetPhysicalPointer(framebuffer_addr); | ||||||
| 
 | 
 | ||||||
|     const s32 stride = framebuffer.stride; |     const s32 pixel_stride = framebuffer.stride / bpp; | ||||||
|     const s32 height = framebuffer.height; |     info.height = framebuffer.height; | ||||||
|     ASSERT(stride * height != 0); |     info.width = pixel_stride; | ||||||
|  |     info.pixels.resize(info.width * info.height * 4); | ||||||
| 
 | 
 | ||||||
|     u32 output_offset = 0; |     for (u32 y = 0; y < info.height; y++) { | ||||||
|     for (u32 y = 0; y < framebuffer.height; y++) { |         for (u32 x = 0; x < info.width; x++) { | ||||||
|         for (u32 x = 0; x < framebuffer.width; x++) { |             const u8* pixel = framebuffer_data + (y * pixel_stride + pixel_stride - x) * bpp; | ||||||
|             const u8* pixel = framebuffer_data + (y * stride + x) * bpp; |  | ||||||
|             const Common::Vec4 color = [&] { |             const Common::Vec4 color = [&] { | ||||||
|                 switch (framebuffer.color_format) { |                 switch (framebuffer.color_format) { | ||||||
|                 case GPU::Regs::PixelFormat::RGBA8: |                 case GPU::Regs::PixelFormat::RGBA8: | ||||||
|  | @ -77,9 +71,9 @@ void RendererSoftware::CopyPixels(int i) { | ||||||
|                 } |                 } | ||||||
|                 UNREACHABLE(); |                 UNREACHABLE(); | ||||||
|             }(); |             }(); | ||||||
|             u8* dest = screen_infos[i].pixels.data() + output_offset; |             const u32 output_offset = (x * info.height + y) * 4; | ||||||
|  |             u8* dest = info.pixels.data() + output_offset; | ||||||
|             std::memcpy(dest, color.AsArray(), sizeof(color)); |             std::memcpy(dest, color.AsArray(), sizeof(color)); | ||||||
|             output_offset += sizeof(color); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ public: | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void PrepareRenderTarget(); |     void PrepareRenderTarget(); | ||||||
|     void CopyPixels(int i); |     void LoadFBToScreenInfo(int i); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Memory::MemorySystem& memory; |     Memory::MemorySystem& memory; | ||||||
|  |  | ||||||
|  | @ -399,8 +399,9 @@ void RasterizerSoftware::ProcessTriangle(const Vertex& v0, const Vertex& v1, con | ||||||
|             const f24 tc0_w = get_interpolated_attribute(v0.tc0_w, v1.tc0_w, v2.tc0_w); |             const f24 tc0_w = get_interpolated_attribute(v0.tc0_w, v1.tc0_w, v2.tc0_w); | ||||||
|             const auto texture_color = TextureColor(uv, textures, tc0_w); |             const auto texture_color = TextureColor(uv, textures, tc0_w); | ||||||
| 
 | 
 | ||||||
|             Common::Vec4<u8> primary_fragment_color{0, 0, 0, 0}; |             Common::Vec4<u8> primary_fragment_color = {0, 0, 0, 0}; | ||||||
|             Common::Vec4<u8> secondary_fragment_color{0, 0, 0, 0}; |             Common::Vec4<u8> secondary_fragment_color = {0, 0, 0, 0}; | ||||||
|  | 
 | ||||||
|             if (!regs.lighting.disable) { |             if (!regs.lighting.disable) { | ||||||
|                 const auto normquat = |                 const auto normquat = | ||||||
|                     Common::Quaternion<f32>{ |                     Common::Quaternion<f32>{ | ||||||
|  | @ -421,9 +422,8 @@ void RasterizerSoftware::ProcessTriangle(const Vertex& v0, const Vertex& v1, con | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // Write the TEV stages.
 |             // Write the TEV stages.
 | ||||||
|             Common::Vec4<u8> combiner_output = |             WriteTevConfig(texture_color, tev_stages, primary_color, primary_fragment_color, | ||||||
|                 WriteTevConfig(texture_color, tev_stages, primary_color, primary_fragment_color, |                            secondary_fragment_color); | ||||||
|                                secondary_fragment_color); |  | ||||||
| 
 | 
 | ||||||
|             const auto& output_merger = regs.framebuffer.output_merger; |             const auto& output_merger = regs.framebuffer.output_merger; | ||||||
|             if (output_merger.fragment_operation_mode == |             if (output_merger.fragment_operation_mode == | ||||||
|  | @ -663,11 +663,11 @@ Common::Vec4<u8> RasterizerSoftware::PixelColor(u16 x, u16 y, | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Common::Vec4<u8> RasterizerSoftware::WriteTevConfig( | void RasterizerSoftware::WriteTevConfig( | ||||||
|     std::span<const Common::Vec4<u8>, 4> texture_color, |     std::span<const Common::Vec4<u8>, 4> texture_color, | ||||||
|     std::span<const Pica::TexturingRegs::TevStageConfig, 6> tev_stages, |     std::span<const Pica::TexturingRegs::TevStageConfig, 6> tev_stages, | ||||||
|     Common::Vec4<u8> primary_color, Common::Vec4<u8> primary_fragment_color, |     Common::Vec4<u8> primary_color, Common::Vec4<u8> primary_fragment_color, | ||||||
|     Common::Vec4<u8> secondary_fragment_color) const { |     Common::Vec4<u8> secondary_fragment_color) { | ||||||
|     /**
 |     /**
 | ||||||
|      * Texture environment - consists of 6 stages of color and alpha combining. |      * Texture environment - consists of 6 stages of color and alpha combining. | ||||||
|      * Color combiners take three input color values from some source (e.g. interpolated |      * Color combiners take three input color values from some source (e.g. interpolated | ||||||
|  | @ -676,7 +676,6 @@ Common::Vec4<u8> RasterizerSoftware::WriteTevConfig( | ||||||
|      * with some basic arithmetic. Alpha combiners can be configured separately but work |      * with some basic arithmetic. Alpha combiners can be configured separately but work | ||||||
|      * analogously. |      * analogously. | ||||||
|      **/ |      **/ | ||||||
|     Common::Vec4<u8> combiner_output; |  | ||||||
|     Common::Vec4<u8> combiner_buffer = {0, 0, 0, 0}; |     Common::Vec4<u8> combiner_buffer = {0, 0, 0, 0}; | ||||||
|     Common::Vec4<u8> next_combiner_buffer = |     Common::Vec4<u8> next_combiner_buffer = | ||||||
|         Common::MakeVec(regs.texturing.tev_combiner_buffer_color.r.Value(), |         Common::MakeVec(regs.texturing.tev_combiner_buffer_color.r.Value(), | ||||||
|  | @ -767,7 +766,6 @@ Common::Vec4<u8> RasterizerSoftware::WriteTevConfig( | ||||||
|             next_combiner_buffer.a() = combiner_output.a(); |             next_combiner_buffer.a() = combiner_output.a(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return combiner_output; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RasterizerSoftware::WriteFog(Common::Vec4<u8>& combiner_output, float depth) const { | void RasterizerSoftware::WriteFog(Common::Vec4<u8>& combiner_output, float depth) const { | ||||||
|  |  | ||||||
|  | @ -55,11 +55,10 @@ private: | ||||||
|     Common::Vec4<u8> PixelColor(u16 x, u16 y, Common::Vec4<u8>& combiner_output) const; |     Common::Vec4<u8> PixelColor(u16 x, u16 y, Common::Vec4<u8>& combiner_output) const; | ||||||
| 
 | 
 | ||||||
|     /// Emulates the TEV configuration and returns the combiner output.
 |     /// Emulates the TEV configuration and returns the combiner output.
 | ||||||
|     Common::Vec4<u8> WriteTevConfig( |     void WriteTevConfig(std::span<const Common::Vec4<u8>, 4> texture_color, | ||||||
|         std::span<const Common::Vec4<u8>, 4> texture_color, |                         std::span<const Pica::TexturingRegs::TevStageConfig, 6> tev_stages, | ||||||
|         std::span<const Pica::TexturingRegs::TevStageConfig, 6> tev_stages, |                         Common::Vec4<u8> primary_color, Common::Vec4<u8> primary_fragment_color, | ||||||
|         Common::Vec4<u8> primary_color, Common::Vec4<u8> primary_fragment_color, |                         Common::Vec4<u8> secondary_fragment_color); | ||||||
|         Common::Vec4<u8> secondary_fragment_color) const; |  | ||||||
| 
 | 
 | ||||||
|     /// Blends fog to the combiner output if enabled.
 |     /// Blends fog to the combiner output if enabled.
 | ||||||
|     void WriteFog(Common::Vec4<u8>& combiner_output, float depth) const; |     void WriteFog(Common::Vec4<u8>& combiner_output, float depth) const; | ||||||
|  | @ -75,6 +74,9 @@ private: | ||||||
|     Pica::State& state; |     Pica::State& state; | ||||||
|     const Pica::Regs& regs; |     const Pica::Regs& regs; | ||||||
|     Framebuffer fb; |     Framebuffer fb; | ||||||
|  |     // Kirby Blowout Blast relies on the combiner output of a previous draw
 | ||||||
|  |     // in order to render the sky correctly.
 | ||||||
|  |     Common::Vec4<u8> combiner_output{}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace SwRenderer
 | } // namespace SwRenderer
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue