893 lines
34 KiB
C++
893 lines
34 KiB
C++
#include "D3D12RHI.h"
|
|
#include "D3D12Resources.h"
|
|
#include <RHI\RHIDefines.h>
|
|
#include <Rendering\Resources.h>
|
|
#include <string>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
void EngineLog(const char* msg, ...) {
|
|
char buffer[1024];
|
|
va_list args;
|
|
va_start(args, msg);
|
|
vsnprintf(buffer, sizeof(buffer), msg, args);
|
|
va_end(args);
|
|
|
|
FILE* f = nullptr;
|
|
fopen_s(&f, "D:\\xcengine_debug.log", "a");
|
|
if (f) { fprintf(f, "%s\n", buffer); fclose(f); }
|
|
|
|
printf("%s\n", buffer);
|
|
OutputDebugStringA(buffer);
|
|
OutputDebugStringA("\n");
|
|
}
|
|
|
|
namespace XCEngine {
|
|
namespace RHI {
|
|
|
|
D3D12Device::D3D12Device() {
|
|
}
|
|
|
|
D3D12Device::~D3D12Device() {
|
|
Shutdown();
|
|
}
|
|
|
|
bool D3D12Device::CreateDXGIDevice(void* windowHandle) {
|
|
|
|
UINT dxgiFactoryFlags = 0;
|
|
#ifdef _DEBUG
|
|
ID3D12Debug* debugController = nullptr;
|
|
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
|
|
debugController->EnableDebugLayer();
|
|
dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
|
|
}
|
|
#endif
|
|
|
|
HRESULT hr = CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&m_dxgiFactory));
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
Microsoft::WRL::ComPtr<IDXGIAdapter1> adapter;
|
|
int adapterIndex = 0;
|
|
bool adapterFound = false;
|
|
|
|
while (m_dxgiFactory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND) {
|
|
DXGI_ADAPTER_DESC1 desc;
|
|
adapter->GetDesc1(&desc);
|
|
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
|
|
adapterIndex++;
|
|
continue;
|
|
}
|
|
|
|
hr = D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), nullptr);
|
|
if (SUCCEEDED(hr)) {
|
|
adapterFound = true;
|
|
break;
|
|
}
|
|
adapterIndex++;
|
|
}
|
|
|
|
if (!adapterFound) {
|
|
return false;
|
|
}
|
|
|
|
m_adapter = adapter;
|
|
|
|
hr = D3D12CreateDevice(m_adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool D3D12Device::Initialize(void* windowHandle, uint32_t width, uint32_t height) {
|
|
if (!CreateDXGIDevice(windowHandle)) {
|
|
return false;
|
|
}
|
|
|
|
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
|
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
|
queueDesc.Priority = 0;
|
|
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
|
|
|
Microsoft::WRL::ComPtr<ID3D12CommandQueue> commandQueue;
|
|
HRESULT hr = m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue));
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
m_commandQueue = new D3D12CommandQueue(this, commandQueue.Get());
|
|
|
|
SwapChainDesc swapChainDesc = {};
|
|
swapChainDesc.width = width;
|
|
swapChainDesc.height = height;
|
|
swapChainDesc.format = Format::R8G8B8A8_UNorm;
|
|
swapChainDesc.bufferCount = 2;
|
|
swapChainDesc.vsync = false;
|
|
swapChainDesc.fullscreen = false;
|
|
|
|
ISwapChain* swapChain = nullptr;
|
|
if (!CreateSwapChain(&swapChain, swapChainDesc, windowHandle)) {
|
|
return false;
|
|
}
|
|
m_swapChain = static_cast<D3D12SwapChain*>(swapChain);
|
|
|
|
return true;
|
|
}
|
|
|
|
void D3D12Device::Shutdown() {
|
|
if (m_commandQueue) {
|
|
delete m_commandQueue;
|
|
m_commandQueue = nullptr;
|
|
}
|
|
if (m_swapChain) {
|
|
delete m_swapChain;
|
|
m_swapChain = nullptr;
|
|
}
|
|
}
|
|
|
|
bool D3D12Device::CreateCommandQueue(ICommandQueue** queue, const CommandQueueDesc& desc) {
|
|
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
|
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
|
queueDesc.Priority = desc.priority;
|
|
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
|
|
|
Microsoft::WRL::ComPtr<ID3D12CommandQueue> commandQueue;
|
|
HRESULT hr = m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&commandQueue));
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
*queue = new D3D12CommandQueue(this, commandQueue.Get());
|
|
return true;
|
|
}
|
|
|
|
bool D3D12Device::CreateCommandAllocator(ICommandAllocator** allocator) {
|
|
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> commandAllocator;
|
|
HRESULT hr = m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&commandAllocator));
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
*allocator = new D3D12CommandAllocator(this, commandAllocator.Get());
|
|
return true;
|
|
}
|
|
|
|
bool D3D12Device::CreateCommandList(ICommandList** list, ICommandAllocator* allocator) {
|
|
D3D12CommandAllocator* d3d12Allocator = static_cast<D3D12CommandAllocator*>(allocator);
|
|
|
|
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> commandList;
|
|
HRESULT hr = m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
|
|
d3d12Allocator->GetNativeAllocator(), nullptr, IID_PPV_ARGS(&commandList));
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
*list = new D3D12CommandList(this, commandList.Get());
|
|
return true;
|
|
}
|
|
|
|
bool D3D12Device::CreateFence(IFence** fence) {
|
|
Microsoft::WRL::ComPtr<ID3D12Fence> d3dFence;
|
|
HRESULT hr = m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&d3dFence));
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
*fence = new D3D12Fence(this, d3dFence.Get());
|
|
return true;
|
|
}
|
|
|
|
bool D3D12Device::CreateDescriptorHeap(IDescriptorHeap** heap, const DescriptorHeapDesc& desc) {
|
|
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
|
|
heapDesc.NumDescriptors = desc.count;
|
|
heapDesc.Flags = desc.shaderVisible ? D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE : D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
|
|
|
switch (desc.type) {
|
|
case DescriptorHeapType::CBV_SRV_UAV:
|
|
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
|
break;
|
|
case DescriptorHeapType::Sampler:
|
|
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
|
break;
|
|
case DescriptorHeapType::RTV:
|
|
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
|
break;
|
|
case DescriptorHeapType::DSV:
|
|
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
|
|
break;
|
|
}
|
|
|
|
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> descriptorHeap;
|
|
HRESULT hr = m_device->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&descriptorHeap));
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
*heap = new D3D12DescriptorHeap(this, descriptorHeap.Get(), desc.type);
|
|
return true;
|
|
}
|
|
|
|
bool D3D12Device::CreateRootSignature(IRootSignature** signature, const RootSignatureDesc& desc) {
|
|
*signature = new D3D12RootSignature(this);
|
|
return (*signature)->Initialize(desc);
|
|
}
|
|
|
|
bool D3D12Device::CreatePipelineState(IPipelineState** pso, const PipelineDesc& desc) {
|
|
*pso = new D3D12PipelineState(this);
|
|
return static_cast<D3D12PipelineState*>(*pso)->Initialize(desc);
|
|
}
|
|
|
|
bool D3D12Device::CreateSwapChain(ISwapChain** swapChain, const SwapChainDesc& desc, void* windowHandle) {
|
|
*swapChain = new D3D12SwapChain(this);
|
|
bool result = (*swapChain)->Initialize(desc, windowHandle);
|
|
return result;
|
|
}
|
|
|
|
D3D12CommandQueue::D3D12CommandQueue(D3D12Device* device, ID3D12CommandQueue* queue)
|
|
: m_device(device), m_commandQueue(queue) {
|
|
}
|
|
|
|
D3D12CommandQueue::~D3D12CommandQueue() {
|
|
}
|
|
|
|
void D3D12CommandQueue::ExecuteCommandLists(void** lists, uint32_t count) {
|
|
ID3D12CommandList** d3dLists = reinterpret_cast<ID3D12CommandList**>(lists);
|
|
m_commandQueue->ExecuteCommandLists(count, d3dLists);
|
|
}
|
|
|
|
void D3D12CommandQueue::Signal(void* fence, uint64_t value) {
|
|
ID3D12Fence* d3dFence = static_cast<ID3D12Fence*>(fence);
|
|
m_commandQueue->Signal(d3dFence, value);
|
|
}
|
|
|
|
void D3D12CommandQueue::Wait(void* fence, uint64_t value) {
|
|
ID3D12Fence* d3dFence = static_cast<ID3D12Fence*>(fence);
|
|
m_commandQueue->Wait(d3dFence, value);
|
|
}
|
|
|
|
uint64_t D3D12CommandQueue::GetTimestampFrequency() const {
|
|
uint64_t frequency = 0;
|
|
m_commandQueue->GetTimestampFrequency(&frequency);
|
|
return frequency;
|
|
}
|
|
|
|
D3D12CommandAllocator::D3D12CommandAllocator(D3D12Device* device, ID3D12CommandAllocator* allocator)
|
|
: m_device(device), m_commandAllocator(allocator) {
|
|
}
|
|
|
|
D3D12CommandAllocator::~D3D12CommandAllocator() {
|
|
}
|
|
|
|
void D3D12CommandAllocator::Reset() {
|
|
m_commandAllocator->Reset();
|
|
}
|
|
|
|
D3D12Fence::D3D12Fence(D3D12Device* device, ID3D12Fence* fence)
|
|
: m_device(device), m_fence(fence) {
|
|
m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
|
}
|
|
|
|
D3D12Fence::~D3D12Fence() {
|
|
if (m_fenceEvent) {
|
|
CloseHandle(m_fenceEvent);
|
|
m_fenceEvent = nullptr;
|
|
}
|
|
}
|
|
|
|
uint64_t D3D12Fence::GetCompletedValue() const {
|
|
return m_fence->GetCompletedValue();
|
|
}
|
|
|
|
void D3D12Fence::Signal(uint64_t value) {
|
|
m_fence->Signal(value);
|
|
}
|
|
|
|
void D3D12Fence::Wait(uint64_t value) {
|
|
if (m_fence->GetCompletedValue() < value) {
|
|
m_fence->SetEventOnCompletion(value, m_fenceEvent);
|
|
WaitForSingleObject(m_fenceEvent, INFINITE);
|
|
}
|
|
}
|
|
|
|
void D3D12Fence::Wait(uint64_t value, uint64_t timeoutMs) {
|
|
if (m_fence->GetCompletedValue() < value) {
|
|
m_fence->SetEventOnCompletion(value, m_fenceEvent);
|
|
WaitForSingleObject(m_fenceEvent, (DWORD)timeoutMs);
|
|
}
|
|
}
|
|
|
|
D3D12DescriptorHeap::D3D12DescriptorHeap(D3D12Device* device, ID3D12DescriptorHeap* heap, DescriptorHeapType type)
|
|
: m_device(device), m_descriptorHeap(heap), m_type(type) {
|
|
m_descriptorCount = heap->GetDesc().NumDescriptors;
|
|
m_descriptorSize = device->GetD3D12Device()->GetDescriptorHandleIncrementSize(
|
|
type == DescriptorHeapType::CBV_SRV_UAV ? D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV :
|
|
type == DescriptorHeapType::Sampler ? D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER :
|
|
type == DescriptorHeapType::RTV ? D3D12_DESCRIPTOR_HEAP_TYPE_RTV : D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
|
|
}
|
|
|
|
D3D12DescriptorHeap::~D3D12DescriptorHeap() {
|
|
}
|
|
|
|
void* D3D12DescriptorHeap::GetCPUDescriptorHandle(uint32_t index) const {
|
|
D3D12_CPU_DESCRIPTOR_HANDLE handle = m_descriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
|
handle.ptr += index * m_descriptorSize;
|
|
return (void*)handle.ptr;
|
|
}
|
|
|
|
uint64_t D3D12DescriptorHeap::GetGPUDescriptorHandle(uint32_t index) const {
|
|
D3D12_GPU_DESCRIPTOR_HANDLE handle = m_descriptorHeap->GetGPUDescriptorHandleForHeapStart();
|
|
handle.ptr += index * m_descriptorSize;
|
|
return handle.ptr;
|
|
}
|
|
|
|
void D3D12DescriptorHeap::SetName(const char* name) {
|
|
if (name) {
|
|
m_descriptorHeap->SetName(std::wstring(name, name + strlen(name)).c_str());
|
|
}
|
|
}
|
|
|
|
D3D12SwapChain::D3D12SwapChain(D3D12Device* device)
|
|
: m_device(device) {
|
|
}
|
|
|
|
D3D12SwapChain::~D3D12SwapChain() {
|
|
Shutdown();
|
|
}
|
|
|
|
bool D3D12SwapChain::Initialize(const SwapChainDesc& desc, void* windowHandle) {
|
|
m_bufferCount = desc.bufferCount;
|
|
m_vsync = desc.vsync;
|
|
m_fullscreen = desc.fullscreen;
|
|
|
|
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
|
|
swapChainDesc.BufferCount = desc.bufferCount;
|
|
swapChainDesc.BufferDesc.Width = desc.width;
|
|
swapChainDesc.BufferDesc.Height = desc.height;
|
|
swapChainDesc.BufferDesc.Format = FormatToDXGIFormat(desc.format);
|
|
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
swapChainDesc.OutputWindow = (HWND)windowHandle;
|
|
swapChainDesc.SampleDesc.Count = 1;
|
|
swapChainDesc.Windowed = !desc.fullscreen;
|
|
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
|
|
|
Microsoft::WRL::ComPtr<IDXGISwapChain> swapChain;
|
|
ID3D12CommandQueue* cmdQueue = (ID3D12CommandQueue*)m_device->GetCommandQueue()->GetNativeQueue();
|
|
HRESULT hr = m_device->GetDXGIFactory()->CreateSwapChain(
|
|
cmdQueue, &swapChainDesc, &swapChain);
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
hr = swapChain.As(&m_swapChain);
|
|
|
|
DescriptorHeapDesc rtvDesc = {};
|
|
rtvDesc.type = DescriptorHeapType::RTV;
|
|
rtvDesc.count = desc.bufferCount;
|
|
rtvDesc.shaderVisible = false;
|
|
|
|
if (!m_device->CreateDescriptorHeap((IDescriptorHeap**)&m_rtvHeap, rtvDesc)) {
|
|
return false;
|
|
}
|
|
|
|
D3D12_CPU_DESCRIPTOR_HANDLE rtvHeapStart;
|
|
rtvHeapStart.ptr = (UINT64)m_rtvHeap->GetCPUDescriptorHandle(0);
|
|
|
|
UINT rtvDescriptorSize = m_device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
|
|
|
|
|
for (uint32_t i = 0; i < desc.bufferCount; i++) {
|
|
hr = m_swapChain->GetBuffer(i, IID_PPV_ARGS(&m_buffers[i]));
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
D3D12_CPU_DESCRIPTOR_HANDLE rtvPointer;
|
|
rtvPointer.ptr = rtvHeapStart.ptr + i * rtvDescriptorSize;
|
|
m_device->GetD3D12Device()->CreateRenderTargetView(m_buffers[i].Get(), nullptr, rtvPointer);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void D3D12SwapChain::Shutdown() {
|
|
m_buffers[0].Reset();
|
|
if (m_rtvHeap) {
|
|
delete m_rtvHeap;
|
|
m_rtvHeap = nullptr;
|
|
}
|
|
m_swapChain.Reset();
|
|
}
|
|
|
|
bool D3D12SwapChain::Present() {
|
|
HRESULT hr = m_swapChain->Present(m_vsync ? 1 : 0, 0);
|
|
return SUCCEEDED(hr);
|
|
}
|
|
|
|
bool D3D12SwapChain::Resize(uint32_t width, uint32_t height) {
|
|
for (uint32_t i = 0; i < m_bufferCount; i++) {
|
|
m_buffers[i].Reset();
|
|
}
|
|
|
|
HRESULT hr = m_swapChain->ResizeBuffers(m_bufferCount, width, height, DXGI_FORMAT_UNKNOWN, 0);
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = *(D3D12_CPU_DESCRIPTOR_HANDLE*)m_rtvHeap->GetCPUDescriptorHandle(0);
|
|
for (uint32_t i = 0; i < m_bufferCount; i++) {
|
|
hr = m_swapChain->GetBuffer(i, IID_PPV_ARGS(&m_buffers[i]));
|
|
if (FAILED(hr)) {
|
|
return false;
|
|
}
|
|
|
|
m_device->GetD3D12Device()->CreateRenderTargetView(m_buffers[i].Get(), nullptr, rtvHandle);
|
|
rtvHandle.ptr += m_rtvHeap->GetDescriptorSize();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
uint32_t D3D12SwapChain::GetCurrentBufferIndex() const {
|
|
return m_swapChain->GetCurrentBackBufferIndex();
|
|
}
|
|
|
|
void* D3D12SwapChain::GetBuffer(uint32_t index) {
|
|
return GetBufferResource(index);
|
|
}
|
|
|
|
void* D3D12SwapChain::GetCurrentRenderTarget() {
|
|
uint32_t index = GetCurrentBufferIndex();
|
|
D3D12_CPU_DESCRIPTOR_HANDLE handle = m_rtvHeap->GetNativeHeap()->GetCPUDescriptorHandleForHeapStart();
|
|
UINT rtvSize = m_device->GetD3D12Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
|
handle.ptr += index * rtvSize;
|
|
return (void*)handle.ptr;
|
|
}
|
|
|
|
void* D3D12SwapChain::GetDepthStencil() {
|
|
return nullptr;
|
|
}
|
|
|
|
void D3D12SwapChain::SetFullscreen(bool fullscreen) {
|
|
m_fullscreen = fullscreen;
|
|
m_swapChain->SetFullscreenState(fullscreen, nullptr);
|
|
}
|
|
|
|
bool D3D12SwapChain::IsFullscreen() const {
|
|
return m_fullscreen;
|
|
}
|
|
|
|
D3D12RootSignature::D3D12RootSignature(D3D12Device* device)
|
|
: m_device(device) {
|
|
}
|
|
|
|
D3D12RootSignature::~D3D12RootSignature() {
|
|
}
|
|
|
|
bool D3D12RootSignature::Initialize(const RootSignatureDesc& desc) {
|
|
EngineLog("RootSignature: Start init, paramCount=%u", desc.parameterCount);
|
|
D3D12_ROOT_PARAMETER rootParameters[16] = {};
|
|
D3D12_DESCRIPTOR_RANGE descriptorRanges[16] = {};
|
|
|
|
for (uint32_t i = 0; i < desc.parameterCount && i < 16; i++) {
|
|
const RootParameter& param = desc.parameters[i];
|
|
|
|
switch (param.type) {
|
|
case RootParameterType::CBV:
|
|
rootParameters[i].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
|
rootParameters[i].ShaderVisibility = (D3D12_SHADER_VISIBILITY)param.visibility;
|
|
rootParameters[i].Descriptor.RegisterSpace = param.registerSpace;
|
|
rootParameters[i].Descriptor.ShaderRegister = param.shaderRegister;
|
|
break;
|
|
case RootParameterType::SRV:
|
|
rootParameters[i].ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
|
|
rootParameters[i].ShaderVisibility = (D3D12_SHADER_VISIBILITY)param.visibility;
|
|
rootParameters[i].Descriptor.RegisterSpace = param.registerSpace;
|
|
rootParameters[i].Descriptor.ShaderRegister = param.shaderRegister;
|
|
break;
|
|
case RootParameterType::Constants:
|
|
rootParameters[i].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
|
|
rootParameters[i].ShaderVisibility = (D3D12_SHADER_VISIBILITY)param.visibility;
|
|
rootParameters[i].Constants.RegisterSpace = param.registerSpace;
|
|
rootParameters[i].Constants.ShaderRegister = param.shaderRegister;
|
|
rootParameters[i].Constants.Num32BitValues = param.num32BitValues;
|
|
break;
|
|
case RootParameterType::DescriptorTable:
|
|
rootParameters[i].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
|
rootParameters[i].ShaderVisibility = (D3D12_SHADER_VISIBILITY)param.visibility;
|
|
rootParameters[i].DescriptorTable.pDescriptorRanges = &descriptorRanges[i];
|
|
rootParameters[i].DescriptorTable.NumDescriptorRanges = 1;
|
|
|
|
descriptorRanges[i].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
|
descriptorRanges[i].RegisterSpace = param.registerSpace;
|
|
descriptorRanges[i].BaseShaderRegister = 0;
|
|
descriptorRanges[i].NumDescriptors = 1;
|
|
descriptorRanges[i].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
|
break;
|
|
default:
|
|
rootParameters[i].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
break;
|
|
}
|
|
EngineLog("RootParam[%d]: type=%d, visibility=%d, reg=%d, space=%d",
|
|
i, (int)param.type, (int)param.visibility, param.shaderRegister, param.registerSpace);
|
|
}
|
|
|
|
D3D12_STATIC_SAMPLER_DESC samplerDesc = {};
|
|
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
|
samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
samplerDesc.MaxLOD = D3D12_FLOAT32_MAX;
|
|
samplerDesc.RegisterSpace = 0;
|
|
samplerDesc.ShaderRegister = 0;
|
|
samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
|
|
|
D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {};
|
|
rootSignatureDesc.NumParameters = desc.parameterCount;
|
|
rootSignatureDesc.pParameters = rootParameters;
|
|
rootSignatureDesc.NumStaticSamplers = 1;
|
|
rootSignatureDesc.pStaticSamplers = &samplerDesc;
|
|
rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
|
|
|
Microsoft::WRL::ComPtr<ID3DBlob> signature;
|
|
Microsoft::WRL::ComPtr<ID3DBlob> errorBlob;
|
|
HRESULT hr = D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &errorBlob);
|
|
if (FAILED(hr)) {
|
|
if (errorBlob) {
|
|
OutputDebugStringA((const char*)errorBlob->GetBufferPointer());
|
|
}
|
|
EngineLog("RootSignature: Serialize FAILED");
|
|
return false;
|
|
}
|
|
|
|
EngineLog("RootSignature: Serialize SUCCESS, size=%llu", (unsigned long long)signature->GetBufferSize());
|
|
|
|
hr = m_device->GetD3D12Device()->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(),
|
|
IID_PPV_ARGS(&m_rootSignature));
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
EngineLog("RootSignature: SUCCESS");
|
|
} else {
|
|
EngineLog("RootSignature: FAILED");
|
|
}
|
|
|
|
return SUCCEEDED(hr);
|
|
}
|
|
|
|
void D3D12RootSignature::SetName(const char* name) {
|
|
if (name && m_rootSignature) {
|
|
m_rootSignature->SetName(std::wstring(name, name + strlen(name)).c_str());
|
|
}
|
|
}
|
|
|
|
void* D3D12RootSignature::GetNativeRootSignature() const {
|
|
return m_rootSignature.Get();
|
|
}
|
|
|
|
D3D12PipelineState::D3D12PipelineState(D3D12Device* device)
|
|
: m_device(device) {
|
|
}
|
|
|
|
D3D12PipelineState::~D3D12PipelineState() {
|
|
}
|
|
|
|
bool D3D12PipelineState::Initialize(const PipelineDesc& desc) {
|
|
EngineLog("PipelineState: Start init");
|
|
|
|
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
|
|
|
|
if (desc.rootSignature) {
|
|
EngineLog("PipelineState: has rootSignature");
|
|
D3D12RootSignature* rs = static_cast<D3D12RootSignature*>(desc.rootSignature);
|
|
psoDesc.pRootSignature = rs->GetNative();
|
|
EngineLog("PipelineState: rootSignature ptr=%p", psoDesc.pRootSignature);
|
|
} else {
|
|
EngineLog("PipelineState: NO rootSignature!");
|
|
}
|
|
|
|
if (desc.vertexShader.size > 0 && desc.vertexShader.bytecode != nullptr) {
|
|
psoDesc.VS.pShaderBytecode = desc.vertexShader.bytecode;
|
|
psoDesc.VS.BytecodeLength = desc.vertexShader.size;
|
|
}
|
|
if (desc.pixelShader.size > 0 && desc.pixelShader.bytecode != nullptr) {
|
|
psoDesc.PS.pShaderBytecode = desc.pixelShader.bytecode;
|
|
psoDesc.PS.BytecodeLength = desc.pixelShader.size;
|
|
}
|
|
if (desc.geometryShader.size > 0 && desc.geometryShader.bytecode != nullptr) {
|
|
psoDesc.GS.pShaderBytecode = desc.geometryShader.bytecode;
|
|
psoDesc.GS.BytecodeLength = desc.geometryShader.size;
|
|
}
|
|
|
|
D3D12_INPUT_ELEMENT_DESC d3d12Elements[16] = {};
|
|
for (uint32_t i = 0; i < desc.inputLayout.elementCount && i < 16; i++) {
|
|
const InputElementDesc& src = desc.inputLayout.elements[i];
|
|
d3d12Elements[i].SemanticName = src.semanticName;
|
|
d3d12Elements[i].SemanticIndex = src.semanticIndex;
|
|
d3d12Elements[i].Format = FormatToDXGIFormat(src.format);
|
|
d3d12Elements[i].InputSlot = src.inputSlot;
|
|
d3d12Elements[i].AlignedByteOffset = src.alignedByteOffset;
|
|
d3d12Elements[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
|
|
d3d12Elements[i].InstanceDataStepRate = 0;
|
|
}
|
|
psoDesc.InputLayout.NumElements = desc.inputLayout.elementCount;
|
|
psoDesc.InputLayout.pInputElementDescs = d3d12Elements;
|
|
|
|
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
|
psoDesc.NumRenderTargets = 1;
|
|
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
psoDesc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
|
psoDesc.SampleDesc.Count = 1;
|
|
psoDesc.SampleDesc.Quality = 0;
|
|
psoDesc.SampleMask = 0xffffffff;
|
|
|
|
psoDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
|
psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK;
|
|
psoDesc.RasterizerState.DepthClipEnable = TRUE;
|
|
|
|
psoDesc.DepthStencilState.DepthEnable = TRUE;
|
|
psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
|
|
psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
|
|
|
|
psoDesc.BlendState = { 0 };
|
|
D3D12_RENDER_TARGET_BLEND_DESC rtBlendDesc = {
|
|
FALSE,FALSE,
|
|
D3D12_BLEND_SRC_ALPHA,D3D12_BLEND_INV_SRC_ALPHA,D3D12_BLEND_OP_ADD,
|
|
D3D12_BLEND_SRC_ALPHA,D3D12_BLEND_INV_SRC_ALPHA,D3D12_BLEND_OP_ADD,
|
|
D3D12_LOGIC_OP_NOOP,
|
|
D3D12_COLOR_WRITE_ENABLE_ALL,
|
|
};
|
|
for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
|
|
psoDesc.BlendState.RenderTarget[i] = rtBlendDesc;
|
|
|
|
EngineLog("PSO: VS=%p(%u), PS=%p(%u), RTV=%d, DSV=%d",
|
|
psoDesc.VS.pShaderBytecode, psoDesc.VS.BytecodeLength,
|
|
psoDesc.PS.pShaderBytecode, psoDesc.PS.BytecodeLength,
|
|
psoDesc.RTVFormats[0], psoDesc.DSVFormat);
|
|
|
|
HRESULT hr = m_device->GetD3D12Device()->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState));
|
|
if (FAILED(hr)) {
|
|
EngineLog("PipelineState: FAILED with HRESULT=%08lx", (unsigned long)hr);
|
|
return false;
|
|
}
|
|
EngineLog("PipelineState: SUCCESS");
|
|
return true;
|
|
}
|
|
|
|
void D3D12PipelineState::SetName(const char* name) {
|
|
if (name && m_pipelineState) {
|
|
m_pipelineState->SetName(std::wstring(name, name + strlen(name)).c_str());
|
|
}
|
|
}
|
|
|
|
void* D3D12PipelineState::GetNativePipelineState() const {
|
|
return m_pipelineState.Get();
|
|
}
|
|
|
|
D3D12CommandList::D3D12CommandList(D3D12Device* device, ID3D12GraphicsCommandList* list)
|
|
: m_device(device), m_commandList(list) {
|
|
}
|
|
|
|
D3D12CommandList::~D3D12CommandList() {
|
|
}
|
|
|
|
void D3D12CommandList::Reset(void* allocator) {
|
|
ICommandAllocator* cmdAlloc = static_cast<ICommandAllocator*>(allocator);
|
|
D3D12CommandAllocator* d3d12Alloc = static_cast<D3D12CommandAllocator*>(cmdAlloc);
|
|
ID3D12CommandAllocator* d3dAllocator = d3d12Alloc->GetNativeAllocator();
|
|
m_commandList->Reset(d3dAllocator, nullptr);
|
|
}
|
|
|
|
void D3D12CommandList::Close() {
|
|
m_commandList->Close();
|
|
}
|
|
|
|
void D3D12CommandList::SetPipelineState(IPipelineState* pso) {
|
|
if (pso) {
|
|
D3D12PipelineState* d3dPso = static_cast<D3D12PipelineState*>(pso);
|
|
m_commandList->SetPipelineState(d3dPso->GetNative());
|
|
}
|
|
}
|
|
|
|
void D3D12CommandList::SetRootSignature(IRootSignature* signature) {
|
|
if (signature) {
|
|
D3D12RootSignature* d3dRs = static_cast<D3D12RootSignature*>(signature);
|
|
m_commandList->SetGraphicsRootSignature(d3dRs->GetNative());
|
|
}
|
|
}
|
|
|
|
void D3D12CommandList::SetPrimitiveTopology(PrimitiveTopology topology) {
|
|
D3D12_PRIMITIVE_TOPOLOGY d3dTopology;
|
|
switch (topology) {
|
|
case PrimitiveTopology::TriangleList:
|
|
d3dTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
|
break;
|
|
case PrimitiveTopology::TriangleStrip:
|
|
d3dTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
|
|
break;
|
|
case PrimitiveTopology::LineList:
|
|
d3dTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
|
|
break;
|
|
default:
|
|
d3dTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
|
break;
|
|
}
|
|
m_commandList->IASetPrimitiveTopology(d3dTopology);
|
|
}
|
|
|
|
void D3D12CommandList::SetVertexBuffer(uint32_t slot, IResource* buffer, uint32_t offset, uint32_t stride) {
|
|
if (buffer) {
|
|
D3D12VertexBuffer* vb = static_cast<D3D12VertexBuffer*>(buffer);
|
|
D3D12_VERTEX_BUFFER_VIEW vbView = {};
|
|
vbView.BufferLocation = vb->GetNative()->GetGPUVirtualAddress() + offset;
|
|
vbView.SizeInBytes = (UINT)vb->GetDesc().size;
|
|
vbView.StrideInBytes = stride;
|
|
m_commandList->IASetVertexBuffers(slot, 1, &vbView);
|
|
}
|
|
}
|
|
|
|
void D3D12CommandList::SetIndexBuffer(IResource* buffer, uint32_t offset) {
|
|
if (buffer) {
|
|
D3D12IndexBuffer* ib = static_cast<D3D12IndexBuffer*>(buffer);
|
|
D3D12_INDEX_BUFFER_VIEW ibView = {};
|
|
ibView.BufferLocation = ib->GetNative()->GetGPUVirtualAddress() + offset;
|
|
ibView.Format = DXGI_FORMAT_R32_UINT;
|
|
ibView.SizeInBytes = (UINT)ib->GetDesc().size;
|
|
m_commandList->IASetIndexBuffer(&ibView);
|
|
}
|
|
}
|
|
|
|
void D3D12CommandList::SetDescriptorHeap(IDescriptorHeap* heap) {
|
|
if (heap) {
|
|
D3D12DescriptorHeap* d3dHeap = static_cast<D3D12DescriptorHeap*>(heap);
|
|
ID3D12DescriptorHeap* heaps[] = { d3dHeap->GetNativeHeap() };
|
|
m_commandList->SetDescriptorHeaps(1, heaps);
|
|
}
|
|
}
|
|
|
|
void D3D12CommandList::SetGraphicsDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) {
|
|
m_commandList->SetGraphicsRootDescriptorTable(rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE{ baseDescriptor });
|
|
}
|
|
|
|
void D3D12CommandList::SetGraphicsRootConstantBufferView(uint32_t slot, IResource* buffer) {
|
|
if (buffer) {
|
|
D3D12Resource* d3dBuffer = static_cast<D3D12Resource*>(buffer);
|
|
m_commandList->SetGraphicsRootConstantBufferView(slot, d3dBuffer->GetNative()->GetGPUVirtualAddress());
|
|
}
|
|
}
|
|
|
|
void D3D12CommandList::SetGraphicsRootConstantBufferViewCBV(uint32_t slot, void* nativeResource) {
|
|
ID3D12Resource* resource = static_cast<ID3D12Resource*>(nativeResource);
|
|
m_commandList->SetGraphicsRootConstantBufferView(slot, resource->GetGPUVirtualAddress());
|
|
}
|
|
|
|
void D3D12CommandList::SetGraphicsRoot32BitConstants(uint32_t rootParameterIndex, uint32_t num32BitValues, const void* data, uint32_t destOffsetIn32BitValues) {
|
|
m_commandList->SetGraphicsRoot32BitConstants(rootParameterIndex, num32BitValues, data, destOffsetIn32BitValues);
|
|
}
|
|
|
|
void D3D12CommandList::SetComputeDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) {
|
|
m_commandList->SetComputeRootDescriptorTable(rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE{ baseDescriptor });
|
|
}
|
|
|
|
void D3D12CommandList::DrawInstanced(uint32_t vertexCountPerInstance, uint32_t instanceCount, uint32_t startVertex, uint32_t startInstance) {
|
|
m_commandList->DrawInstanced(vertexCountPerInstance, instanceCount, startVertex, startInstance);
|
|
}
|
|
|
|
void D3D12CommandList::DrawIndexedInstanced(uint32_t indexCountPerInstance, uint32_t instanceCount, uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) {
|
|
m_commandList->DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndex, baseVertex, startInstance);
|
|
}
|
|
|
|
void D3D12CommandList::Dispatch(uint32_t x, uint32_t y, uint32_t z) {
|
|
m_commandList->Dispatch(x, y, z);
|
|
}
|
|
|
|
void D3D12CommandList::SetViewports(const Viewport* viewports, uint32_t count) {
|
|
D3D12_VIEWPORT d3dViewports[16] = {};
|
|
for (uint32_t i = 0; i < count && i < 16; i++) {
|
|
d3dViewports[i].TopLeftX = viewports[i].topLeftX;
|
|
d3dViewports[i].TopLeftY = viewports[i].topLeftY;
|
|
d3dViewports[i].Width = viewports[i].width;
|
|
d3dViewports[i].Height = viewports[i].height;
|
|
d3dViewports[i].MinDepth = viewports[i].minDepth;
|
|
d3dViewports[i].MaxDepth = viewports[i].maxDepth;
|
|
}
|
|
m_commandList->RSSetViewports(count, d3dViewports);
|
|
}
|
|
|
|
void D3D12CommandList::SetScissorRects(const Rect* rects, uint32_t count) {
|
|
D3D12_RECT d3dRects[16] = {};
|
|
for (uint32_t i = 0; i < count && i < 16; i++) {
|
|
d3dRects[i].left = rects[i].left;
|
|
d3dRects[i].top = rects[i].top;
|
|
d3dRects[i].right = rects[i].right;
|
|
d3dRects[i].bottom = rects[i].bottom;
|
|
}
|
|
m_commandList->RSSetScissorRects(count, d3dRects);
|
|
}
|
|
|
|
void D3D12CommandList::SetRenderTargets(void** targets, uint32_t count, void* depthStencil) {
|
|
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandles[8] = {};
|
|
for (uint32_t i = 0; i < count && i < 8; i++) {
|
|
rtvHandles[i].ptr = (UINT64)targets[i];
|
|
}
|
|
|
|
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = {};
|
|
if (depthStencil) {
|
|
dsvHandle.ptr = (UINT64)depthStencil;
|
|
}
|
|
|
|
m_commandList->OMSetRenderTargets(count, rtvHandles, FALSE, depthStencil ? &dsvHandle : nullptr);
|
|
}
|
|
|
|
void D3D12CommandList::ClearRenderTargetView(void* target, const float color[4]) {
|
|
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = { (UINT64)target };
|
|
m_commandList->ClearRenderTargetView(rtvHandle, color, 0, nullptr);
|
|
}
|
|
|
|
void D3D12CommandList::ClearDepthStencilView(void* depth, float depthValue, uint8_t stencil) {
|
|
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = { (UINT64)depth };
|
|
m_commandList->ClearDepthStencilView(dsvHandle, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, depthValue, stencil, 0, nullptr);
|
|
}
|
|
|
|
void D3D12CommandList::CopyResource(IResource* dst, const IResource* src) {
|
|
D3D12Resource* d3dDst = static_cast<D3D12Resource*>(dst);
|
|
D3D12Resource* d3dSrc = static_cast<D3D12Resource*>(const_cast<IResource*>(src));
|
|
m_commandList->CopyResource(d3dDst->GetNative(), d3dSrc->GetNative());
|
|
}
|
|
|
|
void D3D12CommandList::CopyBuffer(IResource* dst, uint64_t dstOffset, const IResource* src, uint64_t srcOffset, uint64_t size) {
|
|
D3D12Resource* d3dDst = static_cast<D3D12Resource*>(dst);
|
|
D3D12Resource* d3dSrc = static_cast<D3D12Resource*>(const_cast<IResource*>(src));
|
|
m_commandList->CopyBufferRegion(d3dDst->GetNative(), dstOffset, d3dSrc->GetNative(), srcOffset, size);
|
|
}
|
|
|
|
void D3D12CommandList::ResourceBarrier(IResource* resource, ResourceStateFlag before, ResourceStateFlag after) {
|
|
D3D12Resource* d3dResource = static_cast<D3D12Resource*>(resource);
|
|
|
|
D3D12_RESOURCE_STATES beforeState = D3D12_RESOURCE_STATE_COMMON;
|
|
D3D12_RESOURCE_STATES afterState = D3D12_RESOURCE_STATE_COMMON;
|
|
|
|
if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::RenderTarget)) beforeState = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
|
else if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::DepthWrite)) beforeState = D3D12_RESOURCE_STATE_DEPTH_WRITE;
|
|
else if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::DepthRead)) beforeState = D3D12_RESOURCE_STATE_DEPTH_READ;
|
|
else if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::ShaderResource)) beforeState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
|
else if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::CopyDest)) beforeState = D3D12_RESOURCE_STATE_COPY_DEST;
|
|
else if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::CopySource)) beforeState = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
|
else if (static_cast<uint32_t>(before) & static_cast<uint32_t>(ResourceStateFlag::Present)) beforeState = D3D12_RESOURCE_STATE_PRESENT;
|
|
|
|
if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::RenderTarget)) afterState = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
|
else if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::DepthWrite)) afterState = D3D12_RESOURCE_STATE_DEPTH_WRITE;
|
|
else if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::DepthRead)) afterState = D3D12_RESOURCE_STATE_DEPTH_READ;
|
|
else if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::ShaderResource)) afterState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
|
else if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::CopyDest)) afterState = D3D12_RESOURCE_STATE_COPY_DEST;
|
|
else if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::CopySource)) afterState = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
|
else if (static_cast<uint32_t>(after) & static_cast<uint32_t>(ResourceStateFlag::Present)) afterState = D3D12_RESOURCE_STATE_PRESENT;
|
|
|
|
D3D12_RESOURCE_BARRIER barrier = {};
|
|
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
|
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
|
barrier.Transition.pResource = d3dResource->GetNative();
|
|
barrier.Transition.StateBefore = beforeState;
|
|
barrier.Transition.StateAfter = afterState;
|
|
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
|
|
|
m_commandList->ResourceBarrier(1, &barrier);
|
|
}
|
|
|
|
void* D3D12CommandList::GetNativeCommandList() const {
|
|
return m_commandList.Get();
|
|
}
|
|
|
|
D3D12Resource::D3D12Resource(D3D12Device* device, ID3D12Resource* resource)
|
|
: m_device(device), m_resource(resource) {
|
|
}
|
|
|
|
D3D12Resource::~D3D12Resource() {
|
|
m_resource.Reset();
|
|
}
|
|
|
|
} // namespace RHI
|
|
} // namespace XCEngine
|