Skip to content

Instantly share code, notes, and snippets.

@dmitrykolesnikovich
Created September 1, 2021 09:49
Show Gist options
  • Save dmitrykolesnikovich/2e9e11cbd9e5fa9efcd2f16fbfd5a4bc to your computer and use it in GitHub Desktop.
Save dmitrykolesnikovich/2e9e11cbd9e5fa9efcd2f16fbfd5a4bc to your computer and use it in GitHub Desktop.
directx example for windows
#include <Windows.h>
#include <d3d12.h>
#include <dxgi1_6.h>
#include <d3dcompiler.h>
#include <DirectXMath.h>
#pragma comment(lib, "d3d12.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3dcompiler.lib")
HWND MainWindowHandle;
bool AppExitFlag;
ID3D12Device *Device;
IDXGISwapChain3 *SwapChain;
ID3D12CommandQueue *CommandQueue;
ID3D12CommandAllocator *CommandAllocators[2];
ID3D12GraphicsCommandList *CommandList;
ID3D12Resource *BackBufferTextures[2];
D3D12_CPU_DESCRIPTOR_HANDLE BackBufferTexturesRTVs[2];
ID3D12DescriptorHeap *RTDescriptorHeap;
ID3D12Fence *FrameSyncFences[2];
HANDLE FrameSyncEvent;
UINT CurrentFrameIndex;
UINT CurrentBackBufferIndex;
ID3D12DescriptorHeap *CBDescriptorHeaps[2];
ID3D12Resource *VertexBuffer;
ID3D12Resource *ConstantBuffers[2];
ID3D12PipelineState *PipelineState;
ID3D12RootSignature *RootSignature;
struct ConstantBufferStruct
{
DirectX::XMMATRIX TransformMatrix;
DirectX::XMFLOAT4 VertexColors[3];
};
void Init()
{
IDXGIFactory3 *Factory;
CreateDXGIFactory2(0, __uuidof(IDXGIFactory), (void**)&Factory);
IDXGIAdapter *Adapter;
HRESULT hr = Factory->EnumAdapters(0, &Adapter);
IDXGIOutput *Monitor;
hr = Adapter->EnumOutputs(0, &Monitor);
UINT DisplayModesCount = 0;
hr = Monitor->GetDisplayModeList(DXGI_FORMAT::DXGI_FORMAT_R8G8B8A8_UNORM, 0, &DisplayModesCount, nullptr);
DXGI_MODE_DESC *DisplayModes = new DXGI_MODE_DESC[DisplayModesCount];
hr = Monitor->GetDisplayModeList(DXGI_FORMAT::DXGI_FORMAT_R8G8B8A8_UNORM, 0, &DisplayModesCount, DisplayModes);
hr = D3D12CreateDevice(Adapter, D3D_FEATURE_LEVEL::D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), (void**)&Device);
D3D12_COMMAND_QUEUE_DESC CommandQueueDesc;
CommandQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAGS::D3D12_COMMAND_QUEUE_FLAG_NONE;
CommandQueueDesc.NodeMask = 0;
CommandQueueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY::D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
CommandQueueDesc.Type = D3D12_COMMAND_LIST_TYPE::D3D12_COMMAND_LIST_TYPE_DIRECT;
hr = Device->CreateCommandQueue(&CommandQueueDesc, __uuidof(ID3D12CommandQueue), (void**)&CommandQueue);
hr = Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE::D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&CommandAllocators[0]);
hr = Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE::D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&CommandAllocators[1]);
hr = Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE::D3D12_COMMAND_LIST_TYPE_DIRECT, CommandAllocators[0], nullptr, __uuidof(ID3D12GraphicsCommandList), (void**)&CommandList);
hr = CommandList->Close();
DXGI_SWAP_CHAIN_DESC1 SwapChainDesc;
SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE::DXGI_ALPHA_MODE_UNSPECIFIED;
SwapChainDesc.BufferCount = 2;
SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG::DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH | DXGI_SWAP_CHAIN_FLAG::DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
SwapChainDesc.Format = DXGI_FORMAT::DXGI_FORMAT_R8G8B8A8_UNORM;
SwapChainDesc.Height = 720;
SwapChainDesc.SampleDesc.Count = 1;
SwapChainDesc.SampleDesc.Quality = 0;
SwapChainDesc.Scaling = DXGI_SCALING::DXGI_SCALING_STRETCH;
SwapChainDesc.Stereo = FALSE;
SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT::DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
SwapChainDesc.Width = 1280;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC SwapChainFullScreenDesc;
SwapChainFullScreenDesc.RefreshRate = DisplayModes[DisplayModesCount - 1].RefreshRate;
SwapChainFullScreenDesc.Scaling = DXGI_MODE_SCALING::DXGI_MODE_SCALING_UNSPECIFIED;
SwapChainFullScreenDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER::DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
SwapChainFullScreenDesc.Windowed = TRUE;
IDXGISwapChain1 *SwapChain1;
hr = Factory->CreateSwapChainForHwnd(CommandQueue, MainWindowHandle, &SwapChainDesc, &SwapChainFullScreenDesc, nullptr, &SwapChain1);
hr = SwapChain1->QueryInterface<IDXGISwapChain3>(&SwapChain);
(void)SwapChain1->Release();
hr = Factory->MakeWindowAssociation(MainWindowHandle, DXGI_MWA_NO_ALT_ENTER);
CurrentFrameIndex = 0;
CurrentBackBufferIndex = SwapChain->GetCurrentBackBufferIndex();
hr = Device->CreateFence(1, D3D12_FENCE_FLAGS::D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), (void**)&FrameSyncFences[0]);
hr = Device->CreateFence(1, D3D12_FENCE_FLAGS::D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), (void**)&FrameSyncFences[1]);
FrameSyncEvent = CreateEvent(NULL, FALSE, FALSE, L"FrameSyncEvent");
hr = SwapChain->GetBuffer(0, __uuidof(ID3D12Resource), (void**)&BackBufferTextures[0]);
hr = SwapChain->GetBuffer(1, __uuidof(ID3D12Resource), (void**)&BackBufferTextures[1]);
D3D12_DESCRIPTOR_HEAP_DESC DescriptorHeapDesc;
DescriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAGS::D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
DescriptorHeapDesc.NodeMask = 0;
DescriptorHeapDesc.NumDescriptors = 2;
DescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE::D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
hr = Device->CreateDescriptorHeap(&DescriptorHeapDesc, __uuidof(ID3D12DescriptorHeap), (void**)&RTDescriptorHeap);
BackBufferTexturesRTVs[0].ptr = RTDescriptorHeap->GetCPUDescriptorHandleForHeapStart().ptr;
BackBufferTexturesRTVs[1].ptr = BackBufferTexturesRTVs[0].ptr + Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE::D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
D3D12_RENDER_TARGET_VIEW_DESC RTVDesc;
RTVDesc.Format = DXGI_FORMAT::DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
RTVDesc.Texture2D.MipSlice = 0;
RTVDesc.Texture2D.PlaneSlice = 0;
RTVDesc.ViewDimension = D3D12_RTV_DIMENSION::D3D12_RTV_DIMENSION_TEXTURE2D;
Device->CreateRenderTargetView(BackBufferTextures[0], &RTVDesc, BackBufferTexturesRTVs[0]);
Device->CreateRenderTargetView(BackBufferTextures[1], &RTVDesc, BackBufferTexturesRTVs[1]);
D3D12_RESOURCE_DESC ResourceDesc;
ResourceDesc.Alignment = 0;
ResourceDesc.DepthOrArraySize = 1;
ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION::D3D12_RESOURCE_DIMENSION_BUFFER;
ResourceDesc.Flags = D3D12_RESOURCE_FLAGS::D3D12_RESOURCE_FLAG_NONE;
ResourceDesc.Format = DXGI_FORMAT::DXGI_FORMAT_UNKNOWN;
ResourceDesc.Height = 1;
ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT::D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
ResourceDesc.MipLevels = 1;
ResourceDesc.SampleDesc.Count = 1;
ResourceDesc.SampleDesc.Quality = 0;
ResourceDesc.Width = 3 * 2 * sizeof(float);
D3D12_HEAP_PROPERTIES HeapProperties;
HeapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY::D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
HeapProperties.CreationNodeMask = 0;
HeapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL::D3D12_MEMORY_POOL_UNKNOWN;
HeapProperties.Type = D3D12_HEAP_TYPE::D3D12_HEAP_TYPE_DEFAULT;
HeapProperties.VisibleNodeMask = 0;
hr = Device->CreateCommittedResource(&HeapProperties, D3D12_HEAP_FLAGS::D3D12_HEAP_FLAG_NONE, &ResourceDesc, D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_COPY_DEST, nullptr, __uuidof(ID3D12Resource), (void**)&VertexBuffer);
HeapProperties.Type = D3D12_HEAP_TYPE::D3D12_HEAP_TYPE_UPLOAD;
ID3D12Resource *TemporaryBuffer;
hr = Device->CreateCommittedResource(&HeapProperties, D3D12_HEAP_FLAGS::D3D12_HEAP_FLAG_NONE, &ResourceDesc, D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), (void**)&TemporaryBuffer);
void *TemporaryBufferData;
hr = TemporaryBuffer->Map(0, nullptr, &TemporaryBufferData);
((float*)TemporaryBufferData)[0] = 0.0f;
((float*)TemporaryBufferData)[1] = 1.0f;
((float*)TemporaryBufferData)[2] = 1.0f;
((float*)TemporaryBufferData)[3] = -1.0f;
((float*)TemporaryBufferData)[4] = -1.0f;
((float*)TemporaryBufferData)[5] = -1.0f;
TemporaryBuffer->Unmap(0, nullptr);
ID3D12Fence *UploadSyncFence;
hr = Device->CreateFence(0, D3D12_FENCE_FLAGS::D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), (void**)&UploadSyncFence);
HANDLE UploadSyncEvent = CreateEvent(NULL, FALSE, FALSE, L"UploadSyncEvent");
hr = CommandAllocators[0]->Reset();
hr = CommandList->Reset(CommandAllocators[0], nullptr);
CommandList->CopyBufferRegion(VertexBuffer, 0, TemporaryBuffer, 0, 3 * 2 * sizeof(float));
D3D12_RESOURCE_BARRIER ResourceBarrier;
ResourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAGS::D3D12_RESOURCE_BARRIER_FLAG_NONE;
ResourceBarrier.Transition.pResource = VertexBuffer;
ResourceBarrier.Transition.StateAfter = D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
ResourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_COPY_DEST;
ResourceBarrier.Transition.Subresource = 0;
ResourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
CommandList->ResourceBarrier(1, &ResourceBarrier);
hr = CommandList->Close();
CommandQueue->ExecuteCommandLists(1, (ID3D12CommandList**)&CommandList);
hr = CommandQueue->Signal(UploadSyncFence, 1);
if (UploadSyncFence->GetCompletedValue() != 1)
{
hr = UploadSyncFence->SetEventOnCompletion(1, UploadSyncEvent);
DWORD WaitResult = WaitForSingleObject(UploadSyncEvent, INFINITE);
}
(void)TemporaryBuffer->Release();
(void)UploadSyncFence->Release();
(void)CloseHandle(UploadSyncEvent);
DescriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAGS::D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
DescriptorHeapDesc.NodeMask = 0;
DescriptorHeapDesc.NumDescriptors = 90;
DescriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE::D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
hr = Device->CreateDescriptorHeap(&DescriptorHeapDesc, __uuidof(ID3D12DescriptorHeap), (void**)&CBDescriptorHeaps[0]);
hr = Device->CreateDescriptorHeap(&DescriptorHeapDesc, __uuidof(ID3D12DescriptorHeap), (void**)&CBDescriptorHeaps[1]);
ResourceDesc.Alignment = 0;
ResourceDesc.DepthOrArraySize = 1;
ResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION::D3D12_RESOURCE_DIMENSION_BUFFER;
ResourceDesc.Flags = D3D12_RESOURCE_FLAGS::D3D12_RESOURCE_FLAG_NONE;
ResourceDesc.Format = DXGI_FORMAT::DXGI_FORMAT_UNKNOWN;
ResourceDesc.Height = 1;
ResourceDesc.Layout = D3D12_TEXTURE_LAYOUT::D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
ResourceDesc.MipLevels = 1;
ResourceDesc.SampleDesc.Count = 1;
ResourceDesc.SampleDesc.Quality = 0;
ResourceDesc.Width = 256 * 90;
HeapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY::D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
HeapProperties.CreationNodeMask = 0;
HeapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL::D3D12_MEMORY_POOL_UNKNOWN;
HeapProperties.Type = D3D12_HEAP_TYPE::D3D12_HEAP_TYPE_UPLOAD;
HeapProperties.VisibleNodeMask = 0;
hr = Device->CreateCommittedResource(&HeapProperties, D3D12_HEAP_FLAGS::D3D12_HEAP_FLAG_NONE, &ResourceDesc, D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), (void**)&ConstantBuffers[0]);
hr = Device->CreateCommittedResource(&HeapProperties, D3D12_HEAP_FLAGS::D3D12_HEAP_FLAG_NONE, &ResourceDesc, D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), (void**)&ConstantBuffers[1]);
for (UINT i = 0; i < 90; i++)
{
D3D12_CPU_DESCRIPTOR_HANDLE Descriptor = { CBDescriptorHeaps[0]->GetCPUDescriptorHandleForHeapStart().ptr + i * Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE::D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) };
D3D12_CONSTANT_BUFFER_VIEW_DESC CBVDesc;
CBVDesc.BufferLocation = ConstantBuffers[0]->GetGPUVirtualAddress() + i * 256;
CBVDesc.SizeInBytes = 256;
Device->CreateConstantBufferView(&CBVDesc, Descriptor);
Descriptor = { CBDescriptorHeaps[1]->GetCPUDescriptorHandleForHeapStart().ptr + i * Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE::D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) };
CBVDesc.BufferLocation = ConstantBuffers[1]->GetGPUVirtualAddress() + i * 256;
CBVDesc.SizeInBytes = 256;
Device->CreateConstantBufferView(&CBVDesc, Descriptor);
}
D3D12_DESCRIPTOR_RANGE DescriptorRange;
DescriptorRange.BaseShaderRegister = 0;
DescriptorRange.NumDescriptors = 90;
DescriptorRange.OffsetInDescriptorsFromTableStart = 0;
DescriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE::D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
DescriptorRange.RegisterSpace = 0;
D3D12_ROOT_PARAMETER RootParameter;
RootParameter.DescriptorTable.NumDescriptorRanges = 1;
RootParameter.DescriptorTable.pDescriptorRanges = &DescriptorRange;
RootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE::D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
RootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY::D3D12_SHADER_VISIBILITY_VERTEX;
D3D12_ROOT_SIGNATURE_DESC RootSignatureDesc;
RootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAGS::D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
RootSignatureDesc.NumParameters = 1;
RootSignatureDesc.NumStaticSamplers = 0;
RootSignatureDesc.pParameters = &RootParameter;
RootSignatureDesc.pStaticSamplers = nullptr;
ID3DBlob *RootSignatureBlob;
hr = D3D12SerializeRootSignature(&RootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION::D3D_ROOT_SIGNATURE_VERSION_1_0, &RootSignatureBlob, nullptr);
hr = Device->CreateRootSignature(0, RootSignatureBlob->GetBufferPointer(), RootSignatureBlob->GetBufferSize(), __uuidof(ID3D12RootSignature), (void**)&RootSignature);
(void)RootSignatureBlob->Release();
ID3DBlob *VertexShaderBlob, *PixelShaderBlob;
hr = D3DCompileFromFile(L"Shaders.hlsl", nullptr, nullptr, "VS", "vs_5_1", D3DCOMPILE_PACK_MATRIX_ROW_MAJOR, 0, &VertexShaderBlob, nullptr);
hr = D3DCompileFromFile(L"Shaders.hlsl", nullptr, nullptr, "PS", "ps_5_1", D3DCOMPILE_PACK_MATRIX_ROW_MAJOR, 0, &PixelShaderBlob, nullptr);
D3D12_INPUT_ELEMENT_DESC InputElementDesc;
InputElementDesc.AlignedByteOffset = 0;
InputElementDesc.Format = DXGI_FORMAT::DXGI_FORMAT_R32G32_FLOAT;
InputElementDesc.InputSlot = 0;
InputElementDesc.InputSlotClass = D3D12_INPUT_CLASSIFICATION::D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
InputElementDesc.InstanceDataStepRate = 0;
InputElementDesc.SemanticIndex = 0;
InputElementDesc.SemanticName = "POSITION";
D3D12_GRAPHICS_PIPELINE_STATE_DESC GraphicsPipelineStateDesc;
ZeroMemory(&GraphicsPipelineStateDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
GraphicsPipelineStateDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE::D3D12_COLOR_WRITE_ENABLE_ALL;
GraphicsPipelineStateDesc.InputLayout.NumElements = 1;
GraphicsPipelineStateDesc.InputLayout.pInputElementDescs = &InputElementDesc;
GraphicsPipelineStateDesc.NumRenderTargets = 1;
GraphicsPipelineStateDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE::D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
GraphicsPipelineStateDesc.pRootSignature = RootSignature;
GraphicsPipelineStateDesc.PS.BytecodeLength = PixelShaderBlob->GetBufferSize();
GraphicsPipelineStateDesc.PS.pShaderBytecode = PixelShaderBlob->GetBufferPointer();
GraphicsPipelineStateDesc.RasterizerState.CullMode = D3D12_CULL_MODE::D3D12_CULL_MODE_BACK;
GraphicsPipelineStateDesc.RasterizerState.FillMode = D3D12_FILL_MODE::D3D12_FILL_MODE_SOLID;
GraphicsPipelineStateDesc.RTVFormats[0] = DXGI_FORMAT::DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
GraphicsPipelineStateDesc.SampleDesc.Count = 1;
GraphicsPipelineStateDesc.SampleDesc.Quality = 0;
GraphicsPipelineStateDesc.SampleMask = D3D12_DEFAULT_SAMPLE_MASK;
GraphicsPipelineStateDesc.VS.BytecodeLength = VertexShaderBlob->GetBufferSize();
GraphicsPipelineStateDesc.VS.pShaderBytecode = VertexShaderBlob->GetBufferPointer();
hr = Device->CreateGraphicsPipelineState(&GraphicsPipelineStateDesc, __uuidof(ID3D12PipelineState), (void**)&PipelineState);
(void)VertexShaderBlob->Release();
(void)PixelShaderBlob->Release();
ULONG RefCount;
RefCount = Factory->Release();
RefCount = Adapter->Release();
RefCount = Monitor->Release();
delete[] DisplayModes;
}
void Render()
{
HRESULT hr;
if (FrameSyncFences[CurrentFrameIndex]->GetCompletedValue() != 1)
{
hr = FrameSyncFences[CurrentFrameIndex]->SetEventOnCompletion(1, FrameSyncEvent);
DWORD WaitResult = WaitForSingleObject(FrameSyncEvent, INFINITE);
}
hr = FrameSyncFences[CurrentFrameIndex]->Signal(0);
hr = CommandAllocators[CurrentFrameIndex]->Reset();
hr = CommandList->Reset(CommandAllocators[CurrentFrameIndex], nullptr);
D3D12_RESOURCE_BARRIER ResourceBarrier;
ResourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAGS::D3D12_RESOURCE_BARRIER_FLAG_NONE;
ResourceBarrier.Transition.pResource = BackBufferTextures[CurrentFrameIndex];
ResourceBarrier.Transition.StateAfter = D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_RENDER_TARGET;
ResourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_PRESENT;
ResourceBarrier.Transition.Subresource = 0;
ResourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
CommandList->ResourceBarrier(1, &ResourceBarrier);
float ClearColor[4] = { 0.0f, 0.5f, 0.75f, 1.0f };
CommandList->ClearRenderTargetView(BackBufferTexturesRTVs[CurrentFrameIndex], ClearColor, 0, nullptr);
BYTE *ConstantBufferData;
hr = ConstantBuffers[CurrentFrameIndex]->Map(0, nullptr, (void**)&ConstantBufferData);
for (UINT x = 0; x < 10; x++)
{
for (UINT y = 0; y < 9; y++)
{
UINT i = y * 10 + x;
((ConstantBufferStruct*)ConstantBufferData)->TransformMatrix = DirectX::XMMatrixScaling(1.0f / 20.0f, 1.0f / 14.0f, 1.0f) * DirectX::XMMatrixTranslation(-0.703125f + x * 0.15625f, -0.777778f + y * 0.19444f, 0.0f);
((ConstantBufferStruct*)ConstantBufferData)->VertexColors[0] = DirectX::XMFLOAT4(1.0f * (x / 9.0f), 0.0f, 0.0f, 1.0f);
((ConstantBufferStruct*)ConstantBufferData)->VertexColors[1] = DirectX::XMFLOAT4(1.0f * (y / 8.0f), 0.5f, 1.0f * (x / 9.0f), 1.0f);
((ConstantBufferStruct*)ConstantBufferData)->VertexColors[2] = DirectX::XMFLOAT4(0.0f, 0.0f, 1.0f * (y / 8.0f), 1.0f);
ConstantBufferData += 256;
}
}
ConstantBuffers[CurrentFrameIndex]->Unmap(0, nullptr);
CommandList->SetDescriptorHeaps(1, &CBDescriptorHeaps[CurrentFrameIndex]);
CommandList->SetGraphicsRootSignature(RootSignature);
CommandList->SetPipelineState(PipelineState);
CommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY::D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
CommandList->OMSetRenderTargets(1, &BackBufferTexturesRTVs[CurrentBackBufferIndex], TRUE, nullptr);
D3D12_VERTEX_BUFFER_VIEW VertexBufferView;
VertexBufferView.BufferLocation = VertexBuffer->GetGPUVirtualAddress();
VertexBufferView.SizeInBytes = 3 * 2 * sizeof(float);
VertexBufferView.StrideInBytes = 2 * sizeof(float);
CommandList->IASetVertexBuffers(0, 1, &VertexBufferView);
D3D12_VIEWPORT Viewport;
Viewport.Height = 720.0f;
Viewport.MaxDepth = 1.0f;
Viewport.MinDepth = 0.0f;
Viewport.TopLeftX = 0.0f;
Viewport.TopLeftY = 0.0f;
Viewport.Width = 1280.0f;
CommandList->RSSetViewports(1, &Viewport);
D3D12_RECT ScissorRect;
ScissorRect.bottom = 720;
ScissorRect.left = 0;
ScissorRect.right = 1280;
ScissorRect.top = 0;
CommandList->RSSetScissorRects(1, &ScissorRect);
D3D12_GPU_DESCRIPTOR_HANDLE Descriptor = { CBDescriptorHeaps[CurrentFrameIndex]->GetGPUDescriptorHandleForHeapStart().ptr };
CommandList->SetGraphicsRootDescriptorTable(0, Descriptor);
CommandList->DrawInstanced(3, 90, 0, 0);
ResourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAGS::D3D12_RESOURCE_BARRIER_FLAG_NONE;
ResourceBarrier.Transition.pResource = BackBufferTextures[CurrentFrameIndex];
ResourceBarrier.Transition.StateAfter = D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_PRESENT;
ResourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_RENDER_TARGET;
ResourceBarrier.Transition.Subresource = 0;
ResourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE::D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
CommandList->ResourceBarrier(1, &ResourceBarrier);
hr = CommandList->Close();
CommandQueue->ExecuteCommandLists(1, (ID3D12CommandList**)&CommandList);
hr = SwapChain->Present(0, DXGI_PRESENT_ALLOW_TEARING);
hr = CommandQueue->Signal(FrameSyncFences[CurrentFrameIndex], 1);
CurrentFrameIndex = (CurrentFrameIndex + 1) % 2;
CurrentBackBufferIndex = SwapChain->GetCurrentBackBufferIndex();
}
void Shutdown()
{
CurrentFrameIndex = (CurrentFrameIndex + 1) % 2;
HRESULT hr;
if (FrameSyncFences[CurrentFrameIndex]->GetCompletedValue() != 1)
{
hr = FrameSyncFences[CurrentFrameIndex]->SetEventOnCompletion(1, FrameSyncEvent);
DWORD WaitResult = WaitForSingleObject(FrameSyncEvent, INFINITE);
}
ULONG RefCount;
RefCount = RTDescriptorHeap->Release();
RefCount = CBDescriptorHeaps[0]->Release();
RefCount = CBDescriptorHeaps[1]->Release();
RefCount = PipelineState->Release();
RefCount = RootSignature->Release();
RefCount = ConstantBuffers[0]->Release();
RefCount = ConstantBuffers[1]->Release();
RefCount = VertexBuffer->Release();
RefCount = BackBufferTextures[0]->Release();
RefCount = BackBufferTextures[1]->Release();
RefCount = FrameSyncFences[0]->Release();
RefCount = FrameSyncFences[1]->Release();
BOOL Result = CloseHandle(FrameSyncEvent);
RefCount = CommandList->Release();
RefCount = CommandAllocators[0]->Release();
RefCount = CommandAllocators[1]->Release();
RefCount = CommandQueue->Release();
RefCount = SwapChain->Release();
RefCount = Device->Release();
}
LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (Msg == WM_CLOSE)
AppExitFlag = true;
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX WndClassEx;
ZeroMemory(&WndClassEx, sizeof(WNDCLASSEX));
WndClassEx.cbSize = sizeof(WNDCLASSEX);
WndClassEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
WndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClassEx.hIcon = NULL;
WndClassEx.hIconSm = NULL;
WndClassEx.hInstance = hInstance;
WndClassEx.lpfnWndProc = &MainWindowProc;
WndClassEx.lpszClassName = L"MainWndClass";
WndClassEx.lpszMenuName = NULL;
WndClassEx.style = 0;
ATOM Atom = RegisterClassEx(&WndClassEx);
DWORD WindowStyle = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
RECT WindowRect;
WindowRect.bottom = 720;
WindowRect.left = 0;
WindowRect.right = 1280;
WindowRect.top = 0;
BOOL Result = AdjustWindowRect(&WindowRect, WindowStyle, FALSE);
int ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
int ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
int WindowWidth = WindowRect.right - WindowRect.left;
int WindowHeight = WindowRect.bottom - WindowRect.top;
int WindowLeft = ScreenWidth / 2 - WindowWidth / 2;
int WindowTop = ScreenHeight / 2 - WindowHeight / 2;
MainWindowHandle = CreateWindowEx(0, L"MainWndClass", L"Constant Buffer Test", WindowStyle, WindowLeft, WindowTop, WindowWidth, WindowHeight, NULL, NULL, hInstance, NULL);
Result = UpdateWindow(MainWindowHandle);
Result = ShowWindow(MainWindowHandle, SW_SHOW);
AppExitFlag = false;
Init();
MSG Message;
while (!AppExitFlag)
{
while (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) AppExitFlag = true;
Render();
}
Shutdown();
Result = DestroyWindow(MainWindowHandle);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment