Skip to content

Instantly share code, notes, and snippets.

@rdeioris
Created June 25, 2019 11:26
Show Gist options
  • Save rdeioris/b8739124a91cba48f32897515669e7d6 to your computer and use it in GitHub Desktop.
Save rdeioris/b8739124a91cba48f32897515669e7d6 to your computer and use it in GitHub Desktop.
#include <dxgi1_6.h>
#include <d3d12.h>
#include <iostream>
#include <string>
#include <system_error>
#include "vs.h"
#include "ps.h"
namespace aiv
{
void check(HRESULT result)
{
if (result != S_OK)
{
std::cerr << std::system_category().message(result) << std::endl;
std::exit(1);
}
}
}
int main(int argc, char **argv)
{
IDXGIFactory4* factory = nullptr;
aiv::check(CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, __uuidof(IDXGIFactory4), reinterpret_cast<void**>(&factory)));
IDXGIAdapter1* adapter = nullptr;
UINT adapter_index = 0;
while (factory->EnumAdapters1(adapter_index++, &adapter) != DXGI_ERROR_NOT_FOUND)
{
DXGI_ADAPTER_DESC adapter_desc;
adapter->GetDesc(&adapter_desc);
std::wcout << adapter_desc.Description << std::endl;
}
// choose the adapter 1
factory->EnumAdapters1(1, &adapter);
ID3D12Debug1* debug = nullptr;
aiv::check(D3D12GetDebugInterface(__uuidof(ID3D12Debug1), reinterpret_cast<void**>(&debug)));
debug->EnableDebugLayer();
debug->SetEnableSynchronizedCommandQueueValidation(true);
ID3D12Device4* device = nullptr;
aiv::check(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_12_1, __uuidof(ID3D12Device4), reinterpret_cast<void**>(&device)));
D3D12_COMMAND_QUEUE_DESC queue_desc = {};
queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
ID3D12CommandQueue* queue = nullptr;
aiv::check(device->CreateCommandQueue(&queue_desc, __uuidof(ID3D12CommandQueue), reinterpret_cast<void**>(&queue)));
ID3D12Fence* fence = nullptr;
aiv::check(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), reinterpret_cast<void**>(&fence)));
HANDLE fence_event = CreateEvent(nullptr, false, false, nullptr);
float vertices[] =
{
0, 1,
1, -1,
-1, -1,
};
ID3D12Resource* vertex_resource = nullptr;
D3D12_RESOURCE_DESC vertex_desc = {};
vertex_desc.DepthOrArraySize = 1;
vertex_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
vertex_desc.SampleDesc.Count = 1;
vertex_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
vertex_desc.Height = 1;
vertex_desc.Width = sizeof(vertices);
vertex_desc.MipLevels = 1;
vertex_desc.Format = DXGI_FORMAT_UNKNOWN;
D3D12_HEAP_PROPERTIES upload_heap_props = {};
upload_heap_props.Type = D3D12_HEAP_TYPE_UPLOAD;
aiv::check(device->CreateCommittedResource(&upload_heap_props, D3D12_HEAP_FLAG_NONE,
&vertex_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource),
reinterpret_cast<void**>(&vertex_resource)));
vertex_resource->SetName(L"Tumadre");
// map the gpu memory of vertex resource to cpu
float* gpu_ptr = nullptr;
aiv::check(vertex_resource->Map(0, nullptr, reinterpret_cast<void**>(&gpu_ptr)));
std::memcpy(gpu_ptr, vertices, sizeof(vertices));
vertex_resource->Unmap(0, nullptr);
D3D12_HEAP_PROPERTIES fast_heap_props = {};
fast_heap_props.Type = D3D12_HEAP_TYPE_DEFAULT;
ID3D12Resource* gpu_vertices = nullptr;
aiv::check(device->CreateCommittedResource(&fast_heap_props, D3D12_HEAP_FLAG_NONE,
&vertex_desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, __uuidof(ID3D12Resource),
reinterpret_cast<void**>(&gpu_vertices)));
ID3D12CommandAllocator* command_allocator = nullptr;
aiv::check(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator),
reinterpret_cast<void**>(&command_allocator)));
ID3D12GraphicsCommandList* command_list = nullptr;
aiv::check(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
command_allocator, nullptr, __uuidof(ID3D12GraphicsCommandList),
reinterpret_cast<void**>(&command_list)));
command_list->CopyResource(gpu_vertices, vertex_resource);
D3D12_RESOURCE_BARRIER barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Transition.pResource = gpu_vertices;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
command_list->ResourceBarrier(1, &barrier);
command_list->Close();
queue->ExecuteCommandLists(1, reinterpret_cast<ID3D12CommandList**>(&command_list));
queue->Signal(fence, 1);
if (fence->GetCompletedValue() < 1)
{
fence->SetEventOnCompletion(1, fence_event);
WaitForSingleObject(fence_event, INFINITE);
}
/*for (;;)
{
UINT64 value = fence->GetCompletedValue();
std::cout << value << std::endl;
if (value == 1)
break;
}*/
vertex_resource->Release();
WNDCLASS wclass = {};
wclass.lpszClassName = "DX12WindowClass";
wclass.hInstance = GetModuleHandle(nullptr);
wclass.lpfnWndProc = DefWindowProc;
RegisterClass(&wclass);
DWORD style = WS_OVERLAPPEDWINDOW;
RECT rect = { 0, 0, 512, 512 };
// this will compute the right dimension
AdjustWindowRect(&rect, style, false);
HWND new_handle = CreateWindow(wclass.lpszClassName, "D3D12",
style, CW_USEDEFAULT, CW_USEDEFAULT,
rect.right - rect.left, rect.bottom - rect.top, nullptr, nullptr, wclass.hInstance, nullptr);
if (!new_handle)
throw std::exception("unable to create the main window");
ShowWindow(new_handle, SW_SHOW);
/*aiv::check(device->CreatePlacedResource(upload_heap, 0, &vertex_desc, D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr, __uuidof(ID3D12Resource), reinterpret_cast<void**>(&vertex_resource)));*/
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {};
swap_chain_desc.BufferCount = 2;
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swap_chain_desc.Stereo = false;
swap_chain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swap_chain_desc.Height = 512;
swap_chain_desc.Width = 512;
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swap_chain_desc.SampleDesc.Count = 1;
swap_chain_desc.SampleDesc.Quality = 0;
swap_chain_desc.Scaling = DXGI_SCALING_STRETCH;
IDXGISwapChain4* swap_chain = nullptr;
aiv::check(factory->CreateSwapChainForHwnd(queue, new_handle, &swap_chain_desc, nullptr, nullptr,
reinterpret_cast<IDXGISwapChain1**>(&swap_chain)));
ID3D12Resource* backbuffer0 = nullptr;
aiv::check(swap_chain->GetBuffer(0, __uuidof(ID3D12Resource), reinterpret_cast<void**>(&backbuffer0)));
ID3D12Resource* backbuffer1 = nullptr;
aiv::check(swap_chain->GetBuffer(1, __uuidof(ID3D12Resource), reinterpret_cast<void**>(&backbuffer1)));
ID3D12DescriptorHeap* rtv_descriptor_heap = nullptr;
D3D12_DESCRIPTOR_HEAP_DESC rtv_dh_desc = {};
rtv_dh_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
rtv_dh_desc.NumDescriptors = 2;
aiv::check(device->CreateDescriptorHeap(&rtv_dh_desc, __uuidof(ID3D12DescriptorHeap),
reinterpret_cast<void**>(&rtv_descriptor_heap)));
auto increment = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
auto cpu_start = rtv_descriptor_heap->GetCPUDescriptorHandleForHeapStart();
auto gpu_start = rtv_descriptor_heap->GetGPUDescriptorHandleForHeapStart();
D3D12_INPUT_ELEMENT_DESC input_layout = {};
input_layout.Format = DXGI_FORMAT_R32G32_FLOAT;
input_layout.SemanticName = "POSITION";
input_layout.InstanceDataStepRate = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
D3D12_VERSIONED_ROOT_SIGNATURE_DESC versioned_root_desc = {};
versioned_root_desc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1;
versioned_root_desc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
ID3DBlob *root_signature_blob = nullptr;
ID3DBlob *root_signature_error = nullptr;
aiv::check(D3D12SerializeVersionedRootSignature(&versioned_root_desc, &root_signature_blob, &root_signature_error));
ID3D12RootSignature* root_signature = nullptr;
aiv::check(device->CreateRootSignature(0,
root_signature_blob->GetBufferPointer(),
root_signature_blob->GetBufferSize(),
__uuidof(ID3D12RootSignature),
reinterpret_cast<void**>(&root_signature)));
ID3D12PipelineState* pso = nullptr;
D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = {};
pso_desc.VS.pShaderBytecode = vs;
pso_desc.VS.BytecodeLength = sizeof(vs);
pso_desc.PS.pShaderBytecode = ps;
pso_desc.PS.BytecodeLength = sizeof(ps);
pso_desc.InputLayout.NumElements = 1;
pso_desc.InputLayout.pInputElementDescs = &input_layout;
pso_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
pso_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
pso_desc.pRootSignature = root_signature;
pso_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
pso_desc.NumRenderTargets = 1;
pso_desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
pso_desc.SampleDesc.Count = 1;
pso_desc.SampleMask = 0xffffffff;
pso_desc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
aiv::check(device->CreateGraphicsPipelineState(&pso_desc, __uuidof(ID3D12PipelineState), reinterpret_cast<void**>(&pso)));
device->CreateRenderTargetView(backbuffer0, nullptr, cpu_start);
cpu_start.ptr += increment;
device->CreateRenderTargetView(backbuffer1, nullptr, cpu_start);
D3D12_VERTEX_BUFFER_VIEW bview = {};
bview.BufferLocation = gpu_vertices->GetGPUVirtualAddress();
bview.SizeInBytes = sizeof(vertices);
bview.StrideInBytes = sizeof(float) * 2;
ID3D12GraphicsCommandList* clear_list = nullptr;
aiv::check(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
command_allocator, pso, __uuidof(ID3D12GraphicsCommandList),
reinterpret_cast<void**>(&clear_list)));
D3D12_VIEWPORT viewport = {};
viewport.Width = 512;
viewport.Height = 512;
D3D12_RECT scissor = {};
scissor.bottom = 512;
scissor.right = 512;
float red[] = { 0, 0, 1, 1 };
barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Transition.pResource = backbuffer0;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
clear_list->ResourceBarrier(1, &barrier);
cpu_start.ptr -= increment;
clear_list->SetGraphicsRootSignature(root_signature);
clear_list->ClearRenderTargetView(cpu_start, red, 0, nullptr);
clear_list->OMSetRenderTargets(1, &cpu_start, false, nullptr);
clear_list->RSSetViewports(1, &viewport);
clear_list->RSSetScissorRects(1, &scissor);
clear_list->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
clear_list->IASetVertexBuffers(0, 1, &bview);
clear_list->DrawInstanced(3, 1, 0, 0);
barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Transition.pResource = backbuffer0;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
clear_list->ResourceBarrier(1, &barrier);
clear_list->Close();
ID3D12GraphicsCommandList* clear_list2 = nullptr;
aiv::check(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
command_allocator, pso, __uuidof(ID3D12GraphicsCommandList),
reinterpret_cast<void**>(&clear_list2)));
cpu_start.ptr += increment;
float blue[] = { 0, 0, 1, 1 };
barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Transition.pResource = backbuffer1;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
clear_list2->ResourceBarrier(1, &barrier);
clear_list2->SetGraphicsRootSignature(root_signature);
clear_list2->ClearRenderTargetView(cpu_start, blue, 0, nullptr);
clear_list2->RSSetViewports(1, &viewport);
clear_list2->RSSetScissorRects(1, &scissor);
clear_list2->OMSetRenderTargets(1, &cpu_start, false, nullptr);
clear_list2->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
clear_list2->IASetVertexBuffers(0, 1, &bview);
clear_list2->DrawInstanced(3, 1, 0, 0);
barrier = {};
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Transition.pResource = backbuffer1;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
clear_list2->ResourceBarrier(1, &barrier);
clear_list2->Close();
UINT64 fence_value = 1;
for (;;)
{
MSG msg;
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UINT back_buffer = swap_chain->GetCurrentBackBufferIndex();
if (back_buffer == 0)
{
queue->ExecuteCommandLists(1, reinterpret_cast<ID3D12CommandList**>(&clear_list));
}
else
{
queue->ExecuteCommandLists(1, reinterpret_cast<ID3D12CommandList**>(&clear_list2));
}
queue->Signal(fence, ++fence_value);
if (fence->GetCompletedValue() < fence_value)
{
fence->SetEventOnCompletion(fence_value, fence_event);
WaitForSingleObject(fence_event, INFINITE);
}
swap_chain->Present(1, 0);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment