Blender V4.5
eevee_gbuffer.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#pragma once
12
13#include "DRW_render.hh"
14#include "GPU_capabilities.hh"
15
16#include "GPU_platform.hh"
17#include "eevee_material.hh"
19
20namespace blender::eevee {
21
22class Instance;
23
128struct GBuffer {
129 public:
130 /* TODO(fclem): Use texture from pool once they support texture array and layer views. */
131 Texture header_tx = {"GBufferHeader"};
132 Texture closure_tx = {"GBufferClosure"};
133 Texture normal_tx = {"GBufferNormal"};
134
135 /* Expected number of layer written through the framebuffer. */
139
140 private:
141 /* References to optional GBuffer layers that are not always required or written to.
142 * These will point to either the dummy textures bellow or to a layer range view of the above
143 * textures. In the later case, these layers are written with imageStore instead of being part
144 * of the #Framebuffer. */
145 GPUTexture *closure_opt_layers_ = nullptr;
146 GPUTexture *normal_opt_layers_ = nullptr;
147 GPUTexture *header_opt_layers_ = nullptr;
148
149 /* Textures used to fulfill the GBuffer optional layers binding when textures do not have enough
150 * layers for the optional layers image views. The shader are then expected to never write to
151 * them. */
152 Texture dummy_header_tx_ = {"GBufferDummyHeader"};
153 Texture dummy_closure_tx_ = {"GBufferDummyClosure"};
154 Texture dummy_normal_tx_ = {"GBufferDummyNormal"};
155
156 public:
157 void acquire(int2 extent, int header_count, int data_count, int normal_count)
158 {
159 /* Always allocate enough layers so that the frame-buffer attachments are always valid. */
160 header_count = max_ii(header_fb_layer_count, header_count);
161 data_count = max_ii(closure_fb_layer_count, data_count);
162 normal_count = max_ii(normal_fb_layer_count, normal_count);
163
164 dummy_header_tx_.ensure_2d_array(GPU_R32UI, int2(1), 1, GPU_TEXTURE_USAGE_SHADER_WRITE);
165 dummy_closure_tx_.ensure_2d_array(GPU_RGB10_A2, int2(1), 1, GPU_TEXTURE_USAGE_SHADER_WRITE);
166 dummy_normal_tx_.ensure_2d_array(GPU_RG16, int2(1), 1, GPU_TEXTURE_USAGE_SHADER_WRITE);
167
170 header_tx.ensure_2d_array(GPU_R32UI, extent, header_count, usage);
171 closure_tx.ensure_2d_array(GPU_RGB10_A2, extent, data_count, usage);
172 normal_tx.ensure_2d_array(GPU_RG16, extent, normal_count, usage);
173 /* Ensure layer view for frame-buffer attachment. */
174 header_tx.ensure_layer_views();
175 closure_tx.ensure_layer_views();
176 normal_tx.ensure_layer_views();
177 /* Ensure layer view for image store. */
178 auto range = [](int layer_count, int fb_layer_count, Texture &tx, Texture &dummy) {
179 return (layer_count > fb_layer_count) ?
180 tx.layer_range_view(fb_layer_count, layer_count - fb_layer_count) :
181 dummy;
182 };
183 header_opt_layers_ = range(header_count, header_fb_layer_count, header_tx, dummy_header_tx_);
184 closure_opt_layers_ = range(data_count, closure_fb_layer_count, closure_tx, dummy_closure_tx_);
185 normal_opt_layers_ = range(normal_count, normal_fb_layer_count, normal_tx, dummy_normal_tx_);
186 }
187
188 /* Bind the GBuffer frame-buffer correctly using the correct workarounds. */
189 void bind(Framebuffer &gbuffer_fb)
190 {
191 /* Workaround a Metal bug that is only showing up on ATI/Intel GPUs. */
194 {
195 header_tx.clear(uint4(0));
196 GPU_framebuffer_bind(gbuffer_fb);
197 return;
198 }
199
201 /* Clearing custom load-store frame-buffers is invalid,
202 * clear the stencil as a regular frame-buffer first. */
203 GPU_framebuffer_bind(gbuffer_fb);
204 GPU_framebuffer_clear_stencil(gbuffer_fb, 0x0u);
205 }
207 gbuffer_fb,
208 {
211 {GPU_LOADACTION_CLEAR, GPU_STOREACTION_STORE, {0}}, /* GBuf Header. */
213 {GPU_LOADACTION_DONT_CARE, GPU_STOREACTION_STORE}, /* GBuf Closure. */
214 {GPU_LOADACTION_DONT_CARE, GPU_STOREACTION_STORE}, /* GBuf Closure 2. */
215 });
216 }
217
218 void release()
219 {
220 /* TODO(fclem): Use texture from pool once they support texture array. */
221 // header_tx.release();
222 // closure_tx.release();
223 // normal_tx.release();
224
225 header_opt_layers_ = nullptr;
226 closure_opt_layers_ = nullptr;
227 normal_opt_layers_ = nullptr;
228 }
229
230 template<typename PassType> void bind_resources(PassType &pass)
231 {
232 pass.bind_texture("gbuf_header_tx", &header_tx);
233 pass.bind_texture("gbuf_closure_tx", &closure_tx);
234 pass.bind_texture("gbuf_normal_tx", &normal_tx);
235 }
236
237 template<typename PassType> void bind_optional_layers(PassType &pass)
238 {
239 pass.bind_image(GBUF_NORMAL_SLOT, &normal_opt_layers_);
240 pass.bind_image(GBUF_CLOSURE_SLOT, &closure_opt_layers_);
241 pass.bind_image(GBUF_HEADER_SLOT, &header_opt_layers_);
242 }
243};
244
245} // namespace blender::eevee
MINLINE int max_ii(int a, int b)
unsigned int uint
bool GPU_stencil_export_support()
@ GPU_LOADACTION_LOAD
@ GPU_LOADACTION_DONT_CARE
@ GPU_LOADACTION_CLEAR
@ GPU_STOREACTION_STORE
void GPU_framebuffer_clear_stencil(GPUFrameBuffer *fb, uint clear_stencil)
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
#define GPU_framebuffer_bind_ex(_fb,...)
@ GPU_DRIVER_ANY
@ GPU_OS_MAC
@ GPU_DEVICE_ATI
@ GPU_DEVICE_INTEL_UHD
@ GPU_DEVICE_INTEL
bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver)
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_SHADER_WRITE
@ GPU_TEXTURE_USAGE_ATTACHMENT
@ GPU_RGB10_A2
@ GPU_RG16
@ GPU_R32UI
A running instance of the engine.
#define GBUF_NORMAL_FB_LAYER_COUNT
#define GBUF_CLOSURE_SLOT
#define GBUF_HEADER_SLOT
#define GBUF_CLOSURE_FB_LAYER_COUNT
#define GBUF_NORMAL_SLOT
#define GBUF_HEADER_FB_LAYER_COUNT
PassType
VecBase< uint32_t, 4 > uint4
VecBase< int32_t, 2 > int2
void acquire(int2 extent, int header_count, int data_count, int normal_count)
void bind_resources(PassType &pass)
void bind_optional_layers(PassType &pass)
void bind(Framebuffer &gbuffer_fb)