From 38d5ef4764e9271ce2360f42b0759a236cddd9fe Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Mon, 2 Apr 2018 19:59:33 -0400 Subject: 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 --- tools/render-test/resource-d3d12.cpp | 214 +++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 tools/render-test/resource-d3d12.cpp (limited to 'tools/render-test/resource-d3d12.cpp') diff --git a/tools/render-test/resource-d3d12.cpp b/tools/render-test/resource-d3d12.cpp new file mode 100644 index 000000000..160c7f898 --- /dev/null +++ b/tools/render-test/resource-d3d12.cpp @@ -0,0 +1,214 @@ +// resource-d3d12.cpp +#include "resource-d3d12.h" + +namespace renderer_test { +using namespace Slang; + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! D3D12BarrierSubmitter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +void D3D12BarrierSubmitter::_flush() +{ + assert(m_numBarriers > 0); + + if (m_commandList) + { + m_commandList->ResourceBarrier(UINT(m_numBarriers), m_barriers); + } + m_numBarriers = 0; +} + +D3D12_RESOURCE_BARRIER& D3D12BarrierSubmitter::_expandOne() +{ + _flush(); + return m_barriers[m_numBarriers++]; +} + +void D3D12BarrierSubmitter::transition(ID3D12Resource* resource, D3D12_RESOURCE_STATES prevState, D3D12_RESOURCE_STATES nextState) +{ + if (nextState != prevState) + { + D3D12_RESOURCE_BARRIER& barrier = expandOne(); + + const UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + const D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + + ::memset(&barrier, 0, sizeof(barrier)); + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Flags = flags; + barrier.Transition.pResource = resource; + barrier.Transition.StateBefore = prevState; + barrier.Transition.StateAfter = nextState; + barrier.Transition.Subresource = subresource; + } + else + { + if (nextState == D3D12_RESOURCE_STATE_UNORDERED_ACCESS) + { + D3D12_RESOURCE_BARRIER& barrier = expandOne(); + + ::memset(&barrier, 0, sizeof(barrier)); + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barrier.UAV.pResource = resource; + } + } +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! D3D12ResourceBase !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +/* static */DXGI_FORMAT D3D12ResourceBase::calcFormat(D3DUtil::UsageType usage, ID3D12Resource* resource) +{ + return resource ? D3DUtil::calcFormat(usage, resource->GetDesc().Format) : DXGI_FORMAT_UNKNOWN; +} + +void D3D12ResourceBase::transition(D3D12_RESOURCE_STATES nextState, D3D12BarrierSubmitter& submitter) +{ + // Transition only if there is a resource + if (m_resource) + { + submitter.transition(m_resource, m_state, nextState); + m_state = nextState; + } +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! D3D12CounterFence !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +D3D12CounterFence::~D3D12CounterFence() +{ + if (m_event) + { + CloseHandle(m_event); + } +} + +Result D3D12CounterFence::init(ID3D12Device* device, uint64_t initialValue) +{ + m_currentValue = initialValue; + + SLANG_RETURN_ON_FAIL(device->CreateFence(m_currentValue, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(m_fence.writeRef()))); + // Create an event handle to use for frame synchronization. + m_event = ::CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (m_event == nullptr) + { + Result res = HRESULT_FROM_WIN32(GetLastError()); + return SLANG_FAILED(res) ? res : SLANG_FAIL; + } + return SLANG_OK; +} + +UInt64 D3D12CounterFence::nextSignal(ID3D12CommandQueue* commandQueue) +{ + // Increment the fence value. Save on the frame - we'll know that frame is done when the fence value >= + m_currentValue++; + // Schedule a Signal command in the queue. + Result res = commandQueue->Signal(m_fence, m_currentValue); + if (SLANG_FAILED(res)) + { + assert(!"Signal failed"); + } + return m_currentValue; +} + +void D3D12CounterFence::waitUntilCompleted(uint64_t completedValue) +{ + // You can only wait for a value that is less than or equal to the current value + assert(completedValue <= m_currentValue); + + // Wait until the previous frame is finished. + while (m_fence->GetCompletedValue() < completedValue) + { + // Make it signal with the current value + SLANG_ASSERT_VOID_ON_FAIL(m_fence->SetEventOnCompletion(completedValue, m_event)); + WaitForSingleObject(m_event, INFINITE); + } +} + +void D3D12CounterFence::nextSignalAndWait(ID3D12CommandQueue* commandQueue) +{ + waitUntilCompleted(nextSignal(commandQueue)); +} + +/* !!!!!!!!!!!!!!!!!!!!!!!!! D3D12Resource !!!!!!!!!!!!!!!!!!!!!!!! */ + +/* static */void D3D12Resource::setDebugName(ID3D12Resource* resource, const char* name) +{ + if (resource) + { + size_t len = ::strlen(name); + List buf; + buf.SetSize(len + 1); + + D3DUtil::appendWideChars(name, buf); + resource->SetName(buf.begin()); + } +} + +void D3D12Resource::setDebugName(const char* name) +{ + setDebugName(m_resource, name); +} + +void D3D12Resource::setDebugName(const wchar_t* name) +{ + if (m_resource) + { + m_resource->SetName(name); + } +} + +void D3D12Resource::setResource(ID3D12Resource* resource, D3D12_RESOURCE_STATES initialState) +{ + if (resource != m_resource) + { + if (resource) + { + resource->AddRef(); + } + if (m_resource) + { + m_resource->Release(); + } + m_resource = resource; + } + m_prevState = initialState; + m_state = initialState; +} + +void D3D12Resource::setResourceNull() +{ + if (m_resource) + { + m_resource->Release(); + m_resource = nullptr; + } +} + +Result D3D12Resource::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) +{ + setResourceNull(); + ComPtr resource; + SLANG_RETURN_ON_FAIL(device->CreateCommittedResource(&heapProps, heapFlags, &resourceDesc, initState, clearValue, IID_PPV_ARGS(resource.writeRef()))); + setResource(resource, initState); + return SLANG_OK; +} + +ID3D12Resource* D3D12Resource::detach() +{ + ID3D12Resource* resource = m_resource; + m_resource = nullptr; + return resource; +} + +void D3D12Resource::swap(ComPtr& resourceInOut) +{ + ID3D12Resource* tmp = m_resource; + m_resource = resourceInOut.detach(); + resourceInOut.attach(tmp); +} + +void D3D12Resource::setState(D3D12_RESOURCE_STATES state) +{ + m_prevState = state; + m_state = state; +} + +} // renderer_test -- cgit v1.2.3