#pragma once
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers.
#endif
#pragma comment(lib, "d3d12.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3dcompiler.lib")
#include <Vector.hpp>
#include "Types.hpp"
#include "Allocator.hpp"
#include "Memory.hpp"
#include "Thread.hpp"
#include <d3d12.h>
#include <dxgi1_4.h>
#include <D3Dcompiler.h>
#include <DirectXMath.h>
#include "d3dx12.h"
#include <string>
#include <wrl.h>
#include <windows.h>
using namespace DirectX;
using namespace Microsoft::WRL;
#define SAFE_RELEASE(p) { if ( (p) ) { (p)->Release(); (p) = 0; } }
struct ConstantBufferPerObject
{
XMFLOAT4X4 wvpMat;
};
struct Vertex
{
Vertex(float x, float y, float z, float r, float g, float b, float a) : pos(x, y, z), color(r, g, b, a) {}
XMFLOAT3 pos;
XMFLOAT4 color;
};
HWND hwnd = NULL;
int32 Width = 800;
int32 Height = 600;
bool FullScreen = false;
bool Running = true;
bool InitializeWindow(HINSTANCE hInstance, int32 ShowWnd, bool fullscreen);
bool InitD3D();
void Update();
void UpdatePipeline();
void Render();
void Cleanup();
void WaitForPreviousFrame();
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
const int32 frameBufferCount = 3;
ComPtr<ID3D12Device> device;
IDXGISwapChain3* swapChain;
ID3D12CommandQueue* commandQueue;
ID3D12DescriptorHeap* rtvDescriptorHeap;
ID3D12Resource* renderTargets[frameBufferCount];
ID3D12CommandAllocator* commandAllocator[frameBufferCount];
ID3D12GraphicsCommandList* commandList;
ID3D12Fence* fence[frameBufferCount];
HANDLE fenceEvent;
uint64 fenceValue[frameBufferCount];
SIZE_T frameIndex;
int32 rtvDescriptorSize;
ID3D12PipelineState* pipelineStateObject;
ID3D12RootSignature* rootSignature;
D3D12_VIEWPORT viewport;
D3D12_RECT scissorRect;
ID3D12Resource* vertexBuffer;
ID3D12Resource* indexBuffer;
D3D12_VERTEX_BUFFER_VIEW vertexBufferView;
D3D12_INDEX_BUFFER_VIEW indexBufferView;
ID3D12Resource* depthStencilBuffer;
ID3D12DescriptorHeap* dsDescriptorHeap;
int32 ConstantBufferPerObjectAlignedSize = (sizeof(ConstantBufferPerObject) + 255) & ~255;
ConstantBufferPerObject cbPerObject;
ID3D12Resource* constantBufferUploadHeaps[frameBufferCount];
uint8* cbvGPUAddress[frameBufferCount];
XMFLOAT4X4 cameraProjMat;
XMFLOAT4X4 cameraViewMat;
XMFLOAT4 cameraPosition;
XMFLOAT4 cameraTarget;
XMFLOAT4 cameraUp;
XMFLOAT4X4 cube1WorldMat;
XMFLOAT4X4 cube1RotMat;
XMFLOAT4 cube1Position;
XMFLOAT4X4 cube2WorldMat;
XMFLOAT4X4 cube2RotMat;
XMFLOAT4 cube2PositionOffset;
int32 numCubeIndices;
struct SThreadTest
{
uint8 DoWork()
{
for (SIZE_T i = 0; i < 100; ++i)
{
OutputDebugStringA("thread stuff\n");
}
return 0;
}
};
struct SThreadTest2
{
uint8 DoWork()
{
for (SIZE_T i = 0; i < 100; ++i)
{
OutputDebugStringA("thread stuff2\n");
}
return 0;
}
};
int32 WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int32 nShowCmd)
{
using namespace Aberration::Memory;
using namespace Aberration::OS;
//default memory allocator, basically aligned malloc and aligned free
IAllocator* allocator = GlobalAllocator;
//allocate single int
auto mem = TMemory<int>::Allocate(allocator);
//do something with memory mem
//free single int
TMemory<int>::Free(allocator, mem);
//allocate an array of 10 ints, non initialized
auto array = TMemory<int[]>::Allocate(allocator, 10);
//do something with memory array
//free array of ints
TMemory<int[]>::Free(allocator, array, 10);
//allocate an array of 10 ints, initialized
auto defaultinitedarray = TMemory<int[]>::Allocate(allocator, 10, 7);
//do something with memory defaultinitedarray
//free array of ints
TMemory<int[]>::Free(allocator, defaultinitedarray, 10);
Aberration::OS::FThread::FMainFunctionType ThreadMain;
SThreadTest ThreadTest;
ThreadMain.Bind<SThreadTest, &SThreadTest::DoWork>(&ThreadTest);
Aberration::OS::FThread::FMainFunctionType ThreadMain2;
SThreadTest2 ThreadTest2;
ThreadMain2.Bind<SThreadTest2, &SThreadTest2::DoWork>(&ThreadTest2);
//FThread TestThread;
//auto err = TestThread.Create(ThreadMain, "test", 0);
//FThread TestThread2;
//err = TestThread2.Create(ThreadMain2, "test2", 0);
/*for (SIZE_T i = 0; i < 100; ++i)
{
OutputDebugStringA("main thread\n");
}
*/
if (!InitializeWindow(hInstance, nShowCmd, FullScreen))
{
MessageBox(0, L"Window Initialization - Failed", L"Error", MB_OK);
return 1;
}
if (!InitD3D())
{
MessageBox(0, L"Failed to initialize direct3d 12", L"Error", MB_OK);
Cleanup();
return 1;
}
MSG msg = MSG();
while (Running)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
Update();
Render();
}
}
WaitForPreviousFrame();
CloseHandle(fenceEvent);
Cleanup();
return 0;
}
bool InitializeWindow(HINSTANCE hInstance, int32 ShowWnd, bool fullscreen)
{
if (fullscreen)
{
HMONITOR hmon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
MONITORINFO mi = { sizeof(mi) };
GetMonitorInfo(hmon, &mi);
Width = mi.rcMonitor.right - mi.rcMonitor.left;
Height = mi.rcMonitor.bottom - mi.rcMonitor.top;
}
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = NULL;
wc.cbWndExtra = NULL;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);
wc.lpszMenuName = NULL;
wc.lpszClassName = L"AberrationEngineWindowName";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, L"Error registering class", L"Error", MB_OK | MB_ICONERROR);
return false;
}
hwnd = CreateWindowEx(NULL, L"AberrationEngineWindowName", L"Aberration Engine", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, Width, Height, NULL, NULL, hInstance, NULL);
if (!hwnd)
{
MessageBox(NULL, L"Error creating window", L"Error", MB_OK | MB_ICONERROR);
return false;
}
if (fullscreen)
{
SetWindowLong(hwnd, GWL_STYLE, 0);
}
ShowWindow(hwnd, ShowWnd);
UpdateWindow(hwnd);
return true;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
{
if (MessageBox(0, L"Are you sure you want to exit?", L"Really?", MB_YESNO | MB_ICONQUESTION) == IDYES)
{
Running = false;
DestroyWindow(hwnd);
}
}
return 0;
case WM_DESTROY:
Running = false;
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
bool InitD3D()
{
IDXGIFactory4* dxgiFactory;
auto hr = CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory));
if (FAILED(hr))
{
return false;
}
IDXGIAdapter1* adapter;
int32 adapterIndex = 0;
bool adapterFound = false;
while (dxgiFactory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND)
{
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
{
adapterIndex++;
continue;
}
auto hresult = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr);
if (SUCCEEDED(hresult))
{
adapterFound = true;
break;
}
adapterIndex++;
}
if (!adapterFound)
{
return false;
}
{
// Create the device
auto res = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device));
if (FAILED(res))
{
return false;
}
}
D3D12_COMMAND_QUEUE_DESC cqDesc = {};
cqDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
cqDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
if (FAILED(device->CreateCommandQueue(&cqDesc, IID_PPV_ARGS(&commandQueue))))
{
return false;
}
DXGI_MODE_DESC backBufferDesc = {};
backBufferDesc.Width = Width;
backBufferDesc.Height = Height;
backBufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
swapChainDesc.BufferCount = frameBufferCount;
swapChainDesc.BufferDesc = backBufferDesc;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapChainDesc.OutputWindow = hwnd;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.Windowed = !FullScreen;
IDXGISwapChain* tempSwapChain;
dxgiFactory->CreateSwapChain(commandQueue, &swapChainDesc, &tempSwapChain);
swapChain = static_cast<IDXGISwapChain3*>(tempSwapChain);
frameIndex = swapChain->GetCurrentBackBufferIndex();
D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = D3D12_DESCRIPTOR_HEAP_DESC();
rtvHeapDesc.NumDescriptors = frameBufferCount;
rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
hr = device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&rtvDescriptorHeap));
if (FAILED(hr))
{
return false;
}
rtvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle(rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
for (SIZE_T i = 0; i < frameBufferCount; i++)
{
hr = swapChain->GetBuffer((UINT)i, IID_PPV_ARGS(&renderTargets[i]));
if (FAILED(hr))
{
return false;
}
device->CreateRenderTargetView(renderTargets[i], nullptr, rtvHandle);
rtvHandle.ptr += 1 * rtvDescriptorSize;
}
for (SIZE_T i = 0; i < frameBufferCount; i++)
{
if (FAILED(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&commandAllocator[i]))))
{
return false;
}
}
if (FAILED(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, commandAllocator[frameIndex], NULL, IID_PPV_ARGS(&commandList))))
{
return false;
}
for (SIZE_T i = 0; i < frameBufferCount; i++)
{
hr = device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence[i]));
if (FAILED(hr))
{
return false;
}
fenceValue[i] = 0;
}
fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
if (fenceEvent == nullptr)
{
return false;
}
D3D12_ROOT_DESCRIPTOR rootCBVDescriptor;
rootCBVDescriptor.RegisterSpace = 0;
rootCBVDescriptor.ShaderRegister = 0;
D3D12_ROOT_PARAMETER rootParameters[1];
rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
rootParameters[0].Descriptor = rootCBVDescriptor;
rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = D3D12_ROOT_SIGNATURE_DESC();
rootSignatureDesc.NumParameters = _countof(rootParameters);
rootSignatureDesc.pParameters = rootParameters;
rootSignatureDesc.NumStaticSamplers = 0;
rootSignatureDesc.pStaticSamplers = nullptr;
rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS;
ID3DBlob* signature;
if (FAILED(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, nullptr))) { return false; }
if (FAILED(device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&rootSignature)))) { return false; }
ID3DBlob* vertexShader;
ID3DBlob* errorBuff;
hr = D3DCompileFromFile(L"BaseShader.vs.hlsl", nullptr, nullptr, "main", "vs_5_0", D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION, 0, &vertexShader, &errorBuff);
if (FAILED(hr))
{
OutputDebugStringA((LPCSTR)errorBuff->GetBufferPointer());
return false;
}
D3D12_SHADER_BYTECODE vertexShaderBytecode = {};
vertexShaderBytecode.BytecodeLength = vertexShader->GetBufferSize();
vertexShaderBytecode.pShaderBytecode = vertexShader->GetBufferPointer();
// compile pixel shader
ID3DBlob* pixelShader;
hr = D3DCompileFromFile(L"BaseShader.ps.hlsl", nullptr, nullptr, "main", "ps_5_0", D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION, 0, &pixelShader, &errorBuff);
if (FAILED(hr))
{
OutputDebugStringA((LPCSTR)errorBuff->GetBufferPointer());
return false;
}
D3D12_SHADER_BYTECODE pixelShaderBytecode = {};
pixelShaderBytecode.BytecodeLength = pixelShader->GetBufferSize();
pixelShaderBytecode.pShaderBytecode = pixelShader->GetBufferPointer();
const D3D12_INPUT_ELEMENT_DESC inputLayout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
};
D3D12_INPUT_LAYOUT_DESC inputLayoutDesc = {};
inputLayoutDesc.NumElements = sizeof(inputLayout) / sizeof(D3D12_INPUT_ELEMENT_DESC);
inputLayoutDesc.pInputElementDescs = inputLayout;
D3D12_RASTERIZER_DESC rasterDesc = D3D12_RASTERIZER_DESC();
rasterDesc.FillMode = D3D12_FILL_MODE_SOLID;
rasterDesc.CullMode = D3D12_CULL_MODE_BACK;
rasterDesc.FrontCounterClockwise = FALSE;
rasterDesc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
rasterDesc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
rasterDesc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
rasterDesc.DepthClipEnable = TRUE;
rasterDesc.MultisampleEnable = FALSE;
rasterDesc.AntialiasedLineEnable = FALSE;
rasterDesc.ForcedSampleCount = 0;
rasterDesc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
D3D12_BLEND_DESC blendDesc = D3D12_BLEND_DESC();
blendDesc.IndependentBlendEnable = FALSE;
const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc =
{
FALSE,FALSE,
D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
D3D12_LOGIC_OP_NOOP,
D3D12_COLOR_WRITE_ENABLE_ALL,
};
for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
{
blendDesc.RenderTarget[i] = defaultRenderTargetBlendDesc;
}
D3D12_DEPTH_STENCIL_DESC dsDesc = D3D12_DEPTH_STENCIL_DESC();
dsDesc.DepthEnable = TRUE;
dsDesc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
dsDesc.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
dsDesc.StencilEnable = FALSE;
dsDesc.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;
dsDesc.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;
const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =
{ D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };
dsDesc.FrontFace = defaultStencilOp;
dsDesc.BackFace = defaultStencilOp;
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.InputLayout = inputLayoutDesc;
psoDesc.pRootSignature = rootSignature;
psoDesc.VS = vertexShaderBytecode;
psoDesc.PS = pixelShaderBytecode;
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
psoDesc.SampleDesc.Count = 1;
psoDesc.SampleMask = 0xffffffff;
psoDesc.RasterizerState = rasterDesc;
psoDesc.BlendState = blendDesc;
psoDesc.NumRenderTargets = 1;
psoDesc.DepthStencilState = dsDesc;
// create the pso
if (FAILED(device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pipelineStateObject))))
{
return false;
}
Vertex vList[] = {
// front face
{ -0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f },
{ 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f },
{ -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f },
{ 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f },
// right side face
{ 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f },
{ 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f },
{ 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f },
{ 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f },
// left side face
{ -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f },
{ -0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f },
{ -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f },
{ -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f },
// back face
{ 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f },
{ -0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f },
{ 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f },
{ -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f },
// top face
{ -0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f },
{ 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f },
{ 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f },
{ -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f },
// bottom face
{ 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f },
{ -0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f },
{ 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f },
{ -0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f },
};
int32 vBufferSize = sizeof(vList);
D3D12_HEAP_PROPERTIES heapProps = D3D12_HEAP_PROPERTIES();
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapProps.CreationNodeMask = 1;
heapProps.VisibleNodeMask = 1;
D3D12_RESOURCE_DESC bufferResourceDesc = D3D12_RESOURCE_DESC();
bufferResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
bufferResourceDesc.Alignment = 0;
bufferResourceDesc.Width = vBufferSize;
bufferResourceDesc.Height = 1;
bufferResourceDesc.DepthOrArraySize = 1;
bufferResourceDesc.MipLevels = 1;
bufferResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
bufferResourceDesc.SampleDesc.Count = 1;
bufferResourceDesc.SampleDesc.Quality = 0;
bufferResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
bufferResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &bufferResourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&vertexBuffer));
vertexBuffer->SetName(L"Vertex Buffer Resource Heap");
ID3D12Resource* vBufferUploadHeap;
heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &bufferResourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&vBufferUploadHeap));
vBufferUploadHeap->SetName(L"Vertex Buffer Upload Resource Heap");
D3D12_SUBRESOURCE_DATA vertexData = {};
vertexData.pData = reinterpret_cast<BYTE*>(vList);
vertexData.RowPitch = vBufferSize;
vertexData.SlicePitch = vBufferSize;
UpdateSubresources(commandList, vertexBuffer, vBufferUploadHeap, 0, 0, 1, &vertexData);
D3D12_RESOURCE_BARRIER barrier = D3D12_RESOURCE_BARRIER();
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = vertexBuffer;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
commandList->ResourceBarrier(1, &barrier);
DWORD iList[] =
{
// ffront face
0, 1, 2, // first triangle
0, 3, 1, // second triangle
// left face
4, 5, 6, // first triangle
4, 7, 5, // second triangle
// right face
8, 9, 10, // first triangle
8, 11, 9, // second triangle
// back face
12, 13, 14, // first triangle
12, 15, 13, // second triangle
// top face
16, 17, 18, // first triangle
16, 19, 17, // second triangle
// bottom face
20, 21, 22, // first triangle
20, 23, 21, // second triangle
};
int32 iBufferSize = sizeof(iList);
numCubeIndices = sizeof(iList) / sizeof(DWORD);
D3D12_RESOURCE_DESC indexBufferResourceDesc = D3D12_RESOURCE_DESC();
indexBufferResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
indexBufferResourceDesc.Alignment = 0;
indexBufferResourceDesc.Width = iBufferSize;
indexBufferResourceDesc.Height = 1;
indexBufferResourceDesc.DepthOrArraySize = 1;
indexBufferResourceDesc.MipLevels = 1;
indexBufferResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
indexBufferResourceDesc.SampleDesc.Count = 1;
indexBufferResourceDesc.SampleDesc.Quality = 0;
indexBufferResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
indexBufferResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &indexBufferResourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&indexBuffer));
vertexBuffer->SetName(L"Index Buffer Resource Heap");
ID3D12Resource* iBufferUploadHeap;
heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &bufferResourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&iBufferUploadHeap));
vBufferUploadHeap->SetName(L"Index Buffer Upload Resource Heap");
D3D12_SUBRESOURCE_DATA indexData = {};
indexData.pData = reinterpret_cast<BYTE*>(iList);
indexData.RowPitch = iBufferSize;
indexData.SlicePitch = iBufferSize;
UpdateSubresources(commandList, indexBuffer, iBufferUploadHeap, 0, 0, 1, &indexData);
D3D12_RESOURCE_BARRIER indexBufferBarrier = D3D12_RESOURCE_BARRIER();
indexBufferBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
indexBufferBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
indexBufferBarrier.Transition.pResource = indexBuffer;
indexBufferBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
indexBufferBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
indexBufferBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
commandList->ResourceBarrier(1, &indexBufferBarrier);
D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {};
dsvHeapDesc.NumDescriptors = 1;
dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
if (FAILED(device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&dsDescriptorHeap))))
{
Running = false;
}
D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilDesc = {};
depthStencilDesc.Format = DXGI_FORMAT_D32_FLOAT;
depthStencilDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
depthStencilDesc.Flags = D3D12_DSV_FLAG_NONE;
D3D12_CLEAR_VALUE depthOptimizedClearValue = {};
depthOptimizedClearValue.Format = DXGI_FORMAT_D32_FLOAT;
depthOptimizedClearValue.DepthStencil.Depth = 1.0f;
depthOptimizedClearValue.DepthStencil.Stencil = 0;
D3D12_RESOURCE_DESC depthstencilResourceDesc = D3D12_RESOURCE_DESC();
depthstencilResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
depthstencilResourceDesc.Alignment = 0;
depthstencilResourceDesc.Width = Width;
depthstencilResourceDesc.Height = Height;
depthstencilResourceDesc.DepthOrArraySize = 1;
depthstencilResourceDesc.MipLevels = 0;
depthstencilResourceDesc.Format = DXGI_FORMAT_D32_FLOAT;
depthstencilResourceDesc.SampleDesc.Count = 1;
depthstencilResourceDesc.SampleDesc.Quality = 0;
depthstencilResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
depthstencilResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &depthstencilResourceDesc, D3D12_RESOURCE_STATE_DEPTH_WRITE, &depthOptimizedClearValue, IID_PPV_ARGS(&depthStencilBuffer));
dsDescriptorHeap->SetName(L"Depth/Stencil Resource Heap");
device->CreateDepthStencilView(depthStencilBuffer, &depthStencilDesc, dsDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
for (int32 i = 0; i < frameBufferCount; ++i)
{
D3D12_RESOURCE_DESC constantBufferResourceDesc = D3D12_RESOURCE_DESC();
constantBufferResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
constantBufferResourceDesc.Alignment = 0;
constantBufferResourceDesc.Width = 1024 * 64;
constantBufferResourceDesc.Height = 1;
constantBufferResourceDesc.DepthOrArraySize = 1;
constantBufferResourceDesc.MipLevels = 1;
constantBufferResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
constantBufferResourceDesc.SampleDesc.Count = 1;
constantBufferResourceDesc.SampleDesc.Quality = 0;
constantBufferResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
constantBufferResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
hr = device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &constantBufferResourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&constantBufferUploadHeaps[i]));
constantBufferUploadHeaps[i]->SetName(L"Constant Buffer Upload Resource Heap");
ZeroMemory(&cbPerObject, sizeof(cbPerObject));
D3D12_RANGE readRange = D3D12_RANGE();
readRange.Begin = 0;
readRange.End = 0;
hr = constantBufferUploadHeaps[i]->Map(0, &readRange, reinterpret_cast<void**>(&cbvGPUAddress[i]));
memcpy(cbvGPUAddress[i], &cbPerObject, sizeof(cbPerObject));
memcpy(cbvGPUAddress[i] + ConstantBufferPerObjectAlignedSize, &cbPerObject, sizeof(cbPerObject));
}
commandList->Close();
ID3D12CommandList* ppCommandLists[] = { commandList };
commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
fenceValue[frameIndex]++;
hr = commandQueue->Signal(fence[frameIndex], fenceValue[frameIndex]);
if (FAILED(hr))
{
Running = false;
}
vertexBufferView.BufferLocation = vertexBuffer->GetGPUVirtualAddress();
vertexBufferView.StrideInBytes = sizeof(Vertex);
vertexBufferView.SizeInBytes = vBufferSize;
indexBufferView.BufferLocation = indexBuffer->GetGPUVirtualAddress();
indexBufferView.Format = DXGI_FORMAT_R32_UINT;
indexBufferView.SizeInBytes = iBufferSize;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = (FLOAT)Width;
viewport.Height = (FLOAT)Height;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
scissorRect.left = 0;
scissorRect.top = 0;
scissorRect.right = (LONG)Width;
scissorRect.bottom = (LONG)Height;
XMMATRIX tmpMat = XMMatrixPerspectiveFovLH(45.0f*(3.14f / 180.0f), (float)Width / (float)Height, 0.1f, 1000.0f);
XMStoreFloat4x4(&cameraProjMat, tmpMat);
cameraPosition = XMFLOAT4(0.0f, 2.0f, -4.0f, 0.0f);
cameraTarget = XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f);
cameraUp = XMFLOAT4(0.0f, 1.0f, 0.0f, 0.0f);
XMVECTOR cPos = XMLoadFloat4(&cameraPosition);
XMVECTOR cTarg = XMLoadFloat4(&cameraTarget);
XMVECTOR cUp = XMLoadFloat4(&cameraUp);
tmpMat = XMMatrixLookAtLH(cPos, cTarg, cUp);
XMStoreFloat4x4(&cameraViewMat, tmpMat);
// first cube
cube1Position = XMFLOAT4(0.0f, 0.0f, 0.0f, 0.0f);
XMVECTOR posVec = XMLoadFloat4(&cube1Position);
tmpMat = XMMatrixTranslationFromVector(posVec);
XMStoreFloat4x4(&cube1RotMat, XMMatrixIdentity());
XMStoreFloat4x4(&cube1WorldMat, tmpMat);
// second cube
cube2PositionOffset = XMFLOAT4(1.5f, 0.0f, 0.0f, 0.0f);
posVec = XMLoadFloat4(&cube2PositionOffset) + XMLoadFloat4(&cube1Position);
tmpMat = XMMatrixTranslationFromVector(posVec);
XMStoreFloat4x4(&cube2RotMat, XMMatrixIdentity());
XMStoreFloat4x4(&cube2WorldMat, tmpMat);
return true;
}
void Update()
{
XMMATRIX rotXMat = XMMatrixRotationX(0.0001f);
XMMATRIX rotYMat = XMMatrixRotationY(0.0002f);
XMMATRIX rotZMat = XMMatrixRotationZ(0.0003f);
XMMATRIX rotMat = XMLoadFloat4x4(&cube1RotMat) * rotXMat * rotYMat * rotZMat;
XMStoreFloat4x4(&cube1RotMat, rotMat);
XMMATRIX translationMat = XMMatrixTranslationFromVector(XMLoadFloat4(&cube1Position));
XMMATRIX worldMat = rotMat * translationMat;
XMStoreFloat4x4(&cube1WorldMat, worldMat);
XMMATRIX viewMat = XMLoadFloat4x4(&cameraViewMat);
XMMATRIX projMat = XMLoadFloat4x4(&cameraProjMat);
XMMATRIX wvpMat = XMLoadFloat4x4(&cube1WorldMat) * viewMat * projMat;
XMMATRIX transposed = XMMatrixTranspose(wvpMat);
XMStoreFloat4x4(&cbPerObject.wvpMat, transposed);
memcpy(cbvGPUAddress[frameIndex], &cbPerObject, sizeof(cbPerObject));
rotXMat = XMMatrixRotationX(0.0003f);
rotYMat = XMMatrixRotationY(0.0002f);
rotZMat = XMMatrixRotationZ(0.0001f);
rotMat = rotZMat * (XMLoadFloat4x4(&cube2RotMat) * (rotXMat * rotYMat));
XMStoreFloat4x4(&cube2RotMat, rotMat);
XMMATRIX translationOffsetMat = XMMatrixTranslationFromVector(XMLoadFloat4(&cube2PositionOffset));
XMMATRIX scaleMat = XMMatrixScaling(0.5f, 0.5f, 0.5f);
worldMat = scaleMat * translationOffsetMat * rotMat * translationMat;
wvpMat = XMLoadFloat4x4(&cube2WorldMat) * viewMat * projMat;
transposed = XMMatrixTranspose(wvpMat);
XMStoreFloat4x4(&cbPerObject.wvpMat, transposed);
memcpy(cbvGPUAddress[frameIndex] + ConstantBufferPerObjectAlignedSize, &cbPerObject, sizeof(cbPerObject));
XMStoreFloat4x4(&cube2WorldMat, worldMat);
}
void UpdatePipeline()
{
HRESULT hr;
WaitForPreviousFrame();
if (FAILED(commandAllocator[frameIndex]->Reset()))
{
Running = false;
}
hr = commandList->Reset(commandAllocator[frameIndex], pipelineStateObject);
if (FAILED(hr))
{
Running = false;
}
D3D12_RESOURCE_BARRIER renderTargetsBarrier = D3D12_RESOURCE_BARRIER();
renderTargetsBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
renderTargetsBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
renderTargetsBarrier.Transition.pResource = renderTargets[frameIndex];
renderTargetsBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
renderTargetsBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
renderTargetsBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
commandList->ResourceBarrier(1, &renderTargetsBarrier);
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle(rtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
rtvHandle.ptr += (int32)frameIndex * rtvDescriptorSize;
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle(dsDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);
const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
commandList->ClearDepthStencilView(dsDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
commandList->SetGraphicsRootSignature(rootSignature);
commandList->RSSetViewports(1, &viewport);
commandList->RSSetScissorRects(1, &scissorRect);
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
commandList->IASetVertexBuffers(0, 1, &vertexBufferView);
commandList->IASetIndexBuffer(&indexBufferView);
//first cube
commandList->SetGraphicsRootConstantBufferView(0, constantBufferUploadHeaps[frameIndex]->GetGPUVirtualAddress());
commandList->DrawIndexedInstanced(numCubeIndices, 1, 0, 0, 0);
//second cube
commandList->SetGraphicsRootConstantBufferView(0, constantBufferUploadHeaps[frameIndex]->GetGPUVirtualAddress() + ConstantBufferPerObjectAlignedSize);
commandList->DrawIndexedInstanced(numCubeIndices, 1, 0, 0, 0);
D3D12_RESOURCE_BARRIER presentBarrier = D3D12_RESOURCE_BARRIER();
presentBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
presentBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
presentBarrier.Transition.pResource = renderTargets[frameIndex];
presentBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
presentBarrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
presentBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
commandList->ResourceBarrier(1, &presentBarrier);
hr = commandList->Close();
if (FAILED(hr))
{
Running = false;
}
}
void Render()
{
UpdatePipeline();
ID3D12CommandList* ppCommandLists[] = { commandList };
commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
auto hr = commandQueue->Signal(fence[frameIndex], fenceValue[frameIndex]);
if (FAILED(hr))
{
Running = false;
}
hr = swapChain->Present(0, 0);
if (FAILED(hr))
{
Running = false;
}
}
void Cleanup()
{
for (SIZE_T i = 0; i < frameBufferCount; ++i)
{
frameIndex = i;
WaitForPreviousFrame();
}
BOOL fs = false;
if (swapChain->GetFullscreenState(&fs, NULL))
{
swapChain->SetFullscreenState(false, NULL);
}
SAFE_RELEASE(swapChain);
SAFE_RELEASE(commandQueue);
SAFE_RELEASE(rtvDescriptorHeap);
SAFE_RELEASE(commandList);
for (SIZE_T i = 0; i < frameBufferCount; ++i)
{
SAFE_RELEASE(renderTargets[i]);
SAFE_RELEASE(commandAllocator[i]);
SAFE_RELEASE(fence[i]);
};
SAFE_RELEASE(pipelineStateObject);
SAFE_RELEASE(rootSignature);
SAFE_RELEASE(vertexBuffer);
SAFE_RELEASE(indexBuffer);
SAFE_RELEASE(depthStencilBuffer);
SAFE_RELEASE(dsDescriptorHeap);
for (SIZE_T i = 0; i < frameBufferCount; ++i)
{
SAFE_RELEASE(constantBufferUploadHeaps[i]);
};
}
void WaitForPreviousFrame()
{
frameIndex = swapChain->GetCurrentBackBufferIndex();
if (fence[frameIndex]->GetCompletedValue() < fenceValue[frameIndex])
{
auto hr = fence[frameIndex]->SetEventOnCompletion(fenceValue[frameIndex], fenceEvent);
if (FAILED(hr))
{
Running = false;
}
WaitForSingleObject(fenceEvent, INFINITE);
}
fenceValue[frameIndex]++;
}
Comments
0 B
|👍
/👎
0 B
|0 👍
/0 👎
0 B
|0 👍
/0 👎