DX12: first triangle.
This commit is contained in:
parent
9b01830559
commit
a32a863d83
31
src/engine/renderer/shaders/shaders.hlsl
Normal file
31
src/engine/renderer/shaders/shaders.hlsl
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
|
||||
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
|
||||
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
struct PSInput
|
||||
{
|
||||
float4 position : SV_POSITION;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
PSInput VSMain(float4 position : POSITION, float4 color : COLOR)
|
||||
{
|
||||
PSInput result;
|
||||
|
||||
result.position = position;
|
||||
result.color = color;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float4 PSMain(PSInput input) : SV_TARGET
|
||||
{
|
||||
return input.color;
|
||||
}
|
||||
|
|
@ -797,6 +797,8 @@ static void deinit_vulkan_library() {
|
|||
|
||||
VkPipeline create_pipeline(const Vk_Pipeline_Def&);
|
||||
|
||||
void wait_for_previous_frame();
|
||||
|
||||
// Helper function for acquiring the first available hardware adapter that supports Direct3D 12.
|
||||
// If no such adapter can be found, *ppAdapter will be set to nullptr.
|
||||
void get_hardware_adapter(IDXGIFactory4* p_factory, IDXGIAdapter1** pp_adapter) {
|
||||
|
|
@ -899,13 +901,108 @@ void dx_initialize() {
|
|||
|
||||
DX_CHECK(vk.dx_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&vk.dx_command_allocator)));
|
||||
|
||||
// Create an empty root signature.
|
||||
{
|
||||
CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc;
|
||||
rootSignatureDesc.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
|
||||
|
||||
DX_CHECK(vk.dx_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, vk.dx_command_allocator, nullptr, IID_PPV_ARGS(&vk.dx_command_list)));
|
||||
ComPtr<ID3DBlob> signature;
|
||||
ComPtr<ID3DBlob> error;
|
||||
DX_CHECK(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
|
||||
DX_CHECK(vk.dx_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&vk.dx_root_signature)));
|
||||
}
|
||||
|
||||
// Create the pipeline state, which includes compiling and loading shaders.
|
||||
{
|
||||
ComPtr<ID3DBlob> vertexShader;
|
||||
ComPtr<ID3DBlob> pixelShader;
|
||||
|
||||
#if defined(_DEBUG)
|
||||
// Enable better shader debugging with the graphics debugging tools.
|
||||
UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||
#else
|
||||
UINT compileFlags = 0;
|
||||
#endif
|
||||
|
||||
DX_CHECK(D3DCompileFromFile(L"../src/engine/renderer/shaders/shaders.hlsl", nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &vertexShader, nullptr));
|
||||
DX_CHECK(D3DCompileFromFile(L"../src/engine/renderer/shaders/shaders.hlsl", nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, &pixelShader, nullptr));
|
||||
|
||||
// Define the vertex input layout.
|
||||
D3D12_INPUT_ELEMENT_DESC inputElementDescs[] =
|
||||
{
|
||||
{ "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 }
|
||||
};
|
||||
|
||||
// Describe and create the graphics pipeline state object (PSO).
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
|
||||
psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) };
|
||||
psoDesc.pRootSignature = vk.dx_root_signature;
|
||||
psoDesc.VS = CD3DX12_SHADER_BYTECODE(vertexShader.Get());
|
||||
psoDesc.PS = CD3DX12_SHADER_BYTECODE(pixelShader.Get());
|
||||
psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
|
||||
psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
|
||||
psoDesc.DepthStencilState.DepthEnable = FALSE;
|
||||
psoDesc.DepthStencilState.StencilEnable = FALSE;
|
||||
psoDesc.SampleMask = UINT_MAX;
|
||||
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
psoDesc.NumRenderTargets = 1;
|
||||
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
psoDesc.SampleDesc.Count = 1;
|
||||
DX_CHECK(vk.dx_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&vk.dx_pipeline_state)));
|
||||
}
|
||||
|
||||
DX_CHECK(vk.dx_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, vk.dx_command_allocator, vk.dx_pipeline_state, IID_PPV_ARGS(&vk.dx_command_list)));
|
||||
|
||||
// Command lists are created in the recording state, but there is nothing
|
||||
// to record yet. The main loop expects it to be closed, so close it now.
|
||||
DX_CHECK(vk.dx_command_list->Close());
|
||||
|
||||
// Create the vertex buffer.
|
||||
{
|
||||
struct Vertex
|
||||
{
|
||||
XMFLOAT3 position;
|
||||
XMFLOAT4 color;
|
||||
};
|
||||
|
||||
float aspect_ratio = float(glConfig.vidWidth) / float(glConfig.vidHeight);
|
||||
|
||||
// Define the geometry for a triangle.
|
||||
Vertex triangleVertices[] =
|
||||
{
|
||||
{ { 0.0f, 0.25f * aspect_ratio, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
|
||||
{ { 0.25f, -0.25f * aspect_ratio, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
|
||||
{ { -0.25f, -0.25f * aspect_ratio, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }
|
||||
};
|
||||
|
||||
const UINT vertexBufferSize = sizeof(triangleVertices);
|
||||
|
||||
// Note: using upload heaps to transfer static data like vert buffers is not
|
||||
// recommended. Every time the GPU needs it, the upload heap will be marshalled
|
||||
// over. Please read up on Default Heap usage. An upload heap is used here for
|
||||
// code simplicity and because there are very few verts to actually transfer.
|
||||
DX_CHECK(vk.dx_device->CreateCommittedResource(
|
||||
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize),
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&vk.dx_vertex_buffer)));
|
||||
|
||||
// Copy the triangle data to the vertex buffer.
|
||||
UINT8* pVertexDataBegin;
|
||||
CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU.
|
||||
DX_CHECK(vk.dx_vertex_buffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin)));
|
||||
memcpy(pVertexDataBegin, triangleVertices, sizeof(triangleVertices));
|
||||
vk.dx_vertex_buffer->Unmap(0, nullptr);
|
||||
|
||||
// Initialize the vertex buffer view.
|
||||
vk.dx_vertex_buffer_view.BufferLocation = vk.dx_vertex_buffer->GetGPUVirtualAddress();
|
||||
vk.dx_vertex_buffer_view.StrideInBytes = sizeof(Vertex);
|
||||
vk.dx_vertex_buffer_view.SizeInBytes = vertexBufferSize;
|
||||
}
|
||||
|
||||
// Create synchronization objects.
|
||||
{
|
||||
DX_CHECK(vk.dx_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&vk.dx_fence)));
|
||||
|
|
@ -917,18 +1014,50 @@ void dx_initialize() {
|
|||
{
|
||||
DX_CHECK(HRESULT_FROM_WIN32(GetLastError()));
|
||||
}
|
||||
|
||||
// Wait for the command list to execute; we are reusing the same command
|
||||
// list in our main loop but for now, we just want to wait for setup to
|
||||
// complete before continuing.
|
||||
wait_for_previous_frame();
|
||||
}
|
||||
}
|
||||
|
||||
void dx_shutdown() {
|
||||
vk.dx_swapchain.Reset();
|
||||
|
||||
vk.dx_command_allocator->Release();
|
||||
vk.dx_command_allocator = nullptr;
|
||||
|
||||
for (int i = 0; i < D3D_FRAME_COUNT; i++) {
|
||||
vk.dx_render_targets[i]->Release();
|
||||
}
|
||||
|
||||
// Create an empty root signature.
|
||||
/* {
|
||||
CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc;
|
||||
rootSignatureDesc.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
|
||||
vk.dx_rtv_heap->Release();
|
||||
vk.dx_rtv_heap = nullptr;
|
||||
|
||||
ComPtr<ID3DBlob> signature;
|
||||
ComPtr<ID3DBlob> error;
|
||||
DX_CHECK(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
|
||||
DX_CHECK(vk.dx_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature)));
|
||||
}*/
|
||||
vk.dx_root_signature->Release();
|
||||
vk.dx_root_signature = nullptr;
|
||||
|
||||
vk.dx_command_queue->Release();
|
||||
vk.dx_command_queue = nullptr;
|
||||
|
||||
vk.dx_command_list->Release();
|
||||
vk.dx_command_list = nullptr;
|
||||
|
||||
vk.dx_pipeline_state->Release();
|
||||
vk.dx_pipeline_state = nullptr;
|
||||
|
||||
vk.dx_fence->Release();
|
||||
vk.dx_fence = nullptr;
|
||||
|
||||
::CloseHandle(vk.dx_fence_event);
|
||||
vk.dx_fence_event = NULL;
|
||||
|
||||
vk.dx_vertex_buffer->Release();
|
||||
vk.dx_vertex_buffer = nullptr;
|
||||
|
||||
vk.dx_device->Release();
|
||||
vk.dx_device = nullptr;
|
||||
}
|
||||
|
||||
void vk_initialize() {
|
||||
|
|
@ -1411,35 +1540,6 @@ void vk_initialize() {
|
|||
vk.active = true;
|
||||
}
|
||||
|
||||
void dx_shutdown() {
|
||||
vk.dx_swapchain.Reset();
|
||||
|
||||
vk.dx_command_allocator->Release();
|
||||
vk.dx_command_allocator = nullptr;
|
||||
|
||||
for (int i = 0; i < D3D_FRAME_COUNT; i++) {
|
||||
vk.dx_render_targets[i]->Release();
|
||||
}
|
||||
|
||||
vk.dx_rtv_heap->Release();
|
||||
vk.dx_rtv_heap = nullptr;
|
||||
|
||||
vk.dx_command_queue->Release();
|
||||
vk.dx_command_queue = nullptr;
|
||||
|
||||
vk.dx_command_list->Release();
|
||||
vk.dx_command_list = nullptr;
|
||||
|
||||
vk.dx_fence->Release();
|
||||
vk.dx_fence = nullptr;
|
||||
|
||||
::CloseHandle(vk.dx_fence_event);
|
||||
vk.dx_fence_event = NULL;
|
||||
|
||||
vk.dx_device->Release();
|
||||
vk.dx_device = nullptr;
|
||||
}
|
||||
|
||||
void vk_shutdown() {
|
||||
vkDestroyImage(vk.device, vk.depth_image, nullptr);
|
||||
vkFreeMemory(vk.device, vk.depth_image_memory, nullptr);
|
||||
|
|
@ -2463,15 +2563,28 @@ void dx_begin_frame() {
|
|||
// re-recording.
|
||||
DX_CHECK(vk.dx_command_list->Reset(vk.dx_command_allocator, vk.dx_pipeline_state));
|
||||
|
||||
// Set necessary state.
|
||||
vk.dx_command_list->SetGraphicsRootSignature(vk.dx_root_signature);
|
||||
|
||||
CD3DX12_VIEWPORT viewport(0.0f, 0.0f, static_cast<float>(glConfig.vidWidth), static_cast<float>(glConfig.vidHeight));
|
||||
vk.dx_command_list->RSSetViewports(1, &viewport);
|
||||
|
||||
CD3DX12_RECT scissorRect(0, 0, static_cast<LONG>(glConfig.vidWidth), static_cast<LONG>(glConfig.vidHeight));
|
||||
vk.dx_command_list->RSSetScissorRects(1, &scissorRect);
|
||||
|
||||
// Indicate that the back buffer will be used as a render target.
|
||||
vk.dx_command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(vk.dx_render_targets[vk.dx_frame_index],
|
||||
D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
|
||||
|
||||
CD3DX12_CPU_DESCRIPTOR_HANDLE rtv_handle(vk.dx_rtv_heap->GetCPUDescriptorHandleForHeapStart(), vk.dx_frame_index, vk.dx_rtv_descriptor_size);
|
||||
vk.dx_command_list->OMSetRenderTargets(1, &rtv_handle, FALSE, nullptr);
|
||||
|
||||
// Record commands.
|
||||
const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
|
||||
vk.dx_command_list->ClearRenderTargetView(rtv_handle, clearColor, 0, nullptr);
|
||||
vk.dx_command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
vk.dx_command_list->IASetVertexBuffers(0, 1, &vk.dx_vertex_buffer_view);
|
||||
vk.dx_command_list->DrawInstanced(3, 1, 0, 0);
|
||||
|
||||
// Indicate that the back buffer will now be used to present.
|
||||
vk.dx_command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(vk.dx_render_targets[vk.dx_frame_index],
|
||||
|
|
|
|||
|
|
@ -13,9 +13,12 @@
|
|||
#include "DXGI1_4.h"
|
||||
#include "wrl.h"
|
||||
#include "d3dx12.h"
|
||||
#include "D3Dcompiler.h"
|
||||
#include <DirectXMath.h>
|
||||
#include "../../engine/platform/win_local.h"
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
using namespace DirectX;
|
||||
|
||||
const int MAX_SWAPCHAIN_IMAGES = 8;
|
||||
const int MAX_VK_SAMPLERS = 32;
|
||||
|
|
@ -138,6 +141,7 @@ struct Vk_Instance {
|
|||
ID3D12DescriptorHeap* dx_rtv_heap = nullptr;
|
||||
UINT dx_rtv_descriptor_size = 0;
|
||||
ID3D12Resource* dx_render_targets[D3D_FRAME_COUNT];
|
||||
ID3D12RootSignature* dx_root_signature = nullptr;
|
||||
ID3D12CommandAllocator* dx_command_allocator = nullptr;
|
||||
ID3D12GraphicsCommandList* dx_command_list = nullptr;
|
||||
ID3D12PipelineState* dx_pipeline_state = nullptr;
|
||||
|
|
@ -147,6 +151,9 @@ struct Vk_Instance {
|
|||
UINT64 dx_fence_value = 0;
|
||||
HANDLE dx_fence_event = NULL;
|
||||
|
||||
ID3D12Resource* dx_vertex_buffer = nullptr;
|
||||
D3D12_VERTEX_BUFFER_VIEW dx_vertex_buffer_view;
|
||||
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkPhysicalDevice physical_device = VK_NULL_HANDLE;
|
||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@
|
|||
<Culture>0x0409</Culture>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>winmm.lib;wsock32.lib;D3d12.lib;DXGI.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>winmm.lib;wsock32.lib;D3d12.lib;DXGI.lib;d3dcompiler.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
<Culture>0x0409</Culture>
|
||||
</ResourceCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>winmm.lib;wsock32.lib;D3d12.lib;DXGI.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>winmm.lib;wsock32.lib;D3d12.lib;DXGI.lib;d3dcompiler.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<StackReserveSize>8388608</StackReserveSize>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user