mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-10-09 05:41:31 +00:00
Refactor D3D12 resource usage to be less rootsig-authoratitive
* The root signature is not a good model for what resources are actually used, instead use the shader reflection as we do on other APIs. In either case this does not work for bindless access (> 1000 registers).
This commit is contained in:
3 files changed
+251
-131
No files matched your search
@@ -1690,8 +1690,8 @@ void D3D12CommandData::AddEvent()
|
||||
m_EventMessages.clear();
|
||||
}
|
||||
|
||||
void D3D12CommandData::AddUsage(D3D12ActionTreeNode &actionNode, ResourceId id, uint32_t EID,
|
||||
ResourceUsage usage)
|
||||
void D3D12CommandData::AddResourceUsage(D3D12ActionTreeNode &actionNode, ResourceId id,
|
||||
uint32_t EID, ResourceUsage usage)
|
||||
{
|
||||
if(id == ResourceId())
|
||||
return;
|
||||
@@ -1699,52 +1699,256 @@ void D3D12CommandData::AddUsage(D3D12ActionTreeNode &actionNode, ResourceId id,
|
||||
actionNode.resourceUsage.push_back(make_rdcpair(id, EventUsage(EID, usage)));
|
||||
}
|
||||
|
||||
void D3D12CommandData::AddUsage(ResourceId id, ResourceUsage usage)
|
||||
void D3D12CommandData::AddCPUUsage(ResourceId id, ResourceUsage usage)
|
||||
{
|
||||
m_ResourceUses[id].push_back(EventUsage(m_RootEventID, usage));
|
||||
}
|
||||
|
||||
void D3D12CommandData::AddUsageForBindInRootSig(const D3D12RenderState &state,
|
||||
D3D12ActionTreeNode &actionNode,
|
||||
const D3D12RenderState::RootSignature *rootsig,
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE type, const Bindpoint &b)
|
||||
{
|
||||
static bool hugeRangeWarned = false;
|
||||
|
||||
ActionDescription &a = actionNode.action;
|
||||
uint32_t eid = a.eventId;
|
||||
|
||||
const uint32_t space = b.bindset;
|
||||
const uint32_t bind = b.bind;
|
||||
// use a 'clamped' range size to avoid annoying overflow issues
|
||||
const uint32_t rangeSize = b.arraySize == ~0U ? 0x10000000 : b.arraySize;
|
||||
|
||||
D3D12ResourceManager *rm = m_pDevice->GetResourceManager();
|
||||
|
||||
WrappedID3D12RootSignature *sig = rm->GetCurrentAs<WrappedID3D12RootSignature>(rootsig->rootsig);
|
||||
|
||||
for(size_t rootEl = 0; rootEl < sig->sig.Parameters.size(); rootEl++)
|
||||
{
|
||||
if(rootEl >= rootsig->sigelems.size())
|
||||
break;
|
||||
|
||||
const D3D12RootSignatureParameter &p = sig->sig.Parameters[rootEl];
|
||||
const D3D12RenderState::SignatureElement &el = rootsig->sigelems[rootEl];
|
||||
|
||||
if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS)
|
||||
continue;
|
||||
|
||||
ResourceUsage cb = ResourceUsage::CS_Constants;
|
||||
ResourceUsage ro = ResourceUsage::CS_Resource;
|
||||
ResourceUsage rw = ResourceUsage::CS_RWResource;
|
||||
|
||||
if(rootsig == &state.graphics)
|
||||
{
|
||||
if(p.ShaderVisibility == D3D12_SHADER_VISIBILITY_ALL)
|
||||
{
|
||||
cb = ResourceUsage::All_Constants;
|
||||
ro = ResourceUsage::All_Resource;
|
||||
rw = ResourceUsage::All_RWResource;
|
||||
}
|
||||
else
|
||||
{
|
||||
cb = CBUsage(p.ShaderVisibility - D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
ro = ResUsage(p.ShaderVisibility - D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
rw = RWResUsage(p.ShaderVisibility - D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
}
|
||||
}
|
||||
|
||||
if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV && el.type == eRootCBV &&
|
||||
type == D3D12_DESCRIPTOR_RANGE_TYPE_CBV && p.Descriptor.RegisterSpace == space &&
|
||||
p.Descriptor.ShaderRegister >= bind && p.Descriptor.ShaderRegister < bind + rangeSize)
|
||||
{
|
||||
AddResourceUsage(actionNode, el.id, eid, cb);
|
||||
|
||||
// common case - root element matches 1:1 with a non-array shader bind, if so we can exit. If
|
||||
// not we might have to continue since other parts of it might be mapped to a table, or
|
||||
// another root element
|
||||
if(rangeSize == 1)
|
||||
return;
|
||||
}
|
||||
else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV && el.type == eRootSRV &&
|
||||
type == D3D12_DESCRIPTOR_RANGE_TYPE_SRV && p.Descriptor.RegisterSpace == space &&
|
||||
p.Descriptor.ShaderRegister >= bind && p.Descriptor.ShaderRegister < bind + rangeSize)
|
||||
{
|
||||
AddResourceUsage(actionNode, el.id, eid, ro);
|
||||
|
||||
// common case - root element matches 1:1 with a non-array shader bind, if so we can exit. If
|
||||
// not we might have to continue since other parts of it might be mapped to a table, or
|
||||
// another root element
|
||||
if(rangeSize == 1)
|
||||
return;
|
||||
}
|
||||
else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV && el.type == eRootUAV &&
|
||||
type == D3D12_DESCRIPTOR_RANGE_TYPE_UAV && p.Descriptor.RegisterSpace == space &&
|
||||
p.Descriptor.ShaderRegister >= bind && p.Descriptor.ShaderRegister < bind + rangeSize)
|
||||
{
|
||||
AddResourceUsage(actionNode, el.id, eid, rw);
|
||||
|
||||
// common case - root element matches 1:1 with a non-array shader bind, if so we can exit. If
|
||||
// not we might have to continue since other parts of it might be mapped to a table, or
|
||||
// another root element
|
||||
if(rangeSize == 1)
|
||||
return;
|
||||
}
|
||||
else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && el.type == eRootTable)
|
||||
{
|
||||
WrappedID3D12DescriptorHeap *heap =
|
||||
m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12DescriptorHeap>(el.id);
|
||||
|
||||
if(heap == NULL)
|
||||
continue;
|
||||
|
||||
UINT prevTableOffset = 0;
|
||||
|
||||
for(size_t r = 0; r < p.ranges.size(); r++)
|
||||
{
|
||||
const D3D12_DESCRIPTOR_RANGE1 &range = p.ranges[r];
|
||||
|
||||
UINT offset = range.OffsetInDescriptorsFromTableStart;
|
||||
|
||||
if(range.OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
|
||||
offset = prevTableOffset;
|
||||
|
||||
D3D12Descriptor *desc = (D3D12Descriptor *)heap->GetCPUDescriptorHandleForHeapStart().ptr;
|
||||
desc += el.offset;
|
||||
desc += offset;
|
||||
|
||||
UINT num = range.NumDescriptors;
|
||||
|
||||
if(num == UINT_MAX)
|
||||
{
|
||||
// find out how many descriptors are left after
|
||||
num = heap->GetNumDescriptors() - offset - UINT(el.offset);
|
||||
}
|
||||
|
||||
prevTableOffset = offset + num;
|
||||
|
||||
// skip ranges that aren't the type or register space we want
|
||||
if(range.RangeType != type || range.RegisterSpace != space)
|
||||
continue;
|
||||
|
||||
// skip ranges that don't overlap with the registers we are looking for at all
|
||||
if(range.BaseShaderRegister + num <= bind || range.BaseShaderRegister >= bind + rangeSize)
|
||||
continue;
|
||||
|
||||
if(num > 1000)
|
||||
{
|
||||
if(!hugeRangeWarned)
|
||||
RDCWARN("Skipping large, most likely 'bindless', descriptor range");
|
||||
hugeRangeWarned = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
bool allInRange = (bind >= range.BaseShaderRegister && b.arraySize <= range.NumDescriptors);
|
||||
|
||||
// move to the first descriptor in the range which is in the binding we want
|
||||
desc += (bind - range.BaseShaderRegister);
|
||||
|
||||
if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV)
|
||||
{
|
||||
EventUsage usage(eid, cb);
|
||||
|
||||
for(UINT i = 0; i < num && i < rangeSize; i++)
|
||||
{
|
||||
ResourceId id = WrappedID3D12Resource::GetResIDFromAddr(desc->GetCBV().BufferLocation);
|
||||
|
||||
AddResourceUsage(actionNode, id, eid, cb);
|
||||
|
||||
desc++;
|
||||
}
|
||||
}
|
||||
else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV ||
|
||||
range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV)
|
||||
{
|
||||
ResourceUsage usage = range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV ? ro : rw;
|
||||
|
||||
for(UINT i = 0; i < num && i < rangeSize; i++)
|
||||
{
|
||||
AddResourceUsage(actionNode, desc->GetResResourceId(), eid, usage);
|
||||
|
||||
desc++;
|
||||
}
|
||||
}
|
||||
|
||||
// if this descriptor range fully covered the binding (which may be quite common) we can
|
||||
// return now, other ranges/root elements won't overlap so don't bother looking at them
|
||||
if(allInRange)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void D3D12CommandData::AddUsage(const D3D12RenderState &state, D3D12ActionTreeNode &actionNode)
|
||||
{
|
||||
ActionDescription &a = actionNode.action;
|
||||
|
||||
uint32_t e = a.eventId;
|
||||
uint32_t eid = a.eventId;
|
||||
|
||||
ActionFlags DrawMask = ActionFlags::Drawcall | ActionFlags::Dispatch;
|
||||
if(!(a.flags & DrawMask))
|
||||
return;
|
||||
|
||||
static bool hugeRangeWarned = false;
|
||||
D3D12ResourceManager *rm = m_pDevice->GetResourceManager();
|
||||
|
||||
const D3D12RenderState::RootSignature *rootdata = NULL;
|
||||
const D3D12RenderState::RootSignature *rootsig = NULL;
|
||||
|
||||
WrappedID3D12PipelineState *pipe = NULL;
|
||||
|
||||
if(state.pipe != ResourceId())
|
||||
pipe = rm->GetCurrentAs<WrappedID3D12PipelineState>(state.pipe);
|
||||
|
||||
const ShaderBindpointMapping *bindMap[6] = {};
|
||||
|
||||
if((a.flags & ActionFlags::Dispatch) && state.compute.rootsig != ResourceId())
|
||||
{
|
||||
rootdata = &state.compute;
|
||||
rootsig = &state.compute;
|
||||
|
||||
if(pipe && pipe->IsCompute())
|
||||
{
|
||||
WrappedID3D12Shader *sh = (WrappedID3D12Shader *)pipe->compute->CS.pShaderBytecode;
|
||||
|
||||
bindMap[uint32_t(ShaderStage::Compute)] = &sh->GetMapping();
|
||||
}
|
||||
}
|
||||
else if(state.graphics.rootsig != ResourceId())
|
||||
{
|
||||
rootdata = &state.graphics;
|
||||
rootsig = &state.graphics;
|
||||
|
||||
if(pipe && pipe->IsGraphics())
|
||||
{
|
||||
D3D12_SHADER_BYTECODE *srcArr[] = {&pipe->graphics->VS, &pipe->graphics->HS,
|
||||
&pipe->graphics->DS, &pipe->graphics->GS,
|
||||
&pipe->graphics->PS};
|
||||
for(size_t stage = 0; stage < 5; stage++)
|
||||
{
|
||||
WrappedID3D12Shader *sh = (WrappedID3D12Shader *)srcArr[stage]->pShaderBytecode;
|
||||
|
||||
if(sh)
|
||||
bindMap[stage] = &sh->GetMapping();
|
||||
}
|
||||
}
|
||||
|
||||
if(a.flags & ActionFlags::Indexed && state.ibuffer.buf != ResourceId())
|
||||
actionNode.resourceUsage.push_back(
|
||||
make_rdcpair(state.ibuffer.buf, EventUsage(e, ResourceUsage::IndexBuffer)));
|
||||
make_rdcpair(state.ibuffer.buf, EventUsage(eid, ResourceUsage::IndexBuffer)));
|
||||
|
||||
for(size_t i = 0; i < state.vbuffers.size(); i++)
|
||||
{
|
||||
if(state.vbuffers[i].buf != ResourceId())
|
||||
actionNode.resourceUsage.push_back(
|
||||
make_rdcpair(state.vbuffers[i].buf, EventUsage(e, ResourceUsage::VertexBuffer)));
|
||||
make_rdcpair(state.vbuffers[i].buf, EventUsage(eid, ResourceUsage::VertexBuffer)));
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < state.streamouts.size(); i++)
|
||||
{
|
||||
if(state.streamouts[i].buf != ResourceId())
|
||||
actionNode.resourceUsage.push_back(
|
||||
make_rdcpair(state.streamouts[i].buf, EventUsage(e, ResourceUsage::StreamOut)));
|
||||
make_rdcpair(state.streamouts[i].buf, EventUsage(eid, ResourceUsage::StreamOut)));
|
||||
if(state.streamouts[i].countbuf != ResourceId())
|
||||
actionNode.resourceUsage.push_back(
|
||||
make_rdcpair(state.streamouts[i].countbuf, EventUsage(e, ResourceUsage::StreamOut)));
|
||||
make_rdcpair(state.streamouts[i].countbuf, EventUsage(eid, ResourceUsage::StreamOut)));
|
||||
}
|
||||
|
||||
rdcarray<ResourceId> rts = state.GetRTVIDs();
|
||||
@@ -1753,138 +1957,48 @@ void D3D12CommandData::AddUsage(const D3D12RenderState &state, D3D12ActionTreeNo
|
||||
{
|
||||
if(rts[i] != ResourceId())
|
||||
actionNode.resourceUsage.push_back(
|
||||
make_rdcpair(rts[i], EventUsage(e, ResourceUsage::ColorTarget)));
|
||||
make_rdcpair(rts[i], EventUsage(eid, ResourceUsage::ColorTarget)));
|
||||
}
|
||||
|
||||
ResourceId id = state.GetDSVID();
|
||||
if(id != ResourceId())
|
||||
actionNode.resourceUsage.push_back(
|
||||
make_rdcpair(id, EventUsage(e, ResourceUsage::DepthStencilTarget)));
|
||||
make_rdcpair(id, EventUsage(eid, ResourceUsage::DepthStencilTarget)));
|
||||
}
|
||||
|
||||
if(rootdata)
|
||||
if(rootsig)
|
||||
{
|
||||
WrappedID3D12RootSignature *sig =
|
||||
m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12RootSignature>(rootdata->rootsig);
|
||||
|
||||
for(size_t rootEl = 0; rootEl < sig->sig.Parameters.size(); rootEl++)
|
||||
// iterate over each stage, looking at its used binds, then for each bind find it in the root
|
||||
// signature. We have to do this kind of N:N lookup because of D3D12's bad design, but this
|
||||
// should be a better way around to do it than iterating over the root signature and finding a
|
||||
// bind for each element
|
||||
for(size_t sh = 0; sh < ARRAY_COUNT(bindMap); sh++)
|
||||
{
|
||||
if(rootEl >= rootdata->sigelems.size())
|
||||
break;
|
||||
if(!bindMap[sh])
|
||||
continue;
|
||||
|
||||
const D3D12RootSignatureParameter &p = sig->sig.Parameters[rootEl];
|
||||
const D3D12RenderState::SignatureElement &el = rootdata->sigelems[rootEl];
|
||||
|
||||
ResourceUsage cb = ResourceUsage::CS_Constants;
|
||||
ResourceUsage ro = ResourceUsage::CS_Resource;
|
||||
ResourceUsage rw = ResourceUsage::CS_RWResource;
|
||||
|
||||
if(rootdata == &state.graphics)
|
||||
for(const Bindpoint &b : bindMap[sh]->constantBlocks)
|
||||
{
|
||||
if(p.ShaderVisibility == D3D12_SHADER_VISIBILITY_ALL)
|
||||
{
|
||||
cb = ResourceUsage::All_Constants;
|
||||
ro = ResourceUsage::All_Resource;
|
||||
rw = ResourceUsage::All_RWResource;
|
||||
}
|
||||
else
|
||||
{
|
||||
cb = CBUsage(p.ShaderVisibility - D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
ro = ResUsage(p.ShaderVisibility - D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
rw = RWResUsage(p.ShaderVisibility - D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
}
|
||||
}
|
||||
|
||||
if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV && el.type == eRootCBV)
|
||||
{
|
||||
AddUsage(actionNode, el.id, e, cb);
|
||||
}
|
||||
else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV && el.type == eRootSRV)
|
||||
{
|
||||
AddUsage(actionNode, el.id, e, ro);
|
||||
}
|
||||
else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV && el.type == eRootUAV)
|
||||
{
|
||||
AddUsage(actionNode, el.id, e, rw);
|
||||
}
|
||||
else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && el.type == eRootTable)
|
||||
{
|
||||
WrappedID3D12DescriptorHeap *heap =
|
||||
m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12DescriptorHeap>(el.id);
|
||||
|
||||
if(heap == NULL)
|
||||
if(!b.used)
|
||||
continue;
|
||||
|
||||
UINT prevTableOffset = 0;
|
||||
AddUsageForBindInRootSig(state, actionNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_CBV, b);
|
||||
}
|
||||
|
||||
for(size_t r = 0; r < p.ranges.size(); r++)
|
||||
{
|
||||
const D3D12_DESCRIPTOR_RANGE1 &range = p.ranges[r];
|
||||
for(const Bindpoint &b : bindMap[sh]->readOnlyResources)
|
||||
{
|
||||
if(!b.used)
|
||||
continue;
|
||||
|
||||
UINT offset = range.OffsetInDescriptorsFromTableStart;
|
||||
AddUsageForBindInRootSig(state, actionNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_SRV, b);
|
||||
}
|
||||
|
||||
if(range.OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
|
||||
offset = prevTableOffset;
|
||||
for(const Bindpoint &b : bindMap[sh]->readWriteResources)
|
||||
{
|
||||
if(!b.used)
|
||||
continue;
|
||||
|
||||
D3D12Descriptor *desc = (D3D12Descriptor *)heap->GetCPUDescriptorHandleForHeapStart().ptr;
|
||||
desc += el.offset;
|
||||
desc += offset;
|
||||
|
||||
UINT num = range.NumDescriptors;
|
||||
|
||||
if(num == UINT_MAX)
|
||||
{
|
||||
// find out how many descriptors are left after
|
||||
num = heap->GetNumDescriptors() - offset - UINT(el.offset);
|
||||
}
|
||||
|
||||
prevTableOffset = offset + num;
|
||||
|
||||
if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV)
|
||||
{
|
||||
EventUsage usage(e, cb);
|
||||
|
||||
if(num > 1000)
|
||||
{
|
||||
if(!hugeRangeWarned)
|
||||
RDCWARN("Skipping large, most likely 'bindless', descriptor range");
|
||||
hugeRangeWarned = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(UINT i = 0; i < num; i++)
|
||||
{
|
||||
ResourceId id =
|
||||
WrappedID3D12Resource::GetResIDFromAddr(desc->GetCBV().BufferLocation);
|
||||
|
||||
AddUsage(actionNode, id, e, cb);
|
||||
|
||||
desc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV ||
|
||||
range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV)
|
||||
{
|
||||
ResourceUsage usage = range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV ? ro : rw;
|
||||
|
||||
if(num > 1000)
|
||||
{
|
||||
if(!hugeRangeWarned)
|
||||
RDCWARN("Skipping large, most likely 'bindless', descriptor range");
|
||||
hugeRangeWarned = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(UINT i = 0; i < num; i++)
|
||||
{
|
||||
AddUsage(actionNode, desc->GetResResourceId(), e, usage);
|
||||
|
||||
desc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
AddUsageForBindInRootSig(state, actionNode, rootsig, D3D12_DESCRIPTOR_RANGE_TYPE_UAV, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,6 +386,12 @@ struct D3D12CommandData
|
||||
void AddAction(const ActionDescription &a);
|
||||
void AddEvent();
|
||||
void AddUsage(const D3D12RenderState &state, D3D12ActionTreeNode &actionNode);
|
||||
void AddUsage(D3D12ActionTreeNode &actionNode, ResourceId id, uint32_t EID, ResourceUsage usage);
|
||||
void AddUsage(ResourceId id, ResourceUsage usage);
|
||||
|
||||
void AddUsageForBindInRootSig(const D3D12RenderState &state, D3D12ActionTreeNode &actionNode,
|
||||
const D3D12RenderState::RootSignature *rootsig,
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE type, const Bindpoint &b);
|
||||
|
||||
void AddResourceUsage(D3D12ActionTreeNode &actionNode, ResourceId id, uint32_t EID,
|
||||
ResourceUsage usage);
|
||||
void AddCPUUsage(ResourceId id, ResourceUsage usage);
|
||||
};
|
||||
@@ -1808,7 +1808,7 @@ bool WrappedID3D12Device::Serialise_MapDataWrite(SerialiserType &ser, ID3D12Reso
|
||||
|
||||
if(IsLoading(m_State))
|
||||
{
|
||||
cmd.AddUsage(GetResID(Resource), ResourceUsage::CPUWrite);
|
||||
cmd.AddCPUUsage(GetResID(Resource), ResourceUsage::CPUWrite);
|
||||
|
||||
// when CPU uploading we just save the range (wouldn't be necessary if the range was
|
||||
// serialised before the blob)
|
||||
@@ -1981,7 +1981,7 @@ bool WrappedID3D12Device::Serialise_WriteToSubresource(SerialiserType &ser, ID3D
|
||||
D3D12CommandData &cmd = *m_Queue->GetCommandData();
|
||||
|
||||
if(IsLoading(m_State))
|
||||
cmd.AddUsage(GetResID(Resource), ResourceUsage::CPUWrite);
|
||||
cmd.AddCPUUsage(GetResID(Resource), ResourceUsage::CPUWrite);
|
||||
|
||||
ResourceId origid = GetResourceManager()->GetOriginalID(GetResID(Resource));
|
||||
if(m_UploadResourceIds.find(origid) != m_UploadResourceIds.end())
|
||||
|
||||
Reference in new issue
Block a user