Skip to content

Commit ea9625f

Browse files
committed
[Kernel] VdSwap virtual/physical address clarification
1 parent 800db1a commit ea9625f

File tree

1 file changed

+29
-23
lines changed

1 file changed

+29
-23
lines changed

src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ dword_result_t VdRetrainEDRAM(unknown_t unk0, unknown_t unk1, unknown_t unk2,
344344
DECLARE_XBOXKRNL_EXPORT1(VdRetrainEDRAM, kVideo, kStub);
345345

346346
void VdSwap(lpvoid_t buffer_ptr, // ptr into primary ringbuffer
347-
lpvoid_t fetch_ptr, // frontbuffer texture fetch
347+
lpvoid_t fetch_ptr, // frontbuffer Direct3D 9 texture header fetch
348348
lpunknown_t unk2, // system writeback ptr
349349
lpunknown_t unk3, // buffer from VdGetSystemCommandBuffer
350350
lpunknown_t unk4, // from VdGetSystemCommandBuffer (0xBEEF0001)
@@ -361,32 +361,38 @@ void VdSwap(lpvoid_t buffer_ptr, // ptr into primary ringbuffer
361361

362362
namespace xenos = xe::gpu::xenos;
363363

364-
xenos::xe_gpu_texture_fetch_t fetch;
364+
xenos::xe_gpu_texture_fetch_t gpu_fetch;
365365
xe::copy_and_swap_32_unaligned(
366-
&fetch, reinterpret_cast<uint32_t*>(fetch_ptr.host_address()), 6);
367-
368-
// Kernel virtual -> GPU physical.
369-
uint32_t frontbuffer_address = fetch.base_address << 12;
370-
assert_true(*frontbuffer_ptr == frontbuffer_address);
371-
frontbuffer_address =
372-
kernel_memory()->GetPhysicalAddress(frontbuffer_address);
373-
assert_true(frontbuffer_address != UINT32_MAX);
374-
if (frontbuffer_address == UINT32_MAX) {
366+
&gpu_fetch, reinterpret_cast<uint32_t*>(fetch_ptr.host_address()), 6);
367+
368+
// The fetch constant passed is not a true GPU fetch constant, but rather, the
369+
// fetch constant stored in the Direct3D 9 texture header, which contains the
370+
// address in one of the virtual mappings of the physical memory rather than
371+
// the physical address itself. We're emulating swapping in the GPU subsystem,
372+
// which works with GPU memory addresses (physical addresses directly) from
373+
// proper fetch constants like ones used to bind textures to shaders, not CPU
374+
// MMU addresses, so translation from virtual to physical is needed.
375+
uint32_t frontbuffer_virtual_address = gpu_fetch.base_address << 12;
376+
assert_true(*frontbuffer_ptr == frontbuffer_virtual_address);
377+
uint32_t frontbuffer_physical_address =
378+
kernel_memory()->GetPhysicalAddress(frontbuffer_virtual_address);
379+
assert_true(frontbuffer_physical_address != UINT32_MAX);
380+
if (frontbuffer_physical_address == UINT32_MAX) {
375381
// Xenia-specific safety check.
376382
XELOGE("VdSwap: Invalid front buffer virtual address 0x{:08X}",
377-
fetch.base_address << 12);
383+
frontbuffer_virtual_address);
378384
return;
379385
}
380-
fetch.base_address = frontbuffer_address >> 12;
386+
gpu_fetch.base_address = frontbuffer_physical_address >> 12;
381387

382388
auto texture_format = gpu::xenos::TextureFormat(texture_format_ptr.value());
383389
auto color_space = *color_space_ptr;
384390
assert_true(texture_format == gpu::xenos::TextureFormat::k_8_8_8_8 ||
385391
texture_format ==
386392
gpu::xenos::TextureFormat::k_2_10_10_10_AS_16_16_16_16);
387393
assert_true(color_space == 0); // RGB(0)
388-
assert_true(*width == 1 + fetch.size_2d.width);
389-
assert_true(*height == 1 + fetch.size_2d.height);
394+
assert_true(*width == 1 + gpu_fetch.size_2d.width);
395+
assert_true(*height == 1 + gpu_fetch.size_2d.height);
390396

391397
// The caller seems to reserve 64 words (256b) in the primary ringbuffer
392398
// for this method to do what it needs. We just zero them out and send a
@@ -398,19 +404,19 @@ void VdSwap(lpvoid_t buffer_ptr, // ptr into primary ringbuffer
398404
uint32_t offset = 0;
399405
auto dwords = buffer_ptr.as_array<uint32_t>();
400406

401-
// Write in the texture fetch.
407+
// Write in the GPU texture fetch.
402408
dwords[offset++] =
403409
xenos::MakePacketType0(gpu::XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0, 6);
404-
dwords[offset++] = fetch.dword_0;
405-
dwords[offset++] = fetch.dword_1;
406-
dwords[offset++] = fetch.dword_2;
407-
dwords[offset++] = fetch.dword_3;
408-
dwords[offset++] = fetch.dword_4;
409-
dwords[offset++] = fetch.dword_5;
410+
dwords[offset++] = gpu_fetch.dword_0;
411+
dwords[offset++] = gpu_fetch.dword_1;
412+
dwords[offset++] = gpu_fetch.dword_2;
413+
dwords[offset++] = gpu_fetch.dword_3;
414+
dwords[offset++] = gpu_fetch.dword_4;
415+
dwords[offset++] = gpu_fetch.dword_5;
410416

411417
dwords[offset++] = xenos::MakePacketType3(xenos::PM4_XE_SWAP, 4);
412418
dwords[offset++] = 'SWAP';
413-
dwords[offset++] = frontbuffer_address;
419+
dwords[offset++] = frontbuffer_physical_address;
414420

415421
dwords[offset++] = *width;
416422
dwords[offset++] = *height;

0 commit comments

Comments
 (0)