src/ngfx/porting/d3d/D3DGraphics.cpp

Functions

Name
void resourceBarrier(D3DCommandList * cmdList, D3DFramebuffer::D3DAttachment * p, D3D12_RESOURCE_STATES currentState, D3D12_RESOURCE_STATES newState, UINT subresourceIndex =D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES)

Functions Documentation

function resourceBarrier

static void resourceBarrier(
    D3DCommandList * cmdList,
    D3DFramebuffer::D3DAttachment * p,
    D3D12_RESOURCE_STATES currentState,
    D3D12_RESOURCE_STATES newState,
    UINT subresourceIndex =D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES
)

Source code

/*
 * Copyright 2020 GoPro Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
#include "ngfx/porting/d3d/D3DGraphics.h"
#include "ngfx/porting/d3d/D3DBuffer.h"
#include "ngfx/porting/d3d/D3DCommandList.h"
#include "ngfx/porting/d3d/D3DComputePipeline.h"
#include "ngfx/porting/d3d/D3DDebugUtil.h"
#include "ngfx/porting/d3d/D3DGraphicsPipeline.h"
#include "ngfx/porting/d3d/D3DTexture.h"
#include <glm/gtc/type_ptr.hpp>
using namespace ngfx;

void D3DGraphics::bindComputePipeline(CommandBuffer *commandBuffer,
                                      ComputePipeline *computePipeline) {
  auto d3dCtx = d3d(ctx);

  auto d3dCommandList = d3d(commandBuffer)->v;
  auto d3dComputePipeline = d3d(computePipeline);
  D3D_TRACE(d3dCommandList->SetPipelineState(
      d3dComputePipeline->d3dPipelineState.Get()));
  D3D_TRACE(d3dCommandList->SetComputeRootSignature(
      d3dComputePipeline->d3dRootSignature.Get()));
  auto cbvSrvUavHeap = d3dCtx->d3dCbvSrvUavDescriptorHeap.v.Get();
  auto samplerDescriptorHeap = d3dCtx->d3dSamplerDescriptorHeap.v.Get();
  std::vector<ID3D12DescriptorHeap *> descriptorHeaps = {cbvSrvUavHeap,
                                                         samplerDescriptorHeap};
  D3D_TRACE(d3dCommandList->SetDescriptorHeaps(UINT(descriptorHeaps.size()),
                                               descriptorHeaps.data()));
  currentPipeline = computePipeline;
}

void D3DGraphics::bindGraphicsPipeline(CommandBuffer *commandBuffer,
                                       GraphicsPipeline *graphicsPipeline) {
  auto d3dCommandList = d3d(commandBuffer)->v;
  auto d3dGraphicsPipeline = d3d(graphicsPipeline);
  D3D_TRACE(d3dCommandList->SetPipelineState(
      d3dGraphicsPipeline->d3dPipelineState.Get()));
  D3D_TRACE(d3dCommandList->IASetPrimitiveTopology(
      d3dGraphicsPipeline->d3dPrimitiveTopology));
  D3D_TRACE(d3dCommandList->SetGraphicsRootSignature(
      d3dGraphicsPipeline->d3dRootSignature.Get()));
  currentPipeline = graphicsPipeline;
}

void D3DGraphics::bindUniformBuffer(CommandBuffer *commandBuffer,
                                    Buffer *buffer, uint32_t binding,
                                    ShaderStageFlags shaderStageFlags) {
  auto d3dCommandList = d3d(commandBuffer)->v.Get();
  auto d3dBuffer = d3d(buffer);
  if (D3DGraphicsPipeline *graphicsPipeline =
          dynamic_cast<D3DGraphicsPipeline *>(currentPipeline)) {
    D3D_TRACE(d3dCommandList->SetGraphicsRootConstantBufferView(
        binding, d3dBuffer->v->GetGPUVirtualAddress()));
  } else if (D3DComputePipeline *computePipeline =
                 dynamic_cast<D3DComputePipeline *>(currentPipeline)) {
    D3D_TRACE(d3dCommandList->SetComputeRootConstantBufferView(
        binding, d3dBuffer->v->GetGPUVirtualAddress()));
  }
}

void D3DGraphics::bindIndexBuffer(CommandBuffer *commandBuffer, Buffer *buffer,
                                  IndexFormat indexFormat) {
  auto d3dBuffer = d3d(buffer);
  D3D12_INDEX_BUFFER_VIEW ib;
  ib.BufferLocation = d3dBuffer->v->GetGPUVirtualAddress();
  ib.Format = DXGI_FORMAT(indexFormat);
  ib.SizeInBytes = d3dBuffer->size;
  d3d(commandBuffer)->v->IASetIndexBuffer(&ib);
}

void D3DGraphics::bindVertexBuffer(CommandBuffer *commandBuffer, Buffer *buffer,
                                   uint32_t location, uint32_t stride) {
  auto d3dBuffer = d3d(buffer);
  D3D12_VERTEX_BUFFER_VIEW vb;
  vb.BufferLocation = d3dBuffer->v->GetGPUVirtualAddress();
  vb.StrideInBytes = stride;
  vb.SizeInBytes = d3dBuffer->size;
  d3d(commandBuffer)->v->IASetVertexBuffers(location, 1, &vb);
}

void D3DGraphics::bindStorageBuffer(CommandBuffer *commandBuffer,
                                    Buffer *buffer, uint32_t binding,
                                    ShaderStageFlags shaderStageFlags) {
  auto d3dCommandList = d3d(commandBuffer)->v.Get();
  auto d3dBuffer = d3d(buffer);
  // TODO encode access flags as read-only or read-write
  if (D3DGraphicsPipeline *graphicsPipeline =
          dynamic_cast<D3DGraphicsPipeline *>(currentPipeline)) {
    D3D_TRACE(d3dCommandList->SetGraphicsRootShaderResourceView(
        binding, d3dBuffer->v->GetGPUVirtualAddress()));
  } else if (D3DComputePipeline *computePipeline =
                 dynamic_cast<D3DComputePipeline *>(currentPipeline)) {
    D3D_TRACE(d3dCommandList->SetComputeRootUnorderedAccessView(
        binding, d3dBuffer->v->GetGPUVirtualAddress()));
  }
}

void D3DGraphics::bindTexture(CommandBuffer *commandBuffer, Texture *texture,
                              uint32_t set) {
  auto d3dCommandList = d3d(commandBuffer)->v.Get();
  auto d3dTexture = d3d(texture);
  if (D3DGraphicsPipeline *graphicsPipeline =
          dynamic_cast<D3DGraphicsPipeline *>(currentPipeline)) {
    D3D_TRACE(d3dCommandList->SetGraphicsRootDescriptorTable(
        set, d3dTexture->defaultSrvDescriptor.gpuHandle));
    D3D_TRACE(d3dCommandList->SetGraphicsRootDescriptorTable(
        set + 1, d3dTexture->defaultSamplerDescriptor.gpuHandle));
  } else if (D3DComputePipeline *computePipeline =
                 dynamic_cast<D3DComputePipeline *>(currentPipeline)) {
    D3D_TRACE(d3dCommandList->SetComputeRootDescriptorTable(
        set, d3dTexture->defaultSrvDescriptor.gpuHandle));
    D3D_TRACE(d3dCommandList->SetComputeRootDescriptorTable(
        set + 1, d3dTexture->defaultSamplerDescriptor.gpuHandle));
  }
}

static void resourceBarrier(
    D3DCommandList *cmdList, D3DFramebuffer::D3DAttachment *p,
    D3D12_RESOURCE_STATES currentState, D3D12_RESOURCE_STATES newState,
    UINT subresourceIndex = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES) {
  if (p->texture)
    p->texture->resourceBarrier(cmdList, newState, subresourceIndex);
  else {
    CD3DX12_RESOURCE_BARRIER resourceBarrier =
        CD3DX12_RESOURCE_BARRIER::Transition(p->resource, currentState,
                                             newState, p->subresourceIndex);
    D3D_TRACE(cmdList->v->ResourceBarrier(1, &resourceBarrier));
  }
}
void D3DGraphics::beginRenderPass(CommandBuffer *commandBuffer,
                                  RenderPass *renderPass,
                                  Framebuffer *framebuffer,
                                  glm::vec4 clearColor, float clearDepth,
                                  uint32_t clearStencil) {
  auto d3dCtx = d3d(ctx);
  auto d3dRenderPass = d3d(renderPass);
  auto d3dCommandList = d3d(commandBuffer);
  auto d3dFramebuffer = d3d(framebuffer);
  auto &colorAttachments = d3dFramebuffer->colorAttachments;
  auto &resolveAttachments = d3dFramebuffer->resolveAttachments;
  auto depthStencilAttachment = d3dFramebuffer->depthStencilAttachment;
  if (!resolveAttachments.empty()) {
    for (auto &colorAttachment : colorAttachments) {
      resourceBarrier(d3dCommandList, colorAttachment,
                      D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
                      D3D12_RESOURCE_STATE_RENDER_TARGET,
                      colorAttachment->subresourceIndex);
    }
  } else {
    for (auto &colorAttachment : colorAttachments) {
      resourceBarrier(d3dCommandList, colorAttachment,
                      d3dRenderPass->finalResourceState,
                      d3dRenderPass->initialResourceState,
                      colorAttachment->subresourceIndex);
    }
  }
  auto cbvSrvUavHeap = d3dCtx->d3dCbvSrvUavDescriptorHeap.v.Get();
  auto samplerDescriptorHeap = d3dCtx->d3dSamplerDescriptorHeap.v.Get();
  std::vector<ID3D12DescriptorHeap *> descriptorHeaps = {cbvSrvUavHeap,
                                                         samplerDescriptorHeap};
  D3D_TRACE(d3dCommandList->v->SetDescriptorHeaps(UINT(descriptorHeaps.size()),
                                                  descriptorHeaps.data()));
  std::vector<D3D12_CPU_DESCRIPTOR_HANDLE> colorAttachmentHandles(
      colorAttachments.size());
  for (uint32_t j = 0; j < colorAttachments.size(); j++)
    colorAttachmentHandles[j] = colorAttachments[j]->cpuDescriptor;
  D3D_TRACE(d3dCommandList->v->OMSetRenderTargets(
      UINT(colorAttachments.size()), colorAttachmentHandles.data(), FALSE,
      depthStencilAttachment ? &depthStencilAttachment->cpuDescriptor
                             : nullptr));
  for (auto &colorAttachment : colorAttachments) {
    D3D_TRACE(d3dCommandList->v->ClearRenderTargetView(
        colorAttachment->cpuDescriptor, glm::value_ptr(clearColor), 0,
        nullptr));
  }
  if (depthStencilAttachment) {
    D3D_TRACE(d3dCommandList->v->ClearDepthStencilView(
        depthStencilAttachment->cpuDescriptor,
        D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, clearDepth,
        clearStencil, 0, nullptr));
  }
  currentRenderPass = renderPass;
  currentFramebuffer = framebuffer;
}

void D3DGraphics::endRenderPass(CommandBuffer *commandBuffer) {
  auto d3dCommandList = d3d(commandBuffer);
  auto d3dFramebuffer = d3d(currentFramebuffer);
  auto &colorAttachments = d3dFramebuffer->colorAttachments;
  auto &resolveAttachments = d3dFramebuffer->resolveAttachments;
  auto d3dRenderPass = d3d(currentRenderPass);
  if (!resolveAttachments.empty()) {
    for (uint32_t j = 0; j < colorAttachments.size(); j++) {
      auto &colorAttachment = colorAttachments[j];
      auto &resolveAttachment = resolveAttachments[j];
      resourceBarrier(d3dCommandList, colorAttachment,
                      D3D12_RESOURCE_STATE_RENDER_TARGET,
                      D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
      resourceBarrier(d3dCommandList, resolveAttachment,
                      D3D12_RESOURCE_STATE_PRESENT,
                      D3D12_RESOURCE_STATE_RESOLVE_DEST);
      D3D_TRACE(d3dCommandList->v->ResolveSubresource(
          resolveAttachment->resource, resolveAttachment->subresourceIndex,
          colorAttachment->resource, colorAttachment->subresourceIndex,
          colorAttachment->format));
      resourceBarrier(d3dCommandList, resolveAttachment,
                      D3D12_RESOURCE_STATE_RESOLVE_DEST,
                      d3dRenderPass->finalResourceState,
                      resolveAttachment->subresourceIndex);
    }
  } else {
    for (auto &colorAttachment : colorAttachments) {
      resourceBarrier(
          d3dCommandList, colorAttachment, d3dRenderPass->initialResourceState,
          d3dRenderPass->finalResourceState, colorAttachment->subresourceIndex);
    }
  }
  currentRenderPass = nullptr;
  currentFramebuffer = nullptr;
}

void D3DGraphics::dispatch(CommandBuffer *commandBuffer, uint32_t groupCountX,
                           uint32_t groupCountY, uint32_t groupCountZ,
                           uint32_t threadsPerGroupX, uint32_t threadsPerGroupY,
                           uint32_t threadsPerGroupZ) {
  D3D_TRACE(
      d3d(commandBuffer)->v->Dispatch(groupCountX, groupCountY, groupCountZ));
}

void D3DGraphics::draw(CommandBuffer *cmdBuffer, uint32_t vertexCount,
                       uint32_t instanceCount, uint32_t firstVertex,
                       uint32_t firstInstance) {
  D3D_TRACE(d3d(cmdBuffer)->v->DrawInstanced(vertexCount, instanceCount,
                                             firstVertex, firstInstance));
}
void D3DGraphics::drawIndexed(CommandBuffer *cmdBuffer, uint32_t indexCount,
                              uint32_t instanceCount, uint32_t firstIndex,
                              int32_t vertexOffset, uint32_t firstInstance) {
  D3D_TRACE(d3d(cmdBuffer)->v->DrawIndexedInstanced(
      indexCount, instanceCount, firstIndex, vertexOffset, firstInstance));
}
void D3DGraphics::setViewport(CommandBuffer *cmdBuffer, Rect2D r) {
  viewport = r;
  D3D12_VIEWPORT d3dViewport = {float(r.x), float(r.y), float(r.w),
                                float(r.h), 0.0f,       1.0f};
  D3D_TRACE(d3d(cmdBuffer)->v->RSSetViewports(1, &d3dViewport));
}
void D3DGraphics::setScissor(CommandBuffer *cmdBuffer, Rect2D r) {
  scissorRect = r;
#ifdef ORIGIN_BOTTOM_LEFT
  auto &v = viewport;
  D3D12_RECT d3dScissorRect = {long(r.x), long(v.h - r.y - r.h),
                               long(r.x + r.w), long(v.h - r.y)};
#else
  D3D12_RECT d3dScissorRect = {long(r.x), long(r.y), long(r.x + r.w),
                               long(r.y + r.h)};
#endif
  D3D_TRACE(d3d(cmdBuffer)->v->RSSetScissorRects(1, &d3dScissorRect));
}

Graphics *Graphics::create(GraphicsContext *ctx) {
  D3DGraphics *d3dGraphics = new D3DGraphics();
  d3dGraphics->ctx = ctx;
  d3dGraphics->create();
  return d3dGraphics;
}

Updated on 3 April 2021 at 20:21:51 PDT