Skip to content

Commit

Permalink
Implement OpenExistingHeapFromAddress
Browse files Browse the repository at this point in the history
  • Loading branch information
misyltoad committed Mar 15, 2021
1 parent 51209a5 commit 4f9af2c
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 7 deletions.
68 changes: 63 additions & 5 deletions helpers/d3d12pba.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,15 +223,56 @@ _map_resource(ID3D12Resource* pResource, void* pData)
g_D3D12AddressMappings.try_emplace(key, _D3D12_MAPPING_WRITE_WATCH, pData, _getMapSize(pResource));
}

static inline void
_unmap_resource(ID3D12Resource* pResource)
static inline size_t _d3d12_AllocationSize(const void *pAddress)
{
D3D12_HEAP_FLAGS flags = _get_heap_flags(pResource);
MEMORY_BASIC_INFORMATION info;

if (!(flags & D3D12_HEAP_FLAG_ALLOW_WRITE_WATCH))
/* Query the base pointer */
if (!VirtualQuery(pAddress, &info, sizeof(info)))
return 0;

/* Allocation base must equal address. */
if (info.AllocationBase != pAddress)
return 0;
if (info.BaseAddress != info.AllocationBase)
return 0;

/* All pages must be committed. */
if (info.State != MEM_COMMIT)
return 0;

const size_t allocation_size = info.RegionSize;

/* All pages must have same protections, so there cannot be multiple regions for VirtualQuery. */
if (VirtualQuery((uint8_t *)pAddress + allocation_size, &info, sizeof(info)) &&
info.AllocationBase == pAddress)
return 0;

return allocation_size;
}


static inline void
_map_resource(ID3D12Heap* pResource, void* pData)
{
SIZE_T allocation_size = _d3d12_AllocationSize(pData);
if (!allocation_size)
return;

SIZE_T key = static_cast<SIZE_T>(reinterpret_cast<uintptr_t>(pResource));
SIZE_T key = reinterpret_cast<SIZE_T>(pResource);
// Assert we're page aligned... If we aren't we need to do more work here.
// TODO(Josh) : Placed resources.
assert(reinterpret_cast<uintptr_t>(pData) % 4096 == 0);
auto iter = g_D3D12AddressMappings.find(key);
if (iter != g_D3D12AddressMappings.end())
iter->second.RefCount++;
else
g_D3D12AddressMappings.try_emplace(key, _D3D12_MAPPING_WRITE_WATCH, pData, allocation_size);
}

static inline void
_unmap_resource(SIZE_T key)
{
auto iter = g_D3D12AddressMappings.find(key);
if (iter == g_D3D12AddressMappings.end())
return;
Expand Down Expand Up @@ -273,6 +314,23 @@ _unmap_resource(ID3D12Resource* pResource)
g_D3D12AddressMappings.erase(iter);
}

static inline void
_unmap_resource(ID3D12Resource* pResource)
{
D3D12_HEAP_FLAGS flags = _get_heap_flags(pResource);

if (!(flags & D3D12_HEAP_FLAG_ALLOW_WRITE_WATCH))
return;

_unmap_resource(static_cast<SIZE_T>(reinterpret_cast<uintptr_t>(pResource)));
}

static inline void
_unmap_resource(ID3D12Heap* pResource)
{
_unmap_resource(static_cast<SIZE_T>(reinterpret_cast<uintptr_t>(pResource)));
}

static inline void
_flush_mappings()
{
Expand Down
7 changes: 7 additions & 0 deletions retrace/dxgiretrace.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,13 @@ def invokeInterfaceMethod(self, interface, method):
print(' for (UINT i = 0; i < Count; i++)')
print(' pParams[i].Dest = g_D3D12AddressSlabs.LookupSlab(pParams[i].Dest);')

if method.name == 'OpenExistingHeapFromAddress':
print(' size_t _AddressSize = call.arg(1).toBlob()->size;')
print(' void *_AlignedAddress = VirtualAlloc(NULL, _AddressSize, MEM_COMMIT, PAGE_READWRITE);')
print(' memcpy(_AlignedAddress, pAddress, _AddressSize);')
print(' pAddress = _AlignedAddress;')
print(' retrace::addRegion(call, (unsigned long long)call.arg(1).toBlob()->base_ptr, _AlignedAddress, _AddressSize);')

if method.name == 'CreatePipelineLibrary':
# Make a fake pipeline library, so we can still make the state objects.
print(' *ppPipelineLibrary = reinterpret_cast<void*>(new _D3D12FakePipelineLibrary(_this));')
Expand Down
2 changes: 1 addition & 1 deletion specs/d3d12.py
Original file line number Diff line number Diff line change
Expand Up @@ -2754,7 +2754,7 @@
ID3D12Device3.methods += [
# TODO(Josh): Implement OpenExistingHeapFromAddress, etc properly
# Mark all dirty then VirtualProtect their stuff. Yuck.
StdMethod(HRESULT, 'OpenExistingHeapFromAddress', [(OpaquePointer(Const(Void)), 'pAddress'), (REFIID, 'riid'), Out(Pointer(ObjPointer(Void)), 'ppvHeap')]),
StdMethod(HRESULT, 'OpenExistingHeapFromAddress', [(Blob(Const(Void), '_d3d12_AllocationSize(pAddress)'), 'pAddress'), (REFIID, 'riid'), Out(Pointer(ObjPointer(Void)), 'ppvHeap')]),
StdMethod(HRESULT, 'OpenExistingHeapFromFileMapping', [(HANDLE, 'hFileMapping'), (REFIID, 'riid'), Out(Pointer(ObjPointer(Void)), 'ppvHeap')]),
StdMethod(HRESULT, 'EnqueueMakeResident', [(D3D12_RESIDENCY_FLAGS, 'Flags'), (UINT, 'NumObjects'), (Array(Const(ObjPointer(ID3D12Pageable)), 'NumObjects'), 'ppObjects'),(ObjPointer(ID3D12Fence), 'pFenceToSignal'), (UINT64, 'FenceValueToSignal')]),
]
Expand Down
16 changes: 15 additions & 1 deletion wrappers/dxgitrace.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ def enumWrapperInterfaceVariables(self, interface):
('D3D12_GPU_VIRTUAL_ADDRESS', 'm_FakeAddress', '0'),
('std::mutex', 'm_RefCountMutex', None)
]
if interface.hasBase(d3d12.ID3D12Heap):
variables += [
('const void *', 'm_UserPointer', '0'),
('std::mutex', 'm_RefCountMutex', None)
]

return variables

Expand Down Expand Up @@ -193,7 +198,7 @@ def implementWrapperInterfaceMethodBody(self, interface, base, method):

# Need to unmap the resource if the last public reference is
# eliminated.
if interface in (d3d12.ID3D12Resource, d3d12.ID3D12Resource1):
if interface in (d3d12.ID3D12Resource, d3d12.ID3D12Resource1, d3d12.ID3D12Heap, d3d12.ID3D12Heap1):
if method.name == 'AddRef':
# Need to lock here to avoid another thread potentially
# releasing while we are flushing.
Expand All @@ -210,6 +215,8 @@ def implementWrapperInterfaceMethodBody(self, interface, base, method):
# avoid a dangling ptr.
print(' std::unique_lock<std::mutex> _ordering_lock;')
print(' if (_current_ref == 1) {')
if interface in (d3d12.ID3D12Heap, d3d12.ID3D12Heap1):
print(' if (m_UserPointer != nullptr)')
print(' _unmap_resource(m_pInstance);')
print(' _ordering_lock = std::unique_lock<std::mutex>(g_D3D12AddressMappingsMutex);')
print(' }')
Expand Down Expand Up @@ -282,6 +289,13 @@ def implementWrapperInterfaceMethodBody(self, interface, base, method):
print(' _MapDesc.Size = 0;')
print(' }')

if method.name == 'OpenExistingHeapFromAddress':
print(' if (SUCCEEDED(_result) && pAddress) {')
print(' auto *pHeap = *reinterpret_cast<WrapID3D12Heap**>(ppvHeap);')
print(' _map_resource(pHeap->m_pInstance, (void *) pAddress);')
print(' pHeap->m_UserPointer = pAddress;')
print(' }')

if interface.hasBase(d3d11.ID3D11VideoContext) and \
method.name == 'GetDecoderBuffer':
print(' if (SUCCEEDED(_result)) {')
Expand Down

0 comments on commit 4f9af2c

Please sign in to comment.