mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-10-27 17:15:23 +00:00
219 lines
7.5 KiB
C++
219 lines
7.5 KiB
C++
/******************************************************************************
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2021-2026 Baldur Karlsson
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
******************************************************************************/
|
|
|
|
#include "d3d12_device.h"
|
|
#include "driver/dxgi/dxgi_common.h"
|
|
#include "d3d12_command_queue.h"
|
|
#include "d3d12_resources.h"
|
|
|
|
HRESULT WrappedID3D12Device::CreateShaderCacheSession(_In_ const D3D12_SHADER_CACHE_SESSION_DESC *pDesc,
|
|
REFIID riid, _COM_Outptr_opt_ void **ppvSession)
|
|
{
|
|
if(ppvSession == NULL)
|
|
return m_pDevice9->CreateShaderCacheSession(pDesc, riid, NULL);
|
|
|
|
if(riid != __uuidof(ID3D12ShaderCacheSession))
|
|
return E_NOINTERFACE;
|
|
|
|
ID3D12ShaderCacheSession *real = NULL;
|
|
HRESULT ret;
|
|
SERIALISE_TIME_CALL(ret = m_pDevice9->CreateShaderCacheSession(
|
|
pDesc, __uuidof(ID3D12ShaderCacheSession), (void **)&real));
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
WrappedID3D12ShaderCacheSession *wrapped =
|
|
new WrappedID3D12ShaderCacheSession(ResourceId(), real, this);
|
|
|
|
if(riid == __uuidof(ID3D12ShaderCacheSession))
|
|
*ppvSession = (ID3D12ShaderCacheSession *)wrapped;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
HRESULT WrappedID3D12Device::ShaderCacheControl(D3D12_SHADER_CACHE_KIND_FLAGS Kinds,
|
|
D3D12_SHADER_CACHE_CONTROL_FLAGS Control)
|
|
{
|
|
return m_pDevice9->ShaderCacheControl(Kinds, Control);
|
|
}
|
|
|
|
template <typename SerialiserType>
|
|
bool WrappedID3D12Device::Serialise_CreateCommandQueue1(SerialiserType &ser,
|
|
const D3D12_COMMAND_QUEUE_DESC *pDesc,
|
|
REFIID CreatorID, REFIID riid,
|
|
void **ppCommandQueue)
|
|
{
|
|
SERIALISE_ELEMENT_LOCAL(Descriptor, *pDesc).Named("pDesc"_lit).Important();
|
|
SERIALISE_ELEMENT_LOCAL(creator, CreatorID).Named("CreatorID"_lit);
|
|
SERIALISE_ELEMENT_LOCAL(guid, riid).Named("riid"_lit);
|
|
SERIALISE_ELEMENT_LOCAL(pCommandQueue,
|
|
((WrappedID3D12CommandQueue *)*ppCommandQueue)->GetResourceID())
|
|
.TypedAs("ID3D12CommandQueue *"_lit);
|
|
|
|
SERIALISE_CHECK_READ_ERRORS();
|
|
|
|
if(IsReplayingAndReading())
|
|
{
|
|
ID3D12CommandQueue *ret = NULL;
|
|
HRESULT hr = E_NOINTERFACE;
|
|
if(m_pDevice9)
|
|
{
|
|
void *realptr = NULL;
|
|
hr = m_pDevice9->CreateCommandQueue1(&Descriptor, creator, guid, &realptr);
|
|
|
|
if(guid == __uuidof(ID3D12CommandQueue))
|
|
ret = (ID3D12CommandQueue *)realptr;
|
|
else if(guid == __uuidof(ID3D12CommandQueue1))
|
|
ret = (ID3D12CommandQueue1 *)realptr;
|
|
}
|
|
else
|
|
{
|
|
SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
|
|
"Capture requires ID3D12Device9 which isn't available");
|
|
return false;
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIReplayFailed,
|
|
"Failed creating command queue, HRESULT: %s", ToStr(hr).c_str());
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
SetObjName(ret, StringFormat::Fmt("Command Queue %s", ToStr(pCommandQueue).c_str()));
|
|
|
|
ret = new WrappedID3D12CommandQueue(pCommandQueue, ret, this, m_State);
|
|
|
|
AddResource(pCommandQueue, ResourceType::Queue, "Command Queue");
|
|
|
|
WrappedID3D12CommandQueue *wrapped = (WrappedID3D12CommandQueue *)ret;
|
|
|
|
if(Descriptor.Type == D3D12_COMMAND_LIST_TYPE_DIRECT && m_Queue == NULL)
|
|
{
|
|
m_Queue = wrapped;
|
|
// we hold an extra ref on this during capture to keep it alive, for simplicity match that
|
|
// behaviour here.
|
|
m_Queue->AddRef();
|
|
CreateInternalResources();
|
|
}
|
|
|
|
m_Queues.push_back(wrapped);
|
|
|
|
// create a dummy (dummy) fence
|
|
ID3D12Fence *fence = NULL;
|
|
hr = this->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), (void **)&fence);
|
|
|
|
RDCASSERTEQUAL(hr, S_OK);
|
|
|
|
m_QueueFences.push_back(fence);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
HRESULT WrappedID3D12Device::CreateCommandQueue1(const D3D12_COMMAND_QUEUE_DESC *pDesc,
|
|
REFIID CreatorID, REFIID riid, void **ppCommandQueue)
|
|
{
|
|
if(ppCommandQueue == NULL)
|
|
return m_pDevice9->CreateCommandQueue1(pDesc, CreatorID, riid, NULL);
|
|
|
|
if(riid != __uuidof(ID3D12CommandQueue) && riid != __uuidof(ID3D12CommandQueue1))
|
|
return E_NOINTERFACE;
|
|
|
|
void *realptr = NULL;
|
|
HRESULT ret;
|
|
SERIALISE_TIME_CALL(ret = m_pDevice9->CreateCommandQueue1(pDesc, CreatorID, riid, &realptr));
|
|
|
|
ID3D12CommandQueue *real = NULL;
|
|
if(riid == __uuidof(ID3D12CommandQueue))
|
|
real = (ID3D12CommandQueue *)realptr;
|
|
else if(riid == __uuidof(ID3D12CommandQueue1))
|
|
real = (ID3D12CommandQueue1 *)realptr;
|
|
|
|
if(SUCCEEDED(ret))
|
|
{
|
|
WrappedID3D12CommandQueue *wrapped =
|
|
new WrappedID3D12CommandQueue(ResourceId(), real, this, m_State);
|
|
|
|
if(IsCaptureMode(m_State))
|
|
{
|
|
CACHE_THREAD_SERIALISER();
|
|
|
|
SCOPED_SERIALISE_CHUNK(D3D12Chunk::Device_CreateCommandQueue1);
|
|
Serialise_CreateCommandQueue1(ser, pDesc, CreatorID, riid, (void **)&wrapped);
|
|
|
|
wrapped->GetCreationRecord()->AddChunk(scope.Get());
|
|
}
|
|
|
|
if(pDesc->Type == D3D12_COMMAND_LIST_TYPE_DIRECT && m_Queue == NULL)
|
|
{
|
|
m_Queue = wrapped;
|
|
// keep this queue alive even if the application frees it, for our own use
|
|
m_Queue->AddRef();
|
|
InternalRef();
|
|
CreateInternalResources();
|
|
}
|
|
|
|
m_Queues.push_back(wrapped);
|
|
|
|
bool capframe = false;
|
|
{
|
|
SCOPED_READLOCK(m_CapTransitionLock);
|
|
capframe = IsActiveCapturing(m_State);
|
|
|
|
// while capturing don't allow any queues to be freed, by adding another refcount, since we
|
|
// gather any commands submitted to them at the end of the capture.
|
|
if(capframe)
|
|
{
|
|
wrapped->AddRef();
|
|
m_RefQueues.push_back(wrapped);
|
|
}
|
|
}
|
|
|
|
if(capframe)
|
|
{
|
|
GetResourceManager()->MarkResourceFrameReferenced(
|
|
wrapped->GetCreationRecord()->GetResourceID(), eFrameRef_Read);
|
|
}
|
|
|
|
if(riid == __uuidof(ID3D12CommandQueue))
|
|
*ppCommandQueue = (ID3D12CommandQueue *)wrapped;
|
|
else if(riid == __uuidof(ID3D12CommandQueue1))
|
|
*ppCommandQueue = (ID3D12CommandQueue1 *)wrapped;
|
|
}
|
|
else
|
|
{
|
|
CHECK_HR(this, ret);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
INSTANTIATE_FUNCTION_SERIALISED(void, WrappedID3D12Device, CreateCommandQueue1,
|
|
const D3D12_COMMAND_QUEUE_DESC *pDesc, REFIID CreatorID,
|
|
REFIID riid, void **ppCommandQueue);
|