src/ngfx/porting/d3d/D3DGraphicsContext.cpp
Defines
Name | |
---|---|
MAX_DESCRIPTORS |
Macro Documentation
define MAX_DESCRIPTORS
#define MAX_DESCRIPTORS 1024
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/D3DGraphicsContext.h"
#include "ngfx/porting/d3d/D3DDebugUtil.h"
#include <dxgi1_4.h>
#include <wrl.h>
using namespace ngfx;
using namespace std;
using Microsoft::WRL::ComPtr;
#define MAX_DESCRIPTORS 1024
void D3DGraphicsContext::create(const char *appName, bool enableDepthStencil,
bool debug) {
HRESULT hResult;
this->debug = debug;
this->enableDepthStencil = enableDepthStencil;
depthFormat = PIXELFORMAT_D16_UNORM;
UINT dxgiFactoryFlags = 0;
if (debug) {
ComPtr<ID3D12Debug> debugController;
V(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)));
debugController->EnableDebugLayer();
// Enable additional debug layers.
dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
}
V(CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&d3dFactory)));
d3dDevice.create(this);
d3dCommandQueue.create(this);
createDescriptorHeaps();
}
void D3DGraphicsContext::createDescriptorHeaps() {
d3dRtvDescriptorHeap.create(d3dDevice.v.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
MAX_DESCRIPTORS, D3D12_DESCRIPTOR_HEAP_FLAG_NONE);
d3dCbvSrvUavDescriptorHeap.create(
d3dDevice.v.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
MAX_DESCRIPTORS * 3, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE);
d3dSamplerDescriptorHeap.create(
d3dDevice.v.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, MAX_DESCRIPTORS,
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE);
d3dDsvDescriptorHeap.create(d3dDevice.v.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
MAX_DESCRIPTORS, D3D12_DESCRIPTOR_HEAP_FLAG_NONE);
}
void D3DGraphicsContext::setSurface(Surface *surface) {
defaultOffscreenSurfaceFormat = PIXELFORMAT_RGBA8_UNORM;
if (surface && !surface->offscreen) {
offscreen = false;
d3dSwapchain.create(this, d3d(surface));
surfaceFormat = PixelFormat(DXGI_FORMAT_R8G8B8A8_UNORM);
numDrawCommandBuffers = d3dSwapchain.numImages;
} else {
offscreen = true;
numDrawCommandBuffers = 1;
surfaceFormat = defaultOffscreenSurfaceFormat;
}
d3dDrawCommandLists.resize(numDrawCommandBuffers);
for (auto &cmdList : d3dDrawCommandLists) {
cmdList.create(d3dDevice.v.Get());
}
d3dCopyCommandList.create(d3dDevice.v.Get());
d3dComputeCommandList.create(d3dDevice.v.Get());
if (surface && numSamples != 1) {
NGFX_TODO("");
}
if (surface && enableDepthStencil) {
d3dDepthStencilView.reset((D3DTexture *)Texture::create(
this, nullptr, nullptr, depthFormat, surface->w * surface->h * 4,
surface->w, surface->h, 1, 1,
IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT));
if (numSamples != 1) {
NGFX_TODO("");
}
}
std::optional<AttachmentDescription> depthAttachmentDescription;
if (enableDepthStencil)
depthAttachmentDescription = {depthFormat};
else
depthAttachmentDescription = nullopt;
if (surface && !surface->offscreen) {
RenderPassConfig onscreenRenderPassConfig = {
{{surfaceFormat, IMAGE_LAYOUT_UNDEFINED, IMAGE_LAYOUT_PRESENT_SRC}},
depthAttachmentDescription,
false,
numSamples};
d3dDefaultRenderPass =
(D3DRenderPass *)getRenderPass(onscreenRenderPassConfig);
}
defaultOffscreenSurfaceFormat = PIXELFORMAT_RGBA8_UNORM;
RenderPassConfig offscreenRenderPassConfig = {
{{defaultOffscreenSurfaceFormat}},
depthAttachmentDescription,
false,
numSamples};
d3dDefaultOffscreenRenderPass =
(D3DRenderPass *)getRenderPass(offscreenRenderPassConfig);
if (surface && !surface->offscreen) {
createSwapchainFramebuffers(surface->w, surface->h);
}
// initSemaphores(vkDevice.v);
createFences(d3dDevice.v.Get());
createBindings();
}
RenderPass *D3DGraphicsContext::getRenderPass(RenderPassConfig config) {
for (auto &r : d3dRenderPassCache) {
if (r->config == config)
return &r->d3dRenderPass;
}
auto renderPassData = make_unique<D3DRenderPassData>();
createRenderPass(config, renderPassData->d3dRenderPass);
auto result = &renderPassData->d3dRenderPass;
d3dRenderPassCache.emplace_back(std::move(renderPassData));
return result;
}
void D3DGraphicsContext::createRenderPass(const RenderPassConfig &config,
D3DRenderPass &renderPass) {
D3D12_RESOURCE_STATES
initialResourceState = D3D12_RESOURCE_STATE_RENDER_TARGET,
finalResourceState =
(config.colorAttachmentDescriptions[0].finalLayout ==
IMAGE_LAYOUT_PRESENT_SRC)
? D3D12_RESOURCE_STATE_PRESENT
: D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE |
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
renderPass.create(this, initialResourceState, finalResourceState);
}
void D3DGraphicsContext::createFences(ID3D12Device *device) {
d3dWaitFences.resize(numDrawCommandBuffers);
for (auto &fence : d3dWaitFences) {
fence.create(device, D3DFence::SIGNALED);
}
d3dComputeFence.create(device);
}
void D3DGraphicsContext::createSwapchainFramebuffers(int w, int h) {
// Create frame buffers for every swap chain image
d3dSwapchainFramebuffers.resize(d3dSwapchain.numImages);
for (uint32_t i = 0; i < d3dSwapchainFramebuffers.size(); i++) {
// TODO: add support for MSAA
std::vector<D3DFramebuffer::D3DAttachment> attachments = {
{d3dSwapchain.renderTargets[i].Get(),
d3dSwapchain.renderTargetDescriptors[i].cpuHandle, 0,
IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 1, DXGI_FORMAT(surfaceFormat),
nullptr}};
if (enableDepthStencil) {
attachments.push_back({d3dDepthStencilView->v.Get(),
d3dDepthStencilView->dsvDescriptor.cpuHandle, 0,
IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 1,
DXGI_FORMAT(depthFormat),
d3dDepthStencilView.get()});
}
d3dSwapchainFramebuffers[i].create(attachments, w, h);
}
}
CommandBuffer *D3DGraphicsContext::drawCommandBuffer(int32_t index) {
if (index == -1)
index = currentImageIndex;
return &d3dDrawCommandLists[index];
}
CommandBuffer *D3DGraphicsContext::copyCommandBuffer() {
return &d3dCopyCommandList;
}
CommandBuffer *D3DGraphicsContext::computeCommandBuffer() {
return &d3dComputeCommandList;
}
void D3DGraphicsContext::createBindings() {
device = &d3dDevice;
queue = &d3dCommandQueue;
defaultRenderPass =
offscreen ? d3dDefaultOffscreenRenderPass : d3dDefaultRenderPass;
defaultOffscreenRenderPass = d3dDefaultOffscreenRenderPass;
swapchain = &d3dSwapchain;
frameFences.resize(d3dWaitFences.size());
for (int j = 0; j < d3dWaitFences.size(); j++)
frameFences[j] = &d3dWaitFences[j];
swapchainFramebuffers.resize(d3dSwapchainFramebuffers.size());
for (int j = 0; j < d3dSwapchainFramebuffers.size(); j++)
swapchainFramebuffers[j] = &d3dSwapchainFramebuffers[j];
pipelineCache = &d3dPipelineCache;
}
GraphicsContext *GraphicsContext::create(const char *appName,
bool enableDepthStencil, bool debug) {
NGFX_LOG("debug: %s", (debug) ? "true" : "false");
auto d3dGraphicsContext = new D3DGraphicsContext();
d3dGraphicsContext->create(appName, enableDepthStencil, debug);
return d3dGraphicsContext;
}
Updated on 3 April 2021 at 20:21:51 PDT