mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #1461 from yuriks/imm-mode2
Immediate-mode improvements
This commit is contained in:
		
						commit
						a950188c11
					
				
					 6 changed files with 59 additions and 29 deletions
				
			
		|  | @ -75,12 +75,17 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | ||||||
|             GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::P3D); |             GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::P3D); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|  |         case PICA_REG_INDEX_WORKAROUND(triangle_topology, 0x25E): | ||||||
|  |             g_state.primitive_assembler.Reconfigure(regs.triangle_topology); | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|  |         case PICA_REG_INDEX_WORKAROUND(restart_primitive, 0x25F): | ||||||
|  |             g_state.primitive_assembler.Reset(); | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|         case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.index, 0x232): |         case PICA_REG_INDEX_WORKAROUND(vs_default_attributes_setup.index, 0x232): | ||||||
|             if (regs.vs_default_attributes_setup.index == 15) { |             g_state.immediate.current_attribute = 0; | ||||||
|                 // Reset immediate primitive state
 |             default_attr_counter = 0; | ||||||
|                 g_state.immediate.primitive_assembler.Reconfigure(regs.triangle_topology); |  | ||||||
|                 g_state.immediate.attribute_id = 0; |  | ||||||
|             } |  | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         // Load default vertex input attributes
 |         // Load default vertex input attributes
 | ||||||
|  | @ -105,7 +110,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 Math::Vec4<float24>& attribute = g_state.vs.default_attributes[setup.index]; |                 Math::Vec4<float24> attribute; | ||||||
| 
 | 
 | ||||||
|                 // NOTE: The destination component order indeed is "backwards"
 |                 // NOTE: The destination component order indeed is "backwards"
 | ||||||
|                 attribute.w = float24::FromRaw(default_attr_write_buffer[0] >> 8); |                 attribute.w = float24::FromRaw(default_attr_write_buffer[0] >> 8); | ||||||
|  | @ -119,26 +124,29 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | ||||||
| 
 | 
 | ||||||
|                 // TODO: Verify that this actually modifies the register!
 |                 // TODO: Verify that this actually modifies the register!
 | ||||||
|                 if (setup.index < 15) { |                 if (setup.index < 15) { | ||||||
|  |                     g_state.vs.default_attributes[setup.index] = attribute; | ||||||
|                     setup.index++; |                     setup.index++; | ||||||
|                 } else { |                 } else { | ||||||
|                     // Put each attribute into an immediate input buffer.
 |                     // Put each attribute into an immediate input buffer.
 | ||||||
|                     // When all specified immediate attributes are present, the Vertex Shader is invoked and everything is
 |                     // When all specified immediate attributes are present, the Vertex Shader is invoked and everything is
 | ||||||
|                     // sent to the primitive assembler.
 |                     // sent to the primitive assembler.
 | ||||||
| 
 | 
 | ||||||
|                     auto& immediate_input = g_state.immediate.input; |                     auto& immediate_input = g_state.immediate.input_vertex; | ||||||
|                     auto& immediate_attribute_id = g_state.immediate.attribute_id; |                     auto& immediate_attribute_id = g_state.immediate.current_attribute; | ||||||
|                     const auto& attribute_config = regs.vertex_attributes; |  | ||||||
| 
 | 
 | ||||||
|                     immediate_input.attr[immediate_attribute_id++] = attribute; |                     immediate_input.attr[immediate_attribute_id++] = attribute; | ||||||
| 
 | 
 | ||||||
|                     if (immediate_attribute_id >= attribute_config.GetNumTotalAttributes()) { |                     if (immediate_attribute_id >= regs.vs.num_input_attributes+1) { | ||||||
|                         immediate_attribute_id = 0; |                         immediate_attribute_id = 0; | ||||||
| 
 | 
 | ||||||
|                         Shader::UnitState<false> shader_unit; |                         Shader::UnitState<false> shader_unit; | ||||||
|                         Shader::Setup(shader_unit); |                         Shader::Setup(shader_unit); | ||||||
| 
 | 
 | ||||||
|  |                         if (g_debug_context) | ||||||
|  |                             g_debug_context->OnEvent(DebugContext::Event::VertexLoaded, static_cast<void*>(&immediate_input)); | ||||||
|  | 
 | ||||||
|                         // Send to vertex shader
 |                         // Send to vertex shader
 | ||||||
|                         Shader::OutputVertex output = Shader::Run(shader_unit, immediate_input, attribute_config.GetNumTotalAttributes()); |                         Shader::OutputVertex output = Shader::Run(shader_unit, immediate_input, regs.vs.num_input_attributes+1); | ||||||
| 
 | 
 | ||||||
|                         // Send to renderer
 |                         // Send to renderer
 | ||||||
|                         using Pica::Shader::OutputVertex; |                         using Pica::Shader::OutputVertex; | ||||||
|  | @ -146,7 +154,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | ||||||
|                             VideoCore::g_renderer->Rasterizer()->AddTriangle(v0, v1, v2); |                             VideoCore::g_renderer->Rasterizer()->AddTriangle(v0, v1, v2); | ||||||
|                         }; |                         }; | ||||||
| 
 | 
 | ||||||
|                         g_state.immediate.primitive_assembler.SubmitVertex(output, AddTriangle); |                         g_state.primitive_assembler.SubmitVertex(output, AddTriangle); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -154,9 +162,13 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         case PICA_REG_INDEX(gpu_mode): |         case PICA_REG_INDEX(gpu_mode): | ||||||
|             if (regs.gpu_mode == Regs::GPUMode::Configuring && regs.vs_default_attributes_setup.index == 15) { |             if (regs.gpu_mode == Regs::GPUMode::Configuring) { | ||||||
|                 // Draw immediate mode triangles when GPU Mode is set to GPUMode::Configuring
 |                 // Draw immediate mode triangles when GPU Mode is set to GPUMode::Configuring
 | ||||||
|                 VideoCore::g_renderer->Rasterizer()->DrawTriangles(); |                 VideoCore::g_renderer->Rasterizer()->DrawTriangles(); | ||||||
|  | 
 | ||||||
|  |                 if (g_debug_context) { | ||||||
|  |                     g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch, nullptr); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|  | @ -241,7 +253,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | ||||||
|             DebugUtils::GeometryDumper geometry_dumper; |             DebugUtils::GeometryDumper geometry_dumper; | ||||||
|             PrimitiveAssembler<DebugUtils::GeometryDumper::Vertex> dumping_primitive_assembler(regs.triangle_topology.Value()); |             PrimitiveAssembler<DebugUtils::GeometryDumper::Vertex> dumping_primitive_assembler(regs.triangle_topology.Value()); | ||||||
| #endif | #endif | ||||||
|             PrimitiveAssembler<Shader::OutputVertex> primitive_assembler(regs.triangle_topology.Value()); |             PrimitiveAssembler<Shader::OutputVertex>& primitive_assembler = g_state.primitive_assembler; | ||||||
| 
 | 
 | ||||||
|             if (g_debug_context) { |             if (g_debug_context) { | ||||||
|                 for (int i = 0; i < 3; ++i) { |                 for (int i = 0; i < 3; ++i) { | ||||||
|  | @ -412,16 +424,10 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | ||||||
|                                                           range.second, range.first); |                                                           range.second, range.first); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             VideoCore::g_renderer->Rasterizer()->DrawTriangles(); |  | ||||||
| 
 |  | ||||||
| #if PICA_DUMP_GEOMETRY | #if PICA_DUMP_GEOMETRY | ||||||
|             geometry_dumper.Dump(); |             geometry_dumper.Dump(); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|             if (g_debug_context) { |  | ||||||
|                 g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch, nullptr); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -493,12 +493,25 @@ std::string Regs::GetCommandName(int index) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Init() { | void Init() { | ||||||
|  |     g_state.Reset(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Shutdown() { | void Shutdown() { | ||||||
|     Shader::Shutdown(); |     Shader::Shutdown(); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     memset(&g_state, 0, sizeof(State)); | template <typename T> | ||||||
|  | void Zero(T& o) { | ||||||
|  |     memset(&o, 0, sizeof(o)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void State::Reset() { | ||||||
|  |     Zero(regs); | ||||||
|  |     Zero(vs); | ||||||
|  |     Zero(gs); | ||||||
|  |     Zero(cmd_list); | ||||||
|  |     Zero(immediate); | ||||||
|  |     primitive_assembler.Reconfigure(Regs::TriangleTopology::List); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1123,7 +1123,12 @@ struct Regs { | ||||||
|             BitField<24, 8, u32> w; |             BitField<24, 8, u32> w; | ||||||
|         } int_uniforms[4]; |         } int_uniforms[4]; | ||||||
| 
 | 
 | ||||||
|         INSERT_PADDING_WORDS(0x5); |         INSERT_PADDING_WORDS(0x4); | ||||||
|  | 
 | ||||||
|  |         union { | ||||||
|  |             // Number of input attributes to shader unit - 1
 | ||||||
|  |             BitField<0, 4, u32> num_input_attributes; | ||||||
|  |         }; | ||||||
| 
 | 
 | ||||||
|         // Offset to shader program entry point (in words)
 |         // Offset to shader program entry point (in words)
 | ||||||
|         BitField<0, 16, u32> main_offset; |         BitField<0, 16, u32> main_offset; | ||||||
|  |  | ||||||
|  | @ -12,6 +12,8 @@ namespace Pica { | ||||||
| 
 | 
 | ||||||
| /// Struct used to describe current Pica state
 | /// Struct used to describe current Pica state
 | ||||||
| struct State { | struct State { | ||||||
|  |     void Reset(); | ||||||
|  | 
 | ||||||
|     /// Pica registers
 |     /// Pica registers
 | ||||||
|     Regs regs; |     Regs regs; | ||||||
| 
 | 
 | ||||||
|  | @ -46,13 +48,14 @@ struct State { | ||||||
| 
 | 
 | ||||||
|     /// Struct used to describe immediate mode rendering state
 |     /// Struct used to describe immediate mode rendering state
 | ||||||
|     struct ImmediateModeState { |     struct ImmediateModeState { | ||||||
|         Shader::InputVertex input; |         // Used to buffer partial vertices for immediate-mode rendering.
 | ||||||
|         // This is constructed with a dummy triangle topology
 |         Shader::InputVertex input_vertex; | ||||||
|         PrimitiveAssembler<Shader::OutputVertex> primitive_assembler; |         // Index of the next attribute to be loaded into `input_vertex`.
 | ||||||
|         int attribute_id = 0; |         int current_attribute = 0; | ||||||
| 
 |  | ||||||
|         ImmediateModeState() : primitive_assembler(Regs::TriangleTopology::List) {} |  | ||||||
|     } immediate; |     } immediate; | ||||||
|  | 
 | ||||||
|  |     // This is constructed with a dummy triangle topology
 | ||||||
|  |     PrimitiveAssembler<Shader::OutputVertex> primitive_assembler; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| extern State g_state; ///< Current Pica state
 | extern State g_state; ///< Current Pica state
 | ||||||
|  |  | ||||||
|  | @ -20,7 +20,7 @@ struct PrimitiveAssembler { | ||||||
|                                                VertexType& v1, |                                                VertexType& v1, | ||||||
|                                                VertexType& v2)>; |                                                VertexType& v2)>; | ||||||
| 
 | 
 | ||||||
|     PrimitiveAssembler(Regs::TriangleTopology topology); |     PrimitiveAssembler(Regs::TriangleTopology topology = Regs::TriangleTopology::List); | ||||||
| 
 | 
 | ||||||
|     /*
 |     /*
 | ||||||
|      * Queues a vertex, builds primitives from the vertex queue according to the given |      * Queues a vertex, builds primitives from the vertex queue according to the given | ||||||
|  |  | ||||||
|  | @ -190,6 +190,9 @@ void RasterizerOpenGL::AddTriangle(const Pica::Shader::OutputVertex& v0, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RasterizerOpenGL::DrawTriangles() { | void RasterizerOpenGL::DrawTriangles() { | ||||||
|  |     if (vertex_batch.empty()) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     SyncFramebuffer(); |     SyncFramebuffer(); | ||||||
|     SyncDrawState(); |     SyncDrawState(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue