Blender V5.0
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_gpu_wrapper.hh"
14#include "DRW_render.hh"
15#include "GPU_capabilities.hh"
16#include "GPU_platform.hh"
17
18#include "eevee_defines.hh"
19
20namespace blender::eevee {
21
22using namespace draw;
23
24class Instance;
25
130struct GBuffer {
131 public:
132 /* TODO(fclem): Use texture from pool once they support texture array and layer views. */
133 Texture header_tx = {"GBufferHeader"};
134 Texture closure_tx = {"GBufferClosure"};
135 Texture normal_tx = {"GBufferNormal"};
136
137 /* Expected number of layer written through the framebuffer. */
141
142 private:
143 /* References to optional GBuffer layers that are not always required or written to.
144 * These will point to either the dummy textures bellow or to a layer range view of the above
145 * textures. In the later case, these layers are written with imageStore instead of being part
146 * of the #Framebuffer. */
147 gpu::Texture *closure_opt_layers_ = nullptr;
148 gpu::Texture *normal_opt_layers_ = nullptr;
149 gpu::Texture *header_opt_layers_ = nullptr;
150
151 /* Textures used to fulfill the GBuffer optional layers binding when textures do not have enough
152 * layers for the optional layers image views. The shader are then expected to never write to
153 * them. */
154 Texture dummy_header_tx_ = {"GBufferDummyHeader"};
155 Texture dummy_closure_tx_ = {"GBufferDummyClosure"};
156 Texture dummy_normal_tx_ = {"GBufferDummyNormal"};
157
158 public:
159 void acquire(int2 extent, int header_count, int data_count, int normal_count)
160 {
161 /* Always allocate enough layers so that the frame-buffer attachments are always valid. */
162 header_count = max_ii(header_fb_layer_count, header_count);
163 data_count = max_ii(closure_fb_layer_count, data_count);
164 normal_count = max_ii(normal_fb_layer_count, normal_count);
165
166 dummy_header_tx_.ensure_2d_array(
167 gpu::TextureFormat::UINT_32, int2(1), 1, GPU_TEXTURE_USAGE_SHADER_WRITE);
168 dummy_closure_tx_.ensure_2d_array(
169 gpu::TextureFormat::UNORM_10_10_10_2, int2(1), 1, GPU_TEXTURE_USAGE_SHADER_WRITE);
170 dummy_normal_tx_.ensure_2d_array(
171 gpu::TextureFormat::UNORM_16_16, int2(1), 1, GPU_TEXTURE_USAGE_SHADER_WRITE);
172
175 header_tx.ensure_2d_array(gpu::TextureFormat::UINT_32, extent, header_count, usage);
176 closure_tx.ensure_2d_array(gpu::TextureFormat::UNORM_10_10_10_2, extent, data_count, usage);
177 normal_tx.ensure_2d_array(gpu::TextureFormat::UNORM_16_16, extent, normal_count, usage);
178 /* Ensure layer view for frame-buffer attachment. */
179 header_tx.ensure_layer_views();
180 closure_tx.ensure_layer_views();
181 normal_tx.ensure_layer_views();
182 /* Ensure layer view for image store. */
183 auto range = [](int layer_count, int fb_layer_count, Texture &tx, Texture &dummy) {
184 return (layer_count > fb_layer_count) ?
185 tx.layer_range_view(fb_layer_count, layer_count - fb_layer_count) :
186 dummy;
187 };
188 header_opt_layers_ = range(header_count, header_fb_layer_count, header_tx, dummy_header_tx_);
189 closure_opt_layers_ = range(data_count, closure_fb_layer_count, closure_tx, dummy_closure_tx_);
190 normal_opt_layers_ = range(normal_count, normal_fb_layer_count, normal_tx, dummy_normal_tx_);
191 }
192
193 /* Bind the GBuffer frame-buffer correctly using the correct workarounds. */
194 void bind(Framebuffer &gbuffer_fb)
195 {
196 /* Workaround a Metal bug that is only showing up on ATI/Intel GPUs. */
199 {
200 header_tx.clear(uint4(0));
201 GPU_framebuffer_bind(gbuffer_fb);
202 return;
203 }
204
206 /* Clearing custom load-store frame-buffers is invalid,
207 * clear the stencil as a regular frame-buffer first. */
208 GPU_framebuffer_bind(gbuffer_fb);
209 GPU_framebuffer_clear_stencil(gbuffer_fb, 0x0u);
210 }
212 gbuffer_fb,
213 {
216 {GPU_LOADACTION_CLEAR, GPU_STOREACTION_STORE, {0}}, /* GBuf Header. */
218 {GPU_LOADACTION_DONT_CARE, GPU_STOREACTION_STORE}, /* GBuf Closure. */
219 {GPU_LOADACTION_DONT_CARE, GPU_STOREACTION_STORE}, /* GBuf Closure 2. */
220 });
221 }
222
223 void release()
224 {
225 /* TODO(fclem): Use texture from pool once they support texture array. */
226 // header_tx.release();
227 // closure_tx.release();
228 // normal_tx.release();
229
230 header_opt_layers_ = nullptr;
231 closure_opt_layers_ = nullptr;
232 normal_opt_layers_ = nullptr;
233 }
234
235 template<typename PassType> void bind_resources(PassType &pass)
236 {
237 pass.bind_texture("gbuf_header_tx", &header_tx);
238 pass.bind_texture("gbuf_closure_tx", &closure_tx);
239 pass.bind_texture("gbuf_normal_tx", &normal_tx);
240 }
241
242 template<typename PassType> void bind_optional_layers(PassType &pass)
243 {
244 pass.bind_image(GBUF_NORMAL_SLOT, &normal_opt_layers_);
245 pass.bind_image(GBUF_CLOSURE_SLOT, &closure_opt_layers_);
246 pass.bind_image(GBUF_HEADER_SLOT, &header_opt_layers_);
247 }
248};
249
250} // 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(blender::gpu::FrameBuffer *fb, uint clear_stencil)
#define GPU_framebuffer_bind_ex(_fb,...)
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
@ GPU_DEVICE_ATI
@ GPU_DEVICE_INTEL_UHD
@ GPU_DEVICE_INTEL
bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
@ GPU_DRIVER_ANY
@ GPU_OS_MAC
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_SHADER_WRITE
@ GPU_TEXTURE_USAGE_ATTACHMENT
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)