Program Listing for File D3D12ScopedImage.cpp

Return to documentation for file (Source\Azura\RenderSystem\Src\D3D12\D3D12ScopedImage.cpp)

#include "D3D12/D3D12ScopedImage.h"
#include "D3D12/D3D12TypeMapping.h"
#include "D3D12/D3D12Macros.h"
#include "D3D12/D3D12ScopedBuffer.h"

#include "D3D12/d3dx12.h"
#include "D3D12/D3D12Debug.h"


namespace Azura {
namespace D3D12 {

namespace {
DXGI_FORMAT ConvertDepthFormatForSRV(DXGI_FORMAT format) {
  if (format == DXGI_FORMAT_D32_FLOAT) {
    return DXGI_FORMAT_R32_FLOAT;
  }

  if (format == DXGI_FORMAT_D24_UNORM_S8_UINT) {
    return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
  }

  if (format == DXGI_FORMAT_D32_FLOAT_S8X24_UINT) {
    return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
  }

  if (format == DXGI_FORMAT_D16_UNORM) {
    return DXGI_FORMAT_R16_UNORM;
  }

  return DXGI_FORMAT_UNKNOWN;
}

} // namespace

void D3D12ScopedImage::Create(const Microsoft::WRL::ComPtr<ID3D12Device>& device,
                              D3D12_RESOURCE_STATES initState,
                              D3D12_RESOURCE_FLAGS resourceFlags,
                              const TextureDesc& desc,
                              const Log& log_D3D12RenderSystem) {

  const auto format = ToDXGI_FORMAT(desc.m_format);
  VERIFY_OPT(log_D3D12RenderSystem, format, "Unknown Format");

  m_format = desc.m_format;

  m_currentState = initState;

  const auto resourceDimension = ToD3D12_RESOURCE_DIMENSION(desc.m_type);
  VERIFY_OPT(log_D3D12RenderSystem, resourceDimension, "Unknown Resource Dimension");

  D3D12_RESOURCE_DESC textureDesc = {};
  textureDesc.MipLevels           = UINT16(desc.m_mipLevels);
  textureDesc.Format              = format.value();
  textureDesc.Width               = desc.m_bounds.m_width;
  textureDesc.Height              = desc.m_bounds.m_height;
  textureDesc.Flags               = resourceFlags;
  textureDesc.DepthOrArraySize    = UINT16(desc.m_bounds.m_depth > 1 ? desc.m_bounds.m_depth : desc.m_arrayLayers);
  textureDesc.SampleDesc.Count    = 1;
  textureDesc.SampleDesc.Quality  = 0;
  textureDesc.Dimension           = resourceDimension.value();

  const auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);

  // D3D12_CLEAR_VALUE clearValue = {};
  // clearValue.Color[0] = 0.2f;
  // clearValue.Color[1] = 0.2f;
  // clearValue.Color[2] = 0.2f;
  // clearValue.Color[3] = 1.0f;
  // clearValue.Format = format.value();
  //
  // if (HasDepthOrStencilComponent(desc.m_format)) {
  //   clearValue = { format.value() , 1.0f };
  // }

  VERIFY_D3D_OP(log_D3D12RenderSystem, device->CreateCommittedResource(
    &heapProperties,
    D3D12_HEAP_FLAG_NONE,
    &textureDesc,
    initState,
    nullptr,
    IID_PPV_ARGS(&m_texture)), "Failed to create image comitted resource");
}

void D3D12ScopedImage::Transition(ID3D12GraphicsCommandList* commandList,
                                  D3D12_RESOURCE_STATES fromState,
                                  D3D12_RESOURCE_STATES toState, const Log& log_D3D12RenderSystem) const {
  UNUSED(log_D3D12RenderSystem); // Release Mode

  LOG_DBG(log_D3D12RenderSystem, LOG_LEVEL, "[FORCE] Transitioning State: %s => %s", D3D12ResourceStateToString(fromState), D3D12ResourceStateToString(toState));

  const auto resourceBarrier = CD3DX12_RESOURCE_BARRIER::Transition(m_texture.Get(), fromState, toState);
  commandList->ResourceBarrier(1, &resourceBarrier);
}

void D3D12ScopedImage::Transition(ID3D12GraphicsCommandList* commandList,
  D3D12_RESOURCE_STATES toState, const Log& log_D3D12RenderSystem) {
  UNUSED(log_D3D12RenderSystem); // Release Mode

  if (m_currentState == toState)
  {
    LOG_DBG(log_D3D12RenderSystem, LOG_LEVEL, "Current State is same as Transition State: %s", D3D12ResourceStateToString(toState));
    return;
  }

  LOG_DBG(log_D3D12RenderSystem, LOG_LEVEL, "Transitioning State: %s => %s", D3D12ResourceStateToString(m_currentState), D3D12ResourceStateToString(toState));

  const auto resourceBarrier = CD3DX12_RESOURCE_BARRIER::Transition(m_texture.Get(), m_currentState, toState);
  commandList->ResourceBarrier(1, &resourceBarrier);

  m_currentState = toState;
}

D3D12_SHADER_RESOURCE_VIEW_DESC D3D12ScopedImage::GetSRV(RawStorageFormat viewFormat,
                                                         ImageViewType imageView,
                                                         const Log& log_D3D12RenderSystem) {
  const auto format = ToDXGI_FORMAT(viewFormat);
  VERIFY_OPT(log_D3D12RenderSystem, format, "Unknown Format");

  const auto srvView = ToD3D12_SRV_DIMENSION(imageView);
  VERIFY_OPT(log_D3D12RenderSystem, format, "Unknown SRV View Dimensions");

  DXGI_FORMAT srvFormat = format.value();
  if (HasDepthComponent(viewFormat) || HasStencilComponent(viewFormat)) {
    srvFormat = ConvertDepthFormatForSRV(srvFormat);
  }

  D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  srvDesc.Shader4ComponentMapping         = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  srvDesc.Format                          = srvFormat;
  srvDesc.ViewDimension                   = srvView.value();
  srvDesc.Texture2D.MipLevels             = 1; // NOLINT

  return srvDesc;
}

D3D12_UNORDERED_ACCESS_VIEW_DESC D3D12ScopedImage::GetUAV(RawStorageFormat viewFormat,
  ImageViewType imageView,
  const Log& log_D3D12RenderSystem) {
  const auto format = ToDXGI_FORMAT(viewFormat);
  VERIFY_OPT(log_D3D12RenderSystem, format, "Unknown Format");

  const auto uavView = ToD3D12_UAV_DIMENSION(imageView);
  VERIFY_OPT(log_D3D12RenderSystem, format, "Unknown SRV View Dimensions");

  DXGI_FORMAT uavFormat = format.value();
  if (HasDepthComponent(viewFormat) || HasStencilComponent(viewFormat)) {
    uavFormat = ConvertDepthFormatForSRV(uavFormat);
  }

  D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
  uavDesc.Format = uavFormat;
  uavDesc.ViewDimension = uavView.value();
  uavDesc.Texture2D.MipSlice = 0; // NOLINT
  uavDesc.Texture2D.PlaneSlice = 0; // NOLINT

  return uavDesc;
}

D3D12_DEPTH_STENCIL_VIEW_DESC D3D12ScopedImage::GetDSV(RawStorageFormat viewFormat,
                                                       ImageViewType imageView,
                                                       const Log& log_D3D12RenderSystem) {

  if (!HasDepthComponent(viewFormat) && !HasStencilComponent(viewFormat)) {
    LOG_ERR(log_D3D12RenderSystem, LOG_LEVEL, "Unknown Format Requested for DSV: %s", ToString(viewFormat).c_str());
    return {};
  }

  const auto format = ToDXGI_FORMAT(viewFormat);
  VERIFY_OPT(log_D3D12RenderSystem, format, "Unknown Format");

  const auto dsvDimension = ToD3D12_DSV_DIMENSION(imageView);
  VERIFY_OPT(log_D3D12RenderSystem, format, "Unknown SRV View Dimensions");

  D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
  dsvDesc.Texture2D.MipSlice            = 0; // NOLINT
  dsvDesc.Format                        = format.value();
  dsvDesc.ViewDimension                 = dsvDimension.value();
  dsvDesc.Flags                         = D3D12_DSV_FLAG_NONE;

  return dsvDesc;
}

D3D12_RENDER_TARGET_VIEW_DESC D3D12ScopedImage::GetRTV(RawStorageFormat viewFormat,
                                                       ImageViewType imageView,
                                                       const Log& log_D3D12RenderSystem) {

  if (HasDepthComponent(viewFormat) || HasStencilComponent(viewFormat)) {
    LOG_ERR(log_D3D12RenderSystem, LOG_LEVEL, "Unknown Format Requested for RTV: %s", ToString(viewFormat).c_str());
    return {};
  }

  const auto format = ToDXGI_FORMAT(viewFormat);
  VERIFY_OPT(log_D3D12RenderSystem, format, "Unknown Format");

  const auto rtvDimension = ToD3D12_RTV_DIMENSION(imageView);
  VERIFY_OPT(log_D3D12RenderSystem, format, "Unknown SRV View Dimensions");

  D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
  rtvDesc.Texture2D.MipSlice            = 0; // NOLINT
  rtvDesc.Texture2D.PlaneSlice          = 0; // NOLINT
  rtvDesc.Format                        = format.value();
  rtvDesc.ViewDimension                 = rtvDimension.value();

  return rtvDesc;
}

ID3D12Resource* D3D12ScopedImage::Real() const {
  return m_texture.Get();
}

RawStorageFormat D3D12ScopedImage::GetFormat() const {
  return m_format;
}

Microsoft::WRL::ComPtr<ID3D12Resource> D3D12ScopedImage::RealComPtr() const {
  return m_texture;
}

void D3D12ScopedImage::CopyFromBuffer(const Microsoft::WRL::ComPtr<ID3D12Device>& device,
                                      ID3D12GraphicsCommandList* commandList,
                                      const D3D12ScopedBuffer& sourceBuffer,
                                      UINT64 sourceOffset) const {
  const auto textureDesc = m_texture->GetDesc();

  D3D12_PLACED_SUBRESOURCE_FOOTPRINT layouts;
  UINT64 rowSizesInBytes;
  UINT numRows;
  UINT64 requiredSize;

  device->GetCopyableFootprints(&textureDesc, 0, 1, sourceOffset, &layouts, &numRows, &rowSizesInBytes, &requiredSize);

  CD3DX12_TEXTURE_COPY_LOCATION Dst(m_texture.Get(), 0);
  CD3DX12_TEXTURE_COPY_LOCATION Src(sourceBuffer.Real(), layouts);
  commandList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);
}

} // namespace D3D12
} // namespace Azura