KiCad PCB EDA Suite
Loading...
Searching...
No Matches
rhi_compositor.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <rhi/rhi_compositor.h>
21#include <rhi/rhi_device.h>
22
23#include <trace_helpers.h>
24#include <wx/log.h>
25
26#include <utility>
27
28
30 m_device( aDevice )
31{
32}
33
34
39
40
42{
43 RHI_RENDER_PASS_DESC clearRpDesc;
44 RHI_COLOR_ATTACHMENT_DESC clearAttach;
46 clearAttach.loadOp = RHI_LOAD_OP::CLEAR;
47 clearAttach.storeOp = RHI_STORE_OP::STORE;
48 clearAttach.clearColor[0] = 0.0f;
49 clearAttach.clearColor[1] = 0.0f;
50 clearAttach.clearColor[2] = 0.0f;
51 clearAttach.clearColor[3] = 0.0f;
52 clearRpDesc.colorAttachments.push_back( clearAttach );
53
54 m_clearRenderPass = m_device.CreateRenderPass( clearRpDesc );
55
57 {
58 Destroy();
59 return false;
60 }
61
62 // The shared 16-byte vertex layout, of which the compositor uses only position and UV
63 struct QuadVertex
64 {
65 float x, y;
66 uint8_t r, g, b, a;
67 uint16_t u, v;
68 };
69
70 // Half-float encodings of 0.0 and 1.0
71 constexpr uint16_t H0 = 0x0000;
72 constexpr uint16_t H1 = 0x3C00;
73
74 QuadVertex verts[6] = {
75 { -1.0f, -1.0f, 255, 255, 255, 255, H0, H0 },
76 { 1.0f, -1.0f, 255, 255, 255, 255, H1, H0 },
77 { 1.0f, 1.0f, 255, 255, 255, 255, H1, H1 },
78 { -1.0f, -1.0f, 255, 255, 255, 255, H0, H0 },
79 { 1.0f, 1.0f, 255, 255, 255, 255, H1, H1 },
80 { -1.0f, 1.0f, 255, 255, 255, 255, H0, H1 },
81 };
82
83 RHI_BUFFER_DESC bufDesc;
85 bufDesc.sizeBytes = sizeof( verts );
86 bufDesc.mappable = false;
87
88 m_quadVB = m_device.CreateBuffer( bufDesc );
89
90 if( !m_quadVB )
91 {
92 Destroy();
93 return false;
94 }
95
96 m_device.UpdateBuffer( m_quadVB, verts, sizeof( verts ) );
97
98 // Vulkan descriptor sets must match the layout baked into the fullscreen pipelines
99 m_singleTexLayout = aSingleTexLayout;
100 m_ownsSingleTexLayout = !aSingleTexLayout;
101
102 if( !m_singleTexLayout )
103 {
104 RHI_BIND_GROUP_LAYOUT_DESC singleTexLayoutDesc;
105 singleTexLayoutDesc.frequency = RHI_BIND_FREQUENCY::PER_DRAW;
106 singleTexLayoutDesc.entries.push_back(
108
109 m_singleTexLayout = m_device.CreateBindGroupLayout( singleTexLayoutDesc );
110
111 if( !m_singleTexLayout )
112 {
113 Destroy();
114 return false;
115 }
116 }
117
118 m_initialized = true;
119
120 return true;
121}
122
123
125{
127
129 m_device.Release( m_singleTexLayout );
130
133 m_device.Release( m_quadVB );
134 m_device.Release( m_clearRenderPass );
135
136 m_initialized = false;
137}
138
139
144
145
147 uint32_t aHeight, const std::vector<COMPOSITOR_LAYER>& aLayers,
148 const float* aBackgroundColor,
149 const std::function<void()>& aDrawOnTop )
150{
151 if( !m_initialized )
152 return {};
153
155 return {};
156
158 beginDesc.renderPass = m_clearRenderPass;
159 beginDesc.framebuffer = aAccumulationFBO;
160
161 if( aBackgroundColor )
162 {
163 beginDesc.hasClearColorOverride = true;
164 beginDesc.clearColorOverride[0] = aBackgroundColor[0];
165 beginDesc.clearColorOverride[1] = aBackgroundColor[1];
166 beginDesc.clearColorOverride[2] = aBackgroundColor[2];
167 beginDesc.clearColorOverride[3] = aBackgroundColor[3];
168 }
169
170 bool rpOk = m_device.BeginRenderPass( beginDesc );
171
172 if( !rpOk )
173 return {};
174
175 RHI_VIEWPORT viewport;
176 viewport.width = static_cast<float>( aWidth );
177 viewport.height = static_cast<float>( aHeight );
178 m_device.SetViewport( viewport );
179
180 RHI_SCISSOR_RECT scissor;
181 scissor.width = aWidth;
182 scissor.height = aHeight;
183 m_device.SetScissor( scissor );
184
186 m_device.BindPipeline( m_compositorPipeline );
187
188 if( m_quadVB )
189 m_device.BindVertexBuffer( 0, m_quadVB );
190
191 for( const auto& layer : aLayers )
192 {
193 if( layer.fbo )
194 compositeLayer( layer );
195 }
196
197 if( aDrawOnTop )
198 aDrawOnTop();
199
200 m_device.EndRenderPass();
201
202 return aAccumulationFBO;
203}
204
205
208 uint32_t aGroupIndex )
209{
210 RHI_TextureHandle tex = m_device.GetFramebufferColorTexture( aFBO, 0 );
211
212 if( !tex )
213 {
214 wxLogTrace( traceRhi, wxS( "Compositor: missing FBO color texture fbo=%u layout=%u" ),
215 static_cast<unsigned>( aFBO.value ),
216 static_cast<unsigned>( aLayout.value ) );
217 return {};
218 }
219
220 uint64_t key = ( static_cast<uint64_t>( tex.value ) << 32 ) | aLayout.value;
221 auto it = m_fboBindGroups.find( key );
222
223 if( it != m_fboBindGroups.end() )
224 {
225 m_device.BindGroup( aGroupIndex, it->second );
226 return it->second;
227 }
228
229 RHI_BIND_GROUP_DESC bgDesc;
230 bgDesc.layout = aLayout;
231 bgDesc.entries.push_back( { 0, {}, tex } );
232
233 RHI_BindGroupHandle bg = m_device.CreateBindGroup( bgDesc );
234
235 if( !bg )
236 {
237 wxLogTrace( traceRhi, wxS( "Compositor: CreateBindGroup FAILED fbo=%u tex=%u layout=%u" ),
238 static_cast<unsigned>( aFBO.value ),
239 static_cast<unsigned>( tex.value ),
240 static_cast<unsigned>( aLayout.value ) );
241 return {};
242 }
243
244 m_fboBindGroups.emplace( key, bg );
245 m_device.BindGroup( aGroupIndex, bg );
246
247 return bg;
248}
249
250
252{
254
255 if( !bg )
256 return;
257
259 pc.alpha = aLayer.alpha;
260 pc.uvScale[0] = aLayer.uvScale[0];
261 pc.uvScale[1] = aLayer.uvScale[1];
262 pc.uvOffset[0] = aLayer.uvOffset[0];
263 pc.uvOffset[1] = aLayer.uvOffset[1];
264
265 m_device.SetPushConstants( &pc, sizeof( pc ) );
266 m_device.Draw( 6 );
267}
268
269
271{
272 for( auto& [key, bg] : m_fboBindGroups )
273 m_device.DestroyBindGroup( bg );
274
275 m_fboBindGroups.clear();
276}
RHI_BindGroupHandle bindFBOTexture(RHI_FramebufferHandle aFBO, RHI_BindGroupLayoutHandle aLayout, uint32_t aGroupIndex)
RHI_PipelineHandle m_compositorPipeline
RHI_BindGroupLayoutHandle m_singleTexLayout
RHI_DEVICE & m_device
RHI_COMPOSITOR(RHI_DEVICE &aDevice)
void SetCompositorPipeline(RHI_PipelineHandle aPipeline)
Set the pipeline that draws each layer as an alpha-blended fullscreen quad.
std::unordered_map< uint64_t, RHI_BindGroupHandle > m_fboBindGroups
Bind groups over FBO color textures, keyed by texture and layout handles.
RHI_BufferHandle m_quadVB
bool Initialize(RHI_BindGroupLayoutHandle aSingleTexLayout={})
Create the clear pass and fullscreen quad.
void Destroy()
Release all GPU resources.
RHI_FramebufferHandle Composite(RHI_FramebufferHandle aAccumulationFBO, uint32_t aWidth, uint32_t aHeight, const std::vector< COMPOSITOR_LAYER > &aLayers, const float *aBackgroundColor=nullptr, const std::function< void()> &aDrawOnTop={})
Blend aLayers back-to-front into aAccumulationFBO, which is cleared to aBackgroundColor first.
void compositeLayer(const COMPOSITOR_LAYER &aLayer)
RHI_RenderPassHandle m_clearRenderPass
Creates, uses and destroys GPU resources through one graphics API backend.
Definition rhi_device.h:66
const wxChar *const traceRhi
Flag to enable debug output of the RHI rendering backend.
RHI_HANDLE< RHI_TAG_FRAMEBUFFER > RHI_FramebufferHandle
Definition rhi_handle.h:93
RHI_HANDLE< RHI_TAG_TEXTURE > RHI_TextureHandle
Definition rhi_handle.h:84
RHI_HANDLE< RHI_TAG_PIPELINE > RHI_PipelineHandle
Definition rhi_handle.h:86
RHI_HANDLE< RHI_TAG_BIND_GROUP > RHI_BindGroupHandle
Definition rhi_handle.h:90
RHI_HANDLE< RHI_TAG_BIND_GROUP_LAYOUT > RHI_BindGroupLayoutHandle
Definition rhi_handle.h:89
One layer to composite.
RHI_FramebufferHandle fbo
Matches the PushConstants block of the compositor shader.
std::vector< RHI_BIND_GROUP_RESOURCE > entries
RHI_BindGroupLayoutHandle layout
std::vector< RHI_BINDING_ENTRY > entries
RHI_BIND_FREQUENCY frequency
RHI_BUFFER_TYPE type
Definition rhi_buffer.h:35
RHI_TEXTURE_FORMAT format
uint32_t value
Definition rhi_handle.h:35
RHI_FramebufferHandle framebuffer
Definition rhi_command.h:49
bool hasClearColorOverride
Replaces the render pass clear color of every CLEAR color attachment, so the background can change pe...
Definition rhi_command.h:55
RHI_RenderPassHandle renderPass
Definition rhi_command.h:48
std::vector< RHI_COLOR_ATTACHMENT_DESC > colorAttachments
Same pixel space as RHI_VIEWPORT.
Definition rhi_command.h:39
Top-left origin, in device pixels.
Definition rhi_command.h:28
wxLogTrace helper definitions.