summaryrefslogtreecommitdiff
path: root/tools/render-test/resource-d3d12.h
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2018-04-02 19:59:33 -0400
committerTim Foley <tfoleyNV@users.noreply.github.com>2018-04-02 16:59:33 -0700
commit38d5ef4764e9271ce2360f42b0759a236cddd9fe (patch)
tree6c8eafb72eb997167dd77e3d1d5abc3582c5789a /tools/render-test/resource-d3d12.h
parent5a0273848aa4b854bb3c99a81701b044a8929bf8 (diff)
Feature/dx12 (#469)
* Fix signed/unsigned comparison warning. * Split out d3d functions that will work across dx11 and 12. * Improve slang-test/README.md around command line options. * Make Guid comparison honor alignment for comparisons, such that mechanism work on architectures that can only do aligned accesses. * Initial setup of D3D12 Renderer, with presentFrame and clearFrame. * More support for D3D12 * Added FreeList * Added D3D12CircularResourceHeap * First attempt at createBuffer * First pass at map/unmap. * First pass binding vertex/constant buffers, and setting up InputLayout. Note that memory is not kept in scope on binding yet. * First pass of D3DDescriptorHeap * Small tidy up in render-d3d11. Added D3DDescriptorHeap to project. * First pass at D3D12 bind state. * Fix typos in D3D12Resource * Tidy up Dx11 render binding a little to match more with Dx12 style. * First pass at Dx12 BindingState * Handling of the command list d3d12. Support for submitGpuWork and waitForGpu. * First attempt at Dx12 capture of backbuffer to file. * First attempt at D3D12 binding for graphics. * D3D12 setup viewport etc - does now render triangle in render0.hlsl. * First pass at support for compute on D3D12Renderer * Use spaces over tabs in D3DUtil * Tabs to spaces in D3D12DescriptorHeap * Convert tab->spaces on render-d3d12.cpp
Diffstat (limited to 'tools/render-test/resource-d3d12.h')
-rw-r--r--tools/render-test/resource-d3d12.h178
1 files changed, 178 insertions, 0 deletions
diff --git a/tools/render-test/resource-d3d12.h b/tools/render-test/resource-d3d12.h
new file mode 100644
index 000000000..a6537a7d7
--- /dev/null
+++ b/tools/render-test/resource-d3d12.h
@@ -0,0 +1,178 @@
+// resource-d3d12.h
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+#include <Windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#undef NOMINMAX
+
+#include <dxgi1_4.h>
+#include <d3d12.h>
+
+#include "../../source/core/slang-com-ptr.h"
+#include "d3d-util.h"
+
+namespace renderer_test {
+
+// Enables more conservative barriers - restoring the state of resources after they are used.
+// Should not need to be enabled in normal builds, as the barriers should correctly sync resources
+// If enabling fixes an issue it implies regular barriers are not correctly used.
+#define SLANG_ENABLE_CONSERVATIVE_RESOURCE_BARRIERS 0
+
+struct D3D12BarrierSubmitter
+{
+ enum { MAX_BARRIERS = 8 };
+
+ /// Expand one space to hold a barrier
+ SLANG_FORCE_INLINE D3D12_RESOURCE_BARRIER& expandOne() { return (m_numBarriers < MAX_BARRIERS) ? m_barriers[m_numBarriers++] : _expandOne(); }
+ /// Flush barriers to command list
+ SLANG_FORCE_INLINE void flush() { if (m_numBarriers > 0) _flush(); }
+
+ /// Transition resource from prevState to nextState
+ void transition(ID3D12Resource* resource, D3D12_RESOURCE_STATES prevState, D3D12_RESOURCE_STATES nextState);
+
+ /// Ctor
+ SLANG_FORCE_INLINE D3D12BarrierSubmitter(ID3D12GraphicsCommandList* commandList) : m_numBarriers(0), m_commandList(commandList) { }
+ /// Dtor
+ SLANG_FORCE_INLINE ~D3D12BarrierSubmitter() { flush(); }
+
+protected:
+ D3D12_RESOURCE_BARRIER& _expandOne();
+ void _flush();
+
+ ID3D12GraphicsCommandList* m_commandList;
+ int m_numBarriers;
+ D3D12_RESOURCE_BARRIER m_barriers[MAX_BARRIERS];
+};
+
+/*! \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 D3D12CounterFence
+{
+public:
+ /// Must be called before used
+ SlangResult 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
+ SLANG_FORCE_INLINE uint64_t getCurrentValue() const { return m_currentValue; }
+ /// Get the completed value
+ SLANG_FORCE_INLINE uint64_t getCompletedValue() const { return m_fence->GetCompletedValue(); }
+
+ /// Waits for the the specified value
+ void waitUntilCompleted(uint64_t completedValue);
+
+ /// Ctor
+ D3D12CounterFence() :m_event(nullptr), m_currentValue(0) {}
+ /// Dtor
+ ~D3D12CounterFence();
+
+protected:
+ HANDLE m_event;
+ Slang::ComPtr<ID3D12Fence> m_fence;
+ UINT64 m_currentValue;
+};
+
+/** The base class for resource types allows for tracking of state. It does not allow for setting of the resource though, such that
+an interface can return a D3D12ResourceBase, and a client cant manipulate it's state, but it cannot replace/change the actual resource */
+struct D3D12ResourceBase
+{
+ /// Add a transition if necessary to the list
+ void transition(D3D12_RESOURCE_STATES nextState, D3D12BarrierSubmitter& submitter);
+ /// Get the current state
+ SLANG_FORCE_INLINE D3D12_RESOURCE_STATES getState() const { return m_state; }
+
+ /// Get the associated resource
+ SLANG_FORCE_INLINE ID3D12Resource* getResource() const { return m_resource; }
+
+ /// True if a resource is set
+ SLANG_FORCE_INLINE bool isSet() const { return m_resource != nullptr; }
+
+ /// Coercable into ID3D12Resource
+ SLANG_FORCE_INLINE operator ID3D12Resource*() const { return m_resource; }
+
+ /// restore previous state
+#if SLANG_ENABLE_CONSERVATIVE_RESOURCE_BARRIERS
+ NV_FORCE_INLINE Void restore(Dx12BarrierSubmitter& submitter) { transition(m_prevState, submitter); }
+#else
+ SLANG_FORCE_INLINE void restore(D3D12BarrierSubmitter& submitter) { SLANG_UNUSED(submitter) }
+#endif
+
+ /// Given the usage, flags, and format will return the most suitable format. Will return DXGI_UNKNOWN if combination is not possible
+ static DXGI_FORMAT calcFormat(D3DUtil::UsageType usage, ID3D12Resource* resource);
+
+ /// Ctor
+ SLANG_FORCE_INLINE D3D12ResourceBase() :
+ m_state(D3D12_RESOURCE_STATE_COMMON),
+ m_prevState(D3D12_RESOURCE_STATE_COMMON),
+ m_resource(nullptr)
+ {}
+
+protected:
+ /// This is protected so as clients cannot slice the class, and so state tracking is lost
+ ~D3D12ResourceBase() {}
+
+ ID3D12Resource* m_resource;
+ D3D12_RESOURCE_STATES m_state;
+ D3D12_RESOURCE_STATES m_prevState;
+};
+
+struct D3D12Resource : public D3D12ResourceBase
+{
+
+ /// Dtor
+ ~D3D12Resource()
+ {
+ if (m_resource)
+ {
+ m_resource->Release();
+ }
+ }
+
+ /// Initialize as committed resource
+ Slang::Result initCommitted(ID3D12Device* device, const D3D12_HEAP_PROPERTIES& heapProps, D3D12_HEAP_FLAGS heapFlags, const D3D12_RESOURCE_DESC& resourceDesc, D3D12_RESOURCE_STATES initState, const D3D12_CLEAR_VALUE * clearValue);
+
+ /// Set a resource with an initial state
+ void setResource(ID3D12Resource* resource, D3D12_RESOURCE_STATES initialState);
+ /// Make the resource null
+ void setResourceNull();
+ /// Returns the attached resource (with any ref counts) and sets to nullptr on this.
+ ID3D12Resource* detach();
+
+ /// Swaps the resource contents with the contents of the smart pointer
+ void swap(Slang::ComPtr<ID3D12Resource>& resourceInOut);
+
+ /// Sets the current state of the resource (the current state is taken to be the future state once the command list has executed)
+ /// NOTE! This must be used with care, otherwise state tracking can be made incorrect.
+ void setState(D3D12_RESOURCE_STATES state);
+
+ /// Set the debug name on a resource
+ static void setDebugName(ID3D12Resource* resource, const char* name);
+
+ /// Set the the debug name on the resource
+ void setDebugName(const wchar_t* name);
+ /// Set the debug name
+ void setDebugName(const char* name);
+};
+
+} // renderer_test