blob: 9add39b25151d69ade6d8566ec020da9633cd628 (
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
|
/* 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_COUNTER_FENCE_H
#define NV_CO_DX12_COUNTER_FENCE_H
#include <NvResult.h>
#define NOMINMAX
#include <d3d12.h>
#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include <wrl.h>
using namespace Microsoft::WRL;
/** \addtogroup common
@{
*/
namespace nvidia {
namespace Common {
/*! \brief A class to simplify using Dx12 fences.
A fence is a mechanism to track GPU work. This is achieved by having a counter that the CPU holds
called the current value. Calling nextSignal will increase the CPU counter, and add a fence
with that value to the commandQueue. When the GPU has completed all the work before the fence it will
update the completed value. This is typically used when
the CPU needs to know the GPU has finished some piece of work has completed. To do this the CPU
can check the completed value, and when it is greater or equal to the value returned by nextSignal the
CPU will know that all the work prior to when the nextSignal was added to the queue will have completed.
NOTE! This cannot be used across threads, as for amongst other reasons SetEventOnCompletion
only works with a single value.
Signal on the CommandQueue updates the fence on the GPU side. Signal on the fence object changes
the value on the CPU side (not used here).
Useful article describing how Dx12 synchronization works:
https://msdn.microsoft.com/en-us/library/windows/desktop/dn899217%28v=vs.85%29.aspx
*/
class Dx12CounterFence
{
//NV_CO_DECLARE_CLASS_BASE(Dx12CounterFence);
public:
/// Must be called before used
int init(ID3D12Device* device, uint64_t initialValue = 0);
/// Increases the counter, signals the queue and waits for the signal to be hit
void nextSignalAndWait(ID3D12CommandQueue* queue);
/// Signals with next counter value. Returns the value the signal was called on
uint64_t nextSignal(ID3D12CommandQueue* commandQueue);
/// Get the current value
inline uint64_t getCurrentValue() const { return m_currentValue; }
/// Get the completed value
inline uint64_t getCompletedValue() const { return m_fence->GetCompletedValue(); }
/// Waits for the the specified value
void waitUntilCompleted(uint64_t completedValue);
/// Ctor
Dx12CounterFence():m_event(nullptr), m_currentValue(0) {}
/// Dtor
~Dx12CounterFence();
protected:
HANDLE m_event;
ComPtr<ID3D12Fence> m_fence;
uint64_t m_currentValue;
};
} // namespace Common
} // namespace nvidia
/** @} */
#endif // NV_CO_DX12_COUNTER_FENCE_H
|