Files
WickedEngine/WickedEngine/RenderPath2D.cpp
T
Turánszki János f3687dbf4e DX11 removal, Surfel GI
version 0.57.0:
- DX11 removed, DX12 is default now on Windows
- graphics interfaces improved:
	- Bindless descriptor support is now assumed
	- GPU Buffers with USAGE_UPLOAD and USAGE_READBACK will be persistently mapped after creation
	- Removed Map/Unmap
	- added BindDynamicConstantBuffer helper function
	- improved AllocateGPU helper function
	- GPU Queries resolving can be done directly into GPUBuffer
	- UpdateBuffer now doesn't synchronize internally, this allows batching updates
	- removed support for bindless constant buffers (uniform buffers)
	- BindConstantBuffer will accept offset
	- RESOURCE_STATES refactor, they can be combined now in the barriers
	- many other refactors
- gbuffer normals removed, implemented visibility buffer
- bindless decals, bindless lightmaps, bindless hair particles, bindless software path tracing
- hair particles path tracing support
- path tracing eye adaption supported
- Surfel GI (experimental)
2021-09-05 18:59:03 +02:00

522 lines
10 KiB
C++

#include "RenderPath2D.h"
#include "wiResourceManager.h"
#include "wiSprite.h"
#include "wiSpriteFont.h"
#include "wiRenderer.h"
using namespace wiGraphics;
void RenderPath2D::ResizeBuffers()
{
current_buffersize = GetInternalResolution();
current_layoutscale = 0; // invalidate layout
GraphicsDevice* device = wiRenderer::GetDevice();
const Texture* dsv = GetDepthStencil();
if(dsv != nullptr && (resolutionScale != 1.0f || dsv->GetDesc().SampleCount > 1))
{
TextureDesc desc = GetDepthStencil()->GetDesc();
desc.layout = RESOURCE_STATE_SHADER_RESOURCE;
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE;
desc.Format = FORMAT_R8G8B8A8_UNORM;
device->CreateTexture(&desc, nullptr, &rtStenciled);
device->SetName(&rtStenciled, "rtStenciled");
if (desc.SampleCount > 1)
{
desc.SampleCount = 1;
device->CreateTexture(&desc, nullptr, &rtStenciled_resolved);
device->SetName(&rtStenciled_resolved, "rtStenciled_resolved");
}
}
else
{
rtStenciled = Texture(); // this will be deleted here
}
{
TextureDesc desc;
desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE;
desc.Format = FORMAT_R8G8B8A8_UNORM;
desc.Width = GetPhysicalWidth();
desc.Height = GetPhysicalHeight();
device->CreateTexture(&desc, nullptr, &rtFinal);
device->SetName(&rtFinal, "rtFinal");
}
if (rtStenciled.IsValid())
{
RenderPassDesc desc;
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtStenciled, RenderPassAttachment::LOADOP_CLEAR));
desc.attachments.push_back(
RenderPassAttachment::DepthStencil(
dsv,
RenderPassAttachment::LOADOP_LOAD,
RenderPassAttachment::STOREOP_STORE,
RESOURCE_STATE_DEPTHSTENCIL_READONLY,
RESOURCE_STATE_DEPTHSTENCIL_READONLY,
RESOURCE_STATE_DEPTHSTENCIL_READONLY
)
);
if (rtStenciled.GetDesc().SampleCount > 1)
{
desc.attachments.push_back(RenderPassAttachment::Resolve(&rtStenciled_resolved));
}
device->CreateRenderPass(&desc, &renderpass_stenciled);
dsv = nullptr;
}
{
RenderPassDesc desc;
desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtFinal, RenderPassAttachment::LOADOP_CLEAR));
if(dsv != nullptr && !rtStenciled.IsValid())
{
desc.attachments.push_back(
RenderPassAttachment::DepthStencil(
dsv,
RenderPassAttachment::LOADOP_LOAD,
RenderPassAttachment::STOREOP_STORE,
RESOURCE_STATE_DEPTHSTENCIL_READONLY,
RESOURCE_STATE_DEPTHSTENCIL_READONLY,
RESOURCE_STATE_DEPTHSTENCIL_READONLY
)
);
}
device->CreateRenderPass(&desc, &renderpass_final);
}
}
void RenderPath2D::ResizeLayout()
{
current_layoutscale = GetDPIScaling();
}
void RenderPath2D::Update(float dt)
{
XMUINT2 internalResolution = GetInternalResolution();
if (current_buffersize.x != internalResolution.x || current_buffersize.y != internalResolution.y)
{
ResizeBuffers();
}
if (current_layoutscale != GetDPIScaling())
{
ResizeLayout();
}
GetGUI().Update(*this, dt);
for (auto& x : layers)
{
for (auto& y : x.items)
{
switch (y.type)
{
default:
case RenderItem2D::SPRITE:
if (y.sprite != nullptr)
{
y.sprite->Update(dt);
}
break;
case RenderItem2D::FONT:
if (y.font != nullptr)
{
y.font->Update(dt);
}
break;
}
}
}
RenderPath::Update(dt);
}
void RenderPath2D::FixedUpdate()
{
for (auto& x : layers)
{
for (auto& y : x.items)
{
switch (y.type)
{
default:
case RenderItem2D::SPRITE:
if (y.sprite != nullptr)
{
y.sprite->FixedUpdate();
}
break;
case RenderItem2D::FONT:
if (y.font != nullptr)
{
y.font->FixedUpdate();
}
break;
}
}
}
RenderPath::FixedUpdate();
}
void RenderPath2D::Render() const
{
GraphicsDevice* device = wiRenderer::GetDevice();
CommandList cmd = device->BeginCommandList();
wiImage::SetCanvas(*this, cmd);
wiFont::SetCanvas(*this, cmd);
wiRenderer::ProcessDeferredMipGenRequests(cmd);
if (GetGUIBlurredBackground() != nullptr)
{
wiImage::SetBackground(*GetGUIBlurredBackground(), cmd);
}
// Special care for internal resolution, because stencil buffer is of internal resolution,
// so we might need to render stencil sprites to separate render target that matches internal resolution!
if (rtStenciled.IsValid())
{
device->RenderPassBegin(&renderpass_stenciled, cmd);
Viewport vp;
vp.Width = (float)rtStenciled.GetDesc().Width;
vp.Height = (float)rtStenciled.GetDesc().Height;
device->BindViewports(1, &vp, cmd);
wiRenderer::GetDevice()->EventBegin("STENCIL Sprite Layers", cmd);
for (auto& x : layers)
{
for (auto& y : x.items)
{
if (y.type == RenderItem2D::SPRITE &&
y.sprite != nullptr &&
y.sprite->params.stencilComp != STENCILMODE_DISABLED)
{
y.sprite->Draw(cmd);
}
}
}
wiRenderer::GetDevice()->EventEnd(cmd);
device->RenderPassEnd(cmd);
}
device->RenderPassBegin(&renderpass_final, cmd);
Viewport vp;
vp.Width = (float)rtFinal.GetDesc().Width;
vp.Height = (float)rtFinal.GetDesc().Height;
device->BindViewports(1, &vp, cmd);
if (GetDepthStencil() != nullptr)
{
if (rtStenciled.IsValid())
{
wiRenderer::GetDevice()->EventBegin("Copy STENCIL Sprite Layers", cmd);
wiImageParams fx;
fx.enableFullScreen();
if (rtStenciled.GetDesc().SampleCount > 1)
{
wiImage::Draw(&rtStenciled_resolved, fx, cmd);
}
else
{
wiImage::Draw(&rtStenciled, fx, cmd);
}
wiRenderer::GetDevice()->EventEnd(cmd);
}
else
{
wiRenderer::GetDevice()->EventBegin("STENCIL Sprite Layers", cmd);
for (auto& x : layers)
{
for (auto& y : x.items)
{
if (y.type == RenderItem2D::SPRITE &&
y.sprite != nullptr &&
y.sprite->params.stencilComp != STENCILMODE_DISABLED)
{
y.sprite->Draw(cmd);
}
}
}
wiRenderer::GetDevice()->EventEnd(cmd);
}
}
wiRenderer::GetDevice()->EventBegin("Sprite Layers", cmd);
for (auto& x : layers)
{
for (auto& y : x.items)
{
switch (y.type)
{
default:
case RenderItem2D::SPRITE:
if (y.sprite != nullptr && y.sprite->params.stencilComp == STENCILMODE_DISABLED)
{
y.sprite->Draw(cmd);
}
break;
case RenderItem2D::FONT:
if (y.font != nullptr)
{
y.font->Draw(cmd);
}
break;
}
}
}
wiRenderer::GetDevice()->EventEnd(cmd);
GetGUI().Render(*this, cmd);
device->RenderPassEnd(cmd);
RenderPath::Render();
}
void RenderPath2D::Compose(CommandList cmd) const
{
wiImageParams fx;
fx.enableFullScreen();
fx.blendFlag = BLENDMODE_PREMULTIPLIED;
wiImage::Draw(&rtFinal, fx, cmd);
RenderPath::Compose(cmd);
}
void RenderPath2D::AddSprite(wiSprite* sprite, const std::string& layer)
{
for (auto& x : layers)
{
if (!x.name.compare(layer))
{
x.items.push_back(RenderItem2D());
x.items.back().type = RenderItem2D::SPRITE;
x.items.back().sprite = sprite;
}
}
SortLayers();
}
void RenderPath2D::RemoveSprite(wiSprite* sprite)
{
for (auto& x : layers)
{
for (auto& y : x.items)
{
if (y.type == RenderItem2D::SPRITE && y.sprite == sprite)
{
y.sprite = nullptr;
}
}
}
CleanLayers();
}
void RenderPath2D::ClearSprites()
{
for (auto& x : layers)
{
for (auto& y : x.items)
{
if (y.type == RenderItem2D::SPRITE)
{
y.sprite = nullptr;
}
}
}
CleanLayers();
}
int RenderPath2D::GetSpriteOrder(wiSprite* sprite)
{
for (auto& x : layers)
{
for (auto& y : x.items)
{
if (y.sprite == sprite)
{
return y.order;
}
}
}
return 0;
}
void RenderPath2D::AddFont(wiSpriteFont* font, const std::string& layer)
{
for (auto& x : layers)
{
if (!x.name.compare(layer))
{
x.items.push_back(RenderItem2D());
x.items.back().type = RenderItem2D::FONT;
x.items.back().font = font;
}
}
SortLayers();
}
void RenderPath2D::RemoveFont(wiSpriteFont* font)
{
for (auto& x : layers)
{
for (auto& y : x.items)
{
if (y.type == RenderItem2D::FONT && y.font == font)
{
y.font = nullptr;
}
}
}
CleanLayers();
}
void RenderPath2D::ClearFonts()
{
for (auto& x : layers)
{
for (auto& y : x.items)
{
if (y.type == RenderItem2D::FONT)
{
y.font = nullptr;
}
}
}
CleanLayers();
}
int RenderPath2D::GetFontOrder(wiSpriteFont* font)
{
for (auto& x : layers)
{
for (auto& y : x.items)
{
if (y.font == font)
{
return y.order;
}
}
}
return 0;
}
void RenderPath2D::AddLayer(const std::string& name)
{
for (auto& x : layers)
{
if (!x.name.compare(name))
return;
}
RenderLayer2D layer;
layer.name = name;
layer.order = (int)layers.size();
layers.push_back(layer);
layers.back().items.clear();
}
void RenderPath2D::SetLayerOrder(const std::string& name, int order)
{
for (auto& x : layers)
{
if (!x.name.compare(name))
{
x.order = order;
break;
}
}
SortLayers();
}
void RenderPath2D::SetSpriteOrder(wiSprite* sprite, int order)
{
for (auto& x : layers)
{
for (auto& y : x.items)
{
if (y.type == RenderItem2D::SPRITE && y.sprite == sprite)
{
y.order = order;
}
}
}
SortLayers();
}
void RenderPath2D::SetFontOrder(wiSpriteFont* font, int order)
{
for (auto& x : layers)
{
for (auto& y : x.items)
{
if (y.type == RenderItem2D::FONT && y.font == font)
{
y.order = order;
}
}
}
SortLayers();
}
void RenderPath2D::SortLayers()
{
if (layers.empty())
{
return;
}
for (size_t i = 0; i < layers.size() - 1; ++i)
{
for (size_t j = i + 1; j < layers.size(); ++j)
{
if (layers[i].order > layers[j].order)
{
RenderLayer2D swap = layers[i];
layers[i] = layers[j];
layers[j] = swap;
}
}
}
for (auto& x : layers)
{
if (x.items.empty())
{
continue;
}
for (size_t i = 0; i < x.items.size() - 1; ++i)
{
for (size_t j = i + 1; j < x.items.size(); ++j)
{
if (x.items[i].order > x.items[j].order)
{
RenderItem2D swap = x.items[i];
x.items[i] = x.items[j];
x.items[j] = swap;
}
}
}
}
}
void RenderPath2D::CleanLayers()
{
for (auto& x : layers)
{
if (x.items.empty())
{
continue;
}
std::vector<RenderItem2D> itemsToRetain(0);
for (auto& y : x.items)
{
if (y.sprite != nullptr || y.font!=nullptr)
{
itemsToRetain.push_back(y);
}
}
x.items.clear();
x.items = itemsToRetain;
}
}