File size: 5,402 Bytes
0c51b93 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
/* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
* NVIDIA CORPORATION and its licensors retain all intellectual property
* and proprietary rights in and to this software, related documentation
* and any modifications thereto. Any use, reproduction, disclosure or
* distribution of this software and related documentation without an express
* license agreement from NVIDIA CORPORATION is strictly prohibited. */
#include "NvCoDx12ResourceScopeManager.h"
#include <assert.h>
namespace nvidia {
namespace Common {
Dx12ResourceScopeManager::Dx12ResourceScopeManager():
m_fence(nullptr),
m_device(nullptr)
{
}
Dx12ResourceScopeManager::~Dx12ResourceScopeManager()
{
while (!m_entryQueue.empty())
{
Entry& entry = m_entryQueue.front();
entry.m_resource->Release();
m_entryQueue.pop_front();
}
}
int Dx12ResourceScopeManager::init(ID3D12Device* device, Dx12CounterFence* fence)
{
m_fence = fence;
m_device = device;
return NV_OK;
}
void Dx12ResourceScopeManager::addSync(uint64_t signalValue)
{
(void)signalValue;
assert(m_fence->getCurrentValue() == signalValue);
}
void Dx12ResourceScopeManager::updateCompleted()
{
const uint64_t completedValue = m_fence->getCompletedValue();
if (!m_entryQueue.empty())
{
const Entry& entry = m_entryQueue.front();
if (entry.m_completedValue >= completedValue)
{
return;
}
entry.m_resource->Release();
m_entryQueue.pop_front();
}
}
ID3D12Resource* Dx12ResourceScopeManager::newUploadResource(const D3D12_RESOURCE_DESC& resourceDesc, const D3D12_CLEAR_VALUE* clearValue)
{
D3D12_HEAP_PROPERTIES heapProps;
{
heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapProps.CreationNodeMask = 1;
heapProps.VisibleNodeMask = 1;
}
const D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE;
const D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
ComPtr<ID3D12Resource> resource;
int res = m_device->CreateCommittedResource(&heapProps, heapFlags, &resourceDesc, initialState, clearValue, IID_PPV_ARGS(&resource));
if (NV_FAILED(res)) return nullptr;
// Get the current fence count
const uint64_t completedValue = m_fence->getCurrentValue();
Entry entry;
entry.m_completedValue = completedValue;
entry.m_resource = resource.Detach();
m_entryQueue.push_back(entry);
return entry.m_resource;
}
/* static */void Dx12ResourceScopeManager::copy(const D3D12_SUBRESOURCE_DATA& src, size_t rowSizeInBytes, int numRows, int numSlices, const D3D12_MEMCPY_DEST& dst)
{
for (int i = 0; i < numSlices; ++i)
{
uint8_t* dstSlice = reinterpret_cast<uint8_t*>(dst.pData) + dst.SlicePitch * i;
const uint8_t* srcSlice = reinterpret_cast<const uint8_t*>(src.pData) + src.SlicePitch * i;
for (int j = 0; j < numRows; ++j)
{
memcpy(dstSlice + dst.RowPitch * j, srcSlice + src.RowPitch * j, rowSizeInBytes);
}
}
}
int Dx12ResourceScopeManager::upload(ID3D12GraphicsCommandList* commandList, const void* srcDataIn, ID3D12Resource* targetResource, D3D12_RESOURCE_STATES targetState)
{
// Get the targetDesc
const D3D12_RESOURCE_DESC targetDesc = targetResource->GetDesc();
// Ensure it is just a regular buffer
assert(targetDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER);
assert(targetDesc.Layout == D3D12_TEXTURE_LAYOUT_ROW_MAJOR);
// The buffer size is the width
const size_t bufferSize = size_t(targetDesc.Width);
D3D12_RESOURCE_DESC uploadDesc = targetDesc;
uploadDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
// Create the upload resource
ID3D12Resource* uploadResource = newUploadResource(uploadDesc);
// Map it and copy
{
uint8_t* uploadMapped;
NV_RETURN_ON_FAIL(uploadResource->Map(0, nullptr, (void**)&uploadMapped));
memcpy(uploadMapped, srcDataIn, bufferSize);
uploadResource->Unmap(0, nullptr);
}
// Add the copy
commandList->CopyBufferRegion(targetResource, 0, uploadResource, 0, bufferSize);
// Add the barrier
{
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
D3D12_RESOURCE_TRANSITION_BARRIER& transition = barrier.Transition;
transition.pResource = targetResource;
transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
transition.StateAfter = targetState;
transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
commandList->ResourceBarrier(1, &barrier);
}
return NV_OK;
}
void Dx12ResourceScopeManager::add(ID3D12Resource* resource)
{
assert(resource);
// Get the current fence count
const uint64_t completedValue = m_fence->getCurrentValue();
Entry entry;
entry.m_completedValue = completedValue;
resource->AddRef();
entry.m_resource = resource;
m_entryQueue.push_back(entry);
}
int Dx12ResourceScopeManager::uploadWithState(ID3D12GraphicsCommandList* commandList, const void* srcDataIn, Dx12Resource& target, D3D12_RESOURCE_STATES targetState)
{
// make sure we are in the correct initial state
if (target.getState() != D3D12_RESOURCE_STATE_COPY_DEST)
{
Dx12BarrierSubmitter submitter(commandList);
target.transition(D3D12_RESOURCE_STATE_COPY_DEST, submitter);
}
// Do the upload
NV_RETURN_ON_FAIL(upload(commandList, srcDataIn, target.getResource(), targetState));
target.setState(targetState);
return NV_OK;
}
} // namespace Common
} // namespace nvidia
|