Cogs.Core
ResolveResourceTask.cpp
1#include "ResolveResourceTask.h"
2
3#include "ProcessTask.h"
4
5#include "Rendering/CommandGroupAnnotation.h"
6#include "Rendering/IBuffers.h"
7#include "Rendering/ICapabilities.h"
8#include "Rendering/IContext.h"
9#include "Rendering/IEffects.h"
10#include "Rendering/IGraphicsDevice.h"
11#include "Rendering/ITextures.h"
12
13#include "Resources/VertexFormats.h"
14
15#include "Renderer/Renderer.h"
16#include "Renderer/RenderTarget.h"
17#include "Renderer/RenderTexture.h"
18
19#include "Platform/Instrumentation.h"
20
21#include "Foundation/Logging/Logger.h"
22
23#include <cassert>
24
25using namespace Cogs;
26
27namespace
28{
29 Cogs::Logging::Log logger = Cogs::Logging::getLogger("ResolveResourceTask");
30}
31
32Cogs::ResourceStatus Cogs::Core::ResolveResourceTask::setupColorEffect(RenderTaskContext * context)
33{
34 if (!colorEffect) {
36 desc.vs = "Engine/FullscreenV3T2VS.hlsl";
37 desc.ps = "PostProcess/ResolveColor.hlsl";
38 colorEffect = context->renderer->getEffectCache().loadEffect(context, desc);
39 }
40
41 IEffects* effects = context->device->getEffects();
42 Cogs::ResourceStatus status = HandleIsValid(colorEffect->handle) ? effects->checkEffect(colorEffect->handle) : Cogs::ResourceStatus::Error;
43
44 if (status == Cogs::ResourceStatus::Ready && colorEffectStatus != Cogs::ResourceStatus::Ready) {
45 IBuffers* buffers = context->device->getBuffers();
46 colorInputLayout = buffers->loadInputLayout(&VertexFormats::Pos4f, 1, colorEffect->handle);
47 colorTextureBinding = effects->getTextureBinding(colorEffect->handle, "colorTexture", 0);
48 }
49
50 if (status == Cogs::ResourceStatus::Error && colorEffectStatus != Cogs::ResourceStatus::Error) {
51 LOG_ERROR(logger, "Invalid resolve color effect handle.");
52 }
53
54 colorEffectStatus = status;
55 return colorEffectStatus;
56}
57Cogs::ResourceStatus Cogs::Core::ResolveResourceTask::setupDepthEffect(RenderTaskContext * context)
58{
59 if (!depthEffect) {
61 desc.vs = "Engine/FullscreenV3T2VS.hlsl";
62 desc.ps = "PostProcess/ResolveDepth.hlsl";
63 depthEffect = context->renderer->getEffectCache().loadEffect(context, desc);
64 }
65
66 IEffects* effects = context->device->getEffects();
67 Cogs::ResourceStatus status = HandleIsValid(depthEffect->handle) ? effects->checkEffect(depthEffect->handle) : Cogs::ResourceStatus::Error;
68
69 if (status == Cogs::ResourceStatus::Ready && depthEffectStatus != Cogs::ResourceStatus::Ready) {
70 IBuffers* buffers = context->device->getBuffers();
71 depthInputLayout = buffers->loadInputLayout(&VertexFormats::Pos4f, 1, depthEffect->handle);
72 depthTextureBinding = effects->getTextureBinding(depthEffect->handle, "depthTexture", 0);
73 }
74
75 if (status == Cogs::ResourceStatus::Error && depthEffectStatus != Cogs::ResourceStatus::Error) {
76 LOG_ERROR(logger, "Invalid resolve depth effect handle.");
77 }
78
79 depthEffectStatus = status;
80 return depthEffectStatus;
81}
82void Cogs::Core::ResolveResourceTask::resolveColorShader(RenderTaskContext * context,
83 RenderTexture * inputTexture,
84 RenderTexture * outputTexture)
85{
86 assert(colorEffectStatus == Cogs::ResourceStatus::Ready);
87
88 IGraphicsDevice* device = context->device;
89 IContext* deviceContext = device->getImmediateContext();
90
91 CommandGroupAnnotation commandGroup(deviceContext, "ResolveResourceTask::ColorShader");
92 if(!outputTexture->resolveTarget){
93 RenderTexture* renderTexture = outputTexture;
94 RenderTarget* resolveTarget = context->resources->createRenderTarget();
95 resolveTarget->setName(outputTexture->getName() + " RT");
96 resolveTarget->textures.push_back(renderTexture);
97 resolveTarget->width = renderTexture->description.width;
98 resolveTarget->height = renderTexture->description.height;
99 resolveTarget->samples = renderTexture->description.samples;
100 resolveTarget->update(context->renderer);
101 renderTexture->resolveTarget = resolveTarget;
102 }
103
104 deviceContext->setEffect(colorEffect->handle);
105
106 RenderTarget* resolveTarget = outputTexture->resolveTarget;
107 assert(HandleIsValid(resolveTarget->renderTargetHandle));
108 if (device->getCapabilities()->getDeviceCapabilities().RenderPass) {
110 info.renderTargetHandle = resolveTarget->renderTargetHandle;
111 info.depthStencilHandle = DepthStencilHandle::NoHandle;
112 info.loadOp[0] = LoadOp::Clear;
113 info.storeOp[0] = StoreOp::Store;
114 info.depthLoadOp = LoadOp::Undefined;
115 info.depthStoreOp = StoreOp::Undefined;
116 info.depthClearValue = context->renderer->getClearDepth();
117 info.depthReadOnly = true;
118 deviceContext->beginRenderPass(info);
119 }
120 else{
121 deviceContext->setRenderTarget(resolveTarget->renderTargetHandle, DepthStencilHandle::NoHandle);
122 float vals[4] = {};
123 deviceContext->clearRenderTarget(vals);
124 }
125
126 deviceContext->setViewport(0.0f, 0.0f, static_cast<float>(resolveTarget->width), static_cast<float>(resolveTarget->height));
127
128 deviceContext->setDepthStencilState(context->states->commonDepthStates[RenderStates::noTestDepthStencilState]);
129 deviceContext->setRasterizerState(context->states->defaultRasterizerStateHandle);
130 deviceContext->setBlendState(context->states->blendStates[size_t(BlendMode::None)].handle);
131
132 deviceContext->setTexture(colorTextureBinding, inputTexture->textureHandle);
133
134 deviceContext->setVertexBuffers(&context->states->fullScreenTriangle, 1);
136 deviceContext->setInputLayout(colorInputLayout);
137 deviceContext->draw(PrimitiveType::TriangleList, 0, 3);
138
139 if (device->getCapabilities()->getDeviceCapabilities().RenderPass) {
140 deviceContext->endRenderPass();
141 }
142}
143void Cogs::Core::ResolveResourceTask::resolveDepthShader(RenderTaskContext * context,
144 RenderTexture * inputTexture,
145 RenderTexture * outputTexture)
146{
147 assert(depthEffectStatus == Cogs::ResourceStatus::Ready);
148
149 IGraphicsDevice* device = context->device;
150 IContext* deviceContext = device->getImmediateContext();
151
152 CommandGroupAnnotation commandGroup(deviceContext, "ResolveResourceTask::DepthShader");
153 if(!outputTexture->resolveTarget){
154 RenderTexture* renderTexture = outputTexture;
155 RenderTarget* resolveTarget = context->resources->createRenderTarget();
156 resolveTarget->setName(outputTexture->getName() + " RT");
157 resolveTarget->depth = renderTexture;
158 resolveTarget->width = renderTexture->description.width;
159 resolveTarget->height = renderTexture->description.height;
160 resolveTarget->samples = renderTexture->description.samples;
161 resolveTarget->update(context->renderer);
162 renderTexture->resolveTarget = resolveTarget;
163 }
164
165 deviceContext->setEffect(depthEffect->handle);
166
167 RenderTarget* resolveTarget = outputTexture->resolveTarget;
168 assert(HandleIsValid(resolveTarget->depthTargetHandle));
169 if (device->getCapabilities()->getDeviceCapabilities().RenderPass) {
171 info.renderTargetHandle = RenderTargetHandle::NoHandle;
172 info.depthStencilHandle = resolveTarget->depthTargetHandle;
173 info.depthLoadOp = LoadOp::Clear;
174 info.depthStoreOp = StoreOp::Store;
175 info.depthClearValue = context->renderer->getClearDepth();
176 info.depthReadOnly = false;
177 deviceContext->beginRenderPass(info);
178 }
179 else{
180 deviceContext->setRenderTarget(RenderTargetHandle::NoHandle, resolveTarget->depthTargetHandle);
181 deviceContext->clearDepth(context->renderer->getClearDepth());
182 }
183
184 deviceContext->setViewport(0.0f, 0.0f, static_cast<float>(resolveTarget->width), static_cast<float>(resolveTarget->height));
185
186 deviceContext->setDepthStencilState(context->states->commonDepthStates[RenderStates::noTestDepthStencilState]);
187 deviceContext->setRasterizerState(context->states->defaultRasterizerStateHandle);
188 deviceContext->setBlendState(context->states->blendStates[size_t(BlendMode::Zero)].handle);
189
190 deviceContext->setTexture(depthTextureBinding, inputTexture->textureHandle);
191
192 deviceContext->setVertexBuffers(&context->states->fullScreenTriangle, 1);
194 deviceContext->setInputLayout(depthInputLayout);
195 deviceContext->draw(PrimitiveType::TriangleList, 0, 3);
196
197 if (device->getCapabilities()->getDeviceCapabilities().RenderPass) {
198 deviceContext->endRenderPass();
199 }
200}
201
202void Cogs::Core::ResolveResourceTask::cleanup(RenderTaskContext * context)
203{
204 if(colorEffect) context->renderer->getEffectCache().release(context, colorEffect);
205 if(depthEffect) context->renderer->getEffectCache().release(context, depthEffect);
206}
207
209{
210 RenderTexture* inputTexture = input.get(RenderResourceType::RenderTexture)->renderTexure;
211 IGraphicsDevice* device = context->device;
212
213 if (!HandleIsValid(inputTexture->textureHandle)) {
214 action = ResolveAction::None;
216 }
217
218 if (device->getType() != GraphicsDeviceType::OpenGLES30 &&
219 inputTexture->description.flags & TextureFlags::DepthBuffer) {
220 action = ResolveAction::DepthShader;
221 return setupDepthEffect(context);
222 }
223
224 if (inputTexture->description.samples == 1) {
225 action = ResolveAction::Copy;
227 }
228
229 if (device->getType() == GraphicsDeviceType::WebGPU) {
230 action = ResolveAction::ColorShader;
231 return setupColorEffect(context);
232 }
233
234 action = ResolveAction::Resolve;
236}
237
238void Cogs::Core::ResolveResourceTask::apply(RenderTaskContext * context)
239{
240 RenderInstrumentationScope(context->device->getImmediateContext(), SCOPE_RENDERING, "ResolveResourceTask::apply");
241
242 RenderTexture* inputTexture = input.get(RenderResourceType::RenderTexture)->renderTexure;
243 RenderTexture* outputTexture = output.get(RenderResourceType::RenderTexture)->renderTexure;
244
245 IContext* deviceContext = context->device->getImmediateContext();
246
247 switch (action) {
248 case ResolveAction::None:
249 break;
250 case ResolveAction::Copy:
251 deviceContext->copyResource(outputTexture->textureHandle, inputTexture->textureHandle);
252 break;
253 case ResolveAction::Resolve:
254 deviceContext->resolveResource(inputTexture->textureHandle, outputTexture->textureHandle);
255 break;
256 case ResolveAction::ColorShader:
257 resolveColorShader(context, inputTexture, outputTexture);
258 break;
259 case ResolveAction::DepthShader:
260 resolveDepthShader(context, inputTexture, outputTexture);
261 break;
262 }
263}
Cogs::ResourceStatus checkReady(RenderTaskContext *context) override
Check if the task is ready to be applied, e.g.
Represents a graphics device used to manage graphics resources and issue drawing commands.
virtual ICapabilities * getCapabilities()=0
Get a pointer to the capability management interface used to query the graphics device capability fla...
virtual IContext * getImmediateContext()=0
Get a pointer to the immediate context used to issue commands to the graphics device.
virtual GraphicsDeviceType getType() const
Get the type of the graphics device.
Log implementation class.
Definition: LogManager.h:140
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
@ None
No blending enabled for opaque shapes, defaults to Blend for transparent shapes.
@ Zero
Disable all color writes.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:181
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
@ WebGPU
Graphics device using the WebGPU API Backend.
ResourceStatus
Status of an asynchronously loaded resource, such as an effect or a pipeline.
Definition: Common.h:198
@ Error
The resource failed to load.
@ Ready
The resource has loaded successfully and is ready for use.
@ TriangleList
List of triangles.
RAII-helper for pushCommandGroupAnnotation/pushCommandGroupAnnotation.
Contains an effect description used to load a single effect.
Definition: IEffects.h:62
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:78
Provides buffer management functionality.
Definition: IBuffers.h:13
virtual InputLayoutHandle loadInputLayout(const VertexFormatHandle *vertexFormats, const size_t count, EffectHandle effectHandle)=0
Loads a new input layout to map vertex flow between vertex buffers with the given vertexFormats to ef...
virtual const GraphicsDeviceCapabilities & getDeviceCapabilities() const
Gets the device capabilities in a structure.
Represents a graphics device context which can receive rendering commands.
Definition: IContext.h:43
virtual void setTexture(const StringView &name, unsigned int unit, TextureHandle textureHandle)=0
Sets the texture slot given by unit with the given name to contain the given texture.
virtual void setRasterizerState(const RasterizerStateHandle handle)=0
Set the current rasterizer state.
virtual void setBlendState(const BlendStateHandle handle, const float *constant=nullptr)=0
Set the current blend state.
virtual void setInputLayout(const InputLayoutHandle inputLayoutHandle)=0
Sets the current input layout.
virtual void clearRenderTarget(const float *value)=0
Clear the currently set render target to the given value (4 component floating point RGBA).
virtual void endRenderPass()=0
End a render pass.
virtual void setIndexBuffer(IndexBufferHandle bufferHandle, uint32_t stride=4, uint32_t offset=0)=0
Sets the current index buffer.
virtual void setDepthStencilState(const DepthStencilStateHandle handle)=0
Set the current depth stencil state.
virtual void resolveResource(TextureHandle source, TextureHandle destination)=0
Resolves the given source resource target into the given destination texture.
virtual void clearDepth(const float depth=1.0f)=0
Clear the currently set depth/stencil target to the given depth.
virtual void setViewport(const float x, const float y, const float width, const float height)=0
Sets the current viewport to the given location and dimensions.
virtual void draw(PrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes)=0
Draws non-indexed, non-instanced primitives.
virtual void beginRenderPass(const RenderPassInfo &info)=0
Begin a render pass.
virtual void setVertexBuffers(const VertexBufferHandle *vertexBufferHandles, const size_t count, const uint32_t *strides, const uint32_t *offsets)=0
Sets the current vertex buffers.
virtual void setEffect(EffectHandle handle)=0
Set the current effect.
virtual void setRenderTarget(const RenderTargetHandle handle, const DepthStencilHandle depthStencilHandle)=0
Sets the current render target and an associated depth stencil target.
Provides effects and shader management functionality.
Definition: IEffects.h:158
virtual TextureBindingHandle getTextureBinding(EffectHandle effectHandle, const StringView &name, const unsigned int slot)=0
Get a handle to a texture object binding, mapping how to bind textures to the given effect.
virtual ResourceStatus checkEffect(EffectHandle effectHandle)=0
Check the load status of the effect with the given effectHandle.
@ DepthBuffer
The texture can be used as a depth target and have depth buffer values written into.
Definition: Flags.h:122