I'm learning DirectX 12. I would like to draw a triangle, but DirectX 12 doesn't draw it. I wonder if there's something I forgot.
This is Init() part.
void Engine::Init() {
mDevice = new Device();
mCommandQueue = new CommandQueue();
mSwapChain = new SwapChain();
mDescriptorHeap = new DescriptorHeap();
mRootSignature = new RootSignature();
mDevice->Init();
mCommandQueue->Init(mDevice->GetDevice());
mSwapChain->Init(mDevice->GetDevice(), mDevice->GetFactory(), mCommandQueue->GetCommandQueue(), mWndInfo);
mDescriptorHeap->Init(mDevice->GetDevice(), mSwapChain);
mRootSignature->Init(mDevice->GetDevice());
mesh = new Mesh();
shader = new Shader(mRootSignature);
D3D12_INPUT_ELEMENT_DESC desc[] = {
{"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}
};
shader->Init(mDevice->GetDevice(), L"..\\Resources\\Shader\\default.hlsli");
shader->SetPipelineState(mDevice->GetDevice(), desc, _countof(desc));
std::vector<Vertex> vec(3);
vec[0].pos = Vec3(0.0f, 0.5f, 0.5f);
vec[0].color = Vec4(1.0f, 0.0f, 0.0f, 1.0f);
vec[1].pos = Vec3(0.5f, -0.5f, 0.5f);
vec[1].color = Vec4(0.0f, 1.0f, 0.0f, 1.0f);
vec[2].pos = Vec3(-0.5f, -0.5f, 0.5f);
vec[2].color = Vec4(0.0f, 0.0f, 1.0f, 1.0f);
mesh->Init(mDevice->GetDevice(), vec);
mCommandQueue->WaitForPreviousFrame(mSwapChain);
}
void Mesh::Init(ID3D12Device* const device, const std::vector<Vertex>& vec) {
mVertexCount = static_cast<uint32>(vec.size());
const uint32 bufferSize = mVertexCount * sizeof(Vertex);
D3D12_HEAP_PROPERTIES heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
D3D12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Buffer(bufferSize);
ThrowIfFailed(device->CreateCommittedResource(
&heapProperties,
D3D12_HEAP_FLAG_NONE,
&resourceDesc,
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&mVertexBuffer)));
// Copy the triangle data to the vertex buffer.
void* pVertexDataBuffer = nullptr;
CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU.
ThrowIfFailed(mVertexBuffer->Map(0, &readRange, &pVertexDataBuffer));
std::memcpy(pVertexDataBuffer, &vec[0], bufferSize);
mVertexBuffer->Unmap(0, nullptr);
// Initialize the vertex buffer view.
mVertexBufferView.BufferLocation = mVertexBuffer->GetGPUVirtualAddress();
mVertexBufferView.StrideInBytes = sizeof(Vertex);
mVertexBufferView.SizeInBytes = bufferSize;
}
After Init, This code will be executed.
void Engine::Render() {
mCommandQueue->RenderBegin(mSwapChain, mDescriptorHeap, shader->GetGraphicsPSO(), &mViewport, &mScissorRect);
mesh->Render(mCommandQueue->GetCommandList());
mCommandQueue->RenderEnd(mSwapChain);
}
void CommandQueue::RenderBegin(SwapChain* swapChain, DescriptorHeap* descHeap, GraphicsPSO* graphicsPSO, const D3D12_VIEWPORT* viewPort, const D3D12_RECT* scissorRect) {
ThrowIfFailed(mCommandAllocator->Reset());
ThrowIfFailed(mCommandList->Reset(mCommandAllocator, graphicsPSO->GetPipelineState()));
mCommandList->SetGraphicsRootSignature(graphicsPSO->GetRootSignatrue()->GetRootSignature());
mCommandList->RSSetViewports(1, viewPort);
mCommandList->RSSetScissorRects(1, scissorRect);
// Indicate that the back buffer will be used as a render target.
D3D12_RESOURCE_BARRIER resourceBarrierDesc = CD3DX12_RESOURCE_BARRIER::Transition(swapChain->GetBackRtvBuffer(),
D3D12_RESOURCE_STATE_PRESENT,
D3D12_RESOURCE_STATE_RENDER_TARGET);
mCommandList->ResourceBarrier(1, &resourceBarrierDesc);
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = descHeap->GetBackRtvHandle();
const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
mCommandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);
mCommandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
}
void Mesh::Render(ID3D12GraphicsCommandList* cmdList) {
cmdList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
cmdList->IASetVertexBuffers(0, 1, &mVertexBufferView);
cmdList->DrawInstanced(mVertexCount, 1, 0, 0);
}
void CommandQueue::RenderEnd(SwapChain* swapChain) {
// Indicate that the back buffer will now be used to present.
D3D12_RESOURCE_BARRIER resourceBarrierDesc = CD3DX12_RESOURCE_BARRIER::Transition(swapChain->GetBackRtvBuffer(),
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PRESENT);
mCommandList->ResourceBarrier(1, &resourceBarrierDesc);
ThrowIfFailed(mCommandList->Close());
// Execute the command list.
ID3D12CommandList* ppCommandLists[] = { mCommandList };
mCommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
// Back buffer <-> Front buffer
swapChain->Present();
WaitForPreviousFrame(swapChain);
swapChain->SwapIndex();
}
Result is like this: enter image description here
There's no error. I compared my code with DirectX sample code "Hello Triangle", but I wrote most of DirectX code to render such as OMSetRenderTargets
, ResourceBarrier
, etc.
Windows 10, GTX 750ti, support DirectX 12.