summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/service/gsp_gpu.cpp34
-rw-r--r--src/core/hle/service/gsp_gpu.h4
-rw-r--r--src/core/hw/gpu.cpp41
-rw-r--r--src/core/hw/gpu.h32
4 files changed, 78 insertions, 33 deletions
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 31e61391f..c23cfa3c8 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -368,28 +368,28 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
368 case CommandId::SET_MEMORY_FILL: 368 case CommandId::SET_MEMORY_FILL:
369 { 369 {
370 auto& params = command.memory_fill; 370 auto& params = command.memory_fill;
371 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)), 371 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)),
372 Memory::VirtualToPhysicalAddress(params.start1) >> 3); 372 Memory::VirtualToPhysicalAddress(params.start1) >> 3);
373 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)), 373 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)),
374 Memory::VirtualToPhysicalAddress(params.end1) >> 3); 374 Memory::VirtualToPhysicalAddress(params.end1) >> 3);
375 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].size)), params.end1 - params.start1); 375 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].value_32bit)), params.value1);
376 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].value)), params.value1); 376 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].control)), params.control1);
377 377
378 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)), 378 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)),
379 Memory::VirtualToPhysicalAddress(params.start2) >> 3); 379 Memory::VirtualToPhysicalAddress(params.start2) >> 3);
380 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)), 380 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)),
381 Memory::VirtualToPhysicalAddress(params.end2) >> 3); 381 Memory::VirtualToPhysicalAddress(params.end2) >> 3);
382 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].size)), params.end2 - params.start2); 382 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].value_32bit)), params.value2);
383 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].value)), params.value2); 383 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].control)), params.control2);
384 break; 384 break;
385 } 385 }
386 386
387 case CommandId::SET_DISPLAY_TRANSFER: 387 case CommandId::SET_DISPLAY_TRANSFER:
388 { 388 {
389 auto& params = command.image_copy; 389 auto& params = command.image_copy;
390 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_address)), 390 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_address)),
391 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); 391 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3);
392 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_address)), 392 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_address)),
393 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); 393 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3);
394 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_size)), params.in_buffer_size); 394 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_size)), params.in_buffer_size);
395 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_size)), params.out_buffer_size); 395 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_size)), params.out_buffer_size);
@@ -402,9 +402,9 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
402 case CommandId::SET_TEXTURE_COPY: 402 case CommandId::SET_TEXTURE_COPY:
403 { 403 {
404 auto& params = command.image_copy; 404 auto& params = command.image_copy;
405 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_address)), 405 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_address)),
406 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); 406 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3);
407 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_address)), 407 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_address)),
408 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); 408 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3);
409 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_size)), params.in_buffer_size); 409 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_size)), params.in_buffer_size);
410 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_size)), params.out_buffer_size); 410 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_size)), params.out_buffer_size);
diff --git a/src/core/hle/service/gsp_gpu.h b/src/core/hle/service/gsp_gpu.h
index 65abb194a..a435d418a 100644
--- a/src/core/hle/service/gsp_gpu.h
+++ b/src/core/hle/service/gsp_gpu.h
@@ -109,9 +109,13 @@ struct Command {
109 u32 start1; 109 u32 start1;
110 u32 value1; 110 u32 value1;
111 u32 end1; 111 u32 end1;
112
112 u32 start2; 113 u32 start2;
113 u32 value2; 114 u32 value2;
114 u32 end2; 115 u32 end2;
116
117 u16 control1;
118 u16 control2;
115 } memory_fill; 119 } memory_fill;
116 120
117 struct { 121 struct {
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index aad0e5d0d..bd7d92cd1 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -67,23 +67,38 @@ inline void Write(u32 addr, const T data) {
67 switch (index) { 67 switch (index) {
68 68
69 // Memory fills are triggered once the fill value is written. 69 // Memory fills are triggered once the fill value is written.
70 // NOTE: This is not verified. 70 case GPU_REG_INDEX_WORKAROUND(memory_fill_config[0].trigger, 0x00004 + 0x3):
71 case GPU_REG_INDEX_WORKAROUND(memory_fill_config[0].value, 0x00004 + 0x3): 71 case GPU_REG_INDEX_WORKAROUND(memory_fill_config[1].trigger, 0x00008 + 0x3):
72 case GPU_REG_INDEX_WORKAROUND(memory_fill_config[1].value, 0x00008 + 0x3):
73 { 72 {
74 const bool is_second_filler = (index != GPU_REG_INDEX(memory_fill_config[0].value)); 73 const bool is_second_filler = (index != GPU_REG_INDEX(memory_fill_config[0].trigger));
75 const auto& config = g_regs.memory_fill_config[is_second_filler]; 74 auto& config = g_regs.memory_fill_config[is_second_filler];
76 75
77 // TODO: Not sure if this check should be done at GSP level instead 76 if (config.address_start && config.trigger) {
78 if (config.address_start) { 77 u8* start = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetStartAddress()));
79 // TODO: Not sure if this algorithm is correct, particularly because it doesn't use the size member at all 78 u8* end = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetEndAddress()));
80 u32* start = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetStartAddress())); 79
81 u32* end = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetEndAddress())); 80 if (config.fill_24bit) {
82 for (u32* ptr = start; ptr < end; ++ptr) 81 // fill with 24-bit values
83 *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation 82 for (u8* ptr = start; ptr < end; ptr += 3) {
83 ptr[0] = config.value_24bit_b;
84 ptr[1] = config.value_24bit_g;
85 ptr[2] = config.value_24bit_r;
86 }
87 } else if (config.fill_32bit) {
88 // fill with 32-bit values
89 for (u32* ptr = (u32*)start; ptr < (u32*)end; ++ptr)
90 *ptr = config.value_32bit;
91 } else {
92 // fill with 16-bit values
93 for (u16* ptr = (u16*)start; ptr < (u16*)end; ++ptr)
94 *ptr = config.value_16bit;
95 }
84 96
85 LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress()); 97 LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress());
86 98
99 config.trigger = 0;
100 config.finished = 1;
101
87 if (!is_second_filler) { 102 if (!is_second_filler) {
88 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0); 103 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0);
89 } else { 104 } else {
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h
index 9fd694f65..df9aa0d71 100644
--- a/src/core/hw/gpu.h
+++ b/src/core/hw/gpu.h
@@ -84,9 +84,35 @@ struct Regs {
84 84
85 struct { 85 struct {
86 u32 address_start; 86 u32 address_start;
87 u32 address_end; // ? 87 u32 address_end;
88 u32 size; 88
89 u32 value; // ? 89 union {
90 u32 value_32bit;
91
92 BitField<0, 16, u32> value_16bit;
93
94 // TODO: Verify component order
95 BitField< 0, 8, u32> value_24bit_r;
96 BitField< 8, 8, u32> value_24bit_g;
97 BitField<16, 8, u32> value_24bit_b;
98 };
99
100 union {
101 u32 control;
102
103 // Setting this field to 1 triggers the memory fill.
104 // This field also acts as a status flag, and gets reset to 0 upon completion.
105 BitField<0, 1, u32> trigger;
106
107 // Set to 1 upon completion.
108 BitField<0, 1, u32> finished;
109
110 // 0: fill with 16- or 32-bit wide values; 1: fill with 24-bit wide values
111 BitField<8, 1, u32> fill_24bit;
112
113 // 0: fill with 16-bit wide values; 1: fill with 32-bit wide values
114 BitField<9, 1, u32> fill_32bit;
115 };
90 116
91 inline u32 GetStartAddress() const { 117 inline u32 GetStartAddress() const {
92 return DecodeAddressRegister(address_start); 118 return DecodeAddressRegister(address_start);