static void MemoryFill(const Regs::MemoryFillConfig& config) { const PAddr start_addr = config.GetStartAddress(); const PAddr end_addr = config.GetEndAddress(); // TODO: do hwtest with these cases if (!Memory::IsValidPhysicalAddress(start_addr)) { LOG_CRITICAL(HW_GPU, "invalid start address 0x%08X", start_addr); return; } if (!Memory::IsValidPhysicalAddress(end_addr)) { LOG_CRITICAL(HW_GPU, "invalid end address 0x%08X", end_addr); return; } if (end_addr <= start_addr) { LOG_CRITICAL(HW_GPU, "invalid memory range from 0x%08X to 0x%08X", start_addr, end_addr); return; } u8* start = Memory::GetPhysicalPointer(start_addr); u8* end = Memory::GetPhysicalPointer(end_addr); // TODO: Consider always accelerating and returning vector of // regions that the accelerated fill did not cover to // reduce/eliminate the fill that the cpu has to do. // This would also mean that the flush below is not needed. // Fill should first flush all surfaces that touch but are // not completely within the fill range. // Then fill all completely covered surfaces, and return the // regions that were between surfaces or within the touching // ones for cpu to manually fill here. if (VideoCore::g_renderer->Rasterizer()->AccelerateFill(config)) return; Memory::RasterizerFlushAndInvalidateRegion(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress()); if (config.fill_24bit) { // fill with 24-bit values for (u8* ptr = start; ptr < end; ptr += 3) { ptr[0] = config.value_24bit_r; ptr[1] = config.value_24bit_g; ptr[2] = config.value_24bit_b; } } else if (config.fill_32bit) { // fill with 32-bit values if (end > start) { u32 value = config.value_32bit; size_t len = (end - start) / sizeof(u32); for (size_t i = 0; i < len; ++i) memcpy(&start[i * sizeof(u32)], &value, sizeof(u32)); } } else { // fill with 16-bit values u16 value_16bit = config.value_16bit.Value(); for (u8* ptr = start; ptr < end; ptr += sizeof(u16)) memcpy(ptr, &value_16bit, sizeof(u16)); } }
static void MemoryFill(const Regs::MemoryFillConfig& config) { const PAddr start_addr = config.GetStartAddress(); const PAddr end_addr = config.GetEndAddress(); // TODO: do hwtest with these cases if (!Memory::IsValidPhysicalAddress(start_addr)) { LOG_CRITICAL(HW_GPU, "invalid start address {:#010X}", start_addr); return; } if (!Memory::IsValidPhysicalAddress(end_addr)) { LOG_CRITICAL(HW_GPU, "invalid end address {:#010X}", end_addr); return; } if (end_addr <= start_addr) { LOG_CRITICAL(HW_GPU, "invalid memory range from {:#010X} to {:#010X}", start_addr, end_addr); return; } u8* start = Memory::GetPhysicalPointer(start_addr); u8* end = Memory::GetPhysicalPointer(end_addr); if (VideoCore::g_renderer->Rasterizer()->AccelerateFill(config)) return; Memory::RasterizerInvalidateRegion(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress()); if (config.fill_24bit) { // fill with 24-bit values for (u8* ptr = start; ptr < end; ptr += 3) { ptr[0] = config.value_24bit_r; ptr[1] = config.value_24bit_g; ptr[2] = config.value_24bit_b; } } else if (config.fill_32bit) { // fill with 32-bit values if (end > start) { u32 value = config.value_32bit; size_t len = (end - start) / sizeof(u32); for (size_t i = 0; i < len; ++i) memcpy(&start[i * sizeof(u32)], &value, sizeof(u32)); } } else { // fill with 16-bit values u16 value_16bit = config.value_16bit.Value(); for (u8* ptr = start; ptr < end; ptr += sizeof(u16)) memcpy(ptr, &value_16bit, sizeof(u16)); } }