aboutsummaryrefslogtreecommitdiff
path: root/demo/d3d12/imguiGraphD3D12.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'demo/d3d12/imguiGraphD3D12.cpp')
-rw-r--r--demo/d3d12/imguiGraphD3D12.cpp667
1 files changed, 667 insertions, 0 deletions
diff --git a/demo/d3d12/imguiGraphD3D12.cpp b/demo/d3d12/imguiGraphD3D12.cpp
new file mode 100644
index 0000000..64c507d
--- /dev/null
+++ b/demo/d3d12/imguiGraphD3D12.cpp
@@ -0,0 +1,667 @@
+/*
+ * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, related documentation
+ * and any modifications thereto. Any use, reproduction, disclosure or
+ * distribution of this software and related documentation without an express
+ * license agreement from NVIDIA CORPORATION is strictly prohibited.
+ */
+
+//direct3d headers
+#define NOMINMAX
+#include <d3d12.h>
+
+#include "imguiGraphD3D12.h"
+
+#include "../d3d/shaders/imguiVS.hlsl.h"
+#include "../d3d/shaders/imguiPS.hlsl.h"
+
+namespace
+{
+ template <class T>
+ void inline COMRelease(T& t)
+ {
+ if (t) t->Release();
+ t = nullptr;
+ }
+}
+
+namespace
+{
+ ImguiGraphDescD3D12 m_desc = {};
+
+ struct Vertex
+ {
+ float x, y;
+ float u, v;
+ uint8_t rgba[4];
+ };
+
+ ID3D12RootSignature* m_rootSignature = nullptr;
+ ID3D12PipelineState* m_pipelineState = nullptr;
+ ID3D12Resource* m_constantBuffer = nullptr;
+ UINT8* m_constantBufferData = nullptr;
+ ID3D12Resource* m_vertexBuffer = nullptr;
+ Vertex* m_vertexBufferData = nullptr;
+ D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView = {};
+
+ struct Scissor
+ {
+ int beginIdx;
+ int stopIdx;
+ int x;
+ int y;
+ int width;
+ int height;
+ };
+ Scissor m_stateScissor = {};
+
+ ID3D12Resource* m_textureUploadHeap = nullptr;
+ ID3D12Resource* m_texture = nullptr;
+
+ ID3D12DescriptorHeap* m_srvUavHeapCPU = nullptr;
+ ID3D12DescriptorHeap* m_srvUavHeapGPU = nullptr;
+
+ Vertex m_stateVert;
+ uint32_t m_stateVertIdx = 0u;
+
+ struct Params
+ {
+ float projection[16];
+
+ float padding[64 - 16];
+ };
+ static const int frameCount = 4;
+ int frameIndex = 0;
+}
+
+void imguiGraphContextInitD3D12(const ImguiGraphDesc* descIn)
+{
+ const auto desc = cast_to_imguiGraphDescD3D12(descIn);
+
+ m_desc = *desc;
+
+ // create the root signature
+ {
+ D3D12_DESCRIPTOR_RANGE ranges[1];
+ ranges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+ ranges[0].NumDescriptors = 1u;
+ ranges[0].BaseShaderRegister = 0u;
+ ranges[0].RegisterSpace = 0u;
+ ranges[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+
+ D3D12_ROOT_PARAMETER params[2];
+ params[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
+ params[0].Descriptor.ShaderRegister = 0u;
+ params[0].Descriptor.RegisterSpace = 0u;
+ params[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+ params[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+ params[1].DescriptorTable.NumDescriptorRanges = 1;
+ params[1].DescriptorTable.pDescriptorRanges = ranges;
+ params[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
+
+ D3D12_STATIC_SAMPLER_DESC sampler = {};
+ sampler.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
+ sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
+ sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
+ sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
+ sampler.MipLODBias = 0;
+ sampler.MaxAnisotropy = 0;
+ sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
+ sampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
+ sampler.MinLOD = 0.f;
+ sampler.MaxLOD = D3D12_FLOAT32_MAX;
+ sampler.ShaderRegister = 0;
+ sampler.RegisterSpace = 0;
+ sampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
+
+ D3D12_ROOT_SIGNATURE_DESC desc;
+ desc.NumParameters = 2;
+ desc.pParameters = params;
+ desc.NumStaticSamplers = 1u;
+ desc.pStaticSamplers = &sampler;
+ desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
+
+ ID3DBlob* signature = nullptr;
+ ID3DBlob* error = nullptr;
+ HRESULT hr = S_OK;
+ if (hr = D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error))
+ {
+ return;
+ }
+ if (hr = m_desc.device->CreateRootSignature(0u, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature)))
+ {
+ return;
+ }
+ COMRelease(signature);
+ COMRelease(error);
+ }
+
+ // create the pipeline state object
+ {
+ D3D12_INPUT_ELEMENT_DESC inputElementDescs[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ };
+
+ const bool wireFrame = false;
+
+ D3D12_RASTERIZER_DESC rasterDesc;
+ if (wireFrame)
+ {
+ rasterDesc.FillMode = D3D12_FILL_MODE_WIREFRAME;
+ rasterDesc.CullMode = D3D12_CULL_MODE_NONE;
+ }
+ else
+ {
+ rasterDesc.FillMode = D3D12_FILL_MODE_SOLID;
+ rasterDesc.CullMode = D3D12_CULL_MODE_BACK;
+ }
+ rasterDesc.FrontCounterClockwise = TRUE; // 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;
+ blendDesc.AlphaToCoverageEnable = FALSE;
+ blendDesc.IndependentBlendEnable = FALSE;
+ {
+ const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc =
+ {
+ TRUE,FALSE,
+ D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD,
+ D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA, 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_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
+ psoDesc.InputLayout.NumElements = 3;
+ psoDesc.InputLayout.pInputElementDescs = inputElementDescs;
+ psoDesc.pRootSignature = m_rootSignature;
+ psoDesc.VS.pShaderBytecode = g_imguiVS;
+ psoDesc.VS.BytecodeLength = sizeof(g_imguiVS);
+ psoDesc.PS.pShaderBytecode = g_imguiPS;
+ psoDesc.PS.BytecodeLength = sizeof(g_imguiPS);
+ psoDesc.RasterizerState = rasterDesc;
+ psoDesc.BlendState = blendDesc;
+ 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 = desc->numMSAASamples;
+ HRESULT hr = S_OK;
+ if (hr = m_desc.device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState)))
+ {
+ return;
+ }
+ }
+
+ // create a constant buffer
+ {
+ Params params = {
+ 1.f, 0.f, 0.f, 0.f,
+ 0.f, 1.f, 0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ 0.f, 0.f, 0.f, 1.f
+ };
+
+ HRESULT hr = S_OK;
+
+ D3D12_HEAP_PROPERTIES heapProps = {};
+ heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
+ heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ heapProps.CreationNodeMask = 0u;
+ heapProps.VisibleNodeMask = 0u;
+
+ D3D12_RESOURCE_DESC desc = {};
+ desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ desc.Alignment = 0u;
+ desc.Width = frameCount*sizeof(params);
+ desc.Height = 1u;
+ desc.DepthOrArraySize = 1u;
+ desc.MipLevels = 1;
+ desc.Format = DXGI_FORMAT_UNKNOWN;
+ desc.SampleDesc.Count = 1u;
+ desc.SampleDesc.Quality = 0u;
+ desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ desc.Flags = D3D12_RESOURCE_FLAG_NONE;
+
+ if (hr = m_desc.device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ,
+ nullptr, IID_PPV_ARGS(&m_constantBuffer)))
+ {
+ return;
+ }
+
+ UINT8* pdata;
+ D3D12_RANGE readRange = {};
+ if (hr = m_constantBuffer->Map(0, &readRange, (void**)&pdata))
+ {
+ return;
+ }
+ else
+ {
+ memcpy(pdata, &params, sizeof(params));
+ m_constantBufferData = pdata;
+ //m_constantBuffer->Unmap(0, nullptr); // leave mapped
+ }
+ }
+
+ // create a vertex buffer
+ {
+ HRESULT hr = S_OK;
+
+ UINT bufferSize = (UINT)(m_desc.maxVertices * frameCount) * sizeof(Vertex);
+
+ D3D12_HEAP_PROPERTIES heapProps = {};
+ heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
+ heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ heapProps.CreationNodeMask = 0u;
+ heapProps.VisibleNodeMask = 0u;
+
+ D3D12_RESOURCE_DESC desc = {};
+ desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ desc.Alignment = 0u;
+ desc.Width = bufferSize;
+ desc.Height = 1u;
+ desc.DepthOrArraySize = 1u;
+ desc.MipLevels = 1;
+ desc.Format = DXGI_FORMAT_UNKNOWN;
+ desc.SampleDesc.Count = 1u;
+ desc.SampleDesc.Quality = 0u;
+ desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ desc.Flags = D3D12_RESOURCE_FLAG_NONE;
+
+ if (hr = m_desc.device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ,
+ nullptr, IID_PPV_ARGS(&m_vertexBuffer)))
+ {
+ return;
+ }
+
+ UINT8* pdata;
+ D3D12_RANGE readRange = {};
+ if (hr = m_vertexBuffer->Map(0, &readRange, (void**)&pdata))
+ {
+ return;
+ }
+ else
+ {
+ m_vertexBufferData = (Vertex*)pdata;
+ //m_vertexBufferUpload->Unmap(0, nullptr);
+ }
+
+ m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress();
+ m_vertexBufferView.StrideInBytes = sizeof(Vertex);
+ m_vertexBufferView.SizeInBytes = bufferSize;
+ }
+}
+
+void imguiGraphContextUpdateD3D12(const ImguiGraphDesc* descIn)
+{
+ const auto desc = cast_to_imguiGraphDescD3D12(descIn);
+
+ m_desc = *desc;
+}
+
+void imguiGraphContextDestroyD3D12()
+{
+ COMRelease(m_rootSignature);
+ COMRelease(m_pipelineState);
+ COMRelease(m_constantBuffer);
+ COMRelease(m_vertexBuffer);
+}
+
+void imguiGraphRecordBeginD3D12()
+{
+ frameIndex = (frameIndex + 1) % frameCount;
+
+ Params params = {
+ 2.f / float(m_desc.winW), 0.f, 0.f, -1.f,
+ 0.f, 2.f / float(m_desc.winH), 0.f, -1.f,
+ 0.f, 0.f, 1.f, 0.f,
+ 0.f, 0.f, 0.f, 1.f
+ };
+
+ memcpy(m_constantBufferData + frameIndex*sizeof(Params), &params, sizeof(Params));
+
+ // clear state
+ m_stateVert = Vertex{ 0.f, 0.f, -1.f, -1.f, 0,0,0,0 };
+ m_stateVertIdx = 0u;
+
+ m_stateScissor = Scissor { 0, 0, 0, 0, m_desc.winW, m_desc.winH };
+
+ // configure for triangle renderering
+ ID3D12GraphicsCommandList* commandList = m_desc.commandList;
+
+ D3D12_CPU_DESCRIPTOR_HANDLE srvHandleCPU;
+ D3D12_GPU_DESCRIPTOR_HANDLE srvHandleGPU;
+ ID3D12DescriptorHeap* heap = nullptr;
+ if (m_desc.dynamicHeapCbvSrvUav.reserveDescriptors)
+ {
+ auto handle = m_desc.dynamicHeapCbvSrvUav.reserveDescriptors(m_desc.dynamicHeapCbvSrvUav.userdata,
+ 1u, m_desc.lastFenceCompleted, m_desc.nextFenceValue);
+ heap = handle.heap;
+ srvHandleCPU = handle.cpuHandle;
+ srvHandleGPU = handle.gpuHandle;
+ }
+ else
+ {
+ if (m_srvUavHeapGPU == nullptr)
+ {
+ D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
+ srvHeapDesc.NumDescriptors = 1;
+ srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
+ srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
+ m_desc.device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&m_srvUavHeapGPU));
+ }
+ heap = m_srvUavHeapGPU;
+ srvHandleCPU = m_srvUavHeapGPU->GetCPUDescriptorHandleForHeapStart();
+ srvHandleGPU = m_srvUavHeapGPU->GetGPUDescriptorHandleForHeapStart();
+ }
+
+ commandList->SetDescriptorHeaps(1, &heap);
+
+ m_desc.device->CopyDescriptorsSimple(1u, srvHandleCPU, m_srvUavHeapCPU->GetCPUDescriptorHandleForHeapStart(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+
+ commandList->SetGraphicsRootSignature(m_rootSignature);
+ commandList->SetPipelineState(m_pipelineState);
+
+ D3D12_GPU_VIRTUAL_ADDRESS cbvHandle = m_constantBuffer->GetGPUVirtualAddress();
+ commandList->SetGraphicsRootConstantBufferView(0, cbvHandle + frameIndex * sizeof(Params));
+
+ commandList->SetGraphicsRootDescriptorTable(1, srvHandleGPU);
+
+ commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);
+}
+
+static void imguiGraphFlush()
+{
+ ID3D12GraphicsCommandList* commandList = m_desc.commandList;
+
+ Scissor& p = m_stateScissor;
+ if (p.beginIdx < p.stopIdx)
+ {
+ int winH = m_desc.winH;
+ D3D12_RECT rect;
+ rect.left = p.x;
+ rect.right = p.x + p.width;
+ rect.top = (winH) - (p.y + p.height);
+ rect.bottom = (winH) - (p.y);
+ commandList->RSSetScissorRects(1, &rect);
+
+ UINT vertexCount = (p.stopIdx - p.beginIdx);
+ UINT startIndex = p.beginIdx + frameIndex * m_desc.maxVertices;
+ commandList->DrawInstanced(vertexCount, 1, startIndex, 0);
+ }
+}
+
+void imguiGraphRecordEndD3D12()
+{
+ ID3D12GraphicsCommandList* commandList = m_desc.commandList;
+
+ // no need to hold onto this
+ COMRelease(m_textureUploadHeap);
+
+ // restore scissor
+ Scissor& p = m_stateScissor;
+ int winH = m_desc.winH;
+ D3D12_RECT rect;
+ rect.left = p.x;
+ rect.right = p.x + p.width;
+ rect.top = (winH) - (p.y + p.height);
+ rect.bottom = (winH) - (p.y);
+ commandList->RSSetScissorRects(1, &rect);
+}
+
+void imguiGraphEnableScissorD3D12(int x, int y, int width, int height)
+{
+ // mark end of last region
+ m_stateScissor.stopIdx = m_stateVertIdx;
+
+ imguiGraphFlush();
+
+ m_stateScissor.beginIdx = m_stateVertIdx;
+ m_stateScissor.stopIdx = m_stateVertIdx;
+ m_stateScissor.x = x;
+ m_stateScissor.y = y;
+ m_stateScissor.width = width;
+ m_stateScissor.height = height;
+}
+
+void imguiGraphDisableScissorD3D12()
+{
+ if (m_stateVertIdx == 0) return;
+
+ // mark end of last region
+ m_stateScissor.stopIdx = m_stateVertIdx;
+
+ imguiGraphFlush();
+
+ m_stateScissor.beginIdx = m_stateVertIdx;
+ m_stateScissor.stopIdx = m_stateVertIdx;
+ m_stateScissor.x = 0;
+ m_stateScissor.y = 0;
+ m_stateScissor.width = m_desc.winW;
+ m_stateScissor.height = m_desc.winH;
+}
+
+void imguiGraphVertex2fD3D12(float x, float y)
+{
+ float v[2] = { x,y };
+ imguiGraphVertex2fvD3D12(v);
+}
+
+void imguiGraphVertex2fvD3D12(const float* v)
+{
+ // update state
+ m_stateVert.x = v[0];
+ m_stateVert.y = v[1];
+
+ Vertex* vdata = &m_vertexBufferData[frameIndex * m_desc.maxVertices];
+
+ // push vertex
+ if ((m_stateVertIdx) < m_desc.maxVertices)
+ {
+ vdata[m_stateVertIdx++] = m_stateVert;
+ }
+}
+
+void imguiGraphTexCoord2fD3D12(float u, float v)
+{
+ m_stateVert.u = u;
+ m_stateVert.v = v;
+}
+
+void imguiGraphColor4ubD3D12(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
+{
+ m_stateVert.rgba[0] = red;
+ m_stateVert.rgba[1] = green;
+ m_stateVert.rgba[2] = blue;
+ m_stateVert.rgba[3] = alpha;
+}
+
+void imguiGraphColor4ubvD3D12(const uint8_t* v)
+{
+ m_stateVert.rgba[0] = v[0];
+ m_stateVert.rgba[1] = v[1];
+ m_stateVert.rgba[2] = v[2];
+ m_stateVert.rgba[3] = v[3];
+}
+
+void imguiGraphFontTextureEnableD3D12()
+{
+
+}
+
+void imguiGraphFontTextureDisableD3D12()
+{
+ m_stateVert.u = -1.f;
+ m_stateVert.v = -1.f;
+}
+
+void imguiGraphFontTextureInitD3D12(unsigned char* data)
+{
+ ID3D12GraphicsCommandList* commandList = m_desc.commandList;
+
+ // Create the texture
+ {
+ UINT width = 512;
+ UINT height = 512;
+
+ D3D12_HEAP_PROPERTIES heapProps = {};
+ heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
+ heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ heapProps.CreationNodeMask = 0u;
+ heapProps.VisibleNodeMask = 0u;
+
+ D3D12_RESOURCE_DESC texDesc = {};
+ texDesc.MipLevels = 1u;
+ texDesc.Format = DXGI_FORMAT_R8_UNORM;
+ texDesc.Width = width;
+ texDesc.Height = height;
+ texDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+ texDesc.DepthOrArraySize = 1u;
+ texDesc.SampleDesc.Count = 1u;
+ texDesc.SampleDesc.Quality = 0u;
+ texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+
+ if (m_desc.device->CreateCommittedResource(
+ &heapProps,
+ D3D12_HEAP_FLAG_NONE,
+ &texDesc,
+ D3D12_RESOURCE_STATE_COPY_DEST,
+ nullptr,
+ IID_PPV_ARGS(&m_texture)
+ ))
+ {
+ return;
+ }
+
+ // get footprint information
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint = {};
+ UINT64 uploadHeapSize = 0u;
+ m_desc.device->GetCopyableFootprints(&texDesc, 0u, 1u, 0u, &footprint, nullptr, nullptr, &uploadHeapSize);
+
+ heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
+ D3D12_RESOURCE_DESC bufferDesc = texDesc;
+ bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ bufferDesc.Alignment = 0u;
+ bufferDesc.Width = uploadHeapSize;
+ bufferDesc.Height = 1u;
+ bufferDesc.DepthOrArraySize = 1u;
+ bufferDesc.MipLevels = 1;
+ bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
+ bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ bufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+
+ if (m_desc.device->CreateCommittedResource(
+ &heapProps,
+ D3D12_HEAP_FLAG_NONE,
+ &bufferDesc,
+ D3D12_RESOURCE_STATE_GENERIC_READ,
+ nullptr,
+ IID_PPV_ARGS(&m_textureUploadHeap)
+ ))
+ {
+ return;
+ }
+
+ // map upload heap, and convert rgb bitmap to rgba
+ UINT8* pdata;
+ D3D12_RANGE readRange = {};
+ if (m_textureUploadHeap->Map(0, &readRange, (void**)&pdata))
+ {
+ return;
+ }
+ else
+ {
+ UINT8* dst = pdata;
+ UINT elements = width*height;
+ UINT8* src = data;
+ for (UINT j = 0; j < height; j++)
+ {
+ for (UINT i = 0; i < width; i++)
+ {
+ UINT idx = j * (footprint.Footprint.RowPitch) + i;
+
+ UINT8 a = src[j * width + i];
+ dst[idx] = a;
+ }
+ }
+
+ m_textureUploadHeap->Unmap(0, nullptr);
+ }
+
+ // add copy from upload heap to default heap to command list
+ D3D12_TEXTURE_COPY_LOCATION dstCopy = {};
+ D3D12_TEXTURE_COPY_LOCATION srcCopy = {};
+ dstCopy.pResource = m_texture;
+ dstCopy.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ dstCopy.SubresourceIndex = 0u;
+ srcCopy.pResource = m_textureUploadHeap;
+ srcCopy.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+ srcCopy.PlacedFootprint = footprint;
+ commandList->CopyTextureRegion(&dstCopy, 0, 0, 0, &srcCopy, nullptr);
+
+ D3D12_RESOURCE_BARRIER barrier[1] = {};
+ auto textureBarrier = [&barrier](UINT idx, ID3D12Resource* texture)
+ {
+ barrier[idx].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ barrier[idx].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ barrier[idx].Transition.pResource = texture;
+ barrier[idx].Transition.Subresource = 0u;
+ barrier[idx].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
+ barrier[idx].Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
+ };
+ textureBarrier(0, m_texture);
+ commandList->ResourceBarrier(1, barrier);
+
+ // create an SRV heap and descriptor for the texture
+ D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
+ srvHeapDesc.NumDescriptors = 1;
+ srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
+ srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
+ if (m_desc.device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&m_srvUavHeapCPU)))
+ {
+ return;
+ }
+
+ D3D12_CPU_DESCRIPTOR_HANDLE srvUavHandle = m_srvUavHeapCPU->GetCPUDescriptorHandleForHeapStart();
+
+ D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+ srvDesc.Format = texDesc.Format;
+ srvDesc.Texture2D.MipLevels = 1;
+ srvDesc.Texture2D.MostDetailedMip = 0;
+ srvDesc.Texture2D.ResourceMinLODClamp = 0.f;
+
+ m_desc.device->CreateShaderResourceView(m_texture, &srvDesc, srvUavHandle);
+ }
+
+}
+
+void imguiGraphFontTextureReleaseD3D12()
+{
+ COMRelease(m_texture);
+ COMRelease(m_textureUploadHeap);
+ COMRelease(m_srvUavHeapCPU);
+ COMRelease(m_srvUavHeapGPU);
+} \ No newline at end of file