aboutsummaryrefslogtreecommitdiff
path: root/demo/d3d12/NvCoDx12ResourceScopeManager.h
blob: 7bd71ffd7beb1a593f0c9054ce4c7a5baaced46d (plain) (blame)
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
/* 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. */

#ifndef NV_CO_DX12_RESOURCE_SCOPE_MANAGER_H
#define NV_CO_DX12_RESOURCE_SCOPE_MANAGER_H

#include "NvCoDx12Resource.h"
#include "NvCoDx12CounterFence.h"

// Dx12 types
#define NOMINMAX
#include <d3d12.h>

#include <deque>

/** \addtogroup common
@{
*/

namespace nvidia {
namespace Common { 

/*! \brief A class to manage the lifetime of resources that are transitory (as used only for a single specific piece of GPU work), 
but arbitrarily sized - such as textures. 

With Dx12 there is no management for the lifetime of resources within the Api directly. It is the duty of 
the application to make sure resources are released when they are no longer being referenced. The Dx12ResourceScopeManager
tries to simplify this management for some common use cases. Firstly when creating a GPU based resource and filling it 
with data, the data must first be copied to an upload buffer, and then to the target gpu based buffer. The upload buffer
is only needed whilst copying takes place. The method 'upload' will create a temporary upload buffer, and initiate the
copy into target. 

The upload resource will ONLY BE RELEASED when the fences value is greater than the current value. Assuming the command list 
is added to the queue, and the fence is added afterwards (which is the appropriate way), the resources will only be released 
after the fence has been hit AND when updateCompleted is called. 

The Dx12ResourceScopeManager is most useful for resource uploads that happen at startup, and might be very large. If you want to 
upload constrained sized (like constant buffer) resources quickly and efficiently at runtime you might be better using Dx12CircularResourceHeap.

The Dx12ResourceScopeManager uses the addSync/updateCompleted idiom, see details in Dx12CircularResourceHeap.

*/
class Dx12ResourceScopeManager
{
	//NV_CO_DECLARE_CLASS_BASE(Dx12ResourceScopeManager);
public:
		/// Initialize
	int init(ID3D12Device* device, Dx12CounterFence* fence);
	
		/// Allocate constant buffer of specified size
	ID3D12Resource* newUploadResource(const D3D12_RESOURCE_DESC& resourceDesc, const D3D12_CLEAR_VALUE* clearValue = nullptr);
		/// Do an upload on the specified command list
	int upload(ID3D12GraphicsCommandList* commandList, const void* srcDataIn, ID3D12Resource* target, D3D12_RESOURCE_STATES targetState);
		/// Upload data to the target, and set state. Will add barriers if target is in the wrong state
	int uploadWithState(ID3D12GraphicsCommandList* commandList, const void* srcDataIn, Dx12Resource& target, D3D12_RESOURCE_STATES targetState);

		/// Add a resource, which will be released when updateCompleted has a greater value
	void add(ID3D12Resource* resource);

		/// Look where the GPU has got to and release anything not currently used
	void updateCompleted();
		/// Add a sync point - meaning that when this point is hit in the queue
		/// all of the resources up to this point will no longer be used.
	void addSync(uint64_t signalValue);

		/// Get the device associated with this manager
	inline ID3D12Device* getDevice() const { return m_device; }

		/// Ctor
	Dx12ResourceScopeManager();
		/// Dtor
	~Dx12ResourceScopeManager();

		/// Copy from src to dst
	static void copy(const D3D12_SUBRESOURCE_DATA& src, size_t rowSizeInBytes, int numRows, int numSlices, const D3D12_MEMCPY_DEST& dst);

	protected:
	
	struct Entry
	{
		uint64_t m_completedValue;		///< If less than fence value this is completed
		ID3D12Resource* m_resource;		///< The mapped resource
	};
	
	std::deque<Entry> m_entryQueue;

	Dx12CounterFence* m_fence;			///< The fence to use
	ID3D12Device* m_device;				///< The device that resources will be constructed on
};

} // namespace Common
} // namespace nvidia

/** @} */

#endif // NV_CO_DX12_RESOURCE_SCOPE_MANAGER_H