Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
PostAAPreRenderOperator.cpp
Go to the documentation of this file.
1
2
4
15
16namespace Divide {
17
20{
21 useSMAA(context.context().config().rendering.postFX.postAA.type == "SMAA");
22 postAAQualityLevel(context.context().config().rendering.postFX.postAA.qualityLevel);
23
24 RenderTargetDescriptor desc = {};
25 desc._resolution = parent.screenRT()._rt->getResolution();
26 {
27 SamplerDescriptor sampler = {};
32 sampler._anisotropyLevel = 0u;
33
34 TextureDescriptor weightsDescriptor{};
35 weightsDescriptor._dataType = GFXDataFormat::FLOAT_16;
36 weightsDescriptor._packing = GFXImagePacking::UNNORMALIZED;
37 weightsDescriptor._mipMappingState = MipMappingState::OFF;
38
39 desc._attachments =
40 {
42 };
43
44 desc._name = "SMAAWeights";
45
47 }
48 { //FXAA Shader
49 ShaderProgramDescriptor aaShaderDescriptor = {};
50 aaShaderDescriptor._globalDefines.emplace_back( "dvd_qualityMultiplier int(PushData0[0].x)" );
51 aaShaderDescriptor._modules = {
52 ShaderModuleDescriptor{ ShaderType::VERTEX, "baseVertexShaders.glsl", "FullScreenQuad" },
54 };
55
56 ResourceDescriptor<ShaderProgram> fxaa("FXAA", aaShaderDescriptor );
57 fxaa.waitForReady(false);
58 _fxaa = CreateResource(fxaa);
59
60 PipelineDescriptor pipelineDescriptor;
61 pipelineDescriptor._stateBlock = _context.get2DStateBlock();
62 pipelineDescriptor._shaderProgramHandle = _fxaa;
64
65 _fxaaPipeline = _context.newPipeline( pipelineDescriptor );
66 }
67 { //SMAA Shaders
68 ShaderModuleDescriptor vertModule = {};
70 vertModule._sourceFile = "SMAA.glsl";
71
72 ShaderModuleDescriptor fragModule = {};
74 fragModule._sourceFile = "SMAA.glsl";
75
76
77 vertModule._variant = "Weight";
78 fragModule._variant = "Weight";
79 ShaderProgramDescriptor weightsDescriptor = {};
80 weightsDescriptor._modules = { vertModule, fragModule };
81 weightsDescriptor._globalDefines.emplace_back( "dvd_qualityMultiplier int(PushData0[0].x)" );
82
83 ResourceDescriptor<ShaderProgram> smaaWeights("SMAA.Weights", weightsDescriptor );
84 smaaWeights.waitForReady(false);
86
87 {
88 PipelineDescriptor pipelineDescriptor;
89 pipelineDescriptor._stateBlock = _context.get2DStateBlock();
92
93 _smaaWeightPipeline = _context.newPipeline( pipelineDescriptor );
94 }
95 vertModule._variant = "Blend";
96 fragModule._variant = "Blend";
97 ShaderProgramDescriptor blendDescriptor = {};
98 blendDescriptor._modules = { vertModule, fragModule };
99
100 ResourceDescriptor<ShaderProgram> smaaBlend("SMAA.Blend", blendDescriptor );
101 smaaBlend.waitForReady(false);
102 _smaaBlend = CreateResource(smaaBlend);
103
104 {
105 PipelineDescriptor pipelineDescriptor;
106 pipelineDescriptor._stateBlock = _context.get2DStateBlock();
107 pipelineDescriptor._shaderProgramHandle = _smaaBlend;
109
110 _smaaBlendPipeline = _context.newPipeline( pipelineDescriptor );
111 }
112 }
113 { //SMAA Textures
114 TextureDescriptor textureDescriptor{};
115 textureDescriptor._textureOptions._alphaChannelTransparency = false;
116
117 ResourceDescriptor<Texture> searchDescriptor("SMAA_Search", textureDescriptor );
118 searchDescriptor.assetName("smaa_search.png");
119 searchDescriptor.assetLocation(Paths::g_imagesLocation);
120 searchDescriptor.waitForReady(false);
121 _searchTexture = CreateResource(searchDescriptor);
122
123 ResourceDescriptor<Texture> areaDescriptor("SMAA_Area", textureDescriptor );
124 areaDescriptor.assetName("smaa_area.png");
125 areaDescriptor.assetLocation(Paths::g_imagesLocation);
126 areaDescriptor.waitForReady(false);
127 _areaTexture = CreateResource(areaDescriptor);
128 }
129}
130
132{
139}
140
142{
143 if (_smaaBlendPipeline != nullptr && _smaaWeightPipeline != nullptr && _fxaaPipeline != nullptr)
144 {
146 {
148 }
149 }
150
151 return false;
152}
153
154void PostAAPreRenderOperator::reshape(const U16 width, const U16 height) {
155 PreRenderOperator::reshape(width, height);
156 _smaaWeights._rt->resize(width, height);
157}
158
160bool PostAAPreRenderOperator::execute([[maybe_unused]] const PlayerIndex idx, [[maybe_unused]] const CameraSnapshot& cameraSnapshot, const RenderTargetHandle& input, const RenderTargetHandle& output, GFX::CommandBuffer& bufferInOut) {
161 if (useSMAA() != currentUseSMAA()) {
162 currentUseSMAA(useSMAA());
163
164 _context.context().config().rendering.postFX.postAA.type = (useSMAA() ? "SMAA" : "FXAA");
165 _context.context().config().changed(true);
166 }
167
168 if (postAAQualityLevel() != currentPostAAQualityLevel()) {
169 currentPostAAQualityLevel(postAAQualityLevel());
170
171 _context.context().config().rendering.postFX.postAA.qualityLevel = postAAQualityLevel();
172 _context.context().config().changed(true);
173
174 if (currentPostAAQualityLevel() == 0) {
176 } else {
178 }
179 }
180
182
183 if (useSMAA()) {
184 { //Step 1: Compute weights
185 GFX::BeginRenderPassCommand beginRenderPassCmd{};
186 beginRenderPassCmd._target = _smaaWeights._targetID;
187 beginRenderPassCmd._name = "DO_SMAA_WEIGHT_PASS";
188 beginRenderPassCmd._descriptor = _screenOnlyDraw;
189 beginRenderPassCmd._clearDescriptor[to_base( RTColourAttachmentSlot::SLOT_0 )] = { DefaultColours::WHITE, true };
190 GFX::EnqueueCommand(bufferInOut, beginRenderPassCmd);
191
193
194 SamplerDescriptor samplerDescriptor = {};
195
196 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>(bufferInOut);
197 cmd->_usage = DescriptorSetUsage::PER_DRAW;
198
199 {
201 Set( binding._data, att->texture(), att->_descriptor._sampler );
202 }
203 samplerDescriptor._mipSampling = TextureMipSampling::NONE;
204 {
206 Set( binding._data, _areaTexture, samplerDescriptor );
207 }
208 samplerDescriptor._minFilter = TextureFilter::NEAREST;
209 samplerDescriptor._magFilter = TextureFilter::NEAREST;
210 {
212 Set( binding._data, _searchTexture, samplerDescriptor );
213 }
214
215 GFX::EnqueueCommand<GFX::BindPipelineCommand>(bufferInOut)->_pipeline = _smaaWeightPipeline;
216
217 PushConstantsStruct& pushData = GFX::EnqueueCommand<GFX::SendPushConstantsCommand>( bufferInOut )->_fastData;
218 pushData.data[0]._vec[0].x = to_F32( postAAQualityLevel() - 1 );
219
220 GFX::EnqueueCommand<GFX::DrawCommand>(bufferInOut)->_drawCommands.emplace_back();
221 GFX::EnqueueCommand<GFX::EndRenderPassCommand>(bufferInOut);
222 }
223 { //Step 2: Blend
224 GFX::BeginRenderPassCommand beginRenderPassCmd{};
225 beginRenderPassCmd._target = output._targetID;
226 beginRenderPassCmd._descriptor = _screenOnlyDraw;
227 beginRenderPassCmd._clearDescriptor[to_base( RTColourAttachmentSlot::SLOT_0 )] = { DefaultColours::WHITE, true };
228 beginRenderPassCmd._name = "DO_SMAA_BLEND_PASS";
229 GFX::EnqueueCommand(bufferInOut, beginRenderPassCmd);
230
231 const auto& weightAtt = _smaaWeights._rt->getAttachment(RTAttachmentType::COLOUR);
232
233 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>(bufferInOut);
234 cmd->_usage = DescriptorSetUsage::PER_DRAW;
235
236 {
238 Set( binding._data, screenAtt->texture(), screenAtt->_descriptor._sampler );
239 }
240 {
242 Set( binding._data, weightAtt->texture(), screenAtt->_descriptor._sampler );
243 }
244
245 GFX::EnqueueCommand<GFX::BindPipelineCommand>(bufferInOut)->_pipeline = _smaaBlendPipeline;
246
247 GFX::EnqueueCommand<GFX::DrawCommand>(bufferInOut)->_drawCommands.emplace_back();
248 GFX::EnqueueCommand<GFX::EndRenderPassCommand>(bufferInOut);
249 }
250 } else {
251 // Apply FXAA/SMAA to the specified render target
252 GFX::BeginRenderPassCommand beginRenderPassCmd;
253 beginRenderPassCmd._target = output._targetID;
254 beginRenderPassCmd._descriptor = _screenOnlyDraw;
256 beginRenderPassCmd._name = "DO_POSTAA_PASS";
257 GFX::EnqueueCommand(bufferInOut, beginRenderPassCmd);
258
259 GFX::EnqueueCommand<GFX::BindPipelineCommand>(bufferInOut )->_pipeline = _fxaaPipeline;
260
261 PushConstantsStruct& pushData = GFX::EnqueueCommand<GFX::SendPushConstantsCommand>( bufferInOut )->_fastData;
262 pushData.data[0]._vec[0].x = to_F32( postAAQualityLevel() - 1 );
263
264 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>(bufferInOut);
265 cmd->_usage = DescriptorSetUsage::PER_DRAW;
266
267 {
269 Set( binding._data, screenAtt->texture(), screenAtt->_descriptor._sampler );
270 }
271
272 GFX::EnqueueCommand<GFX::DrawCommand>(bufferInOut)->_drawCommands.emplace_back();
273 GFX::EnqueueCommand<GFX::EndRenderPassCommand>(bufferInOut);
274 }
275
276 return true;
277}
278}
#define WAIT_FOR_CONDITION(...)
Rough around the edges Adapter pattern abstracting the actual rendering API and access to the GPU.
Definition: GFXDevice.h:215
GFXRTPool & renderTargetPool() noexcept
Definition: GFXDevice.inl:133
Pipeline * newPipeline(const PipelineDescriptor &descriptor)
Create and return a new graphics pipeline. This is only used for caching and doesn't use the object a...
Definition: GFXDevice.cpp:3074
const RenderStateBlock & get2DStateBlock() const noexcept
Definition: GFXDevice.inl:123
RenderTargetHandle allocateRT(const RenderTargetDescriptor &descriptor)
Definition: GFXRTPool.cpp:17
PlatformContext & context() noexcept
Configuration & config() noexcept
PostAAPreRenderOperator(GFXDevice &context, PreRenderBatch &parent)
bool ready() const noexcept override
Handle< ShaderProgram > _fxaa
Pipeline * _smaaBlendPipeline
void reshape(U16 width, U16 height) override
Handle< Texture > _areaTexture
Pipeline * _smaaWeightPipeline
RenderTargetHandle _smaaWeights
Handle< Texture > _searchTexture
Handle< ShaderProgram > _smaaBlend
Pipeline * _fxaaPipeline
Handle< ShaderProgram > _smaaWeightComputation
~PostAAPreRenderOperator()
bool execute(PlayerIndex idx, const CameraSnapshot &cameraSnapshot, const RenderTargetHandle &input, const RenderTargetHandle &output, GFX::CommandBuffer &bufferInOut) override
This is tricky as we use our screen as both input and output.
void popFilter(const FilterType filter, const bool overrideScene=false)
Definition: PostFX.h:94
void pushFilter(const FilterType filter, const bool overrideScene=false)
Definition: PostFX.h:77
RenderTargetHandle edgesRT() const noexcept
PostFX & parent() const noexcept
virtual void reshape(U16 width, U16 height)
virtual bool ready() const noexcept
RTDrawDescriptor _screenOnlyDraw
RTAttachment * getAttachment(RTAttachmentType type, RTColourAttachmentSlot slot=RTColourAttachmentSlot::SLOT_0) const
bool resize(U16 width, U16 height)
Resize all attachments.
vec4< T > _vec[4]
Definition: MathMatrices.h:709
FColour4 WHITE
Random stuff added for convenience.
Definition: Colours.cpp:8
FORCE_INLINE T * EnqueueCommand(CommandBuffer &buffer)
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
FORCE_INLINE void DestroyResource(Handle< T > &handle, const bool immediate=false)
@ RES_LOADED
The resource is available for usage.
constexpr F32 to_F32(const T value)
Project & parent
Definition: DefaultScene.h:41
uint16_t U16
void Set(DescriptorSetBindingData &dataInOut, ShaderBuffer *buffer, const BufferRange range) noexcept
DescriptorSetBinding & AddBinding(DescriptorSet &setInOut, U8 slot, U16 stageVisibilityMask)
FORCE_INLINE Handle< T > CreateResource(const ResourceDescriptor< T > &descriptor, bool &wasInCache, std::atomic_uint &taskCounter)
FORCE_INLINE T * Get(const Handle< T > handle)
constexpr auto to_base(const Type value) -> Type
U8 qualityLevel
string type
struct Divide::Configuration::Rendering::PostFX::PostAA postAA
struct Divide::Configuration::Rendering::PostFX postFX
struct Divide::Configuration::Rendering rendering
DescriptorSetBindingData _data
RTClearDescriptor _clearDescriptor
Definition: Commands.inl:97
static constexpr RTColourAttachmentSlot ALBEDO
Definition: GFXDevice.h:228
bool _alphaChannelTransparency
If false, the alpha channel represents arbitrary data (e.g. in splatmaps)
Definition: ImageToolsFwd.h:72
PrimitiveTopology _primitiveTopology
Definition: Pipeline.h:48
Handle< ShaderProgram > _shaderProgramHandle
Definition: Pipeline.h:47
RenderStateBlock _stateBlock
Definition: Pipeline.h:46
vector< ShaderModuleDescriptor > _modules
ImageTools::ImportOptions _textureOptions
InternalRTAttachmentDescriptors _attachments
Definition: RenderTarget.h:52
RenderTargetID _targetID
Definition: RenderTarget.h:47
TextureFilter _minFilter
Texture filtering mode.
TextureWrap _wrapU
Texture wrap mode (Or S-R-T)
U8 _anisotropyLevel
The value must be in the range [0...255] and is automatically clamped by the max HW supported level.
TextureMipSampling _mipSampling