@@ -344,7 +344,7 @@ dword_result_t VdRetrainEDRAM(unknown_t unk0, unknown_t unk1, unknown_t unk2,
344
344
DECLARE_XBOXKRNL_EXPORT1 (VdRetrainEDRAM, kVideo , kStub );
345
345
346
346
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
348
348
lpunknown_t unk2, // system writeback ptr
349
349
lpunknown_t unk3, // buffer from VdGetSystemCommandBuffer
350
350
lpunknown_t unk4, // from VdGetSystemCommandBuffer (0xBEEF0001)
@@ -361,32 +361,38 @@ void VdSwap(lpvoid_t buffer_ptr, // ptr into primary ringbuffer
361
361
362
362
namespace xenos = xe::gpu::xenos;
363
363
364
- xenos::xe_gpu_texture_fetch_t fetch ;
364
+ xenos::xe_gpu_texture_fetch_t gpu_fetch ;
365
365
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) {
375
381
// Xenia-specific safety check.
376
382
XELOGE (" VdSwap: Invalid front buffer virtual address 0x{:08X}" ,
377
- fetch. base_address << 12 );
383
+ frontbuffer_virtual_address );
378
384
return ;
379
385
}
380
- fetch .base_address = frontbuffer_address >> 12 ;
386
+ gpu_fetch .base_address = frontbuffer_physical_address >> 12 ;
381
387
382
388
auto texture_format = gpu::xenos::TextureFormat (texture_format_ptr.value ());
383
389
auto color_space = *color_space_ptr;
384
390
assert_true (texture_format == gpu::xenos::TextureFormat::k_8_8_8_8 ||
385
391
texture_format ==
386
392
gpu::xenos::TextureFormat::k_2_10_10_10_AS_16_16_16_16);
387
393
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 );
390
396
391
397
// The caller seems to reserve 64 words (256b) in the primary ringbuffer
392
398
// 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
398
404
uint32_t offset = 0 ;
399
405
auto dwords = buffer_ptr.as_array <uint32_t >();
400
406
401
- // Write in the texture fetch.
407
+ // Write in the GPU texture fetch.
402
408
dwords[offset++] =
403
409
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 ;
410
416
411
417
dwords[offset++] = xenos::MakePacketType3 (xenos::PM4_XE_SWAP, 4 );
412
418
dwords[offset++] = ' SWAP' ;
413
- dwords[offset++] = frontbuffer_address ;
419
+ dwords[offset++] = frontbuffer_physical_address ;
414
420
415
421
dwords[offset++] = *width;
416
422
dwords[offset++] = *height;
0 commit comments