Created
          June 25, 2019 11:26 
        
      - 
      
- 
        Save rdeioris/b8739124a91cba48f32897515669e7d6 to your computer and use it in GitHub Desktop. 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | #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