text: /* 
  
  bool_t D3D12CommandBuffer::Draw(ref_t<IGfxVertexBuffer> buffer, int_t offset, int_t size)
  {
      // Command list allocators can only be reset when the associated 
      // command lists have finished execution on the GPU; apps should use 
      // fences to determine GPU execution progress.
      ThrowIfFailed(m_commandAllocator->Reset());
  
      // However, when ExecuteCommandList() is called on a particular command 
      // list, that command list can then be reset at any time and must be before 
      // re-recording.
      ThrowIfFailed(m_commandList->Reset(m_commandAllocator, m_pipelineState));
  
      // Set necessary state.
      m_commandList->SetGraphicsRootSignature(m_rootSignature);
      m_commandList->RSSetViewports(1, &m_viewport);
      m_commandList->RSSetScissorRects(1, &m_scissorRect);
  
      // Indicate that the back buffer will be used as a render target.
      m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex], D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
  
      //CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize);
      D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_rtvHeap->GetCPUDescriptorHandleForHeapStart();
      rtvHandle.ptr += INT64(m_frameIndex) * UINT64(m_rtvDescriptorSize);
  
      m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);
  
      // Record commands.
      const float clearColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
      m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
      m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
      m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);
      m_commandList->DrawInstanced(3, 1, 0, 0);
  
      // Indicate that the back buffer will now be used to present.
      m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
  
      ThrowIfFailed(m_commandList->Close());
  }
  
  void D3D12RenderingDevice::LoadAssets()
  {
      // 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);
  
          ID3DBlob* signature;
          ID3DBlob* error;
  
          ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
          ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature)));
      }
  
      // Create the pipeline state, which includes compiling and loading shaders.
      {
          ID3DBlob* vertexShader;
          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
  
          ThrowIfFailed(D3DCompileFromFile(L"c:\\shaders.hlsl", nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &vertexShader, nullptr));
          ThrowIfFailed(D3DCompileFromFile(L"c:\\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 = m_rootSignature;
          psoDesc.VS = CD3DX12_SHADER_BYTECODE(vertexShader);
          psoDesc.PS = CD3DX12_SHADER_BYTECODE(pixelShader);
          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;
          ThrowIfFailed(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState)));
      }
  
      // Create the command list.
      ThrowIfFailed(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator, m_pipelineState, IID_ID3D12CommandList, reinterpret_cast<void**>(&m_commandList)));
  
      // 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.
      ThrowIfFailed(m_commandList->Close());
  
      // Create the vertex buffer.
      {
          float m_aspectRatio = 768.0 / 1024.0;
          // Define the geometry for a triangle.
          Vertex triangleVertices[] =
          {
              { { 0.0f, 0.25f * (m_aspectRatio), 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
              { { 0.25f, -0.25f * m_aspectRatio, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
              { { -0.25f, -0.25f * m_aspectRatio, 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.
          ThrowIfFailed(m_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_ID3D12Resource, reinterpret_cast<void**>(&m_vertexBuffer)));
  
          // 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.
          ThrowIfFailed(m_vertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin)));
          memcpy(pVertexDataBegin, triangleVertices, sizeof(triangleVertices));
          m_vertexBuffer->Unmap(0, nullptr);
  
          // Initialize the vertex buffer view.
          m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress();
          m_vertexBufferView.StrideInBytes = sizeof(Vertex);
          m_vertexBufferView.SizeInBytes = vertexBufferSize;
      }
  
      // Create synchronization objects and wait until assets have been uploaded to the GPU.
      {
          ThrowIfFailed(m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_ID3D12Fence, reinterpret_cast<void**>(&m_fence)));
          m_fenceValue = 1;
  
          // Create an event handle to use for frame synchronization.
          m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
          if (m_fenceEvent == nullptr)
          {
              ThrowIfFailed(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.
          WaitForPreviousFrame();
      }
  }
  
  void D3D12RenderingDevice::WaitForPreviousFrame()
  {
      // WAITING FOR THE FRAME TO COMPLETE BEFORE CONTINUING IS NOT BEST PRACTICE.
      // This is code implemented as such for simplicity. The D3D12HelloFrameBuffering
      // sample illustrates how to use fences for efficient resource usage and to
      // maximize GPU utilization.
  
      // Signal and increment the fence value.
      const UINT64 fence = m_fenceValue;
      ThrowIfFailed(m_commandQueue->Signal(m_fence, fence));
      m_fenceValue++;
  
      // Wait until the previous frame is finished.
      if (m_fence->GetCompletedValue() < fence)
      {
          ThrowIfFailed(m_fence->SetEventOnCompletion(fence, m_fenceEvent));
          WaitForSingleObject(m_fenceEvent, INFINITE);
      }
  
      m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
  }
  
  
  bool_t D3D12Device::CreateGfxCommandBuffer(out_ptr_t<IGfxCommandBuffer> buffer, GfxCommandBufferDesc& desc)
  {
          // 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);
  
          ID3DBlob* signature;
          ID3DBlob* error;
  
          ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
          ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature)));
      }
  
      // Create the pipeline state, which includes compiling and loading shaders.
      {
          ID3DBlob* vertexShader;
          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
  
          ThrowIfFailed(D3DCompileFromFile(L"c:\\shaders.hlsl", nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &vertexShader, nullptr));
          ThrowIfFailed(D3DCompileFromFile(L"c:\\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 = m_rootSignature;
          psoDesc.VS = CD3DX12_SHADER_BYTECODE(vertexShader);
          psoDesc.PS = CD3DX12_SHADER_BYTECODE(pixelShader);
          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;
          ThrowIfFailed(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState)));
      }
  
      // Create the command list.
      ThrowIfFailed(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator, m_pipelineState, IID_ID3D12CommandList, reinterpret_cast<void**>(&m_commandList)));
  
      // 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.
      ThrowIfFailed(m_commandList->Close());
  
      // Create the vertex buffer.
      {
          float m_aspectRatio = 768.0 / 1024.0;
          // Define the geometry for a triangle.
          Vertex triangleVertices[] =
          {
              { { 0.0f, 0.25f * (m_aspectRatio), 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
              { { 0.25f, -0.25f * m_aspectRatio, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
              { { -0.25f, -0.25f * m_aspectRatio, 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.
          ThrowIfFailed(m_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_ID3D12Resource, reinterpret_cast<void**>(&m_vertexBuffer)));
  
          // 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.
          ThrowIfFailed(m_vertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin)));
          memcpy(pVertexDataBegin, triangleVertices, sizeof(triangleVertices));
          m_vertexBuffer->Unmap(0, nullptr);
  
          // Initialize the vertex buffer view.
          m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress();
          m_vertexBufferView.StrideInBytes = sizeof(Vertex);
          m_vertexBufferView.SizeInBytes = vertexBufferSize;
      }
  
      // Create synchronization objects and wait until assets have been uploaded to the GPU.
      {
          ThrowIfFailed(m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_ID3D12Fence, reinterpret_cast<void**>(&m_fence)));
          m_fenceValue = 1;
  
          // Create an event handle to use for frame synchronization.
          m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
          if (m_fenceEvent == nullptr)
          {
              ThrowIfFailed(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.
          WaitForPreviousFrame();
      }
  }
  
  
  
   */