mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Extracted the attribute setup and draw commands into their own functions
This commit is contained in:
		
							parent
							
								
									15c7641bef
								
							
						
					
					
						commit
						b3b34a1e76
					
				@ -119,64 +119,16 @@ static void WriteUniformFloatReg(ShaderRegs& config, Shader::ShaderSetup& setup,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void WritePicaReg(u32 id, u32 value, u32 mask) {
 | 
					static void LoadDefaultVertexAttributes(u32 register_value) {
 | 
				
			||||||
    auto& regs = g_state.regs;
 | 
					    auto& regs = g_state.regs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (id >= Regs::NUM_REGS) {
 | 
					 | 
				
			||||||
        LOG_ERROR(HW_GPU,
 | 
					 | 
				
			||||||
                  "Commandlist tried to write to invalid register 0x%03X (value: %08X, mask: %X)",
 | 
					 | 
				
			||||||
                  id, value, mask);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // TODO: Figure out how register masking acts on e.g. vs.uniform_setup.set_value
 | 
					 | 
				
			||||||
    u32 old_value = regs.reg_array[id];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const u32 write_mask = expand_bits_to_bytes[mask];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    regs.reg_array[id] = (old_value & ~write_mask) | (value & write_mask);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Double check for is_pica_tracing to avoid call overhead
 | 
					 | 
				
			||||||
    if (DebugUtils::IsPicaTracing()) {
 | 
					 | 
				
			||||||
        DebugUtils::OnPicaRegWrite({(u16)id, (u16)mask, regs.reg_array[id]});
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (g_debug_context)
 | 
					 | 
				
			||||||
        g_debug_context->OnEvent(DebugContext::Event::PicaCommandLoaded,
 | 
					 | 
				
			||||||
                                 reinterpret_cast<void*>(&id));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    switch (id) {
 | 
					 | 
				
			||||||
    // Trigger IRQ
 | 
					 | 
				
			||||||
    case PICA_REG_INDEX(trigger_irq):
 | 
					 | 
				
			||||||
        Service::GSP::SignalInterrupt(Service::GSP::InterruptId::P3D);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case PICA_REG_INDEX(pipeline.triangle_topology):
 | 
					 | 
				
			||||||
        g_state.primitive_assembler.Reconfigure(regs.pipeline.triangle_topology);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case PICA_REG_INDEX(pipeline.restart_primitive):
 | 
					 | 
				
			||||||
        g_state.primitive_assembler.Reset();
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case PICA_REG_INDEX(pipeline.vs_default_attributes_setup.index):
 | 
					 | 
				
			||||||
        g_state.immediate.current_attribute = 0;
 | 
					 | 
				
			||||||
        g_state.immediate.reset_geometry_pipeline = true;
 | 
					 | 
				
			||||||
        default_attr_counter = 0;
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Load default vertex input attributes
 | 
					 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(pipeline.vs_default_attributes_setup.set_value[0], 0x233):
 | 
					 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(pipeline.vs_default_attributes_setup.set_value[1], 0x234):
 | 
					 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(pipeline.vs_default_attributes_setup.set_value[2], 0x235): {
 | 
					 | 
				
			||||||
    // TODO: Does actual hardware indeed keep an intermediate buffer or does
 | 
					    // TODO: Does actual hardware indeed keep an intermediate buffer or does
 | 
				
			||||||
    //       it directly write the values?
 | 
					    //       it directly write the values?
 | 
				
			||||||
        default_attr_write_buffer[default_attr_counter++] = value;
 | 
					    default_attr_write_buffer[default_attr_counter++] = register_value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Default attributes are written in a packed format such that four float24 values are
 | 
					    // Default attributes are written in a packed format such that four float24 values are encoded
 | 
				
			||||||
        // encoded in
 | 
					    // in three 32-bit numbers.
 | 
				
			||||||
        // three 32-bit numbers. We write to internal memory once a full such vector is
 | 
					    // We write to internal memory once a full such vector is written.
 | 
				
			||||||
        // written.
 | 
					 | 
				
			||||||
    if (default_attr_counter >= 3) {
 | 
					    if (default_attr_counter >= 3) {
 | 
				
			||||||
        default_attr_counter = 0;
 | 
					        default_attr_counter = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -184,7 +136,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (setup.index >= 16) {
 | 
					        if (setup.index >= 16) {
 | 
				
			||||||
            LOG_ERROR(HW_GPU, "Invalid VS default attribute index %d", (int)setup.index);
 | 
					            LOG_ERROR(HW_GPU, "Invalid VS default attribute index %d", (int)setup.index);
 | 
				
			||||||
                break;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Math::Vec4<float24> attribute;
 | 
					        Math::Vec4<float24> attribute;
 | 
				
			||||||
@ -249,34 +201,16 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
 | 
				
			|||||||
                // See: https://github.com/citra-emu/citra/pull/2866#issuecomment-327011550
 | 
					                // See: https://github.com/citra-emu/citra/pull/2866#issuecomment-327011550
 | 
				
			||||||
                VideoCore::g_renderer->Rasterizer()->DrawTriangles();
 | 
					                VideoCore::g_renderer->Rasterizer()->DrawTriangles();
 | 
				
			||||||
                if (g_debug_context) {
 | 
					                if (g_debug_context) {
 | 
				
			||||||
                        g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch,
 | 
					                    g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch, nullptr);
 | 
				
			||||||
                                                 nullptr);
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case PICA_REG_INDEX(pipeline.gpu_mode):
 | 
					static void Draw(u32 command_id) {
 | 
				
			||||||
        // This register likely just enables vertex processing and doesn't need any special handling
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(pipeline.command_buffer.trigger[0], 0x23c):
 | 
					 | 
				
			||||||
    case PICA_REG_INDEX_WORKAROUND(pipeline.command_buffer.trigger[1], 0x23d): {
 | 
					 | 
				
			||||||
        unsigned index =
 | 
					 | 
				
			||||||
            static_cast<unsigned>(id - PICA_REG_INDEX(pipeline.command_buffer.trigger[0]));
 | 
					 | 
				
			||||||
        u32* head_ptr = (u32*)Memory::GetPhysicalPointer(
 | 
					 | 
				
			||||||
            regs.pipeline.command_buffer.GetPhysicalAddress(index));
 | 
					 | 
				
			||||||
        g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = head_ptr;
 | 
					 | 
				
			||||||
        g_state.cmd_list.length = regs.pipeline.command_buffer.GetSize(index) / sizeof(u32);
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // It seems like these trigger vertex rendering
 | 
					 | 
				
			||||||
    case PICA_REG_INDEX(pipeline.trigger_draw):
 | 
					 | 
				
			||||||
    case PICA_REG_INDEX(pipeline.trigger_draw_indexed): {
 | 
					 | 
				
			||||||
    MICROPROFILE_SCOPE(GPU_Drawing);
 | 
					    MICROPROFILE_SCOPE(GPU_Drawing);
 | 
				
			||||||
 | 
					    auto& regs = g_state.regs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if PICA_LOG_TEV
 | 
					#if PICA_LOG_TEV
 | 
				
			||||||
    DebugUtils::DumpTevStageConfig(regs.GetTevStages());
 | 
					    DebugUtils::DumpTevStageConfig(regs.GetTevStages());
 | 
				
			||||||
@ -291,7 +225,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
 | 
				
			|||||||
    VertexLoader loader(regs.pipeline);
 | 
					    VertexLoader loader(regs.pipeline);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Load vertices
 | 
					    // Load vertices
 | 
				
			||||||
        bool is_indexed = (id == PICA_REG_INDEX(pipeline.trigger_draw_indexed));
 | 
					    bool is_indexed = (command_id == PICA_REG_INDEX(pipeline.trigger_draw_indexed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const auto& index_info = regs.pipeline.index_array;
 | 
					    const auto& index_info = regs.pipeline.index_array;
 | 
				
			||||||
    const u8* index_address_8 = Memory::GetPhysicalPointer(base_address + index_info.offset);
 | 
					    const u8* index_address_8 = Memory::GetPhysicalPointer(base_address + index_info.offset);
 | 
				
			||||||
@ -338,8 +272,8 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for (unsigned int index = 0; index < regs.pipeline.num_vertices; ++index) {
 | 
					    for (unsigned int index = 0; index < regs.pipeline.num_vertices; ++index) {
 | 
				
			||||||
        // Indexed rendering doesn't use the start offset
 | 
					        // Indexed rendering doesn't use the start offset
 | 
				
			||||||
            unsigned int vertex =
 | 
					        unsigned int vertex = is_indexed
 | 
				
			||||||
                is_indexed ? (index_u16 ? index_address_16[index] : index_address_8[index])
 | 
					                                  ? (index_u16 ? index_address_16[index] : index_address_8[index])
 | 
				
			||||||
                                  : (index + regs.pipeline.vertex_offset);
 | 
					                                  : (index + regs.pipeline.vertex_offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // -1 is a common special value used for primitive restart. Since it's unknown if
 | 
					        // -1 is a common special value used for primitive restart. Since it's unknown if
 | 
				
			||||||
@ -356,8 +290,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (g_debug_context && Pica::g_debug_context->recorder) {
 | 
					            if (g_debug_context && Pica::g_debug_context->recorder) {
 | 
				
			||||||
                int size = index_u16 ? 2 : 1;
 | 
					                int size = index_u16 ? 2 : 1;
 | 
				
			||||||
                    memory_accesses.AddAccess(base_address + index_info.offset + size * index,
 | 
					                memory_accesses.AddAccess(base_address + index_info.offset + size * index, size);
 | 
				
			||||||
                                              size);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for (unsigned int i = 0; i < VERTEX_CACHE_SIZE; ++i) {
 | 
					            for (unsigned int i = 0; i < VERTEX_CACHE_SIZE; ++i) {
 | 
				
			||||||
@ -402,10 +335,82 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
 | 
				
			|||||||
    if (g_debug_context) {
 | 
					    if (g_debug_context) {
 | 
				
			||||||
        g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch, nullptr);
 | 
					        g_debug_context->OnEvent(DebugContext::Event::FinishedPrimitiveBatch, nullptr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void WritePicaReg(u32 id, u32 value, u32 mask) {
 | 
				
			||||||
 | 
					    auto& regs = g_state.regs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (id >= Regs::NUM_REGS) {
 | 
				
			||||||
 | 
					        LOG_ERROR(HW_GPU,
 | 
				
			||||||
 | 
					                  "Commandlist tried to write to invalid register 0x%03X (value: %08X, mask: %X)",
 | 
				
			||||||
 | 
					                  id, value, mask);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO: Figure out how register masking acts on e.g. vs.uniform_setup.set_value
 | 
				
			||||||
 | 
					    u32 old_value = regs.reg_array[id];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const u32 write_mask = expand_bits_to_bytes[mask];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    regs.reg_array[id] = (old_value & ~write_mask) | (value & write_mask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Double check for is_pica_tracing to avoid call overhead
 | 
				
			||||||
 | 
					    if (DebugUtils::IsPicaTracing()) {
 | 
				
			||||||
 | 
					        DebugUtils::OnPicaRegWrite({(u16)id, (u16)mask, regs.reg_array[id]});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (g_debug_context)
 | 
				
			||||||
 | 
					        g_debug_context->OnEvent(DebugContext::Event::PicaCommandLoaded,
 | 
				
			||||||
 | 
					                                 reinterpret_cast<void*>(&id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (id) {
 | 
				
			||||||
 | 
					    // Trigger IRQ
 | 
				
			||||||
 | 
					    case PICA_REG_INDEX(trigger_irq):
 | 
				
			||||||
 | 
					        Service::GSP::SignalInterrupt(Service::GSP::InterruptId::P3D);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case PICA_REG_INDEX(pipeline.triangle_topology):
 | 
				
			||||||
 | 
					        g_state.primitive_assembler.Reconfigure(regs.pipeline.triangle_topology);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case PICA_REG_INDEX(pipeline.restart_primitive):
 | 
				
			||||||
 | 
					        g_state.primitive_assembler.Reset();
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case PICA_REG_INDEX(pipeline.vs_default_attributes_setup.index):
 | 
				
			||||||
 | 
					        g_state.immediate.current_attribute = 0;
 | 
				
			||||||
 | 
					        g_state.immediate.reset_geometry_pipeline = true;
 | 
				
			||||||
 | 
					        default_attr_counter = 0;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Load default vertex input attributes
 | 
				
			||||||
 | 
					    case PICA_REG_INDEX_WORKAROUND(pipeline.vs_default_attributes_setup.set_value[0], 0x233):
 | 
				
			||||||
 | 
					    case PICA_REG_INDEX_WORKAROUND(pipeline.vs_default_attributes_setup.set_value[1], 0x234):
 | 
				
			||||||
 | 
					    case PICA_REG_INDEX_WORKAROUND(pipeline.vs_default_attributes_setup.set_value[2], 0x235):
 | 
				
			||||||
 | 
					        LoadDefaultVertexAttributes(value);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case PICA_REG_INDEX(pipeline.gpu_mode):
 | 
				
			||||||
 | 
					        // This register likely just enables vertex processing and doesn't need any special handling
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case PICA_REG_INDEX_WORKAROUND(pipeline.command_buffer.trigger[0], 0x23c):
 | 
				
			||||||
 | 
					    case PICA_REG_INDEX_WORKAROUND(pipeline.command_buffer.trigger[1], 0x23d): {
 | 
				
			||||||
 | 
					        unsigned index =
 | 
				
			||||||
 | 
					            static_cast<unsigned>(id - PICA_REG_INDEX(pipeline.command_buffer.trigger[0]));
 | 
				
			||||||
 | 
					        u32* head_ptr = (u32*)Memory::GetPhysicalPointer(
 | 
				
			||||||
 | 
					            regs.pipeline.command_buffer.GetPhysicalAddress(index));
 | 
				
			||||||
 | 
					        g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = head_ptr;
 | 
				
			||||||
 | 
					        g_state.cmd_list.length = regs.pipeline.command_buffer.GetSize(index) / sizeof(u32);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // It seems like these trigger vertex rendering
 | 
				
			||||||
 | 
					    case PICA_REG_INDEX(pipeline.trigger_draw):
 | 
				
			||||||
 | 
					    case PICA_REG_INDEX(pipeline.trigger_draw_indexed):
 | 
				
			||||||
 | 
					        Draw(id);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case PICA_REG_INDEX(gs.bool_uniforms):
 | 
					    case PICA_REG_INDEX(gs.bool_uniforms):
 | 
				
			||||||
        WriteUniformBoolReg(g_state.gs, g_state.regs.gs.bool_uniforms.Value());
 | 
					        WriteUniformBoolReg(g_state.gs, g_state.regs.gs.bool_uniforms.Value());
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user