Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/engines/eevee_next')
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_cryptomatte.cc132
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_cryptomatte.hh68
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_defines.hh47
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc363
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_depth_of_field.hh39
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_engine.cc22
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_film.cc237
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_film.hh109
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_hizbuffer.cc99
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_hizbuffer.hh88
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_instance.cc117
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_instance.hh10
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_light.cc125
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_light.hh21
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_material.cc93
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_material.hh15
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_motion_blur.cc70
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_motion_blur.hh6
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_pipeline.cc326
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_pipeline.hh84
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_renderbuffers.cc38
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_renderbuffers.hh5
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_sampling.hh6
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_shader.cc42
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_shader.hh4
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_shader_shared.hh92
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_sync.cc87
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_sync.hh12
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_velocity.cc19
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_velocity.hh22
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_view.cc18
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_view.hh3
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_world.cc4
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_cryptomatte_lib.glsl70
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_accumulator_lib.glsl2
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_filter_comp.glsl4
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_gather_comp.glsl4
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_hole_fill_comp.glsl4
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_reduce_comp.glsl12
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_resolve_comp.glsl6
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_stabilize_comp.glsl12
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_film_cryptomatte_post_comp.glsl77
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_film_frag.glsl8
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl87
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_hiz_debug_frag.glsl24
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_hiz_update_comp.glsl121
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_debug_frag.glsl16
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_sort_comp.glsl2
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_zbin_comp.glsl2
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_motion_blur_dilate_comp.glsl3
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl28
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_surf_depth_frag.glsl4
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl11
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_surf_lib.glsl6
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_surf_world_frag.glsl7
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/infos/eevee_depth_of_field_info.hh12
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/infos/eevee_film_info.hh36
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/infos/eevee_hiz_info.hh31
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/infos/eevee_light_culling_info.hh16
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh64
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/infos/eevee_motion_blur_info.hh4
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/infos/eevee_velocity_info.hh22
62 files changed, 2175 insertions, 943 deletions
diff --git a/source/blender/draw/engines/eevee_next/eevee_cryptomatte.cc b/source/blender/draw/engines/eevee_next/eevee_cryptomatte.cc
new file mode 100644
index 00000000000..10be121f533
--- /dev/null
+++ b/source/blender/draw/engines/eevee_next/eevee_cryptomatte.cc
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. */
+#include "BKE_cryptomatte.hh"
+
+#include "GPU_material.h"
+
+#include "eevee_cryptomatte.hh"
+#include "eevee_instance.hh"
+#include "eevee_renderbuffers.hh"
+
+namespace blender::eevee {
+
+void Cryptomatte::begin_sync()
+{
+ const eViewLayerEEVEEPassType enabled_passes = static_cast<eViewLayerEEVEEPassType>(
+ inst_.film.enabled_passes_get() &
+ (EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT | EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET |
+ EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET));
+
+ session_.reset();
+ object_layer_ = nullptr;
+ asset_layer_ = nullptr;
+ material_layer_ = nullptr;
+
+ if (enabled_passes && !inst_.is_viewport()) {
+ session_.reset(BKE_cryptomatte_init_from_view_layer(inst_.view_layer));
+
+ for (const std::string &layer_name :
+ bke::cryptomatte::BKE_cryptomatte_layer_names_get(*session_)) {
+ StringRef layer_name_ref = layer_name;
+ bke::cryptomatte::CryptomatteLayer *layer = bke::cryptomatte::BKE_cryptomatte_layer_get(
+ *session_, layer_name);
+ if (layer_name_ref.endswith(RE_PASSNAME_CRYPTOMATTE_OBJECT)) {
+ object_layer_ = layer;
+ }
+ else if (layer_name_ref.endswith(RE_PASSNAME_CRYPTOMATTE_ASSET)) {
+ asset_layer_ = layer;
+ }
+ else if (layer_name_ref.endswith(RE_PASSNAME_CRYPTOMATTE_MATERIAL)) {
+ material_layer_ = layer;
+ }
+ }
+ }
+
+ if (!(enabled_passes &
+ (EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT | EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET))) {
+ cryptomatte_object_buf.resize(16);
+ }
+}
+
+void Cryptomatte::sync_object(Object *ob, ResourceHandle res_handle)
+{
+ const eViewLayerEEVEEPassType enabled_passes = inst_.film.enabled_passes_get();
+ if (!(enabled_passes &
+ (EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT | EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET))) {
+ return;
+ }
+
+ uint32_t resource_id = res_handle.resource_index();
+ float2 object_hashes(0.0f, 0.0f);
+
+ if (enabled_passes & EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT) {
+ object_hashes[0] = register_id(EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT, ob->id);
+ }
+
+ if (enabled_passes & EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET) {
+ Object *asset = ob;
+ while (asset->parent) {
+ asset = asset->parent;
+ }
+ object_hashes[1] = register_id(EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET, asset->id);
+ }
+ cryptomatte_object_buf.get_or_resize(resource_id) = object_hashes;
+}
+
+void Cryptomatte::sync_material(const ::Material *material)
+{
+ /* Material crypto hashes are generated during shader codegen stage. We only need to register
+ * them to store inside the metadata. */
+ if (material_layer_ && material) {
+ material_layer_->add_ID(material->id);
+ }
+}
+
+void Cryptomatte::end_sync()
+{
+ cryptomatte_object_buf.push_update();
+
+ object_layer_ = nullptr;
+ asset_layer_ = nullptr;
+ material_layer_ = nullptr;
+}
+
+float Cryptomatte::register_id(const eViewLayerEEVEEPassType layer, const ID &id) const
+{
+ BLI_assert(ELEM(layer,
+ EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT,
+ EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET,
+ EEVEE_RENDER_PASS_CRYPTOMATTE_MATERIAL));
+
+ uint32_t cryptomatte_hash = 0;
+ if (session_) {
+ if (layer == EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT) {
+ BLI_assert(object_layer_);
+ cryptomatte_hash = object_layer_->add_ID(id);
+ }
+ else if (layer == EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET) {
+ BLI_assert(asset_layer_);
+ cryptomatte_hash = asset_layer_->add_ID(id);
+ }
+ else if (layer == EEVEE_RENDER_PASS_CRYPTOMATTE_MATERIAL) {
+ BLI_assert(material_layer_);
+ cryptomatte_hash = material_layer_->add_ID(id);
+ }
+ }
+ else {
+ const char *name = &id.name[2];
+ const int name_len = BLI_strnlen(name, MAX_NAME - 2);
+ cryptomatte_hash = BKE_cryptomatte_hash(name, name_len);
+ }
+
+ return BKE_cryptomatte_hash_to_float(cryptomatte_hash);
+}
+
+void Cryptomatte::store_metadata(RenderResult *render_result)
+{
+ if (session_) {
+ BKE_cryptomatte_store_metadata(&*session_, render_result, inst_.view_layer);
+ }
+}
+
+} // namespace blender::eevee \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee_next/eevee_cryptomatte.hh b/source/blender/draw/engines/eevee_next/eevee_cryptomatte.hh
new file mode 100644
index 00000000000..86ab3d97b4b
--- /dev/null
+++ b/source/blender/draw/engines/eevee_next/eevee_cryptomatte.hh
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. */
+
+/** \file
+ * \ingroup eevee
+ *
+ * Cryptomatte.
+ *
+ * During rasterization, cryptomatte hashes are stored into a single array texture.
+ * The film pass then resamples this texture using pixel filter weighting.
+ * Each cryptomatte layer can hold N samples. These are stored in sequential layers
+ * of the array texture. The samples are sorted and merged only for final rendering.
+ */
+
+#pragma once
+
+#include "eevee_shader_shared.hh"
+
+#include "BKE_cryptomatte.hh"
+
+extern "C" {
+struct Material;
+struct CryptomatteSession;
+}
+
+namespace blender::eevee {
+
+class Instance;
+
+/* -------------------------------------------------------------------- */
+/** \name Cryptomatte
+ * \{ */
+
+class Cryptomatte {
+ private:
+ class Instance &inst_;
+
+ bke::cryptomatte::CryptomatteSessionPtr session_;
+
+ /* Cached pointer to the cryptomatte layer instances. */
+ bke::cryptomatte::CryptomatteLayer *object_layer_ = nullptr;
+ bke::cryptomatte::CryptomatteLayer *asset_layer_ = nullptr;
+ bke::cryptomatte::CryptomatteLayer *material_layer_ = nullptr;
+
+ /** Contains per object hashes (object and asset hash). Indexed by resource ID. */
+ CryptomatteObjectBuf cryptomatte_object_buf;
+
+ public:
+ Cryptomatte(Instance &inst) : inst_(inst){};
+
+ void begin_sync();
+ void sync_object(Object *ob, ResourceHandle res_handle);
+ void sync_material(const ::Material *material);
+ void end_sync();
+
+ template<typename T> void bind_resources(draw::detail::PassBase<T> *pass)
+ {
+ pass->bind_ssbo(CRYPTOMATTE_BUF_SLOT, &cryptomatte_object_buf);
+ }
+
+ /* Register ID to use inside cryptomatte layer and returns associated hash as float. */
+ float register_id(const eViewLayerEEVEEPassType layer, const ID &id) const;
+ void store_metadata(RenderResult *render_result);
+};
+
+/** \} */
+
+} // namespace blender::eevee
diff --git a/source/blender/draw/engines/eevee_next/eevee_defines.hh b/source/blender/draw/engines/eevee_next/eevee_defines.hh
index 96c5095317d..248dfae6df9 100644
--- a/source/blender/draw/engines/eevee_next/eevee_defines.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_defines.hh
@@ -11,6 +11,11 @@
#pragma once
+/* Hierarchical Z down-sampling. */
+#define HIZ_MIP_COUNT 8
+/* NOTE: The shader is written to update 5 mipmaps using LDS. */
+#define HIZ_GROUP_SIZE 32
+
/* Avoid too much overhead caused by resizing the light buffers too many time. */
#define LIGHT_CHUNK 256
@@ -35,10 +40,7 @@
#define SHADOW_MAX_PAGE 4096
#define SHADOW_PAGE_PER_ROW 64
-#define HIZ_MIP_COUNT 6u
-/* Group size is 2x smaller because we simply copy the level 0. */
-#define HIZ_GROUP_SIZE 1u << (HIZ_MIP_COUNT - 2u)
-
+/* Ray-tracing. */
#define RAYTRACE_GROUP_SIZE 16
#define RAYTRACE_MAX_TILES (16384 / RAYTRACE_GROUP_SIZE) * (16384 / RAYTRACE_GROUP_SIZE)
@@ -66,3 +68,40 @@
#define DOF_FILTER_GROUP_SIZE 8
#define DOF_GATHER_GROUP_SIZE DOF_TILES_SIZE
#define DOF_RESOLVE_GROUP_SIZE (DOF_TILES_SIZE * 2)
+
+/* Resource bindings. */
+
+/* Texture. */
+#define RBUFS_UTILITY_TEX_SLOT 14
+
+/* Images. */
+#define RBUFS_NORMAL_SLOT 0
+#define RBUFS_LIGHT_SLOT 1
+#define RBUFS_DIFF_COLOR_SLOT 2
+#define RBUFS_SPEC_COLOR_SLOT 3
+#define RBUFS_EMISSION_SLOT 4
+#define RBUFS_AOV_COLOR_SLOT 5
+#define RBUFS_AOV_VALUE_SLOT 6
+#define RBUFS_CRYPTOMATTE_SLOT 7
+
+/* Uniform Buffers. */
+/* Only during prepass. */
+#define VELOCITY_CAMERA_PREV_BUF 3
+#define VELOCITY_CAMERA_CURR_BUF 4
+#define VELOCITY_CAMERA_NEXT_BUF 5
+
+/* Storage Buffers. */
+#define LIGHT_CULL_BUF_SLOT 0
+#define LIGHT_BUF_SLOT 1
+#define LIGHT_ZBIN_BUF_SLOT 2
+#define LIGHT_TILE_BUF_SLOT 3
+#define RBUFS_AOV_BUF_SLOT 5
+#define SAMPLING_BUF_SLOT 6
+#define CRYPTOMATTE_BUF_SLOT 7
+
+/* Only during pre-pass. */
+#define VELOCITY_OBJ_PREV_BUF_SLOT 0
+#define VELOCITY_OBJ_NEXT_BUF_SLOT 1
+#define VELOCITY_GEO_PREV_BUF_SLOT 2
+#define VELOCITY_GEO_NEXT_BUF_SLOT 3
+#define VELOCITY_INDIRECTION_BUF_SLOT 4
diff --git a/source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc b/source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc
index 3700076153e..bc0891ceb92 100644
--- a/source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc
@@ -237,35 +237,34 @@ void DepthOfField::bokeh_lut_pass_sync()
const bool has_anisotropy = data_.bokeh_anisotropic_scale != float2(1.0f);
if (!has_anisotropy && (data_.bokeh_blades == 0.0)) {
/* No need for LUTs in these cases. */
- bokeh_lut_ps_ = nullptr;
+ use_bokeh_lut_ = false;
return;
}
+ use_bokeh_lut_ = true;
/* Precompute bokeh texture. */
- bokeh_lut_ps_ = DRW_pass_create("Dof.bokeh_lut_ps_", DRW_STATE_NO_DRAW);
- GPUShader *sh = inst_.shaders.static_shader_get(DOF_BOKEH_LUT);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, bokeh_lut_ps_);
- DRW_shgroup_uniform_block(grp, "dof_buf", data_);
- DRW_shgroup_uniform_image_ref(grp, "out_gather_lut_img", &bokeh_gather_lut_tx_);
- DRW_shgroup_uniform_image_ref(grp, "out_scatter_lut_img", &bokeh_scatter_lut_tx_);
- DRW_shgroup_uniform_image_ref(grp, "out_resolve_lut_img", &bokeh_resolve_lut_tx_);
- DRW_shgroup_call_compute(grp, 1, 1, 1);
+ bokeh_lut_ps_.init();
+ bokeh_lut_ps_.shader_set(inst_.shaders.static_shader_get(DOF_BOKEH_LUT));
+ bokeh_lut_ps_.bind_ubo("dof_buf", data_);
+ bokeh_lut_ps_.bind_image("out_gather_lut_img", &bokeh_gather_lut_tx_);
+ bokeh_lut_ps_.bind_image("out_scatter_lut_img", &bokeh_scatter_lut_tx_);
+ bokeh_lut_ps_.bind_image("out_resolve_lut_img", &bokeh_resolve_lut_tx_);
+ bokeh_lut_ps_.dispatch(int3(1, 1, 1));
}
void DepthOfField::setup_pass_sync()
{
RenderBuffers &render_buffers = inst_.render_buffers;
- setup_ps_ = DRW_pass_create("Dof.setup_ps_", DRW_STATE_NO_DRAW);
- GPUShader *sh = inst_.shaders.static_shader_get(DOF_SETUP);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, setup_ps_);
- DRW_shgroup_uniform_texture_ref_ex(grp, "color_tx", &input_color_tx_, no_filter);
- DRW_shgroup_uniform_texture_ref_ex(grp, "depth_tx", &render_buffers.depth_tx, no_filter);
- DRW_shgroup_uniform_block(grp, "dof_buf", data_);
- DRW_shgroup_uniform_image_ref(grp, "out_color_img", &setup_color_tx_);
- DRW_shgroup_uniform_image_ref(grp, "out_coc_img", &setup_coc_tx_);
- DRW_shgroup_call_compute_ref(grp, dispatch_setup_size_);
- DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH);
+ setup_ps_.init();
+ setup_ps_.shader_set(inst_.shaders.static_shader_get(DOF_SETUP));
+ setup_ps_.bind_texture("color_tx", &input_color_tx_, no_filter);
+ setup_ps_.bind_texture("depth_tx", &render_buffers.depth_tx, no_filter);
+ setup_ps_.bind_ubo("dof_buf", data_);
+ setup_ps_.bind_image("out_color_img", &setup_color_tx_);
+ setup_ps_.bind_image("out_coc_img", &setup_coc_tx_);
+ setup_ps_.dispatch(&dispatch_setup_size_);
+ setup_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH);
}
void DepthOfField::stabilize_pass_sync()
@@ -273,214 +272,203 @@ void DepthOfField::stabilize_pass_sync()
RenderBuffers &render_buffers = inst_.render_buffers;
VelocityModule &velocity = inst_.velocity;
- stabilize_ps_ = DRW_pass_create("Dof.stabilize_ps_", DRW_STATE_NO_DRAW);
- GPUShader *sh = inst_.shaders.static_shader_get(DOF_STABILIZE);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, stabilize_ps_);
- DRW_shgroup_uniform_block_ref(grp, "camera_prev", &(*velocity.camera_steps[STEP_PREVIOUS]));
- DRW_shgroup_uniform_block_ref(grp, "camera_curr", &(*velocity.camera_steps[STEP_CURRENT]));
+ stabilize_ps_.init();
+ stabilize_ps_.shader_set(inst_.shaders.static_shader_get(DOF_STABILIZE));
+ stabilize_ps_.bind_ubo("camera_prev", &(*velocity.camera_steps[STEP_PREVIOUS]));
+ stabilize_ps_.bind_ubo("camera_curr", &(*velocity.camera_steps[STEP_CURRENT]));
/* This is only for temporal stability. The next step is not needed. */
- DRW_shgroup_uniform_block_ref(grp, "camera_next", &(*velocity.camera_steps[STEP_PREVIOUS]));
- DRW_shgroup_uniform_texture_ref_ex(grp, "coc_tx", &setup_coc_tx_, no_filter);
- DRW_shgroup_uniform_texture_ref_ex(grp, "color_tx", &setup_color_tx_, no_filter);
- DRW_shgroup_uniform_texture_ref_ex(grp, "velocity_tx", &render_buffers.vector_tx, no_filter);
- DRW_shgroup_uniform_texture_ref_ex(grp, "in_history_tx", &stabilize_input_, with_filter);
- DRW_shgroup_uniform_texture_ref_ex(grp, "depth_tx", &render_buffers.depth_tx, no_filter);
- DRW_shgroup_uniform_bool(grp, "use_history", &stabilize_valid_history_, 1);
- DRW_shgroup_uniform_block(grp, "dof_buf", data_);
- DRW_shgroup_uniform_image(grp, "out_coc_img", reduced_coc_tx_.mip_view(0));
- DRW_shgroup_uniform_image(grp, "out_color_img", reduced_color_tx_.mip_view(0));
- DRW_shgroup_uniform_image_ref(grp, "out_history_img", &stabilize_output_tx_);
- DRW_shgroup_call_compute_ref(grp, dispatch_stabilize_size_);
- DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
+ stabilize_ps_.bind_ubo("camera_next", &(*velocity.camera_steps[STEP_PREVIOUS]));
+ stabilize_ps_.bind_texture("coc_tx", &setup_coc_tx_, no_filter);
+ stabilize_ps_.bind_texture("color_tx", &setup_color_tx_, no_filter);
+ stabilize_ps_.bind_texture("velocity_tx", &render_buffers.vector_tx, no_filter);
+ stabilize_ps_.bind_texture("in_history_tx", &stabilize_input_, with_filter);
+ stabilize_ps_.bind_texture("depth_tx", &render_buffers.depth_tx, no_filter);
+ stabilize_ps_.bind_ubo("dof_buf", data_);
+ stabilize_ps_.push_constant("use_history", &stabilize_valid_history_, 1);
+ stabilize_ps_.bind_image("out_coc_img", reduced_coc_tx_.mip_view(0));
+ stabilize_ps_.bind_image("out_color_img", reduced_color_tx_.mip_view(0));
+ stabilize_ps_.bind_image("out_history_img", &stabilize_output_tx_);
+ stabilize_ps_.dispatch(&dispatch_stabilize_size_);
+ stabilize_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
}
void DepthOfField::downsample_pass_sync()
{
- downsample_ps_ = DRW_pass_create("Dof.downsample_ps_", DRW_STATE_NO_DRAW);
- GPUShader *sh = inst_.shaders.static_shader_get(DOF_DOWNSAMPLE);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, downsample_ps_);
- DRW_shgroup_uniform_texture_ex(grp, "color_tx", reduced_color_tx_.mip_view(0), no_filter);
- DRW_shgroup_uniform_texture_ex(grp, "coc_tx", reduced_coc_tx_.mip_view(0), no_filter);
- DRW_shgroup_uniform_image_ref(grp, "out_color_img", &downsample_tx_);
- DRW_shgroup_call_compute_ref(grp, dispatch_downsample_size_);
- DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH);
+ downsample_ps_.init();
+ downsample_ps_.shader_set(inst_.shaders.static_shader_get(DOF_DOWNSAMPLE));
+ downsample_ps_.bind_texture("color_tx", reduced_color_tx_.mip_view(0), no_filter);
+ downsample_ps_.bind_texture("coc_tx", reduced_coc_tx_.mip_view(0), no_filter);
+ downsample_ps_.bind_image("out_color_img", &downsample_tx_);
+ downsample_ps_.dispatch(&dispatch_downsample_size_);
+ downsample_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH);
}
void DepthOfField::reduce_pass_sync()
{
- reduce_ps_ = DRW_pass_create("Dof.reduce_ps_", DRW_STATE_NO_DRAW);
- GPUShader *sh = inst_.shaders.static_shader_get(DOF_REDUCE);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, reduce_ps_);
- DRW_shgroup_uniform_block(grp, "dof_buf", data_);
- DRW_shgroup_uniform_texture_ref_ex(grp, "downsample_tx", &downsample_tx_, no_filter);
- DRW_shgroup_storage_block(grp, "scatter_fg_list_buf", scatter_fg_list_buf_);
- DRW_shgroup_storage_block(grp, "scatter_bg_list_buf", scatter_bg_list_buf_);
- DRW_shgroup_storage_block(grp, "scatter_fg_indirect_buf", scatter_fg_indirect_buf_);
- DRW_shgroup_storage_block(grp, "scatter_bg_indirect_buf", scatter_bg_indirect_buf_);
- DRW_shgroup_uniform_image(grp, "inout_color_lod0_img", reduced_color_tx_.mip_view(0));
- DRW_shgroup_uniform_image(grp, "out_color_lod1_img", reduced_color_tx_.mip_view(1));
- DRW_shgroup_uniform_image(grp, "out_color_lod2_img", reduced_color_tx_.mip_view(2));
- DRW_shgroup_uniform_image(grp, "out_color_lod3_img", reduced_color_tx_.mip_view(3));
- DRW_shgroup_uniform_image(grp, "in_coc_lod0_img", reduced_coc_tx_.mip_view(0));
- DRW_shgroup_uniform_image(grp, "out_coc_lod1_img", reduced_coc_tx_.mip_view(1));
- DRW_shgroup_uniform_image(grp, "out_coc_lod2_img", reduced_coc_tx_.mip_view(2));
- DRW_shgroup_uniform_image(grp, "out_coc_lod3_img", reduced_coc_tx_.mip_view(3));
- DRW_shgroup_call_compute_ref(grp, dispatch_reduce_size_);
+ reduce_ps_.init();
+ reduce_ps_.shader_set(inst_.shaders.static_shader_get(DOF_REDUCE));
+ reduce_ps_.bind_ubo("dof_buf", data_);
+ reduce_ps_.bind_texture("downsample_tx", &downsample_tx_, no_filter);
+ reduce_ps_.bind_ssbo("scatter_fg_list_buf", scatter_fg_list_buf_);
+ reduce_ps_.bind_ssbo("scatter_bg_list_buf", scatter_bg_list_buf_);
+ reduce_ps_.bind_ssbo("scatter_fg_indirect_buf", scatter_fg_indirect_buf_);
+ reduce_ps_.bind_ssbo("scatter_bg_indirect_buf", scatter_bg_indirect_buf_);
+ reduce_ps_.bind_image("inout_color_lod0_img", reduced_color_tx_.mip_view(0));
+ reduce_ps_.bind_image("out_color_lod1_img", reduced_color_tx_.mip_view(1));
+ reduce_ps_.bind_image("out_color_lod2_img", reduced_color_tx_.mip_view(2));
+ reduce_ps_.bind_image("out_color_lod3_img", reduced_color_tx_.mip_view(3));
+ reduce_ps_.bind_image("in_coc_lod0_img", reduced_coc_tx_.mip_view(0));
+ reduce_ps_.bind_image("out_coc_lod1_img", reduced_coc_tx_.mip_view(1));
+ reduce_ps_.bind_image("out_coc_lod2_img", reduced_coc_tx_.mip_view(2));
+ reduce_ps_.bind_image("out_coc_lod3_img", reduced_coc_tx_.mip_view(3));
+ reduce_ps_.dispatch(&dispatch_reduce_size_);
/* NOTE: Command buffer barrier is done automatically by the GPU backend. */
- DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_STORAGE);
+ reduce_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_STORAGE);
}
void DepthOfField::tiles_flatten_pass_sync()
{
- tiles_flatten_ps_ = DRW_pass_create("Dof.tiles_flatten_ps_", DRW_STATE_NO_DRAW);
- GPUShader *sh = inst_.shaders.static_shader_get(DOF_TILES_FLATTEN);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, tiles_flatten_ps_);
+ tiles_flatten_ps_.init();
+ tiles_flatten_ps_.shader_set(inst_.shaders.static_shader_get(DOF_TILES_FLATTEN));
/* NOTE(fclem): We should use the reduced_coc_tx_ as it is stable, but we need the slight focus
* flag from the setup pass. A better way would be to do the brute-force in focus gather without
* this. */
- DRW_shgroup_uniform_texture_ref_ex(grp, "coc_tx", &setup_coc_tx_, no_filter);
- DRW_shgroup_uniform_image_ref(grp, "out_tiles_fg_img", &tiles_fg_tx_.current());
- DRW_shgroup_uniform_image_ref(grp, "out_tiles_bg_img", &tiles_bg_tx_.current());
- DRW_shgroup_call_compute_ref(grp, dispatch_tiles_flatten_size_);
- DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_IMAGE_ACCESS);
+ tiles_flatten_ps_.bind_texture("coc_tx", &setup_coc_tx_, no_filter);
+ tiles_flatten_ps_.bind_image("out_tiles_fg_img", &tiles_fg_tx_.current());
+ tiles_flatten_ps_.bind_image("out_tiles_bg_img", &tiles_bg_tx_.current());
+ tiles_flatten_ps_.dispatch(&dispatch_tiles_flatten_size_);
+ tiles_flatten_ps_.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
}
void DepthOfField::tiles_dilate_pass_sync()
{
- tiles_dilate_minmax_ps_ = DRW_pass_create("Dof.tiles_dilate_minmax_ps_", DRW_STATE_NO_DRAW);
- tiles_dilate_minabs_ps_ = DRW_pass_create("Dof.tiles_dilate_minabs_ps_", DRW_STATE_NO_DRAW);
for (int pass = 0; pass < 2; pass++) {
- DRWPass *drw_pass = (pass == 0) ? tiles_dilate_minmax_ps_ : tiles_dilate_minabs_ps_;
- GPUShader *sh = inst_.shaders.static_shader_get((pass == 0) ? DOF_TILES_DILATE_MINMAX :
- DOF_TILES_DILATE_MINABS);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, drw_pass);
- DRW_shgroup_uniform_image_ref(grp, "in_tiles_fg_img", &tiles_fg_tx_.previous());
- DRW_shgroup_uniform_image_ref(grp, "in_tiles_bg_img", &tiles_bg_tx_.previous());
- DRW_shgroup_uniform_image_ref(grp, "out_tiles_fg_img", &tiles_fg_tx_.current());
- DRW_shgroup_uniform_image_ref(grp, "out_tiles_bg_img", &tiles_bg_tx_.current());
- DRW_shgroup_uniform_int(grp, "ring_count", &tiles_dilate_ring_count_, 1);
- DRW_shgroup_uniform_int(grp, "ring_width_multiplier", &tiles_dilate_ring_width_mul_, 1);
- DRW_shgroup_call_compute_ref(grp, dispatch_tiles_dilate_size_);
- DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_IMAGE_ACCESS);
+ PassSimple &drw_pass = (pass == 0) ? tiles_dilate_minmax_ps_ : tiles_dilate_minabs_ps_;
+ eShaderType sh_type = (pass == 0) ? DOF_TILES_DILATE_MINMAX : DOF_TILES_DILATE_MINABS;
+ drw_pass.init();
+ drw_pass.shader_set(inst_.shaders.static_shader_get(sh_type));
+ drw_pass.bind_image("in_tiles_fg_img", &tiles_fg_tx_.previous());
+ drw_pass.bind_image("in_tiles_bg_img", &tiles_bg_tx_.previous());
+ drw_pass.bind_image("out_tiles_fg_img", &tiles_fg_tx_.current());
+ drw_pass.bind_image("out_tiles_bg_img", &tiles_bg_tx_.current());
+ drw_pass.push_constant("ring_count", &tiles_dilate_ring_count_, 1);
+ drw_pass.push_constant("ring_width_multiplier", &tiles_dilate_ring_width_mul_, 1);
+ drw_pass.dispatch(&dispatch_tiles_dilate_size_);
+ drw_pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
}
}
void DepthOfField::gather_pass_sync()
{
- gather_fg_ps_ = DRW_pass_create("Dof.gather_fg_ps_", DRW_STATE_NO_DRAW);
- gather_bg_ps_ = DRW_pass_create("Dof.gather_bg_ps_", DRW_STATE_NO_DRAW);
for (int pass = 0; pass < 2; pass++) {
+ PassSimple &drw_pass = (pass == 0) ? gather_fg_ps_ : gather_bg_ps_;
SwapChain<TextureFromPool, 2> &color_chain = (pass == 0) ? color_fg_tx_ : color_bg_tx_;
SwapChain<TextureFromPool, 2> &weight_chain = (pass == 0) ? weight_fg_tx_ : weight_bg_tx_;
- bool use_lut = bokeh_lut_ps_ != nullptr;
eShaderType sh_type = (pass == 0) ?
- (use_lut ? DOF_GATHER_FOREGROUND_LUT : DOF_GATHER_FOREGROUND) :
- (use_lut ? DOF_GATHER_BACKGROUND_LUT : DOF_GATHER_BACKGROUND);
- GPUShader *sh = inst_.shaders.static_shader_get(sh_type);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, (pass == 0) ? gather_fg_ps_ : gather_bg_ps_);
- inst_.sampling.bind_resources(grp);
- DRW_shgroup_uniform_block(grp, "dof_buf", data_);
- DRW_shgroup_uniform_texture_ex(grp, "color_bilinear_tx", reduced_color_tx_, gather_bilinear);
- DRW_shgroup_uniform_texture_ex(grp, "color_tx", reduced_color_tx_, gather_nearest);
- DRW_shgroup_uniform_texture_ex(grp, "coc_tx", reduced_coc_tx_, gather_nearest);
- DRW_shgroup_uniform_image_ref(grp, "in_tiles_fg_img", &tiles_fg_tx_.current());
- DRW_shgroup_uniform_image_ref(grp, "in_tiles_bg_img", &tiles_bg_tx_.current());
- DRW_shgroup_uniform_image_ref(grp, "out_color_img", &color_chain.current());
- DRW_shgroup_uniform_image_ref(grp, "out_weight_img", &weight_chain.current());
- DRW_shgroup_uniform_image_ref(grp, "out_occlusion_img", &occlusion_tx_);
- DRW_shgroup_uniform_texture_ref(grp, "bokeh_lut_tx", &bokeh_gather_lut_tx_);
- DRW_shgroup_call_compute_ref(grp, dispatch_gather_size_);
- DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH);
+ (use_bokeh_lut_ ? DOF_GATHER_FOREGROUND_LUT :
+ DOF_GATHER_FOREGROUND) :
+ (use_bokeh_lut_ ? DOF_GATHER_BACKGROUND_LUT : DOF_GATHER_BACKGROUND);
+ drw_pass.init();
+ inst_.sampling.bind_resources(&drw_pass);
+ drw_pass.shader_set(inst_.shaders.static_shader_get(sh_type));
+ drw_pass.bind_ubo("dof_buf", data_);
+ drw_pass.bind_texture("color_bilinear_tx", reduced_color_tx_, gather_bilinear);
+ drw_pass.bind_texture("color_tx", reduced_color_tx_, gather_nearest);
+ drw_pass.bind_texture("coc_tx", reduced_coc_tx_, gather_nearest);
+ drw_pass.bind_image("in_tiles_fg_img", &tiles_fg_tx_.current());
+ drw_pass.bind_image("in_tiles_bg_img", &tiles_bg_tx_.current());
+ drw_pass.bind_image("out_color_img", &color_chain.current());
+ drw_pass.bind_image("out_weight_img", &weight_chain.current());
+ drw_pass.bind_image("out_occlusion_img", &occlusion_tx_);
+ drw_pass.bind_texture("bokeh_lut_tx", &bokeh_gather_lut_tx_);
+ drw_pass.dispatch(&dispatch_gather_size_);
+ drw_pass.barrier(GPU_BARRIER_TEXTURE_FETCH);
}
}
void DepthOfField::filter_pass_sync()
{
- filter_fg_ps_ = DRW_pass_create("Dof.filter_fg_ps_", DRW_STATE_NO_DRAW);
- filter_bg_ps_ = DRW_pass_create("Dof.filter_bg_ps_", DRW_STATE_NO_DRAW);
for (int pass = 0; pass < 2; pass++) {
+ PassSimple &drw_pass = (pass == 0) ? filter_fg_ps_ : filter_bg_ps_;
SwapChain<TextureFromPool, 2> &color_chain = (pass == 0) ? color_fg_tx_ : color_bg_tx_;
SwapChain<TextureFromPool, 2> &weight_chain = (pass == 0) ? weight_fg_tx_ : weight_bg_tx_;
- GPUShader *sh = inst_.shaders.static_shader_get(DOF_FILTER);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, (pass == 0) ? filter_fg_ps_ : filter_bg_ps_);
- DRW_shgroup_uniform_texture_ref(grp, "color_tx", &color_chain.previous());
- DRW_shgroup_uniform_texture_ref(grp, "weight_tx", &weight_chain.previous());
- DRW_shgroup_uniform_image_ref(grp, "out_color_img", &color_chain.current());
- DRW_shgroup_uniform_image_ref(grp, "out_weight_img", &weight_chain.current());
- DRW_shgroup_call_compute_ref(grp, dispatch_filter_size_);
- DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH);
+ drw_pass.init();
+ drw_pass.shader_set(inst_.shaders.static_shader_get(DOF_FILTER));
+ drw_pass.bind_texture("color_tx", &color_chain.previous());
+ drw_pass.bind_texture("weight_tx", &weight_chain.previous());
+ drw_pass.bind_image("out_color_img", &color_chain.current());
+ drw_pass.bind_image("out_weight_img", &weight_chain.current());
+ drw_pass.dispatch(&dispatch_filter_size_);
+ drw_pass.barrier(GPU_BARRIER_TEXTURE_FETCH);
}
}
void DepthOfField::scatter_pass_sync()
{
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL;
- scatter_fg_ps_ = DRW_pass_create("Dof.scatter_fg_ps_", state);
- scatter_bg_ps_ = DRW_pass_create("Dof.scatter_bg_ps_", state);
for (int pass = 0; pass < 2; pass++) {
- GPUStorageBuf *scatter_buf = (pass == 0) ? scatter_fg_indirect_buf_ : scatter_bg_indirect_buf_;
- GPUStorageBuf *rect_list_buf = (pass == 0) ? scatter_fg_list_buf_ : scatter_bg_list_buf_;
-
- GPUShader *sh = inst_.shaders.static_shader_get(DOF_SCATTER);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, (pass == 0) ? scatter_fg_ps_ : scatter_bg_ps_);
- DRW_shgroup_uniform_bool_copy(grp, "use_bokeh_lut", bokeh_lut_ps_ != nullptr);
- DRW_shgroup_storage_block(grp, "scatter_list_buf", rect_list_buf);
- DRW_shgroup_uniform_texture_ref(grp, "bokeh_lut_tx", &bokeh_scatter_lut_tx_);
- DRW_shgroup_uniform_texture_ref(grp, "occlusion_tx", &occlusion_tx_);
- DRW_shgroup_call_procedural_indirect(grp, GPU_PRIM_TRI_STRIP, nullptr, scatter_buf);
+ PassSimple &drw_pass = (pass == 0) ? scatter_fg_ps_ : scatter_bg_ps_;
+ drw_pass.init();
+ drw_pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL);
+ drw_pass.shader_set(inst_.shaders.static_shader_get(DOF_SCATTER));
+ drw_pass.push_constant("use_bokeh_lut", use_bokeh_lut_);
+ drw_pass.bind_texture("bokeh_lut_tx", &bokeh_scatter_lut_tx_);
+ drw_pass.bind_texture("occlusion_tx", &occlusion_tx_);
if (pass == 0) {
+ drw_pass.bind_ssbo("scatter_list_buf", scatter_fg_list_buf_);
+ drw_pass.draw_procedural_indirect(GPU_PRIM_TRI_STRIP, scatter_fg_indirect_buf_);
/* Avoid background gather pass writing to the occlusion_tx mid pass. */
- DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_IMAGE_ACCESS);
+ drw_pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
+ }
+ else {
+ drw_pass.bind_ssbo("scatter_list_buf", scatter_bg_list_buf_);
+ drw_pass.draw_procedural_indirect(GPU_PRIM_TRI_STRIP, scatter_bg_indirect_buf_);
}
}
}
void DepthOfField::hole_fill_pass_sync()
{
- hole_fill_ps_ = DRW_pass_create("Dof.hole_fill_ps_", DRW_STATE_NO_DRAW);
- GPUShader *sh = inst_.shaders.static_shader_get(DOF_GATHER_HOLE_FILL);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, hole_fill_ps_);
- inst_.sampling.bind_resources(grp);
- DRW_shgroup_uniform_block(grp, "dof_buf", data_);
- DRW_shgroup_uniform_texture_ex(grp, "color_bilinear_tx", reduced_color_tx_, gather_bilinear);
- DRW_shgroup_uniform_texture_ex(grp, "color_tx", reduced_color_tx_, gather_nearest);
- DRW_shgroup_uniform_texture_ex(grp, "coc_tx", reduced_coc_tx_, gather_nearest);
- DRW_shgroup_uniform_image_ref(grp, "in_tiles_fg_img", &tiles_fg_tx_.current());
- DRW_shgroup_uniform_image_ref(grp, "in_tiles_bg_img", &tiles_bg_tx_.current());
- DRW_shgroup_uniform_image_ref(grp, "out_color_img", &hole_fill_color_tx_);
- DRW_shgroup_uniform_image_ref(grp, "out_weight_img", &hole_fill_weight_tx_);
- DRW_shgroup_call_compute_ref(grp, dispatch_gather_size_);
- DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH);
+ hole_fill_ps_.init();
+ inst_.sampling.bind_resources(&hole_fill_ps_);
+ hole_fill_ps_.shader_set(inst_.shaders.static_shader_get(DOF_GATHER_HOLE_FILL));
+ hole_fill_ps_.bind_ubo("dof_buf", data_);
+ hole_fill_ps_.bind_texture("color_bilinear_tx", reduced_color_tx_, gather_bilinear);
+ hole_fill_ps_.bind_texture("color_tx", reduced_color_tx_, gather_nearest);
+ hole_fill_ps_.bind_texture("coc_tx", reduced_coc_tx_, gather_nearest);
+ hole_fill_ps_.bind_image("in_tiles_fg_img", &tiles_fg_tx_.current());
+ hole_fill_ps_.bind_image("in_tiles_bg_img", &tiles_bg_tx_.current());
+ hole_fill_ps_.bind_image("out_color_img", &hole_fill_color_tx_);
+ hole_fill_ps_.bind_image("out_weight_img", &hole_fill_weight_tx_);
+ hole_fill_ps_.dispatch(&dispatch_gather_size_);
+ hole_fill_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH);
}
void DepthOfField::resolve_pass_sync()
{
eGPUSamplerState with_filter = GPU_SAMPLER_FILTER;
RenderBuffers &render_buffers = inst_.render_buffers;
-
- resolve_ps_ = DRW_pass_create("Dof.resolve_ps_", DRW_STATE_NO_DRAW);
- bool use_lut = bokeh_lut_ps_ != nullptr;
- eShaderType sh_type = use_lut ? DOF_RESOLVE_LUT : DOF_RESOLVE;
- GPUShader *sh = inst_.shaders.static_shader_get(sh_type);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, resolve_ps_);
- inst_.sampling.bind_resources(grp);
- DRW_shgroup_uniform_block(grp, "dof_buf", data_);
- DRW_shgroup_uniform_texture_ref_ex(grp, "depth_tx", &render_buffers.depth_tx, no_filter);
- DRW_shgroup_uniform_texture_ref_ex(grp, "color_tx", &input_color_tx_, no_filter);
- DRW_shgroup_uniform_texture_ref_ex(grp, "stable_color_tx", &resolve_stable_color_tx_, no_filter);
- DRW_shgroup_uniform_texture_ref_ex(grp, "color_bg_tx", &color_bg_tx_.current(), with_filter);
- DRW_shgroup_uniform_texture_ref_ex(grp, "color_fg_tx", &color_fg_tx_.current(), with_filter);
- DRW_shgroup_uniform_image_ref(grp, "in_tiles_fg_img", &tiles_fg_tx_.current());
- DRW_shgroup_uniform_image_ref(grp, "in_tiles_bg_img", &tiles_bg_tx_.current());
- DRW_shgroup_uniform_texture_ref(grp, "weight_bg_tx", &weight_bg_tx_.current());
- DRW_shgroup_uniform_texture_ref(grp, "weight_fg_tx", &weight_fg_tx_.current());
- DRW_shgroup_uniform_texture_ref(grp, "color_hole_fill_tx", &hole_fill_color_tx_);
- DRW_shgroup_uniform_texture_ref(grp, "weight_hole_fill_tx", &hole_fill_weight_tx_);
- DRW_shgroup_uniform_texture_ref(grp, "bokeh_lut_tx", &bokeh_resolve_lut_tx_);
- DRW_shgroup_uniform_image_ref(grp, "out_color_img", &output_color_tx_);
- DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH);
- DRW_shgroup_call_compute_ref(grp, dispatch_resolve_size_);
- DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH);
+ eShaderType sh_type = use_bokeh_lut_ ? DOF_RESOLVE_LUT : DOF_RESOLVE;
+
+ resolve_ps_.init();
+ inst_.sampling.bind_resources(&resolve_ps_);
+ resolve_ps_.shader_set(inst_.shaders.static_shader_get(sh_type));
+ resolve_ps_.bind_ubo("dof_buf", data_);
+ resolve_ps_.bind_texture("depth_tx", &render_buffers.depth_tx, no_filter);
+ resolve_ps_.bind_texture("color_tx", &input_color_tx_, no_filter);
+ resolve_ps_.bind_texture("stable_color_tx", &resolve_stable_color_tx_, no_filter);
+ resolve_ps_.bind_texture("color_bg_tx", &color_bg_tx_.current(), with_filter);
+ resolve_ps_.bind_texture("color_fg_tx", &color_fg_tx_.current(), with_filter);
+ resolve_ps_.bind_image("in_tiles_fg_img", &tiles_fg_tx_.current());
+ resolve_ps_.bind_image("in_tiles_bg_img", &tiles_bg_tx_.current());
+ resolve_ps_.bind_texture("weight_bg_tx", &weight_bg_tx_.current());
+ resolve_ps_.bind_texture("weight_fg_tx", &weight_fg_tx_.current());
+ resolve_ps_.bind_texture("color_hole_fill_tx", &hole_fill_color_tx_);
+ resolve_ps_.bind_texture("weight_hole_fill_tx", &hole_fill_weight_tx_);
+ resolve_ps_.bind_texture("bokeh_lut_tx", &bokeh_resolve_lut_tx_);
+ resolve_ps_.bind_image("out_color_img", &output_color_tx_);
+ resolve_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH);
+ resolve_ps_.dispatch(&dispatch_resolve_size_);
+ resolve_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH);
}
/** \} */
@@ -509,7 +497,8 @@ void DepthOfField::update_sample_table()
data_.filter_center_weight = film_filter_weight(radius, math::length_squared(subpixel_offset));
}
-void DepthOfField::render(GPUTexture **input_tx,
+void DepthOfField::render(View &view,
+ GPUTexture **input_tx,
GPUTexture **output_tx,
DepthOfFieldBuffer &dof_buffer)
{
@@ -580,6 +569,8 @@ void DepthOfField::render(GPUTexture **input_tx,
DRW_stats_group_start("Depth of Field");
+ Manager &drw = *inst_.manager;
+
{
DRW_stats_group_start("Setup");
{
@@ -587,13 +578,15 @@ void DepthOfField::render(GPUTexture **input_tx,
bokeh_scatter_lut_tx_.acquire(int2(DOF_BOKEH_LUT_SIZE), GPU_R16F);
bokeh_resolve_lut_tx_.acquire(int2(DOF_MAX_SLIGHT_FOCUS_RADIUS * 2 + 1), GPU_R16F);
- DRW_draw_pass(bokeh_lut_ps_);
+ if (use_bokeh_lut_) {
+ drw.submit(bokeh_lut_ps_, view);
+ }
}
{
setup_color_tx_.acquire(half_res, GPU_RGBA16F);
setup_coc_tx_.acquire(half_res, GPU_R16F);
- DRW_draw_pass(setup_ps_);
+ drw.submit(setup_ps_, view);
}
{
stabilize_output_tx_.acquire(half_res, GPU_RGBA16F);
@@ -607,7 +600,7 @@ void DepthOfField::render(GPUTexture **input_tx,
stabilize_input_ = dof_buffer.stabilize_history_tx_;
/* Outputs to reduced_*_tx_ mip 0. */
- DRW_draw_pass(stabilize_ps_);
+ drw.submit(stabilize_ps_, view);
/* WATCH(fclem): Swap Texture an TextureFromPool internal GPUTexture in order to reuse
* the one that we just consumed. */
@@ -626,7 +619,7 @@ void DepthOfField::render(GPUTexture **input_tx,
tiles_fg_tx_.current().acquire(tile_res, GPU_R11F_G11F_B10F);
tiles_bg_tx_.current().acquire(tile_res, GPU_R11F_G11F_B10F);
- DRW_draw_pass(tiles_flatten_ps_);
+ drw.submit(tiles_flatten_ps_, view);
/* Used by tile_flatten and stabilize_ps pass. */
setup_coc_tx_.release();
@@ -655,7 +648,7 @@ void DepthOfField::render(GPUTexture **input_tx,
tiles_fg_tx_.swap();
tiles_bg_tx_.swap();
- DRW_draw_pass((pass == 0) ? tiles_dilate_minmax_ps_ : tiles_dilate_minabs_ps_);
+ drw.submit((pass == 0) ? tiles_dilate_minmax_ps_ : tiles_dilate_minabs_ps_, view);
}
}
@@ -667,12 +660,12 @@ void DepthOfField::render(GPUTexture **input_tx,
downsample_tx_.acquire(quarter_res, GPU_RGBA16F);
- DRW_draw_pass(downsample_ps_);
+ drw.submit(downsample_ps_, view);
scatter_fg_indirect_buf_.clear_to_zero();
scatter_bg_indirect_buf_.clear_to_zero();
- DRW_draw_pass(reduce_ps_);
+ drw.submit(reduce_ps_, view);
/* Used by reduce pass. */
downsample_tx_.release();
@@ -686,15 +679,15 @@ void DepthOfField::render(GPUTexture **input_tx,
SwapChain<TextureFromPool, 2> &color_tx = is_background ? color_bg_tx_ : color_fg_tx_;
SwapChain<TextureFromPool, 2> &weight_tx = is_background ? weight_bg_tx_ : weight_fg_tx_;
Framebuffer &scatter_fb = is_background ? scatter_bg_fb_ : scatter_fg_fb_;
- DRWPass *gather_ps = is_background ? gather_bg_ps_ : gather_fg_ps_;
- DRWPass *filter_ps = is_background ? filter_bg_ps_ : filter_fg_ps_;
- DRWPass *scatter_ps = is_background ? scatter_bg_ps_ : scatter_fg_ps_;
+ PassSimple &gather_ps = is_background ? gather_bg_ps_ : gather_fg_ps_;
+ PassSimple &filter_ps = is_background ? filter_bg_ps_ : filter_fg_ps_;
+ PassSimple &scatter_ps = is_background ? scatter_bg_ps_ : scatter_fg_ps_;
color_tx.current().acquire(half_res, GPU_RGBA16F);
weight_tx.current().acquire(half_res, GPU_R16F);
occlusion_tx_.acquire(half_res, GPU_RG16F);
- DRW_draw_pass(gather_ps);
+ drw.submit(gather_ps, view);
{
/* Filtering pass. */
@@ -704,7 +697,7 @@ void DepthOfField::render(GPUTexture **input_tx,
color_tx.current().acquire(half_res, GPU_RGBA16F);
weight_tx.current().acquire(half_res, GPU_R16F);
- DRW_draw_pass(filter_ps);
+ drw.submit(filter_ps, view);
color_tx.previous().release();
weight_tx.previous().release();
@@ -715,7 +708,7 @@ void DepthOfField::render(GPUTexture **input_tx,
scatter_fb.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(color_tx.current()));
GPU_framebuffer_bind(scatter_fb);
- DRW_draw_pass(scatter_ps);
+ drw.submit(scatter_ps, view);
/* Used by scatter pass. */
occlusion_tx_.release();
@@ -731,7 +724,7 @@ void DepthOfField::render(GPUTexture **input_tx,
hole_fill_color_tx_.acquire(half_res, GPU_RGBA16F);
hole_fill_weight_tx_.acquire(half_res, GPU_R16F);
- DRW_draw_pass(hole_fill_ps_);
+ drw.submit(hole_fill_ps_, view);
/* NOTE: We do not filter the hole-fill pass as effect is likely to not be noticeable. */
@@ -742,7 +735,7 @@ void DepthOfField::render(GPUTexture **input_tx,
resolve_stable_color_tx_ = dof_buffer.stabilize_history_tx_;
- DRW_draw_pass(resolve_ps_);
+ drw.submit(resolve_ps_, view);
color_bg_tx_.current().release();
color_fg_tx_.current().release();
@@ -765,4 +758,4 @@ void DepthOfField::render(GPUTexture **input_tx,
/** \} */
-} // namespace blender::eevee \ No newline at end of file
+} // namespace blender::eevee
diff --git a/source/blender/draw/engines/eevee_next/eevee_depth_of_field.hh b/source/blender/draw/engines/eevee_next/eevee_depth_of_field.hh
index 8c291b241bd..bac0e394d66 100644
--- a/source/blender/draw/engines/eevee_next/eevee_depth_of_field.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_depth_of_field.hh
@@ -56,13 +56,13 @@ class DepthOfField {
TextureFromPool bokeh_gather_lut_tx_ = {"dof_bokeh_gather_lut"};
TextureFromPool bokeh_resolve_lut_tx_ = {"dof_bokeh_resolve_lut"};
TextureFromPool bokeh_scatter_lut_tx_ = {"dof_bokeh_scatter_lut"};
- DRWPass *bokeh_lut_ps_ = nullptr;
+ PassSimple bokeh_lut_ps_ = {"BokehLut"};
/** Outputs half-resolution color and Circle Of Confusion. */
TextureFromPool setup_coc_tx_ = {"dof_setup_coc"};
TextureFromPool setup_color_tx_ = {"dof_setup_color"};
int3 dispatch_setup_size_ = int3(-1);
- DRWPass *setup_ps_ = nullptr;
+ PassSimple setup_ps_ = {"Setup"};
/** Allocated because we need mip chain. Which isn't supported by TextureFromPool. */
Texture reduced_coc_tx_ = {"dof_reduced_coc"};
@@ -73,12 +73,12 @@ class DepthOfField {
GPUTexture *stabilize_input_ = nullptr;
bool1 stabilize_valid_history_ = false;
int3 dispatch_stabilize_size_ = int3(-1);
- DRWPass *stabilize_ps_ = nullptr;
+ PassSimple stabilize_ps_ = {"Stabilize"};
/** 1/4th res color buffer used to speedup the local contrast test in the first reduce pass. */
TextureFromPool downsample_tx_ = {"dof_downsample"};
int3 dispatch_downsample_size_ = int3(-1);
- DRWPass *downsample_ps_ = nullptr;
+ PassSimple downsample_ps_ = {"Downsample"};
/** Create mip-mapped color & COC textures for gather passes as well as scatter rect list. */
DepthOfFieldScatterListBuf scatter_fg_list_buf_;
@@ -86,20 +86,20 @@ class DepthOfField {
DrawIndirectBuf scatter_fg_indirect_buf_;
DrawIndirectBuf scatter_bg_indirect_buf_;
int3 dispatch_reduce_size_ = int3(-1);
- DRWPass *reduce_ps_ = nullptr;
+ PassSimple reduce_ps_ = {"Reduce"};
/** Outputs min & max COC in each 8x8 half res pixel tiles (so 1/16th of full resolution). */
SwapChain<TextureFromPool, 2> tiles_fg_tx_;
SwapChain<TextureFromPool, 2> tiles_bg_tx_;
int3 dispatch_tiles_flatten_size_ = int3(-1);
- DRWPass *tiles_flatten_ps_ = nullptr;
+ PassSimple tiles_flatten_ps_ = {"TilesFlatten"};
/** Dilates the min & max CoCs to cover maximum COC values. */
int tiles_dilate_ring_count_ = -1;
int tiles_dilate_ring_width_mul_ = -1;
int3 dispatch_tiles_dilate_size_ = int3(-1);
- DRWPass *tiles_dilate_minmax_ps_ = nullptr;
- DRWPass *tiles_dilate_minabs_ps_ = nullptr;
+ PassSimple tiles_dilate_minmax_ps_ = {"TilesDilateMinmax"};
+ PassSimple tiles_dilate_minabs_ps_ = {"TilesDilateMinabs"};
/** Gather convolution for low intensity pixels and low contrast areas. */
SwapChain<TextureFromPool, 2> color_bg_tx_;
@@ -108,29 +108,29 @@ class DepthOfField {
SwapChain<TextureFromPool, 2> weight_fg_tx_;
TextureFromPool occlusion_tx_ = {"dof_occlusion"};
int3 dispatch_gather_size_ = int3(-1);
- DRWPass *gather_fg_ps_ = nullptr;
- DRWPass *gather_bg_ps_ = nullptr;
+ PassSimple gather_fg_ps_ = {"GatherFg"};
+ PassSimple gather_bg_ps_ = {"GatherBg"};
/** Hole-fill convolution: Gather pass meant to fill areas of foreground dis-occlusion. */
TextureFromPool hole_fill_color_tx_ = {"dof_color_hole_fill"};
TextureFromPool hole_fill_weight_tx_ = {"dof_weight_hole_fill"};
- DRWPass *hole_fill_ps_ = nullptr;
+ PassSimple hole_fill_ps_ = {"HoleFill"};
/** Small Filter pass to reduce noise out of gather passes. */
int3 dispatch_filter_size_ = int3(-1);
- DRWPass *filter_fg_ps_ = nullptr;
- DRWPass *filter_bg_ps_ = nullptr;
+ PassSimple filter_fg_ps_ = {"FilterFg"};
+ PassSimple filter_bg_ps_ = {"FilterBg"};
/** Scatter convolution: A quad is emitted for every 4 bright enough half pixels. */
Framebuffer scatter_fg_fb_ = {"dof_scatter_fg"};
Framebuffer scatter_bg_fb_ = {"dof_scatter_bg"};
- DRWPass *scatter_fg_ps_ = nullptr;
- DRWPass *scatter_bg_ps_ = nullptr;
+ PassSimple scatter_fg_ps_ = {"ScatterFg"};
+ PassSimple scatter_bg_ps_ = {"ScatterBg"};
/** Recombine the results and also perform a slight out of focus gather. */
GPUTexture *resolve_stable_color_tx_ = nullptr;
int3 dispatch_resolve_size_ = int3(-1);
- DRWPass *resolve_ps_ = nullptr;
+ PassSimple resolve_ps_ = {"Resolve"};
DepthOfFieldDataBuf data_;
@@ -139,6 +139,8 @@ class DepthOfField {
float fx_max_coc_;
/** Use jittered depth of field where we randomize camera location. */
bool do_jitter_;
+ /** Enable bokeh lookup texture. */
+ bool use_bokeh_lut_;
/** Circle of Confusion radius for FX DoF passes. Is in view X direction in [0..1] range. */
float fx_radius_;
@@ -166,7 +168,10 @@ class DepthOfField {
* Will swap input and output texture if rendering happens. The actual output of this function
* is in input_tx.
*/
- void render(GPUTexture **input_tx, GPUTexture **output_tx, DepthOfFieldBuffer &dof_buffer);
+ void render(View &view,
+ GPUTexture **input_tx,
+ GPUTexture **output_tx,
+ DepthOfFieldBuffer &dof_buffer);
bool postfx_enabled() const
{
diff --git a/source/blender/draw/engines/eevee_next/eevee_engine.cc b/source/blender/draw/engines/eevee_next/eevee_engine.cc
index 37b4bde324e..5ef198838c9 100644
--- a/source/blender/draw/engines/eevee_next/eevee_engine.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_engine.cc
@@ -140,7 +140,7 @@ static void eevee_instance_free(void *instance)
delete reinterpret_cast<eevee::Instance *>(instance);
}
-static void eevee_render_to_image(void *UNUSED(vedata),
+static void eevee_render_to_image(void *vedata,
struct RenderEngine *engine,
struct RenderLayer *layer,
const struct rcti *UNUSED(rect))
@@ -164,7 +164,23 @@ static void eevee_render_to_image(void *UNUSED(vedata),
instance->init(size, &rect, engine, depsgraph, nullptr, camera_original_ob, layer);
instance->render_frame(layer, viewname);
+ EEVEE_Data *ved = static_cast<EEVEE_Data *>(vedata);
+ if (ved->instance) {
+ delete ved->instance;
+ }
+ ved->instance = instance;
+}
+
+static void eevee_store_metadata(void *vedata, struct RenderResult *render_result)
+{
+ if (!GPU_shader_storage_buffer_objects_support()) {
+ return;
+ }
+ EEVEE_Data *ved = static_cast<EEVEE_Data *>(vedata);
+ eevee::Instance *instance = ved->instance;
+ instance->store_metadata(render_result);
delete instance;
+ ved->instance = nullptr;
}
static void eevee_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer)
@@ -172,7 +188,7 @@ static void eevee_render_update_passes(RenderEngine *engine, Scene *scene, ViewL
if (!GPU_shader_storage_buffer_objects_support()) {
return;
}
- UNUSED_VARS(engine, scene, view_layer);
+ eevee::Instance::update_passes(engine, scene, view_layer);
}
static const DrawEngineDataSize eevee_data_size = DRW_VIEWPORT_DATA_SIZE(EEVEE_Data);
@@ -194,7 +210,7 @@ DrawEngineType draw_engine_eevee_next_type = {
nullptr,
nullptr,
&eevee_render_to_image,
- nullptr,
+ &eevee_store_metadata,
};
RenderEngineType DRW_engine_viewport_eevee_next_type = {
diff --git a/source/blender/draw/engines/eevee_next/eevee_film.cc b/source/blender/draw/engines/eevee_next/eevee_film.cc
index b3fbe088471..244eb1e54ef 100644
--- a/source/blender/draw/engines/eevee_next/eevee_film.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_film.cc
@@ -5,7 +5,7 @@
/** \file
* \ingroup eevee
*
- * A film is a fullscreen buffer (usually at output extent)
+ * A film is a full-screen buffer (usually at output extent)
* that will be able to accumulate sample in any distorted camera_type
* using a pixel filter.
*
@@ -162,6 +162,45 @@ inline bool operator!=(const FilmData &a, const FilmData &b)
/** \name Film
* \{ */
+static eViewLayerEEVEEPassType enabled_passes(const ViewLayer *view_layer)
+{
+ eViewLayerEEVEEPassType result = eViewLayerEEVEEPassType(view_layer->eevee.render_passes);
+
+#define ENABLE_FROM_LEGACY(name_legacy, name_eevee) \
+ SET_FLAG_FROM_TEST(result, \
+ (view_layer->passflag & SCE_PASS_##name_legacy) != 0, \
+ EEVEE_RENDER_PASS_##name_eevee);
+
+ ENABLE_FROM_LEGACY(COMBINED, COMBINED)
+ ENABLE_FROM_LEGACY(Z, Z)
+ ENABLE_FROM_LEGACY(MIST, MIST)
+ ENABLE_FROM_LEGACY(NORMAL, NORMAL)
+ ENABLE_FROM_LEGACY(SHADOW, SHADOW)
+ ENABLE_FROM_LEGACY(AO, AO)
+ ENABLE_FROM_LEGACY(EMIT, EMIT)
+ ENABLE_FROM_LEGACY(ENVIRONMENT, ENVIRONMENT)
+ ENABLE_FROM_LEGACY(DIFFUSE_COLOR, DIFFUSE_COLOR)
+ ENABLE_FROM_LEGACY(GLOSSY_COLOR, SPECULAR_COLOR)
+ ENABLE_FROM_LEGACY(DIFFUSE_DIRECT, DIFFUSE_LIGHT)
+ ENABLE_FROM_LEGACY(GLOSSY_DIRECT, SPECULAR_LIGHT)
+ ENABLE_FROM_LEGACY(ENVIRONMENT, ENVIRONMENT)
+ ENABLE_FROM_LEGACY(VECTOR, VECTOR)
+
+#undef ENABLE_FROM_LEGACY
+
+ SET_FLAG_FROM_TEST(result,
+ view_layer->cryptomatte_flag & VIEW_LAYER_CRYPTOMATTE_OBJECT,
+ EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT);
+ SET_FLAG_FROM_TEST(result,
+ view_layer->cryptomatte_flag & VIEW_LAYER_CRYPTOMATTE_ASSET,
+ EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET);
+ SET_FLAG_FROM_TEST(result,
+ view_layer->cryptomatte_flag & VIEW_LAYER_CRYPTOMATTE_MATERIAL,
+ EEVEE_RENDER_PASS_CRYPTOMATTE_MATERIAL);
+
+ return result;
+}
+
void Film::init(const int2 &extent, const rcti *output_rect)
{
Sampling &sampling = inst_.sampling;
@@ -186,29 +225,7 @@ void Film::init(const int2 &extent, const rcti *output_rect)
}
else {
/* Render Case. */
- render_passes = eViewLayerEEVEEPassType(inst_.view_layer->eevee.render_passes);
-
-#define ENABLE_FROM_LEGACY(name_legacy, name_eevee) \
- SET_FLAG_FROM_TEST(render_passes, \
- (inst_.view_layer->passflag & SCE_PASS_##name_legacy) != 0, \
- EEVEE_RENDER_PASS_##name_eevee);
-
- ENABLE_FROM_LEGACY(COMBINED, COMBINED)
- ENABLE_FROM_LEGACY(Z, Z)
- ENABLE_FROM_LEGACY(MIST, MIST)
- ENABLE_FROM_LEGACY(NORMAL, NORMAL)
- ENABLE_FROM_LEGACY(SHADOW, SHADOW)
- ENABLE_FROM_LEGACY(AO, AO)
- ENABLE_FROM_LEGACY(EMIT, EMIT)
- ENABLE_FROM_LEGACY(ENVIRONMENT, ENVIRONMENT)
- ENABLE_FROM_LEGACY(DIFFUSE_COLOR, DIFFUSE_COLOR)
- ENABLE_FROM_LEGACY(GLOSSY_COLOR, SPECULAR_COLOR)
- ENABLE_FROM_LEGACY(DIFFUSE_DIRECT, DIFFUSE_LIGHT)
- ENABLE_FROM_LEGACY(GLOSSY_DIRECT, SPECULAR_LIGHT)
- ENABLE_FROM_LEGACY(ENVIRONMENT, ENVIRONMENT)
- ENABLE_FROM_LEGACY(VECTOR, VECTOR)
-
-#undef ENABLE_FROM_LEGACY
+ render_passes = enabled_passes(inst_.view_layer);
}
/* Filter obsolete passes. */
@@ -241,6 +258,7 @@ void Film::init(const int2 &extent, const rcti *output_rect)
/* TODO(fclem): parameter hidden in experimental.
* We need to figure out LOD bias first in order to preserve texture crispiness. */
data.scaling_factor = 1;
+ data.cryptomatte_samples_len = inst_.view_layer->cryptomatte_levels;
data.background_opacity = (scene.r.alphamode == R_ALPHAPREMUL) ? 0.0f : 1.0f;
if (inst_.is_viewport() && false /* TODO(fclem): StudioLight */) {
@@ -270,10 +288,11 @@ void Film::init(const int2 &extent, const rcti *output_rect)
data_.any_render_pass_2 = (enabled_passes_ & color_passes_2) != 0;
}
{
- /* Set pass offsets. */
+ /* Set pass offsets. */
data_.display_id = aovs_info.display_id;
- data_.display_is_value = aovs_info.display_is_value;
+ data_.display_storage_type = aovs_info.display_is_value ? PASS_STORAGE_VALUE :
+ PASS_STORAGE_COLOR;
/* Combined is in a separate buffer. */
data_.combined_id = (enabled_passes_ & EEVEE_RENDER_PASS_COMBINED) ? 0 : -1;
@@ -284,13 +303,13 @@ void Film::init(const int2 &extent, const rcti *output_rect)
data_.value_len = 0;
auto pass_index_get = [&](eViewLayerEEVEEPassType pass_type) {
- bool is_value = pass_is_value(pass_type);
+ ePassStorageType storage_type = pass_storage_type(pass_type);
int index = (enabled_passes_ & pass_type) ?
- (is_value ? data_.value_len : data_.color_len)++ :
+ (storage_type == PASS_STORAGE_VALUE ? data_.value_len : data_.color_len)++ :
-1;
if (inst_.is_viewport() && inst_.v3d->shading.render_pass == pass_type) {
data_.display_id = index;
- data_.display_is_value = is_value;
+ data_.display_storage_type = storage_type;
}
return index;
};
@@ -316,6 +335,24 @@ void Film::init(const int2 &extent, const rcti *output_rect)
data_.color_len += data_.aov_color_len;
data_.value_len += data_.aov_value_len;
+
+ int cryptomatte_id = 0;
+ auto cryptomatte_index_get = [&](eViewLayerEEVEEPassType pass_type) {
+ int index = -1;
+ if (enabled_passes_ & pass_type) {
+ index = cryptomatte_id;
+ cryptomatte_id += data_.cryptomatte_samples_len / 2;
+
+ if (inst_.is_viewport() && inst_.v3d->shading.render_pass == pass_type) {
+ data_.display_id = index;
+ data_.display_storage_type = PASS_STORAGE_CRYPTOMATTE;
+ }
+ }
+ return index;
+ };
+ data_.cryptomatte_object_id = cryptomatte_index_get(EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT);
+ data_.cryptomatte_asset_id = cryptomatte_index_get(EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET);
+ data_.cryptomatte_material_id = cryptomatte_index_get(EEVEE_RENDER_PASS_CRYPTOMATTE_MATERIAL);
}
{
/* TODO(@fclem): Over-scans. */
@@ -327,6 +364,7 @@ void Film::init(const int2 &extent, const rcti *output_rect)
eGPUTextureFormat float_format = GPU_R16F;
eGPUTextureFormat weight_format = GPU_R32F;
eGPUTextureFormat depth_format = GPU_R32F;
+ eGPUTextureFormat cryptomatte_format = GPU_RGBA32F;
int reset = 0;
reset += depth_tx_.ensure_2d(depth_format, data_.extent);
@@ -341,6 +379,12 @@ void Film::init(const int2 &extent, const rcti *output_rect)
reset += value_accum_tx_.ensure_2d_array(float_format,
(data_.value_len > 0) ? data_.extent : int2(1),
(data_.value_len > 0) ? data_.value_len : 1);
+ /* Divided by two as two cryptomatte samples fit in pixel (RG, BA). */
+ int cryptomatte_array_len = cryptomatte_layer_len_get() * data_.cryptomatte_samples_len / 2;
+ reset += cryptomatte_tx_.ensure_2d_array(cryptomatte_format,
+ (cryptomatte_array_len > 0) ? data_.extent : int2(1),
+ (cryptomatte_array_len > 0) ? cryptomatte_array_len :
+ 1);
if (reset > 0) {
sampling.reset();
@@ -353,6 +397,7 @@ void Film::init(const int2 &extent, const rcti *output_rect)
combined_tx_.current().clear(float4(0.0f));
weight_tx_.current().clear(float4(0.0f));
depth_tx_.clear(float4(0.0f));
+ cryptomatte_tx_.clear(float4(0.0f));
}
}
@@ -377,49 +422,62 @@ void Film::sync()
* Still bind previous step to avoid undefined behavior. */
eVelocityStep step_next = inst_.is_viewport() ? STEP_PREVIOUS : STEP_NEXT;
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS;
- accumulate_ps_ = DRW_pass_create("Film.Accumulate", state);
- GPUShader *sh = inst_.shaders.static_shader_get(shader);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, accumulate_ps_);
- DRW_shgroup_uniform_block_ref(grp, "film_buf", &data_);
- DRW_shgroup_uniform_block_ref(grp, "camera_prev", &(*velocity.camera_steps[STEP_PREVIOUS]));
- DRW_shgroup_uniform_block_ref(grp, "camera_curr", &(*velocity.camera_steps[STEP_CURRENT]));
- DRW_shgroup_uniform_block_ref(grp, "camera_next", &(*velocity.camera_steps[step_next]));
- DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &rbuffers.depth_tx);
- DRW_shgroup_uniform_texture_ref(grp, "combined_tx", &combined_final_tx_);
- DRW_shgroup_uniform_texture_ref(grp, "normal_tx", &rbuffers.normal_tx);
- DRW_shgroup_uniform_texture_ref(grp, "vector_tx", &rbuffers.vector_tx);
- DRW_shgroup_uniform_texture_ref(grp, "diffuse_light_tx", &rbuffers.diffuse_light_tx);
- DRW_shgroup_uniform_texture_ref(grp, "diffuse_color_tx", &rbuffers.diffuse_color_tx);
- DRW_shgroup_uniform_texture_ref(grp, "specular_light_tx", &rbuffers.specular_light_tx);
- DRW_shgroup_uniform_texture_ref(grp, "specular_color_tx", &rbuffers.specular_color_tx);
- DRW_shgroup_uniform_texture_ref(grp, "volume_light_tx", &rbuffers.volume_light_tx);
- DRW_shgroup_uniform_texture_ref(grp, "emission_tx", &rbuffers.emission_tx);
- DRW_shgroup_uniform_texture_ref(grp, "environment_tx", &rbuffers.environment_tx);
- DRW_shgroup_uniform_texture_ref(grp, "shadow_tx", &rbuffers.shadow_tx);
- DRW_shgroup_uniform_texture_ref(grp, "ambient_occlusion_tx", &rbuffers.ambient_occlusion_tx);
- DRW_shgroup_uniform_texture_ref(grp, "aov_color_tx", &rbuffers.aov_color_tx);
- DRW_shgroup_uniform_texture_ref(grp, "aov_value_tx", &rbuffers.aov_value_tx);
+ accumulate_ps_.init();
+ accumulate_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ accumulate_ps_.shader_set(inst_.shaders.static_shader_get(shader));
+ accumulate_ps_.bind_ubo("film_buf", &data_);
+ accumulate_ps_.bind_ubo("camera_prev", &(*velocity.camera_steps[STEP_PREVIOUS]));
+ accumulate_ps_.bind_ubo("camera_curr", &(*velocity.camera_steps[STEP_CURRENT]));
+ accumulate_ps_.bind_ubo("camera_next", &(*velocity.camera_steps[step_next]));
+ accumulate_ps_.bind_texture("depth_tx", &rbuffers.depth_tx);
+ accumulate_ps_.bind_texture("combined_tx", &combined_final_tx_);
+ accumulate_ps_.bind_texture("normal_tx", &rbuffers.normal_tx);
+ accumulate_ps_.bind_texture("vector_tx", &rbuffers.vector_tx);
+ accumulate_ps_.bind_texture("light_tx", &rbuffers.light_tx);
+ accumulate_ps_.bind_texture("diffuse_color_tx", &rbuffers.diffuse_color_tx);
+ accumulate_ps_.bind_texture("specular_color_tx", &rbuffers.specular_color_tx);
+ accumulate_ps_.bind_texture("volume_light_tx", &rbuffers.volume_light_tx);
+ accumulate_ps_.bind_texture("emission_tx", &rbuffers.emission_tx);
+ accumulate_ps_.bind_texture("environment_tx", &rbuffers.environment_tx);
+ accumulate_ps_.bind_texture("shadow_tx", &rbuffers.shadow_tx);
+ accumulate_ps_.bind_texture("ambient_occlusion_tx", &rbuffers.ambient_occlusion_tx);
+ accumulate_ps_.bind_texture("aov_color_tx", &rbuffers.aov_color_tx);
+ accumulate_ps_.bind_texture("aov_value_tx", &rbuffers.aov_value_tx);
+ accumulate_ps_.bind_texture("cryptomatte_tx", &rbuffers.cryptomatte_tx);
/* NOTE(@fclem): 16 is the max number of sampled texture in many implementations.
* If we need more, we need to pack more of the similar passes in the same textures as arrays or
* use image binding instead. */
- DRW_shgroup_uniform_image_ref(grp, "in_weight_img", &weight_tx_.current());
- DRW_shgroup_uniform_image_ref(grp, "out_weight_img", &weight_tx_.next());
- DRW_shgroup_uniform_texture_ref_ex(grp, "in_combined_tx", &combined_tx_.current(), filter);
- DRW_shgroup_uniform_image_ref(grp, "out_combined_img", &combined_tx_.next());
- DRW_shgroup_uniform_image_ref(grp, "depth_img", &depth_tx_);
- DRW_shgroup_uniform_image_ref(grp, "color_accum_img", &color_accum_tx_);
- DRW_shgroup_uniform_image_ref(grp, "value_accum_img", &value_accum_tx_);
- /* Sync with rendering passes. */
- DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH);
+ accumulate_ps_.bind_image("in_weight_img", &weight_tx_.current());
+ accumulate_ps_.bind_image("out_weight_img", &weight_tx_.next());
+ accumulate_ps_.bind_texture("in_combined_tx", &combined_tx_.current(), filter);
+ accumulate_ps_.bind_image("out_combined_img", &combined_tx_.next());
+ accumulate_ps_.bind_image("depth_img", &depth_tx_);
+ accumulate_ps_.bind_image("color_accum_img", &color_accum_tx_);
+ accumulate_ps_.bind_image("value_accum_img", &value_accum_tx_);
+ accumulate_ps_.bind_image("cryptomatte_img", &cryptomatte_tx_);
/* Sync with rendering passes. */
- DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_IMAGE_ACCESS);
+ accumulate_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
if (use_compute) {
- int2 dispatch_size = math::divide_ceil(data_.extent, int2(FILM_GROUP_SIZE));
- DRW_shgroup_call_compute(grp, UNPACK2(dispatch_size), 1);
+ accumulate_ps_.dispatch(int3(math::divide_ceil(data_.extent, int2(FILM_GROUP_SIZE)), 1));
}
else {
- DRW_shgroup_call_procedural_triangles(grp, nullptr, 1);
+ accumulate_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
+ }
+
+ const int cryptomatte_layer_count = cryptomatte_layer_len_get();
+ const bool is_cryptomatte_pass_enabled = cryptomatte_layer_count > 0;
+ const bool do_cryptomatte_sorting = inst_.is_viewport() == false;
+ cryptomatte_post_ps_.init();
+ if (is_cryptomatte_pass_enabled && do_cryptomatte_sorting) {
+ cryptomatte_post_ps_.state_set(DRW_STATE_NO_DRAW);
+ cryptomatte_post_ps_.shader_set(inst_.shaders.static_shader_get(FILM_CRYPTOMATTE_POST));
+ cryptomatte_post_ps_.bind_image("cryptomatte_img", &cryptomatte_tx_);
+ cryptomatte_post_ps_.bind_image("weight_img", &weight_tx_.current());
+ cryptomatte_post_ps_.push_constant("cryptomatte_layer_len", cryptomatte_layer_count);
+ cryptomatte_post_ps_.push_constant("cryptomatte_samples_per_layer",
+ inst_.view_layer->cryptomatte_levels);
+ int2 dispatch_size = math::divide_ceil(int2(cryptomatte_tx_.size()), int2(FILM_GROUP_SIZE));
+ cryptomatte_post_ps_.dispatch(int3(UNPACK2(dispatch_size), 1));
}
}
@@ -468,6 +526,29 @@ eViewLayerEEVEEPassType Film::enabled_passes_get() const
return enabled_passes_;
}
+int Film::cryptomatte_layer_len_get() const
+{
+ int result = 0;
+ result += data_.cryptomatte_object_id == -1 ? 0 : 1;
+ result += data_.cryptomatte_asset_id == -1 ? 0 : 1;
+ result += data_.cryptomatte_material_id == -1 ? 0 : 1;
+ return result;
+}
+
+int Film::cryptomatte_layer_max_get() const
+{
+ if (data_.cryptomatte_material_id != -1) {
+ return 3;
+ }
+ if (data_.cryptomatte_asset_id != -1) {
+ return 2;
+ }
+ if (data_.cryptomatte_object_id != -1) {
+ return 1;
+ }
+ return 0;
+}
+
void Film::update_sample_table()
{
data_.subpixel_offset = pixel_jitter_get();
@@ -566,8 +647,9 @@ void Film::accumulate(const DRWView *view, GPUTexture *combined_final_tx)
data_.display_only = false;
data_.push_update();
- DRW_view_set_active(view);
- DRW_draw_pass(accumulate_ps_);
+ draw::View drw_view("MainView", view);
+
+ DRW_manager_get()->submit(accumulate_ps_, drw_view);
combined_tx_.swap();
weight_tx_.swap();
@@ -594,28 +676,37 @@ void Film::display()
data_.display_only = true;
data_.push_update();
- DRW_view_set_active(nullptr);
- DRW_draw_pass(accumulate_ps_);
+ draw::View drw_view("MainView", DRW_view_default_get());
+
+ DRW_manager_get()->submit(accumulate_ps_, drw_view);
inst_.render_buffers.release();
/* IMPORTANT: Do not swap! No accumulation has happened. */
}
-float *Film::read_pass(eViewLayerEEVEEPassType pass_type)
+void Film::cryptomatte_sort()
{
+ DRW_manager_get()->submit(cryptomatte_post_ps_);
+}
+
+float *Film::read_pass(eViewLayerEEVEEPassType pass_type, int layer_offset)
+{
+ ePassStorageType storage_type = pass_storage_type(pass_type);
+ const bool is_value = storage_type == PASS_STORAGE_VALUE;
+ const bool is_cryptomatte = storage_type == PASS_STORAGE_CRYPTOMATTE;
- bool is_value = pass_is_value(pass_type);
Texture &accum_tx = (pass_type == EEVEE_RENDER_PASS_COMBINED) ?
combined_tx_.current() :
(pass_type == EEVEE_RENDER_PASS_Z) ?
depth_tx_ :
- (is_value ? value_accum_tx_ : color_accum_tx_);
+ (is_cryptomatte ? cryptomatte_tx_ :
+ (is_value ? value_accum_tx_ : color_accum_tx_));
accum_tx.ensure_layer_views();
int index = pass_id_get(pass_type);
- GPUTexture *pass_tx = accum_tx.layer_view(index);
+ GPUTexture *pass_tx = accum_tx.layer_view(index + layer_offset);
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
diff --git a/source/blender/draw/engines/eevee_next/eevee_film.hh b/source/blender/draw/engines/eevee_next/eevee_film.hh
index 3e368782d31..5478c20aff2 100644
--- a/source/blender/draw/engines/eevee_next/eevee_film.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_film.hh
@@ -43,11 +43,16 @@ class Film {
/** Incoming combined buffer with post FX applied (motion blur + depth of field). */
GPUTexture *combined_final_tx_ = nullptr;
- /** Main accumulation textures containing every render-pass except depth and combined. */
+ /**
+ * Main accumulation textures containing every render-pass except depth, cryptomatte and
+ * combined.
+ */
Texture color_accum_tx_;
Texture value_accum_tx_;
/** Depth accumulation texture. Separated because using a different format. */
Texture depth_tx_;
+ /** Cryptomatte texture. Separated because it requires full floats. */
+ Texture cryptomatte_tx_;
/** Combined "Color" buffer. Double buffered to allow re-projection. */
SwapChain<Texture, 2> combined_tx_;
/** Weight buffers. Double buffered to allow updating it during accumulation. */
@@ -55,7 +60,8 @@ class Film {
/** User setting to disable reprojection. Useful for debugging or have a more precise render. */
bool force_disable_reprojection_ = false;
- DRWPass *accumulate_ps_ = nullptr;
+ PassSimple accumulate_ps_ = {"Film.Accumulate"};
+ PassSimple cryptomatte_post_ps_ = {"Film.Cryptomatte.Post"};
FilmDataBuf data_;
@@ -73,10 +79,13 @@ class Film {
/** Accumulate the newly rendered sample contained in #RenderBuffers and blit to display. */
void accumulate(const DRWView *view, GPUTexture *combined_final_tx);
+ /** Sort and normalize cryptomatte samples. */
+ void cryptomatte_sort();
+
/** Blit to display. No rendered sample needed. */
void display();
- float *read_pass(eViewLayerEEVEEPassType pass_type);
+ float *read_pass(eViewLayerEEVEEPassType pass_type, int layer_offset);
float *read_aov(ViewLayerAOV *aov);
/** Returns shading views internal resolution. */
@@ -93,17 +102,23 @@ class Film {
}
eViewLayerEEVEEPassType enabled_passes_get() const;
+ int cryptomatte_layer_max_get() const;
+ int cryptomatte_layer_len_get() const;
- static bool pass_is_value(eViewLayerEEVEEPassType pass_type)
+ static ePassStorageType pass_storage_type(eViewLayerEEVEEPassType pass_type)
{
switch (pass_type) {
case EEVEE_RENDER_PASS_Z:
case EEVEE_RENDER_PASS_MIST:
case EEVEE_RENDER_PASS_SHADOW:
case EEVEE_RENDER_PASS_AO:
- return true;
+ return PASS_STORAGE_VALUE;
+ case EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT:
+ case EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET:
+ case EEVEE_RENDER_PASS_CRYPTOMATTE_MATERIAL:
+ return PASS_STORAGE_CRYPTOMATTE;
default:
- return false;
+ return PASS_STORAGE_COLOR;
}
}
@@ -154,8 +169,12 @@ class Film {
return data_.shadow_id;
case EEVEE_RENDER_PASS_AO:
return data_.ambient_occlusion_id;
- case EEVEE_RENDER_PASS_CRYPTOMATTE:
- return -1; /* TODO */
+ case EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT:
+ return data_.cryptomatte_object_id;
+ case EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET:
+ return data_.cryptomatte_asset_id;
+ case EEVEE_RENDER_PASS_CRYPTOMATTE_MATERIAL:
+ return data_.cryptomatte_material_id;
case EEVEE_RENDER_PASS_VECTOR:
return data_.vector_id;
default:
@@ -163,44 +182,80 @@ class Film {
}
}
- static const char *pass_to_render_pass_name(eViewLayerEEVEEPassType pass_type)
+ static const Vector<std::string> pass_to_render_pass_names(eViewLayerEEVEEPassType pass_type,
+ const ViewLayer *view_layer)
{
+ Vector<std::string> result;
+
+ auto build_cryptomatte_passes = [&](const char *pass_name) {
+ const int num_cryptomatte_passes = (view_layer->cryptomatte_levels + 1) / 2;
+ for (int pass = 0; pass < num_cryptomatte_passes; pass++) {
+ std::stringstream ss;
+ ss.fill('0');
+ ss << pass_name;
+ ss.width(2);
+ ss << pass;
+ result.append(ss.str());
+ }
+ };
+
switch (pass_type) {
case EEVEE_RENDER_PASS_COMBINED:
- return RE_PASSNAME_COMBINED;
+ result.append(RE_PASSNAME_COMBINED);
+ break;
case EEVEE_RENDER_PASS_Z:
- return RE_PASSNAME_Z;
+ result.append(RE_PASSNAME_Z);
+ break;
case EEVEE_RENDER_PASS_MIST:
- return RE_PASSNAME_MIST;
+ result.append(RE_PASSNAME_MIST);
+ break;
case EEVEE_RENDER_PASS_NORMAL:
- return RE_PASSNAME_NORMAL;
+ result.append(RE_PASSNAME_NORMAL);
+ break;
case EEVEE_RENDER_PASS_DIFFUSE_LIGHT:
- return RE_PASSNAME_DIFFUSE_DIRECT;
+ result.append(RE_PASSNAME_DIFFUSE_DIRECT);
+ break;
case EEVEE_RENDER_PASS_DIFFUSE_COLOR:
- return RE_PASSNAME_DIFFUSE_COLOR;
+ result.append(RE_PASSNAME_DIFFUSE_COLOR);
+ break;
case EEVEE_RENDER_PASS_SPECULAR_LIGHT:
- return RE_PASSNAME_GLOSSY_DIRECT;
+ result.append(RE_PASSNAME_GLOSSY_DIRECT);
+ break;
case EEVEE_RENDER_PASS_SPECULAR_COLOR:
- return RE_PASSNAME_GLOSSY_COLOR;
+ result.append(RE_PASSNAME_GLOSSY_COLOR);
+ break;
case EEVEE_RENDER_PASS_VOLUME_LIGHT:
- return RE_PASSNAME_VOLUME_LIGHT;
+ result.append(RE_PASSNAME_VOLUME_LIGHT);
+ break;
case EEVEE_RENDER_PASS_EMIT:
- return RE_PASSNAME_EMIT;
+ result.append(RE_PASSNAME_EMIT);
+ break;
case EEVEE_RENDER_PASS_ENVIRONMENT:
- return RE_PASSNAME_ENVIRONMENT;
+ result.append(RE_PASSNAME_ENVIRONMENT);
+ break;
case EEVEE_RENDER_PASS_SHADOW:
- return RE_PASSNAME_SHADOW;
+ result.append(RE_PASSNAME_SHADOW);
+ break;
case EEVEE_RENDER_PASS_AO:
- return RE_PASSNAME_AO;
- case EEVEE_RENDER_PASS_CRYPTOMATTE:
- BLI_assert_msg(0, "Cryptomatte is not implemented yet.");
- return ""; /* TODO */
+ result.append(RE_PASSNAME_AO);
+ break;
+ case EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT:
+ build_cryptomatte_passes(RE_PASSNAME_CRYPTOMATTE_OBJECT);
+ break;
+ case EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET:
+ build_cryptomatte_passes(RE_PASSNAME_CRYPTOMATTE_ASSET);
+ break;
+ case EEVEE_RENDER_PASS_CRYPTOMATTE_MATERIAL:
+ build_cryptomatte_passes(RE_PASSNAME_CRYPTOMATTE_MATERIAL);
+ break;
case EEVEE_RENDER_PASS_VECTOR:
- return RE_PASSNAME_VECTOR;
+ result.append(RE_PASSNAME_VECTOR);
+ break;
default:
BLI_assert(0);
- return "";
+ break;
}
+ return result;
}
private:
diff --git a/source/blender/draw/engines/eevee_next/eevee_hizbuffer.cc b/source/blender/draw/engines/eevee_next/eevee_hizbuffer.cc
new file mode 100644
index 00000000000..cf9049da514
--- /dev/null
+++ b/source/blender/draw/engines/eevee_next/eevee_hizbuffer.cc
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation.
+ */
+
+#include "BKE_global.h"
+
+#include "eevee_instance.hh"
+
+#include "eevee_hizbuffer.hh"
+
+namespace blender::eevee {
+
+/* -------------------------------------------------------------------- */
+/** \name Hierarchical-Z buffer
+ *
+ * \{ */
+
+void HiZBuffer::sync()
+{
+ RenderBuffers &render_buffers = inst_.render_buffers;
+
+ int2 render_extent = inst_.film.render_extent_get();
+ /* Padding to avoid complexity during down-sampling and screen tracing. */
+ int2 hiz_extent = math::ceil_to_multiple(render_extent, int2(1u << (HIZ_MIP_COUNT - 1)));
+ int2 dispatch_size = math::divide_ceil(hiz_extent, int2(HIZ_GROUP_SIZE));
+
+ hiz_tx_.ensure_2d(GPU_R32F, hiz_extent, nullptr, HIZ_MIP_COUNT);
+ hiz_tx_.ensure_mip_views();
+ GPU_texture_mipmap_mode(hiz_tx_, true, false);
+
+ data_.uv_scale = float2(render_extent) / float2(hiz_extent);
+ data_.push_update();
+
+ {
+ hiz_update_ps_.init();
+ hiz_update_ps_.shader_set(inst_.shaders.static_shader_get(HIZ_UPDATE));
+ hiz_update_ps_.bind_ssbo("finished_tile_counter", atomic_tile_counter_);
+ hiz_update_ps_.bind_texture("depth_tx", &render_buffers.depth_tx, with_filter);
+ hiz_update_ps_.bind_image("out_mip_0", hiz_tx_.mip_view(0));
+ hiz_update_ps_.bind_image("out_mip_1", hiz_tx_.mip_view(1));
+ hiz_update_ps_.bind_image("out_mip_2", hiz_tx_.mip_view(2));
+ hiz_update_ps_.bind_image("out_mip_3", hiz_tx_.mip_view(3));
+ hiz_update_ps_.bind_image("out_mip_4", hiz_tx_.mip_view(4));
+ hiz_update_ps_.bind_image("out_mip_5", hiz_tx_.mip_view(5));
+ hiz_update_ps_.bind_image("out_mip_6", hiz_tx_.mip_view(6));
+ hiz_update_ps_.bind_image("out_mip_7", hiz_tx_.mip_view(7));
+ /* TODO(@fclem): There might be occasions where we might not want to
+ * copy mip 0 for performance reasons if there is no need for it. */
+ hiz_update_ps_.push_constant("update_mip_0", true);
+ hiz_update_ps_.dispatch(int3(dispatch_size, 1));
+ hiz_update_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH);
+ }
+
+ if (inst_.debug_mode == eDebugMode::DEBUG_HIZ_VALIDATION) {
+ debug_draw_ps_.init();
+ debug_draw_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM);
+ debug_draw_ps_.shader_set(inst_.shaders.static_shader_get(HIZ_DEBUG));
+ this->bind_resources(&debug_draw_ps_);
+ debug_draw_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
+ }
+}
+
+void HiZBuffer::update()
+{
+ if (!is_dirty_) {
+ return;
+ }
+
+ /* Bind another framebuffer in order to avoid triggering the feedback loop check.
+ * This is safe because we only use compute shaders in this section of the code.
+ * Ideally the check should be smarter. */
+ GPUFrameBuffer *fb = GPU_framebuffer_active_get();
+ if (G.debug & G_DEBUG_GPU) {
+ GPU_framebuffer_restore();
+ }
+
+ inst_.manager->submit(hiz_update_ps_);
+
+ if (G.debug & G_DEBUG_GPU) {
+ GPU_framebuffer_bind(fb);
+ }
+}
+
+void HiZBuffer::debug_draw(View &view, GPUFrameBuffer *view_fb)
+{
+ if (inst_.debug_mode == eDebugMode::DEBUG_HIZ_VALIDATION) {
+ inst_.info =
+ "Debug Mode: HiZ Validation\n"
+ " - Red: pixel in front of HiZ tile value.\n"
+ " - Blue: No error.";
+ inst_.hiz_buffer.update();
+ GPU_framebuffer_bind(view_fb);
+ inst_.manager->submit(debug_draw_ps_, view);
+ }
+}
+
+/** \} */
+
+} // namespace blender::eevee
diff --git a/source/blender/draw/engines/eevee_next/eevee_hizbuffer.hh b/source/blender/draw/engines/eevee_next/eevee_hizbuffer.hh
new file mode 100644
index 00000000000..8b8e4de55b1
--- /dev/null
+++ b/source/blender/draw/engines/eevee_next/eevee_hizbuffer.hh
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2021 Blender Foundation.
+ */
+
+/** \file
+ * \ingroup eevee
+ *
+ * The Hierarchical-Z buffer is texture containing a copy of the depth buffer with mipmaps.
+ * Each mip contains the maximum depth of each 4 pixels on the upper level.
+ * The size of the texture is padded to avoid messing with the mipmap pixels alignments.
+ */
+
+#pragma once
+
+#include "DRW_render.h"
+
+#include "eevee_shader_shared.hh"
+
+namespace blender::eevee {
+
+class Instance;
+
+/* -------------------------------------------------------------------- */
+/** \name Hierarchical-Z buffer
+ * \{ */
+
+class HiZBuffer {
+ private:
+ Instance &inst_;
+
+ /** The texture containing the hiz mip chain. */
+ Texture hiz_tx_ = {"hiz_tx_"};
+ /**
+ * Atomic counter counting the number of tile that have finished down-sampling.
+ * The last one will process the last few mip level.
+ */
+ draw::StorageBuffer<uint4, true> atomic_tile_counter_ = {"atomic_tile_counter"};
+ /** Single pass recursive downsample. */
+ PassSimple hiz_update_ps_ = {"HizUpdate"};
+ /** Debug pass. */
+ PassSimple debug_draw_ps_ = {"HizUpdate.Debug"};
+ /** Dirty flag to check if the update is necessary. */
+ bool is_dirty_ = true;
+
+ HiZDataBuf data_;
+
+ public:
+ HiZBuffer(Instance &inst) : inst_(inst)
+ {
+ atomic_tile_counter_.clear_to_zero();
+ };
+
+ void sync();
+
+ /**
+ * Tag the buffer for update if needed.
+ */
+ void set_dirty()
+ {
+ is_dirty_ = true;
+ }
+
+ /**
+ * Update the content of the HiZ buffer with the depth render target.
+ * Noop if the buffer has not been tagged as dirty.
+ * Should be called before each passes that needs to read the hiz buffer.
+ */
+ void update();
+
+ void debug_draw(View &view, GPUFrameBuffer *view_fb);
+
+ void bind_resources(DRWShadingGroup *grp)
+ {
+ DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", &hiz_tx_);
+ DRW_shgroup_uniform_block_ref(grp, "hiz_buf", &data_);
+ }
+
+ /* TODO(fclem): Hardcoded bind slots. */
+ template<typename T> void bind_resources(draw::detail::PassBase<T> *pass)
+ {
+ pass->bind_texture("hiz_tx", &hiz_tx_);
+ pass->bind_ubo("hiz_buf", &data_);
+ }
+};
+
+/** \} */
+
+} // namespace blender::eevee
diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc
index 57786adb657..8005b27c30e 100644
--- a/source/blender/draw/engines/eevee_next/eevee_instance.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc
@@ -52,6 +52,7 @@ void Instance::init(const int2 &output_res,
drw_view = drw_view_;
v3d = v3d_;
rv3d = rv3d_;
+ manager = DRW_manager_get();
if (assign_if_different(debug_mode, (eDebugMode)G.debug_value)) {
sampling.reset();
@@ -101,11 +102,13 @@ void Instance::begin_sync()
materials.begin_sync();
velocity.begin_sync(); /* NOTE: Also syncs camera. */
lights.begin_sync();
+ cryptomatte.begin_sync();
gpencil_engine_enabled = false;
depth_of_field.sync();
motion_blur.sync();
+ hiz_buffer.sync();
pipelines.sync();
main_view.sync();
world.sync();
@@ -125,12 +128,16 @@ void Instance::object_sync(Object *ob)
return;
}
+ /* TODO cleanup. */
+ ObjectRef ob_ref = DRW_object_ref_get(ob);
+ ResourceHandle res_handle = manager->resource_handle(ob_ref);
+
ObjectHandle &ob_handle = sync.sync_object(ob);
if (partsys_is_visible && ob != DRW_context_state_get()->object_edit) {
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
if (md->type == eModifierType_ParticleSystem) {
- sync.sync_curves(ob, ob_handle, md);
+ sync.sync_curves(ob, ob_handle, res_handle, md);
}
}
}
@@ -141,20 +148,15 @@ void Instance::object_sync(Object *ob)
lights.sync_light(ob, ob_handle);
break;
case OB_MESH:
- case OB_CURVES_LEGACY:
- case OB_SURF:
- case OB_FONT:
- case OB_MBALL: {
- sync.sync_mesh(ob, ob_handle);
+ sync.sync_mesh(ob, ob_handle, res_handle, ob_ref);
break;
- }
case OB_VOLUME:
break;
case OB_CURVES:
- sync.sync_curves(ob, ob_handle);
+ sync.sync_curves(ob, ob_handle, res_handle);
break;
case OB_GPENCIL:
- sync.sync_gpencil(ob, ob_handle);
+ sync.sync_gpencil(ob, ob_handle, res_handle);
break;
default:
break;
@@ -181,6 +183,7 @@ void Instance::end_sync()
lights.end_sync();
sampling.end_sync();
film.end_sync();
+ cryptomatte.end_sync();
}
void Instance::render_sync()
@@ -235,10 +238,15 @@ void Instance::render_read_result(RenderLayer *render_layer, const char *view_na
continue;
}
- const char *pass_name = Film::pass_to_render_pass_name(pass_type);
- RenderPass *rp = RE_pass_find_by_name(render_layer, pass_name, view_name);
- if (rp) {
- float *result = film.read_pass(pass_type);
+ Vector<std::string> pass_names = Film::pass_to_render_pass_names(pass_type, view_layer);
+ for (int64_t pass_offset : IndexRange(pass_names.size())) {
+ RenderPass *rp = RE_pass_find_by_name(
+ render_layer, pass_names[pass_offset].c_str(), view_name);
+ if (!rp) {
+ continue;
+ }
+ float *result = film.read_pass(pass_type, pass_offset);
+
if (result) {
BLI_mutex_lock(&render->update_render_passes_mutex);
/* WORKAROUND: We use texture read to avoid using a framebuffer to get the render result.
@@ -254,10 +262,13 @@ void Instance::render_read_result(RenderLayer *render_layer, const char *view_na
/* The vector pass is initialized to weird values. Set it to neutral value if not rendered. */
if ((pass_bits & EEVEE_RENDER_PASS_VECTOR) == 0) {
- const char *vector_pass_name = Film::pass_to_render_pass_name(EEVEE_RENDER_PASS_VECTOR);
- RenderPass *vector_rp = RE_pass_find_by_name(render_layer, vector_pass_name, view_name);
- if (vector_rp) {
- memset(vector_rp->rect, 0, sizeof(float) * 4 * vector_rp->rectx * vector_rp->recty);
+ for (std::string vector_pass_name :
+ Film::pass_to_render_pass_names(EEVEE_RENDER_PASS_VECTOR, view_layer)) {
+ RenderPass *vector_rp = RE_pass_find_by_name(
+ render_layer, vector_pass_name.c_str(), view_name);
+ if (vector_rp) {
+ memset(vector_rp->rect, 0, sizeof(float) * 4 * vector_rp->rectx * vector_rp->recty);
+ }
}
}
}
@@ -289,6 +300,8 @@ void Instance::render_frame(RenderLayer *render_layer, const char *view_name)
#endif
}
+ this->film.cryptomatte_sort();
+
this->render_read_result(render_layer, view_name);
}
@@ -312,6 +325,76 @@ void Instance::draw_viewport(DefaultFramebufferList *dfbl)
}
}
+void Instance::store_metadata(RenderResult *render_result)
+{
+ cryptomatte.store_metadata(render_result);
+}
+
+void Instance::update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer)
+{
+ RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA);
+
+#define CHECK_PASS_LEGACY(name, type, channels, chanid) \
+ if (view_layer->passflag & (SCE_PASS_##name)) { \
+ RE_engine_register_pass( \
+ engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \
+ } \
+ ((void)0)
+#define CHECK_PASS_EEVEE(name, type, channels, chanid) \
+ if (view_layer->eevee.render_passes & (EEVEE_RENDER_PASS_##name)) { \
+ RE_engine_register_pass( \
+ engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \
+ } \
+ ((void)0)
+
+ CHECK_PASS_LEGACY(Z, SOCK_FLOAT, 1, "Z");
+ CHECK_PASS_LEGACY(MIST, SOCK_FLOAT, 1, "Z");
+ CHECK_PASS_LEGACY(NORMAL, SOCK_VECTOR, 3, "XYZ");
+ CHECK_PASS_LEGACY(DIFFUSE_DIRECT, SOCK_RGBA, 3, "RGB");
+ CHECK_PASS_LEGACY(DIFFUSE_COLOR, SOCK_RGBA, 3, "RGB");
+ CHECK_PASS_LEGACY(GLOSSY_DIRECT, SOCK_RGBA, 3, "RGB");
+ CHECK_PASS_LEGACY(GLOSSY_COLOR, SOCK_RGBA, 3, "RGB");
+ CHECK_PASS_EEVEE(VOLUME_LIGHT, SOCK_RGBA, 3, "RGB");
+ CHECK_PASS_LEGACY(EMIT, SOCK_RGBA, 3, "RGB");
+ CHECK_PASS_LEGACY(ENVIRONMENT, SOCK_RGBA, 3, "RGB");
+ /* TODO: CHECK_PASS_LEGACY(SHADOW, SOCK_RGBA, 3, "RGB");
+ * CHECK_PASS_LEGACY(AO, SOCK_RGBA, 3, "RGB");
+ * When available they should be converted from Value textures to RGB. */
+
+ LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) {
+ if ((aov->flag & AOV_CONFLICT) != 0) {
+ continue;
+ }
+ switch (aov->type) {
+ case AOV_TYPE_COLOR:
+ RE_engine_register_pass(engine, scene, view_layer, aov->name, 4, "RGBA", SOCK_RGBA);
+ break;
+ case AOV_TYPE_VALUE:
+ RE_engine_register_pass(engine, scene, view_layer, aov->name, 1, "X", SOCK_FLOAT);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* NOTE: Name channels lowercase `rgba` so that compression rules check in OpenEXR DWA code uses
+ * lossless compression. Reportedly this naming is the only one which works good from the
+ * interoperability point of view. Using `xyzw` naming is not portable. */
+ auto register_cryptomatte_passes = [&](eViewLayerCryptomatteFlags cryptomatte_layer,
+ eViewLayerEEVEEPassType eevee_pass) {
+ if (view_layer->cryptomatte_flag & cryptomatte_layer) {
+ for (std::string pass_name : Film::pass_to_render_pass_names(eevee_pass, view_layer)) {
+ RE_engine_register_pass(
+ engine, scene, view_layer, pass_name.c_str(), 4, "rgba", SOCK_RGBA);
+ }
+ }
+ };
+ register_cryptomatte_passes(VIEW_LAYER_CRYPTOMATTE_OBJECT, EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT);
+ register_cryptomatte_passes(VIEW_LAYER_CRYPTOMATTE_ASSET, EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET);
+ register_cryptomatte_passes(VIEW_LAYER_CRYPTOMATTE_MATERIAL,
+ EEVEE_RENDER_PASS_CRYPTOMATTE_MATERIAL);
+}
+
/** \} */
} // namespace blender::eevee
diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.hh b/source/blender/draw/engines/eevee_next/eevee_instance.hh
index d52e4a8e43b..c8eecbd812d 100644
--- a/source/blender/draw/engines/eevee_next/eevee_instance.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_instance.hh
@@ -16,8 +16,10 @@
#include "DRW_render.h"
#include "eevee_camera.hh"
+#include "eevee_cryptomatte.hh"
#include "eevee_depth_of_field.hh"
#include "eevee_film.hh"
+#include "eevee_hizbuffer.hh"
#include "eevee_light.hh"
#include "eevee_material.hh"
#include "eevee_motion_blur.hh"
@@ -48,6 +50,8 @@ class Instance {
VelocityModule velocity;
MotionBlurModule motion_blur;
DepthOfField depth_of_field;
+ Cryptomatte cryptomatte;
+ HiZBuffer hiz_buffer;
Sampling sampling;
Camera camera;
Film film;
@@ -57,6 +61,7 @@ class Instance {
/** Input data. */
Depsgraph *depsgraph;
+ Manager *manager;
/** Evaluated IDs. */
Scene *scene;
ViewLayer *view_layer;
@@ -88,6 +93,8 @@ class Instance {
velocity(*this),
motion_blur(*this),
depth_of_field(*this),
+ cryptomatte(*this),
+ hiz_buffer(*this),
sampling(*this),
camera(*this),
film(*this),
@@ -113,9 +120,12 @@ class Instance {
void render_sync();
void render_frame(RenderLayer *render_layer, const char *view_name);
+ void store_metadata(RenderResult *render_result);
void draw_viewport(DefaultFramebufferList *dfbl);
+ static void update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer);
+
bool is_viewport() const
{
return render == nullptr;
diff --git a/source/blender/draw/engines/eevee_next/eevee_light.cc b/source/blender/draw/engines/eevee_next/eevee_light.cc
index dbbf481f3f4..b60246fa3ab 100644
--- a/source/blender/draw/engines/eevee_next/eevee_light.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_light.cc
@@ -333,11 +333,11 @@ void LightModule::end_sync()
/* This scene data buffer is then immutable after this point. */
light_buf_.push_update();
- for (auto key : deleted_keys) {
+ for (auto &key : deleted_keys) {
light_map_.remove(key);
}
- /* Update sampling on deletion or un-hidding (use_scene_lights). */
+ /* Update sampling on deletion or un-hiding (use_scene_lights). */
if (assign_if_different(light_map_size_, light_map_.size())) {
inst_.sampling.reset();
}
@@ -399,74 +399,70 @@ void LightModule::culling_pass_sync()
uint culling_tile_dispatch_size = divide_ceil_u(total_word_count_, CULLING_TILE_GROUP_SIZE);
/* NOTE: We reference the buffers that may be resized or updated later. */
+
+ culling_ps_.init();
{
- DRW_PASS_CREATE(culling_select_ps_, DRW_STATE_NO_DRAW);
- GPUShader *sh = inst_.shaders.static_shader_get(LIGHT_CULLING_SELECT);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, culling_select_ps_);
- DRW_shgroup_storage_block_ref(grp, "light_cull_buf", &culling_data_buf_);
- DRW_shgroup_storage_block(grp, "in_light_buf", light_buf_);
- DRW_shgroup_storage_block(grp, "out_light_buf", culling_light_buf_);
- DRW_shgroup_storage_block(grp, "out_zdist_buf", culling_zdist_buf_);
- DRW_shgroup_storage_block(grp, "out_key_buf", culling_key_buf_);
- DRW_shgroup_call_compute(grp, culling_select_dispatch_size, 1, 1);
- DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_STORAGE);
+ auto &sub = culling_ps_.sub("Select");
+ sub.shader_set(inst_.shaders.static_shader_get(LIGHT_CULLING_SELECT));
+ sub.bind_ssbo("light_cull_buf", &culling_data_buf_);
+ sub.bind_ssbo("in_light_buf", light_buf_);
+ sub.bind_ssbo("out_light_buf", culling_light_buf_);
+ sub.bind_ssbo("out_zdist_buf", culling_zdist_buf_);
+ sub.bind_ssbo("out_key_buf", culling_key_buf_);
+ sub.dispatch(int3(culling_select_dispatch_size, 1, 1));
+ sub.barrier(GPU_BARRIER_SHADER_STORAGE);
}
{
- DRW_PASS_CREATE(culling_sort_ps_, DRW_STATE_NO_DRAW);
- GPUShader *sh = inst_.shaders.static_shader_get(LIGHT_CULLING_SORT);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, culling_sort_ps_);
- DRW_shgroup_storage_block_ref(grp, "light_cull_buf", &culling_data_buf_);
- DRW_shgroup_storage_block(grp, "in_light_buf", light_buf_);
- DRW_shgroup_storage_block(grp, "out_light_buf", culling_light_buf_);
- DRW_shgroup_storage_block(grp, "in_zdist_buf", culling_zdist_buf_);
- DRW_shgroup_storage_block(grp, "in_key_buf", culling_key_buf_);
- DRW_shgroup_call_compute(grp, culling_sort_dispatch_size, 1, 1);
- DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_STORAGE);
+ auto &sub = culling_ps_.sub("Sort");
+ sub.shader_set(inst_.shaders.static_shader_get(LIGHT_CULLING_SORT));
+ sub.bind_ssbo("light_cull_buf", &culling_data_buf_);
+ sub.bind_ssbo("in_light_buf", light_buf_);
+ sub.bind_ssbo("out_light_buf", culling_light_buf_);
+ sub.bind_ssbo("in_zdist_buf", culling_zdist_buf_);
+ sub.bind_ssbo("in_key_buf", culling_key_buf_);
+ sub.dispatch(int3(culling_sort_dispatch_size, 1, 1));
+ sub.barrier(GPU_BARRIER_SHADER_STORAGE);
}
{
- DRW_PASS_CREATE(culling_zbin_ps_, DRW_STATE_NO_DRAW);
- GPUShader *sh = inst_.shaders.static_shader_get(LIGHT_CULLING_ZBIN);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, culling_zbin_ps_);
- DRW_shgroup_storage_block_ref(grp, "light_cull_buf", &culling_data_buf_);
- DRW_shgroup_storage_block(grp, "light_buf", culling_light_buf_);
- DRW_shgroup_storage_block(grp, "out_zbin_buf", culling_zbin_buf_);
- DRW_shgroup_call_compute(grp, 1, 1, 1);
- DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_STORAGE);
+ auto &sub = culling_ps_.sub("Zbin");
+ sub.shader_set(inst_.shaders.static_shader_get(LIGHT_CULLING_ZBIN));
+ sub.bind_ssbo("light_cull_buf", &culling_data_buf_);
+ sub.bind_ssbo("light_buf", culling_light_buf_);
+ sub.bind_ssbo("out_zbin_buf", culling_zbin_buf_);
+ sub.dispatch(int3(1, 1, 1));
+ sub.barrier(GPU_BARRIER_SHADER_STORAGE);
}
{
- DRW_PASS_CREATE(culling_tile_ps_, DRW_STATE_NO_DRAW);
- GPUShader *sh = inst_.shaders.static_shader_get(LIGHT_CULLING_TILE);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, culling_tile_ps_);
- DRW_shgroup_storage_block_ref(grp, "light_cull_buf", &culling_data_buf_);
- DRW_shgroup_storage_block(grp, "light_buf", culling_light_buf_);
- DRW_shgroup_storage_block(grp, "out_light_tile_buf", culling_tile_buf_);
- DRW_shgroup_call_compute(grp, culling_tile_dispatch_size, 1, 1);
- DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_STORAGE);
+ auto &sub = culling_ps_.sub("Tiles");
+ sub.shader_set(inst_.shaders.static_shader_get(LIGHT_CULLING_TILE));
+ sub.bind_ssbo("light_cull_buf", &culling_data_buf_);
+ sub.bind_ssbo("light_buf", culling_light_buf_);
+ sub.bind_ssbo("out_light_tile_buf", culling_tile_buf_);
+ sub.dispatch(int3(culling_tile_dispatch_size, 1, 1));
+ sub.barrier(GPU_BARRIER_SHADER_STORAGE);
}
}
void LightModule::debug_pass_sync()
{
- if (inst_.debug_mode != eDebugMode::DEBUG_LIGHT_CULLING) {
- debug_draw_ps_ = nullptr;
- return;
+ if (inst_.debug_mode == eDebugMode::DEBUG_LIGHT_CULLING) {
+ debug_draw_ps_.init();
+ debug_draw_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM);
+ debug_draw_ps_.shader_set(inst_.shaders.static_shader_get(LIGHT_CULLING_DEBUG));
+ inst_.hiz_buffer.bind_resources(&debug_draw_ps_);
+ debug_draw_ps_.bind_ssbo("light_buf", &culling_light_buf_);
+ debug_draw_ps_.bind_ssbo("light_cull_buf", &culling_data_buf_);
+ debug_draw_ps_.bind_ssbo("light_zbin_buf", &culling_zbin_buf_);
+ debug_draw_ps_.bind_ssbo("light_tile_buf", &culling_tile_buf_);
+ debug_draw_ps_.bind_texture("depth_tx", &inst_.render_buffers.depth_tx);
+ debug_draw_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}
-
- debug_draw_ps_ = DRW_pass_create("LightCulling.Debug", DRW_STATE_WRITE_COLOR);
- GPUShader *sh = inst_.shaders.static_shader_get(LIGHT_CULLING_DEBUG);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, debug_draw_ps_);
- DRW_shgroup_storage_block_ref(grp, "light_buf", &culling_light_buf_);
- DRW_shgroup_storage_block_ref(grp, "light_cull_buf", &culling_data_buf_);
- DRW_shgroup_storage_block_ref(grp, "light_zbin_buf", &culling_zbin_buf_);
- DRW_shgroup_storage_block_ref(grp, "light_tile_buf", &culling_tile_buf_);
- DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &inst_.render_buffers.depth_tx);
- DRW_shgroup_call_procedural_triangles(grp, nullptr, 1);
}
-void LightModule::set_view(const DRWView *view, const int2 extent)
+void LightModule::set_view(View &view, const int2 extent)
{
- float far_z = DRW_view_far_distance_get(view);
- float near_z = DRW_view_near_distance_get(view);
+ float far_z = view.far_clip();
+ float near_z = view.near_clip();
culling_data_buf_.zbin_scale = -CULLING_ZBIN_COUNT / fabsf(far_z - near_z);
culling_data_buf_.zbin_bias = -near_z * culling_data_buf_.zbin_scale;
@@ -474,24 +470,17 @@ void LightModule::set_view(const DRWView *view, const int2 extent)
culling_data_buf_.visible_count = 0;
culling_data_buf_.push_update();
- DRW_stats_group_start("Light Culling");
-
- DRW_view_set_active(view);
- DRW_draw_pass(culling_select_ps_);
- DRW_draw_pass(culling_sort_ps_);
- DRW_draw_pass(culling_zbin_ps_);
- DRW_draw_pass(culling_tile_ps_);
-
- DRW_stats_group_end();
+ inst_.manager->submit(culling_ps_, view);
}
-void LightModule::debug_draw(GPUFrameBuffer *view_fb)
+void LightModule::debug_draw(View &view, GPUFrameBuffer *view_fb)
{
- if (debug_draw_ps_ == nullptr) {
- return;
+ if (inst_.debug_mode == eDebugMode::DEBUG_LIGHT_CULLING) {
+ inst_.info = "Debug Mode: Light Culling Validation";
+ inst_.hiz_buffer.update();
+ GPU_framebuffer_bind(view_fb);
+ inst_.manager->submit(debug_draw_ps_, view);
}
- GPU_framebuffer_bind(view_fb);
- DRW_draw_pass(debug_draw_ps_);
}
/** \} */
diff --git a/source/blender/draw/engines/eevee_next/eevee_light.hh b/source/blender/draw/engines/eevee_next/eevee_light.hh
index c2d7aad34ae..9bacc180ea8 100644
--- a/source/blender/draw/engines/eevee_next/eevee_light.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_light.hh
@@ -116,16 +116,12 @@ class LightModule {
/** Bitmap of lights touching each tiles. */
LightCullingTileBuf culling_tile_buf_ = {"LightCull_tile"};
/** Culling compute passes. */
- DRWPass *culling_select_ps_ = nullptr;
- DRWPass *culling_sort_ps_ = nullptr;
- DRWPass *culling_zbin_ps_ = nullptr;
- DRWPass *culling_tile_ps_ = nullptr;
+ PassSimple culling_ps_ = {"LightCulling"};
/** Total number of words the tile buffer needs to contain for the render resolution. */
uint total_word_count_ = 0;
/** Debug Culling visualization. */
- DRWPass *debug_draw_ps_ = nullptr;
- GPUTexture *input_depth_tx_ = nullptr;
+ PassSimple debug_draw_ps_ = {"LightCulling.Debug"};
public:
LightModule(Instance &inst) : inst_(inst){};
@@ -138,9 +134,9 @@ class LightModule {
/**
* Update acceleration structure for the given view.
*/
- void set_view(const DRWView *view, const int2 extent);
+ void set_view(View &view, const int2 extent);
- void debug_draw(GPUFrameBuffer *view_fb);
+ void debug_draw(View &view, GPUFrameBuffer *view_fb);
void bind_resources(DRWShadingGroup *grp)
{
@@ -154,6 +150,15 @@ class LightModule {
#endif
}
+ template<typename T> void bind_resources(draw::detail::PassBase<T> *pass)
+ {
+ /* Storage Buf. */
+ pass->bind_ssbo(LIGHT_CULL_BUF_SLOT, &culling_data_buf_);
+ pass->bind_ssbo(LIGHT_BUF_SLOT, &culling_light_buf_);
+ pass->bind_ssbo(LIGHT_ZBIN_BUF_SLOT, &culling_zbin_buf_);
+ pass->bind_ssbo(LIGHT_TILE_BUF_SLOT, &culling_tile_buf_);
+ }
+
private:
void culling_pass_sync();
void debug_pass_sync();
diff --git a/source/blender/draw/engines/eevee_next/eevee_material.cc b/source/blender/draw/engines/eevee_next/eevee_material.cc
index b3161a67092..a92f96e8c70 100644
--- a/source/blender/draw/engines/eevee_next/eevee_material.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_material.cc
@@ -72,10 +72,9 @@ bNodeTree *DefaultSurfaceNodeTree::nodetree_get(::Material *ma)
MaterialModule::MaterialModule(Instance &inst) : inst_(inst)
{
{
- bNodeTree *ntree = ntreeAddTree(nullptr, "Shader Nodetree", ntreeType_Shader->idname);
-
diffuse_mat = (::Material *)BKE_id_new_nomain(ID_MA, "EEVEE default diffuse");
- diffuse_mat->nodetree = ntree;
+ bNodeTree *ntree = ntreeAddTreeEmbedded(
+ nullptr, &diffuse_mat->id, "Shader Nodetree", ntreeType_Shader->idname);
diffuse_mat->use_nodes = true;
/* To use the forward pipeline. */
diffuse_mat->blend_method = MA_BM_BLEND;
@@ -95,10 +94,9 @@ MaterialModule::MaterialModule(Instance &inst) : inst_(inst)
nodeSetActive(ntree, output);
}
{
- bNodeTree *ntree = ntreeAddTree(nullptr, "Shader Nodetree", ntreeType_Shader->idname);
-
glossy_mat = (::Material *)BKE_id_new_nomain(ID_MA, "EEVEE default metal");
- glossy_mat->nodetree = ntree;
+ bNodeTree *ntree = ntreeAddTreeEmbedded(
+ nullptr, &glossy_mat->id, "Shader Nodetree", ntreeType_Shader->idname);
glossy_mat->use_nodes = true;
/* To use the forward pipeline. */
glossy_mat->blend_method = MA_BM_BLEND;
@@ -120,10 +118,9 @@ MaterialModule::MaterialModule(Instance &inst) : inst_(inst)
nodeSetActive(ntree, output);
}
{
- bNodeTree *ntree = ntreeAddTree(nullptr, "Shader Nodetree", ntreeType_Shader->idname);
-
error_mat_ = (::Material *)BKE_id_new_nomain(ID_MA, "EEVEE default error");
- error_mat_->nodetree = ntree;
+ bNodeTree *ntree = ntreeAddTreeEmbedded(
+ nullptr, &error_mat_->id, "Shader Nodetree", ntreeType_Shader->idname);
error_mat_->use_nodes = true;
/* Use emission and output material to be compatible with both World and Material. */
@@ -145,9 +142,6 @@ MaterialModule::MaterialModule(Instance &inst) : inst_(inst)
MaterialModule::~MaterialModule()
{
- for (Material *mat : material_map_.values()) {
- delete mat;
- }
BKE_id_free(nullptr, glossy_mat);
BKE_id_free(nullptr, diffuse_mat);
BKE_id_free(nullptr, error_mat_);
@@ -157,13 +151,12 @@ void MaterialModule::begin_sync()
{
queued_shaders_count = 0;
- for (Material *mat : material_map_.values()) {
- mat->init = false;
- }
+ material_map_.clear();
shader_map_.clear();
}
-MaterialPass MaterialModule::material_pass_get(::Material *blender_mat,
+MaterialPass MaterialModule::material_pass_get(Object *ob,
+ ::Material *blender_mat,
eMaterialPipeline pipeline_type,
eMaterialGeometry geometry_type)
{
@@ -203,35 +196,34 @@ MaterialPass MaterialModule::material_pass_get(::Material *blender_mat,
pipeline_type = MAT_PIPE_FORWARD;
}
- if ((pipeline_type == MAT_PIPE_FORWARD) &&
+ if (ELEM(pipeline_type,
+ MAT_PIPE_FORWARD,
+ MAT_PIPE_FORWARD_PREPASS,
+ MAT_PIPE_FORWARD_PREPASS_VELOCITY) &&
GPU_material_flag_get(matpass.gpumat, GPU_MATFLAG_TRANSPARENT)) {
- /* Transparent needs to use one shgroup per object to support reordering. */
- matpass.shgrp = inst_.pipelines.material_add(blender_mat, matpass.gpumat, pipeline_type);
+ /* Transparent pass is generated later. */
+ matpass.sub_pass = nullptr;
}
else {
ShaderKey shader_key(matpass.gpumat, geometry_type, pipeline_type);
- auto add_cb = [&]() -> DRWShadingGroup * {
- /* First time encountering this shader. Create a shading group. */
- return inst_.pipelines.material_add(blender_mat, matpass.gpumat, pipeline_type);
- };
- DRWShadingGroup *grp = shader_map_.lookup_or_add_cb(shader_key, add_cb);
-
- if (grp != nullptr) {
- /* Shading group for this shader already exists. Create a sub one for this material. */
- /* IMPORTANT: We always create a subgroup so that all subgroups are inserted after the
- * first "empty" shgroup. This avoids messing the order of subgroups when there is more
- * nested subgroup (i.e: hair drawing). */
- /* TODO(@fclem): Remove material resource binding from the first group creation. */
- matpass.shgrp = DRW_shgroup_create_sub(grp);
- DRW_shgroup_add_material_resources(matpass.shgrp, matpass.gpumat);
+ PassMain::Sub *shader_sub = shader_map_.lookup_or_add_cb(shader_key, [&]() {
+ /* First time encountering this shader. Create a sub that will contain materials using it. */
+ return inst_.pipelines.material_add(ob, blender_mat, matpass.gpumat, pipeline_type);
+ });
+
+ if (shader_sub != nullptr) {
+ /* Create a sub for this material as `shader_sub` is for sharing shader between materials. */
+ matpass.sub_pass = &shader_sub->sub(GPU_material_get_name(matpass.gpumat));
+ matpass.sub_pass->material_set(*inst_.manager, matpass.gpumat);
}
}
return matpass;
}
-Material &MaterialModule::material_sync(::Material *blender_mat,
+Material &MaterialModule::material_sync(Object *ob,
+ ::Material *blender_mat,
eMaterialGeometry geometry_type,
bool has_motion)
{
@@ -249,27 +241,32 @@ Material &MaterialModule::material_sync(::Material *blender_mat,
MaterialKey material_key(blender_mat, geometry_type, surface_pipe);
- /* TODO: allocate in blocks to avoid memory fragmentation. */
- auto add_cb = [&]() { return new Material(); };
- Material &mat = *material_map_.lookup_or_add_cb(material_key, add_cb);
-
- /* Forward pipeline needs to use one shgroup per object. */
- if (mat.init == false || (surface_pipe == MAT_PIPE_FORWARD)) {
- mat.init = true;
+ Material &mat = material_map_.lookup_or_add_cb(material_key, [&]() {
+ Material mat;
/* Order is important for transparent. */
- mat.prepass = material_pass_get(blender_mat, prepass_pipe, geometry_type);
- mat.shading = material_pass_get(blender_mat, surface_pipe, geometry_type);
+ mat.prepass = material_pass_get(ob, blender_mat, prepass_pipe, geometry_type);
+ mat.shading = material_pass_get(ob, blender_mat, surface_pipe, geometry_type);
if (blender_mat->blend_shadow == MA_BS_NONE) {
mat.shadow = MaterialPass();
}
else {
- mat.shadow = material_pass_get(blender_mat, MAT_PIPE_SHADOW, geometry_type);
+ mat.shadow = material_pass_get(ob, blender_mat, MAT_PIPE_SHADOW, geometry_type);
}
-
mat.is_alpha_blend_transparent = (blender_mat->blend_method == MA_BM_BLEND) &&
- GPU_material_flag_get(mat.prepass.gpumat,
+ GPU_material_flag_get(mat.shading.gpumat,
GPU_MATFLAG_TRANSPARENT);
+ return mat;
+ });
+
+ if (mat.is_alpha_blend_transparent) {
+ /* Transparent needs to use one sub pass per object to support reordering.
+ * NOTE: Pre-pass needs to be created first in order to be sorted first. */
+ mat.prepass.sub_pass = inst_.pipelines.forward.prepass_transparent_add(
+ ob, blender_mat, mat.shading.gpumat);
+ mat.shading.sub_pass = inst_.pipelines.forward.material_transparent_add(
+ ob, blender_mat, mat.shading.gpumat);
}
+
return mat;
}
@@ -297,7 +294,7 @@ MaterialArray &MaterialModule::material_array_get(Object *ob, bool has_motion)
for (auto i : IndexRange(materials_len)) {
::Material *blender_mat = material_from_slot(ob, i);
- Material &mat = material_sync(blender_mat, to_material_geometry(ob), has_motion);
+ Material &mat = material_sync(ob, blender_mat, to_material_geometry(ob), has_motion);
material_array_.materials.append(&mat);
material_array_.gpu_materials.append(mat.shading.gpumat);
}
@@ -310,7 +307,7 @@ Material &MaterialModule::material_get(Object *ob,
eMaterialGeometry geometry_type)
{
::Material *blender_mat = material_from_slot(ob, mat_nr);
- Material &mat = material_sync(blender_mat, geometry_type, has_motion);
+ Material &mat = material_sync(ob, blender_mat, geometry_type, has_motion);
return mat;
}
diff --git a/source/blender/draw/engines/eevee_next/eevee_material.hh b/source/blender/draw/engines/eevee_next/eevee_material.hh
index 23165a741b9..ad0c293926b 100644
--- a/source/blender/draw/engines/eevee_next/eevee_material.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_material.hh
@@ -203,12 +203,11 @@ class DefaultSurfaceNodeTree {
* \{ */
struct MaterialPass {
- GPUMaterial *gpumat = nullptr;
- DRWShadingGroup *shgrp = nullptr;
+ GPUMaterial *gpumat;
+ PassMain::Sub *sub_pass;
};
struct Material {
- bool init = false;
bool is_alpha_blend_transparent;
MaterialPass shadow, shading, prepass;
};
@@ -228,8 +227,8 @@ class MaterialModule {
private:
Instance &inst_;
- Map<MaterialKey, Material *> material_map_;
- Map<ShaderKey, DRWShadingGroup *> shader_map_;
+ Map<MaterialKey, Material> material_map_;
+ Map<ShaderKey, PassMain::Sub *> shader_map_;
MaterialArray material_array_;
@@ -254,13 +253,15 @@ class MaterialModule {
Material &material_get(Object *ob, bool has_motion, int mat_nr, eMaterialGeometry geometry_type);
private:
- Material &material_sync(::Material *blender_mat,
+ Material &material_sync(Object *ob,
+ ::Material *blender_mat,
eMaterialGeometry geometry_type,
bool has_motion);
/** Return correct material or empty default material if slot is empty. */
::Material *material_from_slot(Object *ob, int slot);
- MaterialPass material_pass_get(::Material *blender_mat,
+ MaterialPass material_pass_get(Object *ob,
+ ::Material *blender_mat,
eMaterialPipeline pipeline_type,
eMaterialGeometry geometry_type);
};
diff --git a/source/blender/draw/engines/eevee_next/eevee_motion_blur.cc b/source/blender/draw/engines/eevee_next/eevee_motion_blur.cc
index 660eb9f1e22..f68abafa3d4 100644
--- a/source/blender/draw/engines/eevee_next/eevee_motion_blur.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_motion_blur.cc
@@ -135,53 +135,49 @@ void MotionBlurModule::sync()
eGPUSamplerState no_filter = GPU_SAMPLER_DEFAULT;
RenderBuffers &render_buffers = inst_.render_buffers;
+ motion_blur_ps_.init();
+ inst_.velocity.bind_resources(&motion_blur_ps_);
+ inst_.sampling.bind_resources(&motion_blur_ps_);
{
/* Create max velocity tiles. */
- DRW_PASS_CREATE(tiles_flatten_ps_, DRW_STATE_NO_DRAW);
+ PassSimple::Sub &sub = motion_blur_ps_.sub("TilesFlatten");
eShaderType shader = (inst_.is_viewport()) ? MOTION_BLUR_TILE_FLATTEN_VIEWPORT :
MOTION_BLUR_TILE_FLATTEN_RENDER;
- GPUShader *sh = inst_.shaders.static_shader_get(shader);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, tiles_flatten_ps_);
- inst_.velocity.bind_resources(grp);
- DRW_shgroup_uniform_block(grp, "motion_blur_buf", data_);
- DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &render_buffers.depth_tx);
- DRW_shgroup_uniform_image_ref(grp, "velocity_img", &render_buffers.vector_tx);
- DRW_shgroup_uniform_image_ref(grp, "out_tiles_img", &tiles_tx_);
-
- DRW_shgroup_call_compute_ref(grp, dispatch_flatten_size_);
- DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_IMAGE_ACCESS | GPU_BARRIER_TEXTURE_FETCH);
+ sub.shader_set(inst_.shaders.static_shader_get(shader));
+ sub.bind_ubo("motion_blur_buf", data_);
+ sub.bind_texture("depth_tx", &render_buffers.depth_tx);
+ sub.bind_image("velocity_img", &render_buffers.vector_tx);
+ sub.bind_image("out_tiles_img", &tiles_tx_);
+ sub.dispatch(&dispatch_flatten_size_);
+ sub.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS | GPU_BARRIER_TEXTURE_FETCH);
}
{
/* Expand max velocity tiles by spreading them in their neighborhood. */
- DRW_PASS_CREATE(tiles_dilate_ps_, DRW_STATE_NO_DRAW);
- GPUShader *sh = inst_.shaders.static_shader_get(MOTION_BLUR_TILE_DILATE);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, tiles_dilate_ps_);
- DRW_shgroup_storage_block(grp, "tile_indirection_buf", tile_indirection_buf_);
- DRW_shgroup_uniform_image_ref(grp, "in_tiles_img", &tiles_tx_);
-
- DRW_shgroup_call_compute_ref(grp, dispatch_dilate_size_);
- DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_STORAGE);
+ PassSimple::Sub &sub = motion_blur_ps_.sub("TilesDilate");
+ sub.shader_set(inst_.shaders.static_shader_get(MOTION_BLUR_TILE_DILATE));
+ sub.bind_ssbo("tile_indirection_buf", tile_indirection_buf_);
+ sub.bind_image("in_tiles_img", &tiles_tx_);
+ sub.dispatch(&dispatch_dilate_size_);
+ sub.barrier(GPU_BARRIER_SHADER_STORAGE);
}
{
/* Do the motion blur gather algorithm. */
- DRW_PASS_CREATE(gather_ps_, DRW_STATE_NO_DRAW);
- GPUShader *sh = inst_.shaders.static_shader_get(MOTION_BLUR_GATHER);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, gather_ps_);
- inst_.sampling.bind_resources(grp);
- DRW_shgroup_uniform_block(grp, "motion_blur_buf", data_);
- DRW_shgroup_storage_block(grp, "tile_indirection_buf", tile_indirection_buf_);
- DRW_shgroup_uniform_texture_ref_ex(grp, "depth_tx", &render_buffers.depth_tx, no_filter);
- DRW_shgroup_uniform_texture_ref_ex(grp, "velocity_tx", &render_buffers.vector_tx, no_filter);
- DRW_shgroup_uniform_texture_ref_ex(grp, "in_color_tx", &input_color_tx_, no_filter);
- DRW_shgroup_uniform_image_ref(grp, "in_tiles_img", &tiles_tx_);
- DRW_shgroup_uniform_image_ref(grp, "out_color_img", &output_color_tx_);
-
- DRW_shgroup_call_compute_ref(grp, dispatch_gather_size_);
- DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH);
+ PassSimple::Sub &sub = motion_blur_ps_.sub("ConvolveGather");
+ sub.shader_set(inst_.shaders.static_shader_get(MOTION_BLUR_GATHER));
+ sub.bind_ubo("motion_blur_buf", data_);
+ sub.bind_ssbo("tile_indirection_buf", tile_indirection_buf_);
+ sub.bind_texture("depth_tx", &render_buffers.depth_tx, no_filter);
+ sub.bind_texture("velocity_tx", &render_buffers.vector_tx, no_filter);
+ sub.bind_texture("in_color_tx", &input_color_tx_, no_filter);
+ sub.bind_image("in_tiles_img", &tiles_tx_);
+ sub.bind_image("out_color_img", &output_color_tx_);
+
+ sub.dispatch(&dispatch_gather_size_);
+ sub.barrier(GPU_BARRIER_TEXTURE_FETCH);
}
}
-void MotionBlurModule::render(GPUTexture **input_tx, GPUTexture **output_tx)
+void MotionBlurModule::render(View &view, GPUTexture **input_tx, GPUTexture **output_tx)
{
if (!motion_blur_fx_enabled_) {
return;
@@ -239,9 +235,7 @@ void MotionBlurModule::render(GPUTexture **input_tx, GPUTexture **output_tx)
GPU_storagebuf_clear_to_zero(tile_indirection_buf_);
- DRW_draw_pass(tiles_flatten_ps_);
- DRW_draw_pass(tiles_dilate_ps_);
- DRW_draw_pass(gather_ps_);
+ inst_.manager->submit(motion_blur_ps_, view);
tiles_tx_.release();
@@ -259,4 +253,4 @@ void MotionBlurModule::render(GPUTexture **input_tx, GPUTexture **output_tx)
/** \} */
-} // namespace blender::eevee \ No newline at end of file
+} // namespace blender::eevee
diff --git a/source/blender/draw/engines/eevee_next/eevee_motion_blur.hh b/source/blender/draw/engines/eevee_next/eevee_motion_blur.hh
index 310e94a702b..056c2e323d5 100644
--- a/source/blender/draw/engines/eevee_next/eevee_motion_blur.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_motion_blur.hh
@@ -95,9 +95,7 @@ class MotionBlurModule {
GPUTexture *input_color_tx_ = nullptr;
GPUTexture *output_color_tx_ = nullptr;
- DRWPass *tiles_flatten_ps_ = nullptr;
- DRWPass *tiles_dilate_ps_ = nullptr;
- DRWPass *gather_ps_ = nullptr;
+ PassSimple motion_blur_ps_ = {"MotionBlur"};
MotionBlurTileIndirectionBuf tile_indirection_buf_;
MotionBlurDataBuf data_;
@@ -121,7 +119,7 @@ class MotionBlurModule {
return motion_blur_fx_enabled_;
}
- void render(GPUTexture **input_tx, GPUTexture **output_tx);
+ void render(View &view, GPUTexture **input_tx, GPUTexture **output_tx);
private:
float shutter_time_to_scene_time(float time);
diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc
index 9185ce7904a..33978518ffc 100644
--- a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc
@@ -24,37 +24,36 @@ namespace blender::eevee {
void WorldPipeline::sync(GPUMaterial *gpumat)
{
+ Manager &manager = *inst_.manager;
RenderBuffers &rbufs = inst_.render_buffers;
- DRWState state = DRW_STATE_WRITE_COLOR;
- world_ps_ = DRW_pass_create("World", state);
+ ResourceHandle handle = manager.resource_handle(float4x4::identity().ptr());
- /* Push a matrix at the same location as the camera. */
- float4x4 camera_mat = float4x4::identity();
- // copy_v3_v3(camera_mat[3], inst_.camera.data_get().viewinv[3]);
-
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, world_ps_);
- DRW_shgroup_uniform_texture(grp, "utility_tx", inst_.pipelines.utility_tx);
- DRW_shgroup_call_obmat(grp, DRW_cache_fullscreen_quad_get(), camera_mat.ptr());
- DRW_shgroup_uniform_float_copy(grp, "world_opacity_fade", inst_.film.background_opacity_get());
+ world_ps_.init();
+ world_ps_.state_set(DRW_STATE_WRITE_COLOR);
+ world_ps_.material_set(manager, gpumat);
+ world_ps_.push_constant("world_opacity_fade", inst_.film.background_opacity_get());
+ world_ps_.bind_texture("utility_tx", inst_.pipelines.utility_tx);
/* AOVs. */
- DRW_shgroup_uniform_image_ref(grp, "aov_color_img", &rbufs.aov_color_tx);
- DRW_shgroup_uniform_image_ref(grp, "aov_value_img", &rbufs.aov_value_tx);
- DRW_shgroup_storage_block_ref(grp, "aov_buf", &inst_.film.aovs_info);
+ world_ps_.bind_image("aov_color_img", &rbufs.aov_color_tx);
+ world_ps_.bind_image("aov_value_img", &rbufs.aov_value_tx);
+ world_ps_.bind_ssbo("aov_buf", &inst_.film.aovs_info);
/* RenderPasses. Cleared by background (even if bad practice). */
- DRW_shgroup_uniform_image_ref(grp, "rp_normal_img", &rbufs.normal_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_diffuse_light_img", &rbufs.diffuse_light_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_diffuse_color_img", &rbufs.diffuse_color_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_specular_light_img", &rbufs.specular_light_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_specular_color_img", &rbufs.specular_color_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_emission_img", &rbufs.emission_tx);
+ world_ps_.bind_image("rp_normal_img", &rbufs.normal_tx);
+ world_ps_.bind_image("rp_light_img", &rbufs.light_tx);
+ world_ps_.bind_image("rp_diffuse_color_img", &rbufs.diffuse_color_tx);
+ world_ps_.bind_image("rp_specular_color_img", &rbufs.specular_color_tx);
+ world_ps_.bind_image("rp_emission_img", &rbufs.emission_tx);
+ world_ps_.bind_image("rp_cryptomatte_img", &rbufs.cryptomatte_tx);
+
+ world_ps_.draw(DRW_cache_fullscreen_quad_get(), handle);
/* To allow opaque pass rendering over it. */
- DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_IMAGE_ACCESS);
+ world_ps_.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
}
-void WorldPipeline::render()
+void WorldPipeline::render(View &view)
{
- DRW_draw_pass(world_ps_);
+ inst_.manager->submit(world_ps_, view);
}
/** \} */
@@ -67,216 +66,167 @@ void WorldPipeline::render()
void ForwardPipeline::sync()
{
+ camera_forward_ = inst_.camera.forward();
+
+ DRWState state_depth_only = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ DRWState state_depth_color = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS |
+ DRW_STATE_WRITE_COLOR;
{
- DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
- prepass_ps_ = DRW_pass_create("Forward.Opaque.Prepass", state);
- prepass_velocity_ps_ = DRW_pass_create("Forward.Opaque.Prepass.Velocity",
- state | DRW_STATE_WRITE_COLOR);
+ prepass_ps_.init();
- state |= DRW_STATE_CULL_BACK;
- prepass_culled_ps_ = DRW_pass_create("Forward.Opaque.Prepass.Culled", state);
- prepass_culled_velocity_ps_ = DRW_pass_create("Forward.Opaque.Prepass.Velocity",
- state | DRW_STATE_WRITE_COLOR);
+ {
+ /* Common resources. */
- DRW_pass_link(prepass_ps_, prepass_velocity_ps_);
- DRW_pass_link(prepass_velocity_ps_, prepass_culled_ps_);
- DRW_pass_link(prepass_culled_ps_, prepass_culled_velocity_ps_);
- }
- {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL;
- opaque_ps_ = DRW_pass_create("Forward.Opaque", state);
+ /* Textures. */
+ prepass_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
- state |= DRW_STATE_CULL_BACK;
- opaque_culled_ps_ = DRW_pass_create("Forward.Opaque.Culled", state);
+ inst_.velocity.bind_resources(&prepass_ps_);
+ inst_.sampling.bind_resources(&prepass_ps_);
+ }
+
+ prepass_double_sided_static_ps_ = &prepass_ps_.sub("DoubleSided.Static");
+ prepass_double_sided_static_ps_->state_set(state_depth_only);
+
+ prepass_single_sided_static_ps_ = &prepass_ps_.sub("SingleSided.Static");
+ prepass_single_sided_static_ps_->state_set(state_depth_only | DRW_STATE_CULL_BACK);
- DRW_pass_link(opaque_ps_, opaque_culled_ps_);
+ prepass_double_sided_moving_ps_ = &prepass_ps_.sub("DoubleSided.Moving");
+ prepass_double_sided_moving_ps_->state_set(state_depth_color);
+
+ prepass_single_sided_moving_ps_ = &prepass_ps_.sub("SingleSided.Moving");
+ prepass_single_sided_moving_ps_->state_set(state_depth_color | DRW_STATE_CULL_BACK);
}
{
- DRWState state = DRW_STATE_DEPTH_LESS_EQUAL;
- transparent_ps_ = DRW_pass_create("Forward.Transparent", state);
+ opaque_ps_.init();
+
+ {
+ /* Common resources. */
+
+ /* RenderPasses. */
+ opaque_ps_.bind_image(RBUFS_NORMAL_SLOT, &inst_.render_buffers.normal_tx);
+ opaque_ps_.bind_image(RBUFS_LIGHT_SLOT, &inst_.render_buffers.light_tx);
+ opaque_ps_.bind_image(RBUFS_DIFF_COLOR_SLOT, &inst_.render_buffers.diffuse_color_tx);
+ opaque_ps_.bind_image(RBUFS_SPEC_COLOR_SLOT, &inst_.render_buffers.specular_color_tx);
+ opaque_ps_.bind_image(RBUFS_EMISSION_SLOT, &inst_.render_buffers.emission_tx);
+ /* AOVs. */
+ opaque_ps_.bind_image(RBUFS_AOV_COLOR_SLOT, &inst_.render_buffers.aov_color_tx);
+ opaque_ps_.bind_image(RBUFS_AOV_VALUE_SLOT, &inst_.render_buffers.aov_value_tx);
+ /* Cryptomatte. */
+ opaque_ps_.bind_image(RBUFS_CRYPTOMATTE_SLOT, &inst_.render_buffers.cryptomatte_tx);
+ /* Storage Buf. */
+ opaque_ps_.bind_ssbo(RBUFS_AOV_BUF_SLOT, &inst_.film.aovs_info);
+ /* Textures. */
+ opaque_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
+
+ inst_.lights.bind_resources(&opaque_ps_);
+ inst_.sampling.bind_resources(&opaque_ps_);
+ inst_.cryptomatte.bind_resources(&opaque_ps_);
+ }
+
+ opaque_single_sided_ps_ = &opaque_ps_.sub("SingleSided");
+ opaque_single_sided_ps_->state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL |
+ DRW_STATE_CULL_BACK);
+
+ opaque_double_sided_ps_ = &opaque_ps_.sub("DoubleSided");
+ opaque_double_sided_ps_->state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
}
-}
+ {
+ transparent_ps_.init();
+ /* Workaround limitation of PassSortable. Use dummy pass that will be sorted first in all
+ * circumstances. */
+ PassMain::Sub &sub = transparent_ps_.sub("ResourceBind", -FLT_MAX);
-DRWShadingGroup *ForwardPipeline::material_opaque_add(::Material *blender_mat, GPUMaterial *gpumat)
-{
- RenderBuffers &rbufs = inst_.render_buffers;
- DRWPass *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ? opaque_culled_ps_ : opaque_ps_;
- LightModule &lights = inst_.lights;
- Sampling &sampling = inst_.sampling;
- // LightProbeModule &lightprobes = inst_.lightprobes;
- // RaytracingModule &raytracing = inst_.raytracing;
- // eGPUSamplerState no_interp = GPU_SAMPLER_DEFAULT;
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, pass);
- lights.bind_resources(grp);
- sampling.bind_resources(grp);
- // DRW_shgroup_uniform_block(grp, "sampling_buf", inst_.sampling.ubo_get());
- // DRW_shgroup_uniform_block(grp, "grids_buf", lightprobes.grid_ubo_get());
- // DRW_shgroup_uniform_block(grp, "cubes_buf", lightprobes.cube_ubo_get());
- // DRW_shgroup_uniform_block(grp, "probes_buf", lightprobes.info_ubo_get());
- // DRW_shgroup_uniform_texture_ref(grp, "lightprobe_grid_tx", lightprobes.grid_tx_ref_get());
- // DRW_shgroup_uniform_texture_ref(grp, "lightprobe_cube_tx", lightprobes.cube_tx_ref_get());
- DRW_shgroup_uniform_texture(grp, "utility_tx", inst_.pipelines.utility_tx);
- /* AOVs. */
- DRW_shgroup_uniform_image_ref(grp, "aov_color_img", &rbufs.aov_color_tx);
- DRW_shgroup_uniform_image_ref(grp, "aov_value_img", &rbufs.aov_value_tx);
- DRW_shgroup_storage_block_ref(grp, "aov_buf", &inst_.film.aovs_info);
- /* RenderPasses. */
- DRW_shgroup_uniform_image_ref(grp, "rp_normal_img", &rbufs.normal_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_diffuse_light_img", &rbufs.diffuse_light_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_diffuse_color_img", &rbufs.diffuse_color_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_specular_light_img", &rbufs.specular_light_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_specular_color_img", &rbufs.specular_color_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_emission_img", &rbufs.emission_tx);
-
- /* TODO(fclem): Make this only needed if material uses it ... somehow. */
- // if (true) {
- // DRW_shgroup_uniform_texture_ref(
- // grp, "sss_transmittance_tx", inst_.subsurface.transmittance_ref_get());
- // }
- // if (raytracing.enabled()) {
- // DRW_shgroup_uniform_block(grp, "rt_diffuse_buf", raytracing.diffuse_data);
- // DRW_shgroup_uniform_block(grp, "rt_reflection_buf", raytracing.reflection_data);
- // DRW_shgroup_uniform_block(grp, "rt_refraction_buf", raytracing.refraction_data);
- // DRW_shgroup_uniform_texture_ref_ex(grp, "radiance_tx", &input_screen_radiance_tx_,
- // no_interp);
- // }
- // if (raytracing.enabled()) {
- // DRW_shgroup_uniform_block(grp, "hiz_buf", inst_.hiz.ubo_get());
- // DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", inst_.hiz_front.texture_ref_get());
- // }
- return grp;
-}
+ /* Common resources. */
-DRWShadingGroup *ForwardPipeline::prepass_opaque_add(::Material *blender_mat,
- GPUMaterial *gpumat,
- bool has_motion)
-{
- DRWPass *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ?
- (has_motion ? prepass_culled_velocity_ps_ : prepass_culled_ps_) :
- (has_motion ? prepass_velocity_ps_ : prepass_ps_);
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, pass);
- if (has_motion) {
- inst_.velocity.bind_resources(grp);
+ /* Textures. */
+ sub.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
+
+ inst_.lights.bind_resources(&sub);
+ inst_.sampling.bind_resources(&sub);
}
- return grp;
}
-DRWShadingGroup *ForwardPipeline::material_transparent_add(::Material *blender_mat,
- GPUMaterial *gpumat)
+PassMain::Sub *ForwardPipeline::prepass_opaque_add(::Material *blender_mat,
+ GPUMaterial *gpumat,
+ bool has_motion)
{
- RenderBuffers &rbufs = inst_.render_buffers;
- LightModule &lights = inst_.lights;
- Sampling &sampling = inst_.sampling;
- // LightProbeModule &lightprobes = inst_.lightprobes;
- // RaytracingModule &raytracing = inst_.raytracing;
- // eGPUSamplerState no_interp = GPU_SAMPLER_DEFAULT;
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, transparent_ps_);
- lights.bind_resources(grp);
- sampling.bind_resources(grp);
- // DRW_shgroup_uniform_block(grp, "sampling_buf", inst_.sampling.ubo_get());
- // DRW_shgroup_uniform_block(grp, "grids_buf", lightprobes.grid_ubo_get());
- // DRW_shgroup_uniform_block(grp, "cubes_buf", lightprobes.cube_ubo_get());
- // DRW_shgroup_uniform_block(grp, "probes_buf", lightprobes.info_ubo_get());
- // DRW_shgroup_uniform_texture_ref(grp, "lightprobe_grid_tx", lightprobes.grid_tx_ref_get());
- // DRW_shgroup_uniform_texture_ref(grp, "lightprobe_cube_tx", lightprobes.cube_tx_ref_get());
- DRW_shgroup_uniform_texture(grp, "utility_tx", inst_.pipelines.utility_tx);
- /* TODO(fclem): Make this only needed if material uses it ... somehow. */
- // if (true) {
- // DRW_shgroup_uniform_texture_ref(
- // grp, "sss_transmittance_tx", inst_.subsurface.transmittance_ref_get());
- // }
- // if (raytracing.enabled()) {
- // DRW_shgroup_uniform_block(grp, "rt_diffuse_buf", raytracing.diffuse_data);
- // DRW_shgroup_uniform_block(grp, "rt_reflection_buf", raytracing.reflection_data);
- // DRW_shgroup_uniform_block(grp, "rt_refraction_buf", raytracing.refraction_data);
- // DRW_shgroup_uniform_texture_ref_ex(
- // grp, "rt_radiance_tx", &input_screen_radiance_tx_, no_interp);
- // }
- // if (raytracing.enabled()) {
- // DRW_shgroup_uniform_block(grp, "hiz_buf", inst_.hiz.ubo_get());
- // DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", inst_.hiz_front.texture_ref_get());
- // }
- {
- /* TODO(fclem): This is not needed. This is only to please the OpenGL debug Layer.
- * If we are to introduce transparency render-passes support, it would be through a separate
- * pass. */
- /* AOVs. */
- DRW_shgroup_uniform_image_ref(grp, "aov_color_img", &rbufs.aov_color_tx);
- DRW_shgroup_uniform_image_ref(grp, "aov_value_img", &rbufs.aov_value_tx);
- DRW_shgroup_storage_block_ref(grp, "aov_buf", &inst_.film.aovs_info);
- /* RenderPasses. */
- DRW_shgroup_uniform_image_ref(grp, "rp_normal_img", &rbufs.normal_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_diffuse_light_img", &rbufs.diffuse_light_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_diffuse_color_img", &rbufs.diffuse_color_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_specular_light_img", &rbufs.specular_light_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_specular_color_img", &rbufs.specular_color_tx);
- DRW_shgroup_uniform_image_ref(grp, "rp_emission_img", &rbufs.emission_tx);
- }
+ PassMain::Sub *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ?
+ (has_motion ? prepass_single_sided_moving_ps_ :
+ prepass_single_sided_static_ps_) :
+ (has_motion ? prepass_double_sided_moving_ps_ :
+ prepass_double_sided_static_ps_);
+ return &pass->sub(GPU_material_get_name(gpumat));
+}
- DRWState state_disable = DRW_STATE_WRITE_DEPTH;
- DRWState state_enable = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
- if (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) {
- state_enable |= DRW_STATE_CULL_BACK;
- }
- DRW_shgroup_state_disable(grp, state_disable);
- DRW_shgroup_state_enable(grp, state_enable);
- return grp;
+PassMain::Sub *ForwardPipeline::material_opaque_add(::Material *blender_mat, GPUMaterial *gpumat)
+{
+ PassMain::Sub *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ? opaque_single_sided_ps_ :
+ opaque_double_sided_ps_;
+ return &pass->sub(GPU_material_get_name(gpumat));
}
-DRWShadingGroup *ForwardPipeline::prepass_transparent_add(::Material *blender_mat,
- GPUMaterial *gpumat)
+PassMain::Sub *ForwardPipeline::prepass_transparent_add(const Object *ob,
+ ::Material *blender_mat,
+ GPUMaterial *gpumat)
{
if ((blender_mat->blend_flag & MA_BL_HIDE_BACKFACE) == 0) {
return nullptr;
}
+ DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
+ if ((blender_mat->blend_flag & MA_BL_CULL_BACKFACE)) {
+ state |= DRW_STATE_CULL_BACK;
+ }
+ float sorting_value = math::dot(float3(ob->obmat[3]), camera_forward_);
+ PassMain::Sub *pass = &transparent_ps_.sub(GPU_material_get_name(gpumat), sorting_value);
+ pass->state_set(state);
+ pass->material_set(*inst_.manager, gpumat);
+ return pass;
+}
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, transparent_ps_);
-
- DRWState state_disable = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
- DRWState state_enable = DRW_STATE_WRITE_DEPTH;
- if (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) {
- state_enable |= DRW_STATE_CULL_BACK;
+PassMain::Sub *ForwardPipeline::material_transparent_add(const Object *ob,
+ ::Material *blender_mat,
+ GPUMaterial *gpumat)
+{
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM | DRW_STATE_DEPTH_LESS_EQUAL;
+ if ((blender_mat->blend_flag & MA_BL_CULL_BACKFACE)) {
+ state |= DRW_STATE_CULL_BACK;
}
- DRW_shgroup_state_disable(grp, state_disable);
- DRW_shgroup_state_enable(grp, state_enable);
- return grp;
+ float sorting_value = math::dot(float3(ob->obmat[3]), camera_forward_);
+ PassMain::Sub *pass = &transparent_ps_.sub(GPU_material_get_name(gpumat), sorting_value);
+ pass->state_set(state);
+ pass->material_set(*inst_.manager, gpumat);
+ return pass;
}
-void ForwardPipeline::render(const DRWView *view,
+void ForwardPipeline::render(View &view,
Framebuffer &prepass_fb,
Framebuffer &combined_fb,
- GPUTexture *depth_tx,
GPUTexture *UNUSED(combined_tx))
{
- UNUSED_VARS(view, depth_tx, prepass_fb, combined_fb);
- // HiZBuffer &hiz = inst_.hiz_front;
+ UNUSED_VARS(view);
- DRW_stats_group_start("ForwardOpaque");
+ DRW_stats_group_start("Forward.Opaque");
GPU_framebuffer_bind(prepass_fb);
- DRW_draw_pass(prepass_ps_);
+ inst_.manager->submit(prepass_ps_, view);
- // hiz.set_dirty();
+ // if (!DRW_pass_is_empty(prepass_ps_)) {
+ inst_.hiz_buffer.set_dirty();
+ // }
// if (inst_.raytracing.enabled()) {
// rt_buffer.radiance_copy(combined_tx);
- // hiz.update(depth_tx);
+ // inst_.hiz_buffer.update();
// }
// inst_.shadows.set_view(view, depth_tx);
GPU_framebuffer_bind(combined_fb);
- DRW_draw_pass(opaque_ps_);
+ inst_.manager->submit(opaque_ps_, view);
DRW_stats_group_end();
- DRW_stats_group_start("ForwardTransparent");
- /* TODO(fclem) This is suboptimal. We could sort during sync. */
- /* FIXME(fclem) This wont work for panoramic, where we need
- * to sort by distance to camera, not by z. */
- DRW_pass_sort_shgroup_z(transparent_ps_);
- DRW_draw_pass(transparent_ps_);
- DRW_stats_group_end();
+ inst_.manager->submit(transparent_ps_, view);
// if (inst_.raytracing.enabled()) {
// gbuffer.ray_radiance_tx.release();
diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.hh b/source/blender/draw/engines/eevee_next/eevee_pipeline.hh
index 3bdc718767b..0614a963dec 100644
--- a/source/blender/draw/engines/eevee_next/eevee_pipeline.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.hh
@@ -13,6 +13,7 @@
#pragma once
#include "DRW_render.h"
+#include "draw_shader_shared.h"
/* TODO(fclem): Move it to GPU/DRAW. */
#include "../eevee/eevee_lut.h"
@@ -31,13 +32,13 @@ class WorldPipeline {
private:
Instance &inst_;
- DRWPass *world_ps_ = nullptr;
+ PassSimple world_ps_ = {"World.Background"};
public:
WorldPipeline(Instance &inst) : inst_(inst){};
void sync(GPUMaterial *gpumat);
- void render();
+ void render(View &view);
};
/** \} */
@@ -52,13 +53,18 @@ class ForwardPipeline {
private:
Instance &inst_;
- DRWPass *prepass_ps_ = nullptr;
- DRWPass *prepass_velocity_ps_ = nullptr;
- DRWPass *prepass_culled_ps_ = nullptr;
- DRWPass *prepass_culled_velocity_ps_ = nullptr;
- DRWPass *opaque_ps_ = nullptr;
- DRWPass *opaque_culled_ps_ = nullptr;
- DRWPass *transparent_ps_ = nullptr;
+ PassMain prepass_ps_ = {"Prepass"};
+ PassMain::Sub *prepass_single_sided_static_ps_ = nullptr;
+ PassMain::Sub *prepass_single_sided_moving_ps_ = nullptr;
+ PassMain::Sub *prepass_double_sided_static_ps_ = nullptr;
+ PassMain::Sub *prepass_double_sided_moving_ps_ = nullptr;
+
+ PassMain opaque_ps_ = {"Shading"};
+ PassMain::Sub *opaque_single_sided_ps_ = nullptr;
+ PassMain::Sub *opaque_double_sided_ps_ = nullptr;
+
+ PassSortable transparent_ps_ = {"Forward.Transparent"};
+ float3 camera_forward_;
// GPUTexture *input_screen_radiance_tx_ = nullptr;
@@ -67,31 +73,19 @@ class ForwardPipeline {
void sync();
- DRWShadingGroup *material_add(::Material *blender_mat, GPUMaterial *gpumat)
- {
- return (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) ?
- material_transparent_add(blender_mat, gpumat) :
- material_opaque_add(blender_mat, gpumat);
- }
+ PassMain::Sub *prepass_opaque_add(::Material *blender_mat, GPUMaterial *gpumat, bool has_motion);
+ PassMain::Sub *material_opaque_add(::Material *blender_mat, GPUMaterial *gpumat);
- DRWShadingGroup *prepass_add(::Material *blender_mat, GPUMaterial *gpumat, bool has_motion)
- {
- return (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) ?
- prepass_transparent_add(blender_mat, gpumat) :
- prepass_opaque_add(blender_mat, gpumat, has_motion);
- }
-
- DRWShadingGroup *material_opaque_add(::Material *blender_mat, GPUMaterial *gpumat);
- DRWShadingGroup *prepass_opaque_add(::Material *blender_mat,
- GPUMaterial *gpumat,
- bool has_motion);
- DRWShadingGroup *material_transparent_add(::Material *blender_mat, GPUMaterial *gpumat);
- DRWShadingGroup *prepass_transparent_add(::Material *blender_mat, GPUMaterial *gpumat);
+ PassMain::Sub *prepass_transparent_add(const Object *ob,
+ ::Material *blender_mat,
+ GPUMaterial *gpumat);
+ PassMain::Sub *material_transparent_add(const Object *ob,
+ ::Material *blender_mat,
+ GPUMaterial *gpumat);
- void render(const DRWView *view,
+ void render(View &view,
Framebuffer &prepass_fb,
Framebuffer &combined_fb,
- GPUTexture *depth_tx,
GPUTexture *combined_tx);
};
@@ -193,26 +187,36 @@ class PipelineModule {
// velocity.sync();
}
- DRWShadingGroup *material_add(::Material *blender_mat,
- GPUMaterial *gpumat,
- eMaterialPipeline pipeline_type)
+ PassMain::Sub *material_add(Object *ob,
+ ::Material *blender_mat,
+ GPUMaterial *gpumat,
+ eMaterialPipeline pipeline_type)
{
switch (pipeline_type) {
case MAT_PIPE_DEFERRED_PREPASS:
// return deferred.prepass_add(blender_mat, gpumat, false);
- break;
+ case MAT_PIPE_FORWARD_PREPASS:
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) {
+ return forward.prepass_transparent_add(ob, blender_mat, gpumat);
+ }
+ return forward.prepass_opaque_add(blender_mat, gpumat, false);
+
case MAT_PIPE_DEFERRED_PREPASS_VELOCITY:
// return deferred.prepass_add(blender_mat, gpumat, true);
- break;
- case MAT_PIPE_FORWARD_PREPASS:
- return forward.prepass_add(blender_mat, gpumat, false);
case MAT_PIPE_FORWARD_PREPASS_VELOCITY:
- return forward.prepass_add(blender_mat, gpumat, true);
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) {
+ return forward.prepass_transparent_add(ob, blender_mat, gpumat);
+ }
+ return forward.prepass_opaque_add(blender_mat, gpumat, true);
+
case MAT_PIPE_DEFERRED:
// return deferred.material_add(blender_mat, gpumat);
- break;
case MAT_PIPE_FORWARD:
- return forward.material_add(blender_mat, gpumat);
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) {
+ return forward.material_transparent_add(ob, blender_mat, gpumat);
+ }
+ return forward.material_opaque_add(blender_mat, gpumat);
+
case MAT_PIPE_VOLUME:
/* TODO(fclem) volume pass. */
return nullptr;
diff --git a/source/blender/draw/engines/eevee_next/eevee_renderbuffers.cc b/source/blender/draw/engines/eevee_next/eevee_renderbuffers.cc
index b69fde7b26c..f5638cc5160 100644
--- a/source/blender/draw/engines/eevee_next/eevee_renderbuffers.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_renderbuffers.cc
@@ -5,7 +5,7 @@
/** \file
* \ingroup eevee
*
- * A film is a fullscreen buffer (usually at output extent)
+ * A film is a full-screen buffer (usually at output extent)
* that will be able to accumulate sample in any distorted camera_type
* using a pixel filter.
*
@@ -26,9 +26,11 @@ namespace blender::eevee {
void RenderBuffers::acquire(int2 extent)
{
+ const eViewLayerEEVEEPassType enabled_passes = inst_.film.enabled_passes_get();
+
auto pass_extent = [&](eViewLayerEEVEEPassType pass_bit) -> int2 {
/* Use dummy texture for disabled passes. Allows correct bindings. */
- return (inst_.film.enabled_passes_get() & pass_bit) ? extent : int2(1);
+ return (enabled_passes & pass_bit) ? extent : int2(1);
};
eGPUTextureFormat color_format = GPU_RGBA16F;
@@ -38,17 +40,22 @@ void RenderBuffers::acquire(int2 extent)
depth_tx.acquire(extent, GPU_DEPTH24_STENCIL8);
combined_tx.acquire(extent, color_format);
- bool do_vector_render_pass = (inst_.film.enabled_passes_get() & EEVEE_RENDER_PASS_VECTOR) ||
+ bool do_vector_render_pass = (enabled_passes & EEVEE_RENDER_PASS_VECTOR) ||
(inst_.motion_blur.postfx_enabled() && !inst_.is_viewport());
+ uint32_t max_light_color_layer = max_ii(enabled_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT ?
+ (int)RENDER_PASS_LAYER_DIFFUSE_LIGHT :
+ -1,
+ enabled_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT ?
+ (int)RENDER_PASS_LAYER_SPECULAR_LIGHT :
+ -1) +
+ 1;
/* Only RG16F when only doing only reprojection or motion blur. */
eGPUTextureFormat vector_format = do_vector_render_pass ? GPU_RGBA16F : GPU_RG16F;
/* TODO(fclem): Make vector pass allocation optional if no TAA or motion blur is needed. */
vector_tx.acquire(extent, vector_format);
normal_tx.acquire(pass_extent(EEVEE_RENDER_PASS_NORMAL), color_format);
- diffuse_light_tx.acquire(pass_extent(EEVEE_RENDER_PASS_DIFFUSE_LIGHT), color_format);
diffuse_color_tx.acquire(pass_extent(EEVEE_RENDER_PASS_DIFFUSE_COLOR), color_format);
- specular_light_tx.acquire(pass_extent(EEVEE_RENDER_PASS_SPECULAR_LIGHT), color_format);
specular_color_tx.acquire(pass_extent(EEVEE_RENDER_PASS_SPECULAR_COLOR), color_format);
volume_light_tx.acquire(pass_extent(EEVEE_RENDER_PASS_VOLUME_LIGHT), color_format);
emission_tx.acquire(pass_extent(EEVEE_RENDER_PASS_EMIT), color_format);
@@ -56,11 +63,29 @@ void RenderBuffers::acquire(int2 extent)
shadow_tx.acquire(pass_extent(EEVEE_RENDER_PASS_SHADOW), float_format);
ambient_occlusion_tx.acquire(pass_extent(EEVEE_RENDER_PASS_AO), float_format);
+ light_tx.ensure_2d_array(color_format,
+ max_light_color_layer > 0 ? extent : int2(1),
+ max_ii(1, max_light_color_layer));
+
const AOVsInfoData &aovs = inst_.film.aovs_info;
aov_color_tx.ensure_2d_array(
color_format, (aovs.color_len > 0) ? extent : int2(1), max_ii(1, aovs.color_len));
aov_value_tx.ensure_2d_array(
float_format, (aovs.value_len > 0) ? extent : int2(1), max_ii(1, aovs.value_len));
+
+ eGPUTextureFormat cryptomatte_format = GPU_R32F;
+ const int cryptomatte_layer_len = inst_.film.cryptomatte_layer_max_get();
+ if (cryptomatte_layer_len == 2) {
+ cryptomatte_format = GPU_RG32F;
+ }
+ else if (cryptomatte_layer_len == 3) {
+ cryptomatte_format = GPU_RGBA32F;
+ }
+ cryptomatte_tx.acquire(
+ pass_extent(static_cast<eViewLayerEEVEEPassType>(EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT |
+ EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET |
+ EEVEE_RENDER_PASS_CRYPTOMATTE_MATERIAL)),
+ cryptomatte_format);
}
void RenderBuffers::release()
@@ -70,15 +95,14 @@ void RenderBuffers::release()
normal_tx.release();
vector_tx.release();
- diffuse_light_tx.release();
diffuse_color_tx.release();
- specular_light_tx.release();
specular_color_tx.release();
volume_light_tx.release();
emission_tx.release();
environment_tx.release();
shadow_tx.release();
ambient_occlusion_tx.release();
+ cryptomatte_tx.release();
}
} // namespace blender::eevee
diff --git a/source/blender/draw/engines/eevee_next/eevee_renderbuffers.hh b/source/blender/draw/engines/eevee_next/eevee_renderbuffers.hh
index 787f5604aa4..ae5d7fbae5c 100644
--- a/source/blender/draw/engines/eevee_next/eevee_renderbuffers.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_renderbuffers.hh
@@ -28,17 +28,16 @@ class RenderBuffers {
// TextureFromPool mist_tx; /* Derived from depth_tx during accumulation. */
TextureFromPool normal_tx;
TextureFromPool vector_tx;
- TextureFromPool diffuse_light_tx;
TextureFromPool diffuse_color_tx;
- TextureFromPool specular_light_tx;
TextureFromPool specular_color_tx;
TextureFromPool volume_light_tx;
TextureFromPool emission_tx;
TextureFromPool environment_tx;
TextureFromPool shadow_tx;
TextureFromPool ambient_occlusion_tx;
- // TextureFromPool cryptomatte_tx; /* TODO */
+ TextureFromPool cryptomatte_tx;
/* TODO(fclem): Use texture from pool once they support texture array. */
+ Texture light_tx;
Texture aov_color_tx;
Texture aov_value_tx;
diff --git a/source/blender/draw/engines/eevee_next/eevee_sampling.hh b/source/blender/draw/engines/eevee_next/eevee_sampling.hh
index be87ee74886..c2bf23d20fc 100644
--- a/source/blender/draw/engines/eevee_next/eevee_sampling.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_sampling.hh
@@ -87,6 +87,12 @@ class Sampling {
DRW_shgroup_storage_block_ref(grp, "sampling_buf", &data_);
}
+ template<typename T> void bind_resources(draw::detail::PassBase<T> *pass)
+ {
+ /* Storage Buf. */
+ pass->bind_ssbo(SAMPLING_BUF_SLOT, &data_);
+ }
+
/* Returns a pseudo random number in [0..1] range. Each dimension are de-correlated. */
float rng_get(eSamplingDimension dimension) const
{
diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.cc b/source/blender/draw/engines/eevee_next/eevee_shader.cc
index a535d3407ac..05ff06e7435 100644
--- a/source/blender/draw/engines/eevee_next/eevee_shader.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_shader.cc
@@ -9,6 +9,8 @@
* and static shader usage.
*/
+#include "GPU_capabilities.h"
+
#include "gpu_shader_create_info.hh"
#include "eevee_shader.hh"
@@ -82,6 +84,12 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_
return "eevee_film_frag";
case FILM_COMP:
return "eevee_film_comp";
+ case FILM_CRYPTOMATTE_POST:
+ return "eevee_film_cryptomatte_post";
+ case HIZ_DEBUG:
+ return "eevee_hiz_debug";
+ case HIZ_UPDATE:
+ return "eevee_hiz_update";
case MOTION_BLUR_GATHER:
return "eevee_motion_blur_gather";
case MOTION_BLUR_TILE_DILATE:
@@ -176,11 +184,41 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu
GPUCodegenOutput &codegen = *codegen_;
ShaderCreateInfo &info = *reinterpret_cast<ShaderCreateInfo *>(codegen.create_info);
- info.auto_resource_location(true);
+ /* WORKAROUND: Replace by new ob info. */
+ int64_t ob_info_index = info.additional_infos_.first_index_of_try("draw_object_infos");
+ if (ob_info_index != -1) {
+ info.additional_infos_[ob_info_index] = "draw_object_infos_new";
+ }
+
+ /* WORKAROUND: Add new ob attr buffer. */
+ if (GPU_material_uniform_attributes(gpumat) != nullptr) {
+ info.additional_info("draw_object_attribute_new");
+ }
+
+ /* WORKAROUND: Avoid utility texture merge error. TODO: find a cleaner fix. */
+ for (auto &resource : info.batch_resources_) {
+ if (resource.bind_type == ShaderCreateInfo::Resource::BindType::SAMPLER) {
+ if (resource.slot == RBUFS_UTILITY_TEX_SLOT) {
+ resource.slot = GPU_max_textures_frag() - 1;
+ }
+ }
+ }
if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) {
info.define("MAT_TRANSPARENT");
+ /* Transparent material do not have any velocity specific pipeline. */
+ if (pipeline_type == MAT_PIPE_FORWARD_PREPASS_VELOCITY) {
+ pipeline_type = MAT_PIPE_FORWARD_PREPASS;
+ }
}
+
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT) == false &&
+ pipeline_type == MAT_PIPE_FORWARD) {
+ /* Opaque forward do support AOVs and render pass. */
+ info.additional_info("eevee_aov_out");
+ info.additional_info("eevee_render_pass_out");
+ }
+
if (GPU_material_flag_get(gpumat, GPU_MATFLAG_BARYCENTRIC)) {
switch (geometry_type) {
case MAT_GEOM_MESH:
@@ -433,6 +471,8 @@ GPUMaterial *ShaderModule::material_shader_get(const char *name,
this);
GPU_material_status_set(gpumat, GPU_MAT_QUEUED);
GPU_material_compile(gpumat);
+ /* Queue deferred material optimization. */
+ DRW_shader_queue_optimize_material(gpumat);
return gpumat;
}
diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.hh b/source/blender/draw/engines/eevee_next/eevee_shader.hh
index 5b43a1abf43..88538557c07 100644
--- a/source/blender/draw/engines/eevee_next/eevee_shader.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_shader.hh
@@ -28,6 +28,7 @@ namespace blender::eevee {
enum eShaderType {
FILM_FRAG = 0,
FILM_COMP,
+ FILM_CRYPTOMATTE_POST,
DOF_BOKEH_LUT,
DOF_DOWNSAMPLE,
@@ -47,6 +48,9 @@ enum eShaderType {
DOF_TILES_DILATE_MINMAX,
DOF_TILES_FLATTEN,
+ HIZ_UPDATE,
+ HIZ_DEBUG,
+
LIGHT_CULLING_DEBUG,
LIGHT_CULLING_SELECT,
LIGHT_CULLING_SORT,
diff --git a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh
index 885317fc673..8e96445d6b9 100644
--- a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh
@@ -12,16 +12,16 @@
# include "BLI_memory_utils.hh"
# include "DRW_gpu_wrapper.hh"
+# include "draw_manager.hh"
+# include "draw_pass.hh"
+
# include "eevee_defines.hh"
# include "GPU_shader_shared.h"
namespace blender::eevee {
-using draw::Framebuffer;
-using draw::SwapChain;
-using draw::Texture;
-using draw::TextureFromPool;
+using namespace draw;
constexpr eGPUSamplerState no_filter = GPU_SAMPLER_DEFAULT;
constexpr eGPUSamplerState with_filter = GPU_SAMPLER_FILTER;
@@ -38,40 +38,44 @@ constexpr eGPUSamplerState with_filter = GPU_SAMPLER_FILTER;
enum eDebugMode : uint32_t {
DEBUG_NONE = 0u,
/**
- * Gradient showing light evaluation hotspots.
+ * Gradient showing light evaluation hot-spots.
*/
DEBUG_LIGHT_CULLING = 1u,
/**
- * Tilemaps to screen. Is also present in other modes.
+ * Show incorrectly downsample tiles in red.
+ */
+ DEBUG_HIZ_VALIDATION = 2u,
+ /**
+ * Tile-maps to screen. Is also present in other modes.
* - Black pixels, no pages allocated.
* - Green pixels, pages cached.
* - Red pixels, pages allocated.
*/
- DEBUG_SHADOW_TILEMAPS = 2u,
+ DEBUG_SHADOW_TILEMAPS = 10u,
/**
* Random color per pages. Validates page density allocation and sampling.
*/
- DEBUG_SHADOW_PAGES = 3u,
+ DEBUG_SHADOW_PAGES = 11u,
/**
- * Outputs random color per tilemap (or tilemap level). Validates tilemaps coverage.
- * Black means not covered by any tilemaps LOD of the shadow.
+ * Outputs random color per tile-map (or tile-map level). Validates tile-maps coverage.
+ * Black means not covered by any tile-maps LOD of the shadow.
*/
- DEBUG_SHADOW_LOD = 4u,
+ DEBUG_SHADOW_LOD = 12u,
/**
* Outputs white pixels for pages allocated and black pixels for unused pages.
* This needs DEBUG_SHADOW_PAGE_ALLOCATION_ENABLED defined in order to work.
*/
- DEBUG_SHADOW_PAGE_ALLOCATION = 5u,
+ DEBUG_SHADOW_PAGE_ALLOCATION = 13u,
/**
- * Outputs the tilemap atlas. Default tilemap is too big for the usual screen resolution.
+ * Outputs the tile-map atlas. Default tile-map is too big for the usual screen resolution.
* Try lowering SHADOW_TILEMAP_PER_ROW and SHADOW_MAX_TILEMAP before using this option.
*/
- DEBUG_SHADOW_TILE_ALLOCATION = 6u,
+ DEBUG_SHADOW_TILE_ALLOCATION = 14u,
/**
* Visualize linear depth stored in the atlas regions of the active light.
* This way, one can check if the rendering, the copying and the shadow sampling functions works.
*/
- DEBUG_SHADOW_SHADOW_DEPTH = 7u
+ DEBUG_SHADOW_SHADOW_DEPTH = 15u
};
/** \} */
@@ -190,6 +194,17 @@ BLI_STATIC_ASSERT_ALIGN(CameraData, 16)
#define FILM_PRECOMP_SAMPLE_MAX 16
+enum eFilmWeightLayerIndex : uint32_t {
+ FILM_WEIGHT_LAYER_ACCUMULATION = 0u,
+ FILM_WEIGHT_LAYER_DISTANCE = 1u,
+};
+
+enum ePassStorageType : uint32_t {
+ PASS_STORAGE_COLOR = 0u,
+ PASS_STORAGE_VALUE = 1u,
+ PASS_STORAGE_CRYPTOMATTE = 2u,
+};
+
struct FilmSample {
int2 texel;
float weight;
@@ -246,13 +261,19 @@ struct FilmData {
int combined_id;
/** Id of the render-pass to be displayed. -1 for combined. */
int display_id;
- /** True if the render-pass to be displayed is from the value accum buffer. */
- bool1 display_is_value;
+ /** Storage type of the render-pass to be displayed. */
+ ePassStorageType display_storage_type;
/** True if we bypass the accumulation and directly output the accumulation buffer. */
bool1 display_only;
/** Start of AOVs and number of aov. */
int aov_color_id, aov_color_len;
int aov_value_id, aov_value_len;
+ /** Start of cryptomatte per layer (-1 if pass is not enabled). */
+ int cryptomatte_object_id;
+ int cryptomatte_asset_id;
+ int cryptomatte_material_id;
+ /** Max number of samples stored per layer (is even number). */
+ int cryptomatte_samples_len;
/** Settings to render mist pass */
float mist_scale, mist_bias, mist_exponent;
/** Scene exposure used for better noise reduction. */
@@ -288,6 +309,17 @@ static inline float film_filter_weight(float filter_radius, float sample_distanc
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Render passes
+ * \{ */
+
+enum eRenderPassLayerIndex : uint32_t {
+ RENDER_PASS_LAYER_DIFFUSE_LIGHT = 0u,
+ RENDER_PASS_LAYER_SPECULAR_LIGHT = 1u,
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Arbitrary Output Variables
* \{ */
@@ -613,6 +645,20 @@ BLI_STATIC_ASSERT_ALIGN(LightData, 16)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Hierarchical-Z Buffer
+ * \{ */
+
+struct HiZData {
+ /** Scale factor to remove HiZBuffer padding. */
+ float2 uv_scale;
+
+ float2 _pad0;
+};
+BLI_STATIC_ASSERT_ALIGN(HiZData, 16)
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Ray-Tracing
* \{ */
@@ -699,22 +745,24 @@ float4 utility_tx_sample(sampler2DArray util_tx, float2 uv, float layer)
using AOVsInfoDataBuf = draw::StorageBuffer<AOVsInfoData>;
using CameraDataBuf = draw::UniformBuffer<CameraData>;
-using LightDataBuf = draw::StorageArrayBuffer<LightData, LIGHT_CHUNK>;
+using DepthOfFieldDataBuf = draw::UniformBuffer<DepthOfFieldData>;
+using DepthOfFieldScatterListBuf = draw::StorageArrayBuffer<ScatterRect, 16, true>;
+using DrawIndirectBuf = draw::StorageBuffer<DrawCommand, true>;
+using FilmDataBuf = draw::UniformBuffer<FilmData>;
+using HiZDataBuf = draw::UniformBuffer<HiZData>;
using LightCullingDataBuf = draw::StorageBuffer<LightCullingData>;
using LightCullingKeyBuf = draw::StorageArrayBuffer<uint, LIGHT_CHUNK, true>;
using LightCullingTileBuf = draw::StorageArrayBuffer<uint, LIGHT_CHUNK, true>;
using LightCullingZbinBuf = draw::StorageArrayBuffer<uint, CULLING_ZBIN_COUNT, true>;
using LightCullingZdistBuf = draw::StorageArrayBuffer<float, LIGHT_CHUNK, true>;
-using DepthOfFieldDataBuf = draw::UniformBuffer<DepthOfFieldData>;
-using DepthOfFieldScatterListBuf = draw::StorageArrayBuffer<ScatterRect, 16, true>;
-using DrawIndirectBuf = draw::StorageBuffer<DrawCommand, true>;
-using FilmDataBuf = draw::UniformBuffer<FilmData>;
+using LightDataBuf = draw::StorageArrayBuffer<LightData, LIGHT_CHUNK>;
using MotionBlurDataBuf = draw::UniformBuffer<MotionBlurData>;
using MotionBlurTileIndirectionBuf = draw::StorageBuffer<MotionBlurTileIndirection, true>;
using SamplingDataBuf = draw::StorageBuffer<SamplingData>;
using VelocityGeometryBuf = draw::StorageArrayBuffer<float4, 16, true>;
using VelocityIndexBuf = draw::StorageArrayBuffer<VelocityIndex, 16>;
using VelocityObjectBuf = draw::StorageArrayBuffer<float4x4, 16>;
+using CryptomatteObjectBuf = draw::StorageArrayBuffer<float2, 16>;
} // namespace blender::eevee
#endif
diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.cc b/source/blender/draw/engines/eevee_next/eevee_sync.cc
index e2d4b0ac1c2..09ea7c9ec3d 100644
--- a/source/blender/draw/engines/eevee_next/eevee_sync.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_sync.cc
@@ -74,25 +74,12 @@ WorldHandle &SyncModule::sync_world(::World *world)
/** \name Common
* \{ */
-static inline void shgroup_geometry_call(DRWShadingGroup *grp,
- Object *ob,
- GPUBatch *geom,
- int v_first = -1,
- int v_count = -1,
- bool use_instancing = false)
+static inline void geometry_call(PassMain::Sub *sub_pass,
+ GPUBatch *geom,
+ ResourceHandle resource_handle)
{
- if (grp == nullptr) {
- return;
- }
-
- if (v_first == -1) {
- DRW_shgroup_call(grp, geom, ob);
- }
- else if (use_instancing) {
- DRW_shgroup_call_instance_range(grp, ob, geom, v_first, v_count);
- }
- else {
- DRW_shgroup_call_range(grp, ob, geom, v_first, v_count);
+ if (sub_pass != nullptr) {
+ sub_pass->draw(geom, resource_handle);
}
}
@@ -102,9 +89,13 @@ static inline void shgroup_geometry_call(DRWShadingGroup *grp,
/** \name Mesh
* \{ */
-void SyncModule::sync_mesh(Object *ob, ObjectHandle &ob_handle)
+void SyncModule::sync_mesh(Object *ob,
+ ObjectHandle &ob_handle,
+ ResourceHandle res_handle,
+ const ObjectRef &ob_ref)
{
- bool has_motion = inst_.velocity.step_object_sync(ob, ob_handle.object_key, ob_handle.recalc);
+ bool has_motion = inst_.velocity.step_object_sync(
+ ob, ob_handle.object_key, res_handle, ob_handle.recalc);
MaterialArray &material_array = inst_.materials.material_array_get(ob, has_motion);
@@ -123,14 +114,20 @@ void SyncModule::sync_mesh(Object *ob, ObjectHandle &ob_handle)
continue;
}
Material *material = material_array.materials[i];
- shgroup_geometry_call(material->shading.shgrp, ob, geom);
- shgroup_geometry_call(material->prepass.shgrp, ob, geom);
- shgroup_geometry_call(material->shadow.shgrp, ob, geom);
+ geometry_call(material->shading.sub_pass, geom, res_handle);
+ geometry_call(material->prepass.sub_pass, geom, res_handle);
+ geometry_call(material->shadow.sub_pass, geom, res_handle);
- is_shadow_caster = is_shadow_caster || material->shadow.shgrp != nullptr;
+ is_shadow_caster = is_shadow_caster || material->shadow.sub_pass != nullptr;
is_alpha_blend = is_alpha_blend || material->is_alpha_blend_transparent;
+
+ GPUMaterial *gpu_material = material_array.gpu_materials[i];
+ ::Material *mat = GPU_material_get_material(gpu_material);
+ inst_.cryptomatte.sync_material(mat);
}
+ inst_.manager->extract_object_attributes(res_handle, ob_ref, material_array.gpu_materials);
+ inst_.cryptomatte.sync_object(ob, res_handle);
// shadows.sync_object(ob, ob_handle, is_shadow_caster, is_alpha_blend);
}
@@ -155,11 +152,13 @@ struct gpIterData {
int vcount = 0;
bool instancing = false;
- gpIterData(Instance &inst_, Object *ob_, ObjectHandle &ob_handle)
+ gpIterData(Instance &inst_, Object *ob_, ObjectHandle &ob_handle, ResourceHandle resource_handle)
: inst(inst_),
ob(ob_),
material_array(inst_.materials.material_array_get(
- ob_, inst_.velocity.step_object_sync(ob, ob_handle.object_key, ob_handle.recalc)))
+ ob_,
+ inst_.velocity.step_object_sync(
+ ob, ob_handle.object_key, resource_handle, ob_handle.recalc)))
{
cfra = DEG_get_ctime(inst.depsgraph);
};
@@ -167,26 +166,28 @@ struct gpIterData {
static void gpencil_drawcall_flush(gpIterData &iter)
{
+#if 0 /* Incompatible with new draw manager. */
if (iter.geom != nullptr) {
- shgroup_geometry_call(iter.material->shading.shgrp,
+ geometry_call(iter.material->shading.sub_pass,
iter.ob,
iter.geom,
iter.vfirst,
iter.vcount,
iter.instancing);
- shgroup_geometry_call(iter.material->prepass.shgrp,
+ geometry_call(iter.material->prepass.sub_pass,
iter.ob,
iter.geom,
iter.vfirst,
iter.vcount,
iter.instancing);
- shgroup_geometry_call(iter.material->shadow.shgrp,
+ geometry_call(iter.material->shadow.sub_pass,
iter.ob,
iter.geom,
iter.vfirst,
iter.vcount,
iter.instancing);
}
+#endif
iter.geom = nullptr;
iter.vfirst = -1;
iter.vcount = 0;
@@ -250,21 +251,22 @@ static void gpencil_stroke_sync(bGPDlayer *UNUSED(gpl),
}
}
-void SyncModule::sync_gpencil(Object *ob, ObjectHandle &ob_handle)
+void SyncModule::sync_gpencil(Object *ob, ObjectHandle &ob_handle, ResourceHandle res_handle)
{
/* TODO(fclem): Waiting for a user option to use the render engine instead of gpencil engine. */
if (true) {
inst_.gpencil_engine_enabled = true;
return;
}
+ UNUSED_VARS(res_handle);
- gpIterData iter(inst_, ob, ob_handle);
+ gpIterData iter(inst_, ob, ob_handle, res_handle);
BKE_gpencil_visible_stroke_iter((bGPdata *)ob->data, nullptr, gpencil_stroke_sync, &iter);
gpencil_drawcall_flush(iter);
- // bool is_caster = true; /* TODO material.shadow.shgrp. */
+ // bool is_caster = true; /* TODO material.shadow.sub_pass. */
// bool is_alpha_blend = true; /* TODO material.is_alpha_blend. */
// shadows.sync_object(ob, ob_handle, is_caster, is_alpha_blend);
}
@@ -280,19 +282,24 @@ static void shgroup_curves_call(MaterialPass &matpass,
ParticleSystem *part_sys = nullptr,
ModifierData *modifier_data = nullptr)
{
- if (matpass.shgrp == nullptr) {
+ UNUSED_VARS(ob, modifier_data);
+ if (matpass.sub_pass == nullptr) {
return;
}
if (part_sys != nullptr) {
- DRW_shgroup_hair_create_sub(ob, part_sys, modifier_data, matpass.shgrp, matpass.gpumat);
+ // DRW_shgroup_hair_create_sub(ob, part_sys, modifier_data, matpass.sub_pass, matpass.gpumat);
}
else {
- DRW_shgroup_curves_create_sub(ob, matpass.shgrp, matpass.gpumat);
+ // DRW_shgroup_curves_create_sub(ob, matpass.sub_pass, matpass.gpumat);
}
}
-void SyncModule::sync_curves(Object *ob, ObjectHandle &ob_handle, ModifierData *modifier_data)
+void SyncModule::sync_curves(Object *ob,
+ ObjectHandle &ob_handle,
+ ResourceHandle res_handle,
+ ModifierData *modifier_data)
{
+ UNUSED_VARS(res_handle);
int mat_nr = CURVES_MATERIAL_NR;
ParticleSystem *part_sys = nullptr;
@@ -317,10 +324,16 @@ void SyncModule::sync_curves(Object *ob, ObjectHandle &ob_handle, ModifierData *
shgroup_curves_call(material.prepass, ob, part_sys, modifier_data);
shgroup_curves_call(material.shadow, ob, part_sys, modifier_data);
+ inst_.cryptomatte.sync_object(ob, res_handle);
+ GPUMaterial *gpu_material =
+ inst_.materials.material_array_get(ob, has_motion).gpu_materials[mat_nr - 1];
+ ::Material *mat = GPU_material_get_material(gpu_material);
+ inst_.cryptomatte.sync_material(mat);
+
/* TODO(fclem) Hair velocity. */
// shading_passes.velocity.gpencil_add(ob, ob_handle);
- // bool is_caster = material.shadow.shgrp != nullptr;
+ // bool is_caster = material.shadow.sub_pass != nullptr;
// bool is_alpha_blend = material.is_alpha_blend_transparent;
// shadows.sync_object(ob, ob_handle, is_caster, is_alpha_blend);
}
diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.hh b/source/blender/draw/engines/eevee_next/eevee_sync.hh
index bd8147a2882..ab883ce44c2 100644
--- a/source/blender/draw/engines/eevee_next/eevee_sync.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_sync.hh
@@ -150,9 +150,15 @@ class SyncModule {
ObjectHandle &sync_object(Object *ob);
WorldHandle &sync_world(::World *world);
- void sync_mesh(Object *ob, ObjectHandle &ob_handle);
- void sync_gpencil(Object *ob, ObjectHandle &ob_handle);
- void sync_curves(Object *ob, ObjectHandle &ob_handle, ModifierData *modifier_data = nullptr);
+ void sync_mesh(Object *ob,
+ ObjectHandle &ob_handle,
+ ResourceHandle res_handle,
+ const ObjectRef &ob_ref);
+ void sync_gpencil(Object *ob, ObjectHandle &ob_handle, ResourceHandle res_handle);
+ void sync_curves(Object *ob,
+ ObjectHandle &ob_handle,
+ ResourceHandle res_handle,
+ ModifierData *modifier_data = nullptr);
};
/** \} */
diff --git a/source/blender/draw/engines/eevee_next/eevee_velocity.cc b/source/blender/draw/engines/eevee_next/eevee_velocity.cc
index 36734f0c28c..7af311a8ccc 100644
--- a/source/blender/draw/engines/eevee_next/eevee_velocity.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_velocity.cc
@@ -43,6 +43,10 @@ void VelocityModule::init()
step_ = STEP_CURRENT;
/* Let the main sync loop handle the current step. */
}
+
+ /* For viewport, only previous motion is supported.
+ * Still bind previous step to avoid undefined behavior. */
+ next_step_ = inst_.is_viewport() ? STEP_PREVIOUS : STEP_NEXT;
}
static void step_object_sync_render(void *velocity,
@@ -51,7 +55,9 @@ static void step_object_sync_render(void *velocity,
Depsgraph *UNUSED(depsgraph))
{
ObjectKey object_key(ob);
- reinterpret_cast<VelocityModule *>(velocity)->step_object_sync(ob, object_key);
+ /* NOTE: Dummy resource handle since this will not be used for drawing. */
+ ResourceHandle resource_handle(0);
+ reinterpret_cast<VelocityModule *>(velocity)->step_object_sync(ob, object_key, resource_handle);
}
void VelocityModule::step_sync(eVelocityStep step, float time)
@@ -78,6 +84,7 @@ void VelocityModule::step_camera_sync()
bool VelocityModule::step_object_sync(Object *ob,
ObjectKey &object_key,
+ ResourceHandle resource_handle,
int /*IDRecalcFlag*/ recalc)
{
bool has_motion = object_has_velocity(ob) || (recalc & ID_RECALC_TRANSFORM);
@@ -89,8 +96,6 @@ bool VelocityModule::step_object_sync(Object *ob,
return false;
}
- uint32_t resource_id = DRW_object_resource_id_get(ob);
-
/* Object motion. */
/* FIXME(fclem) As we are using original objects pointers, there is a chance the previous
* object key matches a totally different object if the scene was changed by user or python
@@ -99,7 +104,7 @@ bool VelocityModule::step_object_sync(Object *ob,
* We live with that until we have a correct way of identifying new objects. */
VelocityObjectData &vel = velocity_map.lookup_or_add_default(object_key);
vel.obj.ofs[step_] = object_steps_usage[step_]++;
- vel.obj.resource_id = resource_id;
+ vel.obj.resource_id = resource_handle.resource_index();
vel.id = (ID *)ob->data;
object_steps[step_]->get_or_resize(vel.obj.ofs[step_]) = ob->obmat;
if (step_ == STEP_CURRENT) {
@@ -257,7 +262,7 @@ void VelocityModule::end_sync()
uint32_t max_resource_id_ = 0u;
for (Map<ObjectKey, VelocityObjectData>::Item item : velocity_map.items()) {
- if (item.value.obj.resource_id == (uint)-1) {
+ if (item.value.obj.resource_id == (uint32_t)-1) {
deleted_obj.append(item.key);
}
else {
@@ -273,11 +278,11 @@ void VelocityModule::end_sync()
inst_.sampling.reset();
}
- for (auto key : deleted_obj) {
+ for (auto &key : deleted_obj) {
velocity_map.remove(key);
}
- indirection_buf.resize(power_of_2_max_u(max_resource_id_ + 1));
+ indirection_buf.resize(ceil_to_multiple_u(max_resource_id_, 128));
/* Avoid uploading more data to the GPU as well as an extra level of
* indirection on the GPU by copying back offsets the to VelocityIndex. */
diff --git a/source/blender/draw/engines/eevee_next/eevee_velocity.hh b/source/blender/draw/engines/eevee_next/eevee_velocity.hh
index 01b8a5fb8c1..6f18b05d476 100644
--- a/source/blender/draw/engines/eevee_next/eevee_velocity.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_velocity.hh
@@ -67,7 +67,10 @@ class VelocityModule {
private:
Instance &inst_;
+ /** Step being synced. */
eVelocityStep step_ = STEP_CURRENT;
+ /** Step referenced as next step. */
+ eVelocityStep next_step_ = STEP_NEXT;
public:
VelocityModule(Instance &inst) : inst_(inst)
@@ -102,7 +105,10 @@ class VelocityModule {
void step_sync(eVelocityStep step, float time);
/* Gather motion data. Returns true if the object **can** have motion. */
- bool step_object_sync(Object *ob, ObjectKey &object_key, int recalc = 0);
+ bool step_object_sync(Object *ob,
+ ObjectKey &object_key,
+ ResourceHandle resource_handle,
+ int recalc = 0);
/* Moves next frame data to previous frame data. Nullify next frame data. */
void step_swap();
@@ -112,6 +118,20 @@ class VelocityModule {
void bind_resources(DRWShadingGroup *grp);
+ template<typename T> void bind_resources(draw::detail::Pass<T> *pass)
+ {
+ /* Storage Buf. */
+ pass->bind_ssbo(VELOCITY_OBJ_PREV_BUF_SLOT, &(*object_steps[STEP_PREVIOUS]));
+ pass->bind_ssbo(VELOCITY_OBJ_NEXT_BUF_SLOT, &(*object_steps[next_step_]));
+ pass->bind_ssbo(VELOCITY_GEO_PREV_BUF_SLOT, &(*geometry_steps[STEP_PREVIOUS]));
+ pass->bind_ssbo(VELOCITY_GEO_NEXT_BUF_SLOT, &(*geometry_steps[next_step_]));
+ pass->bind_ssbo(VELOCITY_INDIRECTION_BUF_SLOT, &indirection_buf);
+ /* Uniform Buf. */
+ pass->bind_ubo(VELOCITY_CAMERA_PREV_BUF, &(*camera_steps[STEP_PREVIOUS]));
+ pass->bind_ubo(VELOCITY_CAMERA_CURR_BUF, &(*camera_steps[STEP_CURRENT]));
+ pass->bind_ubo(VELOCITY_CAMERA_NEXT_BUF, &(*camera_steps[next_step_]));
+ }
+
bool camera_has_motion() const;
bool camera_changed_projection() const;
diff --git a/source/blender/draw/engines/eevee_next/eevee_view.cc b/source/blender/draw/engines/eevee_next/eevee_view.cc
index b7154465a70..48951c2bae7 100644
--- a/source/blender/draw/engines/eevee_next/eevee_view.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_view.cc
@@ -102,6 +102,8 @@ void ShadingView::render()
update_view();
+ inst_.hiz_buffer.set_dirty();
+
DRW_stats_group_start(name_);
DRW_view_set_active(render_view_);
@@ -116,10 +118,10 @@ void ShadingView::render()
GPU_framebuffer_bind(combined_fb_);
GPU_framebuffer_clear_color_depth(combined_fb_, clear_color, 1.0f);
- inst_.pipelines.world.render();
+ inst_.pipelines.world.render(render_view_new_);
/* TODO(fclem): Move it after the first prepass (and hiz update) once pipeline is stabilized. */
- inst_.lights.set_view(render_view_, extent_);
+ inst_.lights.set_view(render_view_new_, extent_);
// inst_.pipelines.deferred.render(
// render_view_, rt_buffer_opaque_, rt_buffer_refract_, depth_tx_, combined_tx_);
@@ -128,10 +130,10 @@ void ShadingView::render()
// inst_.lookdev.render_overlay(view_fb_);
- inst_.pipelines.forward.render(
- render_view_, prepass_fb_, combined_fb_, rbufs.depth_tx, rbufs.combined_tx);
+ inst_.pipelines.forward.render(render_view_new_, prepass_fb_, combined_fb_, rbufs.combined_tx);
- inst_.lights.debug_draw(combined_fb_);
+ inst_.lights.debug_draw(render_view_new_, combined_fb_);
+ inst_.hiz_buffer.debug_draw(render_view_new_, combined_fb_);
GPUTexture *combined_final_tx = render_postfx(rbufs.combined_tx);
@@ -155,8 +157,8 @@ GPUTexture *ShadingView::render_postfx(GPUTexture *input_tx)
GPUTexture *output_tx = postfx_tx_;
/* Swapping is done internally. Actual output is set to the next input. */
- inst_.depth_of_field.render(&input_tx, &output_tx, dof_buffer_);
- inst_.motion_blur.render(&input_tx, &output_tx);
+ inst_.depth_of_field.render(render_view_new_, &input_tx, &output_tx, dof_buffer_);
+ inst_.motion_blur.render(render_view_new_, &input_tx, &output_tx);
return input_tx;
}
@@ -184,6 +186,8 @@ void ShadingView::update_view()
* out of the blurring radius. To fix this, use custom enlarged culling matrix. */
inst_.depth_of_field.jitter_apply(winmat, viewmat);
DRW_view_update_sub(render_view_, viewmat.ptr(), winmat.ptr());
+
+ render_view_new_.sync(viewmat, winmat);
}
/** \} */
diff --git a/source/blender/draw/engines/eevee_next/eevee_view.hh b/source/blender/draw/engines/eevee_next/eevee_view.hh
index 65f27aba795..74e513357cd 100644
--- a/source/blender/draw/engines/eevee_next/eevee_view.hh
+++ b/source/blender/draw/engines/eevee_next/eevee_view.hh
@@ -57,6 +57,7 @@ class ShadingView {
DRWView *sub_view_ = nullptr;
/** Same as sub_view_ but has Depth Of Field jitter applied. */
DRWView *render_view_ = nullptr;
+ View render_view_new_;
/** Render size of the view. Can change between scene sample eval. */
int2 extent_ = {-1, -1};
@@ -65,7 +66,7 @@ class ShadingView {
public:
ShadingView(Instance &inst, const char *name, const float (*face_matrix)[4])
- : inst_(inst), name_(name), face_matrix_(face_matrix){};
+ : inst_(inst), name_(name), face_matrix_(face_matrix), render_view_new_(name){};
~ShadingView(){};
diff --git a/source/blender/draw/engines/eevee_next/eevee_world.cc b/source/blender/draw/engines/eevee_next/eevee_world.cc
index 56cb0f127db..313c0bda42e 100644
--- a/source/blender/draw/engines/eevee_next/eevee_world.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_world.cc
@@ -42,10 +42,10 @@ DefaultWorldNodeTree::~DefaultWorldNodeTree()
MEM_SAFE_FREE(ntree_);
}
-/* Configure a default nodetree with the given world. */
+/* Configure a default node-tree with the given world. */
bNodeTree *DefaultWorldNodeTree::nodetree_get(::World *wo)
{
- /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */
+ /* WARNING: This function is not thread-safe. Which is not a problem for the moment. */
copy_v3_fl3(color_socket_->value, wo->horr, wo->horg, wo->horb);
return ntree_;
}
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_cryptomatte_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_cryptomatte_lib.glsl
new file mode 100644
index 00000000000..e874a6b56ea
--- /dev/null
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_cryptomatte_lib.glsl
@@ -0,0 +1,70 @@
+/** Storing/merging and sorting cryptomatte samples. */
+
+bool cryptomatte_can_merge_sample(vec2 dst, vec2 src)
+{
+ if (dst == vec2(0.0, 0.0)) {
+ return true;
+ }
+ if (dst.x == src.x) {
+ return true;
+ }
+ return false;
+}
+
+vec2 cryptomatte_merge_sample(vec2 dst, vec2 src)
+{
+ return vec2(src.x, dst.y + src.y);
+}
+
+vec4 cryptomatte_false_color(float hash)
+{
+ uint m3hash = floatBitsToUint(hash);
+ return vec4(hash,
+ float(m3hash << 8) / float(0xFFFFFFFFu),
+ float(m3hash << 16) / float(0xFFFFFFFFu),
+ 1.0);
+}
+
+void cryptomatte_clear_samples(FilmSample dst)
+{
+ int layer_len = imageSize(cryptomatte_img).z;
+ for (int i = 0; i < layer_len; i++) {
+ imageStore(cryptomatte_img, ivec3(dst.texel, i), vec4(0.0));
+ }
+}
+
+void cryptomatte_store_film_sample(FilmSample dst,
+ int cryptomatte_layer_id,
+ vec2 crypto_sample,
+ out vec4 out_color)
+{
+ if (crypto_sample.y == 0.0) {
+ return;
+ }
+ for (int i = 0; i < film_buf.cryptomatte_samples_len / 2; i++) {
+ ivec3 img_co = ivec3(dst.texel, cryptomatte_layer_id + i);
+ vec4 sample_pair = imageLoad(cryptomatte_img, img_co);
+ if (cryptomatte_can_merge_sample(sample_pair.xy, crypto_sample)) {
+ sample_pair.xy = cryptomatte_merge_sample(sample_pair.xy, crypto_sample);
+ /* In viewport only one layer is active. */
+ /* TODO(jbakker): we are displaying the first sample, but we should display the highest
+ * weighted one. */
+ if (cryptomatte_layer_id + i == 0) {
+ out_color = cryptomatte_false_color(sample_pair.x);
+ }
+ }
+ else if (cryptomatte_can_merge_sample(sample_pair.zw, crypto_sample)) {
+ sample_pair.zw = cryptomatte_merge_sample(sample_pair.zw, crypto_sample);
+ }
+ else if (i == film_buf.cryptomatte_samples_len / 2 - 1) {
+ /* TODO(jbakker): New hash detected, but there is no space left to store it. Currently we
+ * will ignore this sample, but ideally we could replace a sample with a lowest weight. */
+ continue;
+ }
+ else {
+ continue;
+ }
+ imageStore(cryptomatte_img, img_co, sample_pair);
+ break;
+ }
+}
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_accumulator_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_accumulator_lib.glsl
index 57f229feedb..99a47c541e9 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_accumulator_lib.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_accumulator_lib.glsl
@@ -665,7 +665,7 @@ void dof_slight_focus_gather(sampler2D depth_tx,
dof_gather_accumulate_resolve(total_sample_count, bg_accum, bg_col, bg_weight, unused_occlusion);
dof_gather_accumulate_resolve(total_sample_count, fg_accum, fg_col, fg_weight, unused_occlusion);
- /* Fix weighting issues on perfectly focus to slight focus transitionning areas. */
+ /* Fix weighting issues on perfectly focus to slight focus transitioning areas. */
if (abs(center_data.coc) < 0.5) {
bg_col = center_data.color;
bg_weight = 1.0;
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_filter_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_filter_comp.glsl
index c5c0e210109..49c93ca63cd 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_filter_comp.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_filter_comp.glsl
@@ -134,8 +134,8 @@ void main()
{
/**
* NOTE: We can **NOT** optimize by discarding some tiles as the result is sampled using bilinear
- * filtering in the resolve pass. Not outputing to a tile means that border texels have undefined
- * value and tile border will be noticeable in the final image.
+ * filtering in the resolve pass. Not outputting to a tile means that border texels have
+ * undefined value and tile border will be noticeable in the final image.
*/
cache_init();
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_gather_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_gather_comp.glsl
index e9905cd8aaf..cf8dd7a36e6 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_gather_comp.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_gather_comp.glsl
@@ -2,8 +2,8 @@
/**
* Gather pass: Convolve foreground and background parts in separate passes.
*
- * Using the min&max CoC tile buffer, we select the best apropriate method to blur the scene color.
- * A fast gather path is taken if there is not many CoC variation inside the tile.
+ * Using the min&max CoC tile buffer, we select the best appropriate method to blur the scene
+ *color. A fast gather path is taken if there is not many CoC variation inside the tile.
*
* We sample using an octaweb sampling pattern. We randomize the kernel center and each ring
* rotation to ensure maximum coverage.
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_hole_fill_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_hole_fill_comp.glsl
index 2b664520bba..5cdabbc2d4b 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_hole_fill_comp.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_hole_fill_comp.glsl
@@ -2,8 +2,8 @@
/**
* Holefill pass: Gather background parts where foreground is present.
*
- * Using the min&max CoC tile buffer, we select the best apropriate method to blur the scene color.
- * A fast gather path is taken if there is not many CoC variation inside the tile.
+ * Using the min&max CoC tile buffer, we select the best appropriate method to blur the scene
+ *color. A fast gather path is taken if there is not many CoC variation inside the tile.
*
* We sample using an octaweb sampling pattern. We randomize the kernel center and each ring
* rotation to ensure maximum coverage.
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_reduce_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_reduce_comp.glsl
index c757e8304ac..a6426cd06e4 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_reduce_comp.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_reduce_comp.glsl
@@ -8,7 +8,7 @@
* Inputs:
* - Output of setup pass (halfres) and reduce downsample pass (quarter res).
* Outputs:
- * - Halfres padded to avoid mipmap mis-alignment (so possibly not matching input size).
+ * - Halfres padded to avoid mipmap misalignment (so possibly not matching input size).
* - Gather input color (whole mip chain), Scatter rect list, Signed CoC (whole mip chain).
**/
@@ -98,7 +98,7 @@ void main()
do_scatter[LOCAL_INDEX] *= dof_scatter_screen_border_rejection(coc_cache[LOCAL_INDEX], texel);
/* Only scatter if neighborhood is different enough. */
do_scatter[LOCAL_INDEX] *= dof_scatter_neighborhood_rejection(color_cache[LOCAL_INDEX].rgb);
- /* For debuging. */
+ /* For debugging. */
if (no_scatter_pass) {
do_scatter[LOCAL_INDEX] = 0.0;
}
@@ -133,9 +133,9 @@ void main()
/* Issue a sprite for each field if any CoC matches. */
if (any(lessThan(do_scatter4 * sign(coc4), vec4(0.0)))) {
/* Same value for all threads. Not an issue if we don't sync access to it. */
- scatter_fg_indirect_buf.v_count = 4u;
+ scatter_fg_indirect_buf.vertex_len = 4u;
/* Issue 1 strip instance per sprite. */
- uint rect_id = atomicAdd(scatter_fg_indirect_buf.i_count, 1u);
+ uint rect_id = atomicAdd(scatter_fg_indirect_buf.instance_len, 1u);
if (rect_id < dof_buf.scatter_max_rect) {
vec4 coc4_fg = max(vec4(0.0), -coc4);
@@ -166,9 +166,9 @@ void main()
}
if (any(greaterThan(do_scatter4 * sign(coc4), vec4(0.0)))) {
/* Same value for all threads. Not an issue if we don't sync access to it. */
- scatter_bg_indirect_buf.v_count = 4u;
+ scatter_bg_indirect_buf.vertex_len = 4u;
/* Issue 1 strip instance per sprite. */
- uint rect_id = atomicAdd(scatter_bg_indirect_buf.i_count, 1u);
+ uint rect_id = atomicAdd(scatter_bg_indirect_buf.instance_len, 1u);
if (rect_id < dof_buf.scatter_max_rect) {
vec4 coc4_bg = max(vec4(0.0), coc4);
vec4 bg_weights = dof_layer_weight(coc4_bg) * dof_sample_weight(coc4_bg) * do_scatter4;
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_resolve_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_resolve_comp.glsl
index d21f6d69541..5123eb0c238 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_resolve_comp.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_resolve_comp.glsl
@@ -36,7 +36,7 @@ float dof_slight_focus_coc_tile_get(vec2 frag_coord)
}
/* Use atomic reduce operation. */
atomicMax(shared_max_slight_focus_abs_coc, floatBitsToUint(local_abs_max));
- /* "Broadcast" result accross all threads. */
+ /* "Broadcast" result across all threads. */
barrier();
return uintBitsToFloat(shared_max_slight_focus_abs_coc);
@@ -44,7 +44,7 @@ float dof_slight_focus_coc_tile_get(vec2 frag_coord)
vec3 dof_neighborhood_clamp(vec2 frag_coord, vec3 color, float center_coc, float weight)
{
- /* Stabilize color by clamping with the stable half res neighboorhood. */
+ /* Stabilize color by clamping with the stable half res neighborhood. */
vec3 neighbor_min, neighbor_max;
const vec2 corners[4] = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));
for (int i = 0; i < 4; i++) {
@@ -165,7 +165,7 @@ void main()
out_color = out_color * (1.0 - layer_weight) + layer_color;
}
- /* Fix float precision issue in alpha compositing. */
+ /* Fix float precision issue in alpha compositing. */
if (out_color.a > 0.99) {
out_color.a = 1.0;
}
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_stabilize_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_stabilize_comp.glsl
index b22af0e88f0..46a25b84840 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_stabilize_comp.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_depth_of_field_stabilize_comp.glsl
@@ -83,7 +83,7 @@ void dof_cache_init()
barrier();
}
-/* Note: Sample color space is already in YCoCg space. */
+/* NOTE: Sample color space is already in YCoCg space. */
DofSample dof_fetch_input_sample(ivec2 offset)
{
ivec2 coord = offset + 1 + ivec2(gl_LocalInvocationID.xy);
@@ -211,7 +211,7 @@ vec2 dof_pixel_history_motion_vector(ivec2 texel_sample)
return vector.xy * vec2(textureSize(color_tx, 0));
}
-/* Load color using a special filter to avoid loosing detail.
+/* Load color using a special filter to avoid losing detail.
* \a texel is sample position with subpixel accuracy. */
DofSample dof_sample_history(vec2 input_texel)
{
@@ -285,17 +285,17 @@ float dof_history_blend_factor(
/* 5% of incoming color by default. */
float blend = 0.05;
- /* Blend less history if the pixel has substential velocity. */
+ /* Blend less history if the pixel has substantial velocity. */
/* NOTE(fclem): velocity threshold multiplied by 2 because of half resolution. */
blend = mix(blend, 0.20, saturate(velocity * 0.02 * 2.0));
/**
* "High Quality Temporal Supersampling" by Brian Karis at Siggraph 2014 (Slide 43)
- * Bias towards history if incomming pixel is near clamping. Reduces flicker.
+ * Bias towards history if incoming pixel is near clamping. Reduces flicker.
*/
float distance_to_luma_clip = min_v2(vec2(luma_history - luma_min, luma_max - luma_history));
/* Divide by bbox size to get a factor. 2 factor to compensate the line above. */
distance_to_luma_clip *= 2.0 * safe_rcp(luma_max - luma_min);
- /* Linearly blend when history gets bellow to 25% of the bbox size. */
+ /* Linearly blend when history gets below to 25% of the bbox size. */
blend *= saturate(distance_to_luma_clip * 4.0 + 0.1);
/* Progressively discard history until history CoC is twice as big as the filtered CoC.
* Note we use absolute diff here because we are not comparing neighbors and thus do not risk to
@@ -335,7 +335,7 @@ void main()
DofSample dst = dof_sample_history(history_texel);
- /* Get local color bounding box of source neighboorhood. */
+ /* Get local color bounding box of source neighborhood. */
DofNeighborhoodMinMax bbox = dof_neighbor_boundbox();
float blend = dof_history_blend_factor(velocity, history_texel, bbox, src, dst);
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_film_cryptomatte_post_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_film_cryptomatte_post_comp.glsl
new file mode 100644
index 00000000000..120edd9c35e
--- /dev/null
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_film_cryptomatte_post_comp.glsl
@@ -0,0 +1,77 @@
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+
+#define CRYPTOMATTE_LEVELS_MAX 16
+
+void cryptomatte_load_samples(ivec2 texel, int layer, out vec2 samples[CRYPTOMATTE_LEVELS_MAX])
+{
+ int pass_len = divide_ceil(cryptomatte_samples_per_layer, 2);
+ int layer_id = layer * pass_len;
+
+ /* Read all samples from the cryptomatte layer. */
+ for (int p = 0; p < pass_len; p++) {
+ vec4 pass_sample = imageLoad(cryptomatte_img, ivec3(texel, p + layer_id));
+ samples[p * 2] = pass_sample.xy;
+ samples[p * 2 + 1] = pass_sample.zw;
+ }
+ for (int i = pass_len * 2; i < CRYPTOMATTE_LEVELS_MAX; i++) {
+ samples[i] = vec2(0.0);
+ }
+}
+
+void cryptomatte_sort_samples(inout vec2 samples[CRYPTOMATTE_LEVELS_MAX])
+{
+ /* Sort samples. Lame implementation, can be replaced with a more efficient algorithm. */
+ for (int i = 0; i < cryptomatte_samples_per_layer - 1 && samples[i].y != 0.0; i++) {
+ int highest_index = i;
+ float highest_weight = samples[i].y;
+ for (int j = i + 1; j < cryptomatte_samples_per_layer && samples[j].y != 0.0; j++) {
+ if (samples[j].y > highest_weight) {
+ highest_index = j;
+ highest_weight = samples[j].y;
+ }
+ };
+
+ if (highest_index != i) {
+ vec2 tmp = samples[i];
+ samples[i] = samples[highest_index];
+ samples[highest_index] = tmp;
+ }
+ }
+}
+void cryptomatte_normalize_weight(float total_weight, inout vec2 samples[CRYPTOMATTE_LEVELS_MAX])
+{
+ for (int i = 0; i < CRYPTOMATTE_LEVELS_MAX; i++) {
+ samples[i].y /= total_weight;
+ }
+}
+
+void cryptomatte_store_samples(ivec2 texel, int layer, in vec2 samples[CRYPTOMATTE_LEVELS_MAX])
+{
+ int pass_len = divide_ceil(cryptomatte_samples_per_layer, 2);
+ int layer_id = layer * pass_len;
+
+ /* Store samples back to the cryptomatte layer. */
+ for (int p = 0; p < pass_len; p++) {
+ vec4 pass_sample;
+ pass_sample.xy = samples[p * 2];
+ pass_sample.zw = samples[p * 2 + 1];
+ imageStore(cryptomatte_img, ivec3(texel, p + layer_id), pass_sample);
+ }
+}
+
+void main()
+{
+ ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
+ for (int layer = 0; layer < cryptomatte_layer_len; layer++) {
+ vec2 samples[CRYPTOMATTE_LEVELS_MAX];
+ cryptomatte_load_samples(texel, layer, samples);
+ cryptomatte_sort_samples(samples);
+ /* Repeat texture coordinates as the weight can be optimized to a small portion of the film. */
+ float weight = imageLoad(
+ weight_img,
+ ivec3(texel % imageSize(weight_img).xy, FILM_WEIGHT_LAYER_ACCUMULATION))
+ .x;
+ cryptomatte_normalize_weight(weight, samples);
+ cryptomatte_store_samples(texel, layer, samples);
+ }
+}
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_film_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_film_frag.glsl
index 26040234fd0..e2aaf9128a5 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_film_frag.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_film_frag.glsl
@@ -13,13 +13,17 @@ void main()
if (film_buf.display_id == -1) {
out_color = texelFetch(in_combined_tx, texel_film, 0);
}
- else if (film_buf.display_is_value) {
+ else if (film_buf.display_storage_type == PASS_STORAGE_VALUE) {
out_color.rgb = imageLoad(value_accum_img, ivec3(texel_film, film_buf.display_id)).rrr;
out_color.a = 1.0;
}
- else {
+ else if (film_buf.display_storage_type == PASS_STORAGE_COLOR) {
out_color = imageLoad(color_accum_img, ivec3(texel_film, film_buf.display_id));
}
+ else /* PASS_STORAGE_CRYPTOMATTE */ {
+ out_color = cryptomatte_false_color(
+ imageLoad(cryptomatte_img, ivec3(texel_film, film_buf.display_id)).r);
+ }
}
else {
film_process_data(texel_film, out_color, out_depth);
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl
index bf6293d5561..21b9a83abb9 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl
@@ -8,6 +8,7 @@
#pragma BLENDER_REQUIRE(eevee_camera_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_velocity_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_colorspace_lib.glsl)
+#pragma BLENDER_REQUIRE(eevee_cryptomatte_lib.glsl)
/* Return scene linear Z depth from the camera or radial depth for panoramic cameras. */
float film_depth_convert_to_scene(float depth)
@@ -105,12 +106,18 @@ void film_sample_accum(FilmSample samp, int pass_id, sampler2D tex, inout float
accum += texelFetch(tex, samp.texel, 0).x * samp.weight;
}
-void film_sample_accum(FilmSample samp, int pass_id, sampler2DArray tex, inout vec4 accum)
+void film_sample_accum(
+ FilmSample samp, int pass_id, uint layer, sampler2DArray tex, inout vec4 accum)
{
if (pass_id == -1) {
return;
}
- accum += texelFetch(tex, ivec3(samp.texel, pass_id), 0) * samp.weight;
+ accum += texelFetch(tex, ivec3(samp.texel, layer), 0) * samp.weight;
+}
+
+void film_sample_accum(FilmSample samp, int pass_id, sampler2DArray tex, inout vec4 accum)
+{
+ film_sample_accum(samp, pass_id, pass_id, tex, accum);
}
void film_sample_accum(FilmSample samp, int pass_id, sampler2DArray tex, inout float accum)
@@ -152,15 +159,51 @@ void film_sample_accum_combined(FilmSample samp, inout vec4 accum, inout float w
weight_accum += weight;
}
+void film_sample_cryptomatte_accum(FilmSample samp,
+ int layer,
+ sampler2D tex,
+ inout vec2 crypto_samples[4])
+{
+ float hash = texelFetch(tex, samp.texel, 0)[layer];
+ /* Find existing entry. */
+ for (int i = 0; i < 4; i++) {
+ if (crypto_samples[i].x == hash) {
+ crypto_samples[i].y += samp.weight;
+ return;
+ }
+ }
+ /* Overwrite entry with less weight. */
+ for (int i = 0; i < 4; i++) {
+ if (crypto_samples[i].y < samp.weight) {
+ crypto_samples[i] = vec2(hash, samp.weight);
+ return;
+ }
+ }
+}
+
+void film_cryptomatte_layer_accum_and_store(
+ FilmSample dst, ivec2 texel_film, int pass_id, int layer_component, inout vec4 out_color)
+{
+ if (pass_id == -1) {
+ return;
+ }
+ /* x = hash, y = accumed weight. Only keep track of 4 highest weighted samples. */
+ vec2 crypto_samples[4] = vec2[4](vec2(0.0), vec2(0.0), vec2(0.0), vec2(0.0));
+ for (int i = 0; i < film_buf.samples_len; i++) {
+ FilmSample src = film_sample_get(i, texel_film);
+ film_sample_cryptomatte_accum(src, layer_component, cryptomatte_tx, crypto_samples);
+ }
+ for (int i = 0; i < 4; i++) {
+ cryptomatte_store_film_sample(dst, pass_id, crypto_samples[i], out_color);
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
/** \name Load/Store Data
* \{ */
-#define WEIGHT_lAYER_ACCUMULATION 0
-#define WEIGHT_lAYER_DISTANCE 1
-
/* Returns the distance used to store nearest interpolation data. */
float film_distance_load(ivec2 texel)
{
@@ -170,7 +213,7 @@ float film_distance_load(ivec2 texel)
if (!film_buf.use_history || film_buf.use_reprojection) {
return 1.0e16;
}
- return imageLoad(in_weight_img, ivec3(texel, WEIGHT_lAYER_DISTANCE)).x;
+ return imageLoad(in_weight_img, ivec3(texel, FILM_WEIGHT_LAYER_DISTANCE)).x;
}
float film_weight_load(ivec2 texel)
@@ -181,7 +224,7 @@ float film_weight_load(ivec2 texel)
if (!film_buf.use_history || film_buf.use_reprojection) {
return 0.0;
}
- return imageLoad(in_weight_img, ivec3(texel, WEIGHT_lAYER_ACCUMULATION)).x;
+ return imageLoad(in_weight_img, ivec3(texel, FILM_WEIGHT_LAYER_ACCUMULATION)).x;
}
/* Returns motion in pixel space to retrieve the pixel history. */
@@ -544,12 +587,12 @@ void film_store_depth(ivec2 texel_film, float value, out float out_depth)
void film_store_distance(ivec2 texel, float value)
{
- imageStore(out_weight_img, ivec3(texel, WEIGHT_lAYER_DISTANCE), vec4(value));
+ imageStore(out_weight_img, ivec3(texel, FILM_WEIGHT_LAYER_DISTANCE), vec4(value));
}
void film_store_weight(ivec2 texel, float value)
{
- imageStore(out_weight_img, ivec3(texel, WEIGHT_lAYER_ACCUMULATION), vec4(value));
+ imageStore(out_weight_img, ivec3(texel, FILM_WEIGHT_LAYER_ACCUMULATION), vec4(value));
}
float film_display_depth_ammend(ivec2 texel, float depth)
@@ -632,8 +675,16 @@ void film_process_data(ivec2 texel_film, out vec4 out_color, out float out_depth
for (int i = 0; i < film_buf.samples_len; i++) {
FilmSample src = film_sample_get(i, texel_film);
- film_sample_accum(src, film_buf.diffuse_light_id, diffuse_light_tx, diffuse_light_accum);
- film_sample_accum(src, film_buf.specular_light_id, specular_light_tx, specular_light_accum);
+ film_sample_accum(src,
+ film_buf.diffuse_light_id,
+ RENDER_PASS_LAYER_DIFFUSE_LIGHT,
+ light_tx,
+ diffuse_light_accum);
+ film_sample_accum(src,
+ film_buf.specular_light_id,
+ RENDER_PASS_LAYER_SPECULAR_LIGHT,
+ light_tx,
+ specular_light_accum);
film_sample_accum(src, film_buf.volume_light_id, volume_light_tx, volume_light_accum);
film_sample_accum(src, film_buf.emission_id, emission_tx, emission_accum);
}
@@ -687,4 +738,18 @@ void film_process_data(ivec2 texel_film, out vec4 out_color, out float out_depth
}
film_store_value(dst, film_buf.aov_value_id + aov, aov_accum, out_color);
}
+
+ if (film_buf.cryptomatte_samples_len != 0) {
+ /* Cryptomatte passes cannot be cleared by a weighted store like other passes. */
+ if (!film_buf.use_history || film_buf.use_reprojection) {
+ cryptomatte_clear_samples(dst);
+ }
+
+ film_cryptomatte_layer_accum_and_store(
+ dst, texel_film, film_buf.cryptomatte_object_id, 0, out_color);
+ film_cryptomatte_layer_accum_and_store(
+ dst, texel_film, film_buf.cryptomatte_asset_id, 1, out_color);
+ film_cryptomatte_layer_accum_and_store(
+ dst, texel_film, film_buf.cryptomatte_material_id, 2, out_color);
+ }
}
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_hiz_debug_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_hiz_debug_frag.glsl
new file mode 100644
index 00000000000..e93d0f472fa
--- /dev/null
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_hiz_debug_frag.glsl
@@ -0,0 +1,24 @@
+
+/**
+ * Debug hiz down sampling pass.
+ * Output red if above any max pixels, blue otherwise.
+ */
+
+void main()
+{
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+
+ float depth0 = texelFetch(hiz_tx, texel, 0).r;
+
+ vec4 color = vec4(0.1, 0.1, 1.0, 1.0);
+ for (int i = 1; i < HIZ_MIP_COUNT; i++) {
+ ivec2 lvl_texel = texel / ivec2(uvec2(1) << uint(i));
+ lvl_texel = min(lvl_texel, textureSize(hiz_tx, i) - 1);
+ if (texelFetch(hiz_tx, lvl_texel, i).r < depth0) {
+ color = vec4(1.0, 0.1, 0.1, 1.0);
+ break;
+ }
+ }
+ out_debug_color_add = vec4(color.rgb, 0.0) * 0.2;
+ out_debug_color_mul = color;
+}
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_hiz_update_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_hiz_update_comp.glsl
new file mode 100644
index 00000000000..597bc73e2ad
--- /dev/null
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_hiz_update_comp.glsl
@@ -0,0 +1,121 @@
+
+/**
+ * Shader that down-sample depth buffer, creating a Hierarchical-Z buffer.
+ * Saves max value of each 2x2 texel in the mipmap above the one we are
+ * rendering to. Adapted from
+ * http://rastergrid.com/blog/2010/10/hierarchical-z-map-based-occlusion-culling/
+ *
+ * Major simplification has been made since we pad the buffer to always be
+ * bigger than input to avoid mipmapping misalignement.
+ *
+ * Start by copying the base level by quad loading the depth.
+ * Then each thread compute it's local depth for level 1.
+ * After that we use shared variables to do inter thread comunication and
+ * downsample to max level.
+ */
+
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+
+shared float local_depths[gl_WorkGroupSize.y][gl_WorkGroupSize.x];
+
+/* Load values from the previous lod level. */
+vec4 load_local_depths(ivec2 pixel)
+{
+ pixel *= 2;
+ return vec4(local_depths[pixel.y + 1][pixel.x + 0],
+ local_depths[pixel.y + 1][pixel.x + 1],
+ local_depths[pixel.y + 0][pixel.x + 1],
+ local_depths[pixel.y + 0][pixel.x + 0]);
+}
+
+void store_local_depth(ivec2 pixel, float depth)
+{
+ local_depths[pixel.y][pixel.x] = depth;
+}
+
+void main()
+{
+ ivec2 local_px = ivec2(gl_LocalInvocationID.xy);
+ /* Bottom left corner of the kernel. */
+ ivec2 kernel_origin = ivec2(gl_WorkGroupSize.xy * gl_WorkGroupID.xy);
+
+ /* Copy level 0. */
+ ivec2 src_px = ivec2(kernel_origin + local_px) * 2;
+ vec2 samp_co = (vec2(src_px) + 0.5) / vec2(textureSize(depth_tx, 0));
+ vec4 samp = textureGather(depth_tx, samp_co);
+
+ if (update_mip_0) {
+ imageStore(out_mip_0, src_px + ivec2(0, 1), samp.xxxx);
+ imageStore(out_mip_0, src_px + ivec2(1, 1), samp.yyyy);
+ imageStore(out_mip_0, src_px + ivec2(1, 0), samp.zzzz);
+ imageStore(out_mip_0, src_px + ivec2(0, 0), samp.wwww);
+ }
+
+ /* Level 1. (No load) */
+ float max_depth = max_v4(samp);
+ ivec2 dst_px = ivec2(kernel_origin + local_px);
+ imageStore(out_mip_1, dst_px, vec4(max_depth));
+ store_local_depth(local_px, max_depth);
+
+ /* Level 2-5. */
+ bool active_thread;
+ int mask_shift = 1;
+
+#define downsample_level(out_mip__, lod_) \
+ active_thread = all(lessThan(local_px, gl_WorkGroupSize.xy >> uint(mask_shift))); \
+ barrier(); /* Wait for previous writes to finish. */ \
+ if (active_thread) { \
+ max_depth = max_v4(load_local_depths(local_px)); \
+ dst_px = ivec2((kernel_origin >> mask_shift) + local_px); \
+ imageStore(out_mip__, dst_px, vec4(max_depth)); \
+ } \
+ barrier(); /* Wait for previous reads to finish. */ \
+ if (active_thread) { \
+ store_local_depth(local_px, max_depth); \
+ } \
+ mask_shift++;
+
+ downsample_level(out_mip_2, 2);
+ downsample_level(out_mip_3, 3);
+ downsample_level(out_mip_4, 4);
+ downsample_level(out_mip_5, 5);
+
+ /* Since we pad the destination texture, the mip size is equal to the dispatch size. */
+ uint tile_count = uint(imageSize(out_mip_5).x * imageSize(out_mip_5).y);
+ /* Let the last tile handle the remaining LOD. */
+ bool last_tile = atomicAdd(finished_tile_counter, 1u) + 1u < tile_count;
+ if (last_tile == false) {
+ return;
+ }
+ finished_tile_counter = 0u;
+
+ ivec2 iter = divide_ceil(imageSize(out_mip_5), ivec2(gl_WorkGroupSize * 2u));
+ ivec2 image_border = imageSize(out_mip_5) - 1;
+ for (int y = 0; y < iter.y; y++) {
+ for (int x = 0; x < iter.x; x++) {
+ /* Load result of the other work groups. */
+ kernel_origin = ivec2(gl_WorkGroupSize) * ivec2(x, y);
+ src_px = ivec2(kernel_origin + local_px) * 2;
+ vec4 samp;
+ samp.x = imageLoad(out_mip_5, min(src_px + ivec2(0, 1), image_border)).x;
+ samp.y = imageLoad(out_mip_5, min(src_px + ivec2(1, 1), image_border)).x;
+ samp.z = imageLoad(out_mip_5, min(src_px + ivec2(1, 0), image_border)).x;
+ samp.w = imageLoad(out_mip_5, min(src_px + ivec2(0, 0), image_border)).x;
+ /* Level 6. */
+ float max_depth = max_v4(samp);
+ ivec2 dst_px = ivec2(kernel_origin + local_px);
+ imageStore(out_mip_6, dst_px, vec4(max_depth));
+ store_local_depth(local_px, max_depth);
+
+ mask_shift = 1;
+
+ /* Level 7. */
+ downsample_level(out_mip_7, 7);
+
+ /* Limited by OpenGL maximum of 8 image slot. */
+ // downsample_level(out_mip_8, 8);
+ // downsample_level(out_mip_9, 9);
+ // downsample_level(out_mip_10, 10);
+ }
+ }
+}
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_debug_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_debug_frag.glsl
index 321c99f7952..eefc024d0b8 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_debug_frag.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_debug_frag.glsl
@@ -14,7 +14,7 @@ void main()
{
ivec2 texel = ivec2(gl_FragCoord.xy);
- float depth = texelFetch(depth_tx, texel, 0).r;
+ float depth = texelFetch(hiz_tx, texel, 0).r;
float vP_z = get_view_z_from_depth(depth);
vec3 P = get_world_space_from_depth(uvcoordsvar.xy, depth);
@@ -36,17 +36,19 @@ void main()
vec3 L;
float dist;
light_vector_get(light, P, L, dist);
- if (light_attenuation(light_buf[l_idx], L, dist) > 0.0) {
+ if (light_attenuation(light, L, dist) > 0.0) {
light_nocull |= 1u << l_idx;
}
}
LIGHT_FOREACH_END
+ vec4 color = vec4(heatmap_gradient(light_count / 4.0), 1.0);
+
if ((light_cull & light_nocull) != light_nocull) {
/* ERROR. Some lights were culled incorrectly. */
- out_debug_color = vec4(0.0, 1.0, 0.0, 1.0);
- }
- else {
- out_debug_color = vec4(heatmap_gradient(light_count / 4.0), 1.0);
+ color = vec4(0.0, 1.0, 0.0, 1.0);
}
-} \ No newline at end of file
+
+ out_debug_color_add = vec4(color.rgb, 0.0) * 0.2;
+ out_debug_color_mul = color;
+}
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_sort_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_sort_comp.glsl
index daf2016cd35..e98b170cd4c 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_sort_comp.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_sort_comp.glsl
@@ -25,7 +25,7 @@ void main()
int prefix_sum = 0;
/* Iterate over the whole key buffer. */
- uint iter = divide_ceil_u(light_cull_buf.visible_count, gl_WorkGroupSize.x);
+ uint iter = divide_ceil(light_cull_buf.visible_count, gl_WorkGroupSize.x);
for (uint i = 0u; i < iter; i++) {
uint index = gl_WorkGroupSize.x * i + gl_LocalInvocationID.x;
/* NOTE: This will load duplicated values, but they will be discarded. */
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_zbin_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_zbin_comp.glsl
index d96f191fb77..ae20153f26c 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_zbin_comp.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_zbin_comp.glsl
@@ -25,7 +25,7 @@ void main()
}
barrier();
- uint light_iter = divide_ceil_u(light_cull_buf.visible_count, gl_WorkGroupSize.x);
+ uint light_iter = divide_ceil(light_cull_buf.visible_count, gl_WorkGroupSize.x);
for (uint i = 0u; i < light_iter; i++) {
uint index = i * gl_WorkGroupSize.x + gl_LocalInvocationID.x;
if (index >= light_cull_buf.visible_count) {
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_motion_blur_dilate_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_motion_blur_dilate_comp.glsl
index 99186ab6f67..07139ea6a09 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_motion_blur_dilate_comp.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_motion_blur_dilate_comp.glsl
@@ -2,7 +2,6 @@
/**
* Dilate motion vector tiles until we covered maximum velocity.
* Outputs the largest intersecting motion vector in the neighborhood.
- *
*/
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
@@ -20,7 +19,7 @@ MotionRect compute_motion_rect(ivec2 tile, vec2 motion)
#if DEBUG_BYPASS_DILATION
return MotionRect(tile, ivec2(1));
#endif
- /* Ceil to number of tile touched.*/
+ /* Ceil to number of tile touched. */
ivec2 point1 = tile + ivec2(sign(motion) * ceil(abs(motion) / float(MOTION_BLUR_TILE_SIZE)));
ivec2 point2 = tile;
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl
index 13ad387289d..dd047709afd 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl
@@ -409,3 +409,31 @@ vec4 attr_load_color_post(vec4 attr)
#endif
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Uniform Attributes
+ *
+ * TODO(@fclem): These implementation details should concern the DRWManager and not be a fix on
+ * the engine side. But as of now, the engines are responsible for loading the attributes.
+ *
+ * \{ */
+
+vec4 attr_load_uniform(vec4 attr, const uint attr_hash)
+{
+#if defined(OBATTR_LIB)
+ uint index = floatBitsToUint(ObjectAttributeStart);
+ for (uint i = 0; i < floatBitsToUint(ObjectAttributeLen); i++, index++) {
+ if (drw_attrs[index].hash_code == attr_hash) {
+ return vec4(drw_attrs[index].data_x,
+ drw_attrs[index].data_y,
+ drw_attrs[index].data_z,
+ drw_attrs[index].data_w);
+ }
+ }
+ return vec4(0.0);
+#else
+ return attr;
+#endif
+}
+
+/** \} */
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_depth_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_depth_frag.glsl
index bd32215ddc2..183aac1e546 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_depth_frag.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_depth_frag.glsl
@@ -6,6 +6,7 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
+#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_nodetree_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_surf_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_velocity_lib.glsl)
@@ -73,8 +74,7 @@ void main()
nodetree_surface();
- // float noise_offset = sampling_rng_1D_get(SAMPLING_TRANSPARENCY);
- float noise_offset = 0.5;
+ float noise_offset = sampling_rng_1D_get(SAMPLING_TRANSPARENCY);
float random_threshold = hashed_alpha_threshold(1.0, noise_offset, g_data.P);
float transparency = avg(g_transmittance);
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl
index 26d2c066937..ab29067763d 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl
@@ -97,13 +97,20 @@ void main()
out_normal += g_refraction_data.N * g_refraction_data.weight;
out_normal = safe_normalize(out_normal);
+#ifdef MAT_RENDER_PASS_SUPPORT
ivec2 out_texel = ivec2(gl_FragCoord.xy);
imageStore(rp_normal_img, out_texel, vec4(out_normal, 1.0));
- imageStore(rp_diffuse_light_img, out_texel, vec4(diffuse_light, 1.0));
+ imageStore(
+ rp_light_img, ivec3(out_texel, RENDER_PASS_LAYER_DIFFUSE_LIGHT), vec4(diffuse_light, 1.0));
+ imageStore(
+ rp_light_img, ivec3(out_texel, RENDER_PASS_LAYER_SPECULAR_LIGHT), vec4(specular_light, 1.0));
imageStore(rp_diffuse_color_img, out_texel, vec4(g_diffuse_data.color, 1.0));
- imageStore(rp_specular_light_img, out_texel, vec4(specular_light, 1.0));
imageStore(rp_specular_color_img, out_texel, vec4(specular_color, 1.0));
imageStore(rp_emission_img, out_texel, vec4(g_emission, 1.0));
+ imageStore(rp_cryptomatte_img,
+ out_texel,
+ vec4(cryptomatte_object_buf[resource_id], node_tree.crypto_hash, 0.0));
+#endif
out_radiance.rgb *= 1.0 - g_holdout;
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_lib.glsl
index 30b48edaa78..6c1fc818f41 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_lib.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_lib.glsl
@@ -40,7 +40,7 @@ void init_globals_curves()
/* Shade as a cylinder. */
float cos_theta = interp.curves_time_width / interp.curves_thickness;
float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));
- g_data.N = normalize(interp.N * sin_theta + interp.curves_binormal * cos_theta);
+ g_data.N = g_data.Ni = normalize(interp.N * sin_theta + interp.curves_binormal * cos_theta);
/* Costly, but follows cycles per pixel tangent space (not following curve shape). */
vec3 V = cameraVec(g_data.P);
@@ -60,13 +60,14 @@ void init_globals_curves()
void init_globals_gpencil()
{
/* Undo backface flip as the gpencil normal is already pointing towards the camera. */
- g_data.N = interp.N;
+ g_data.N = g_data.Ni = interp.N;
}
void init_globals()
{
/* Default values. */
g_data.P = interp.P;
+ g_data.Ni = interp.N;
g_data.N = safe_normalize(interp.N);
g_data.Ng = g_data.N;
g_data.is_strand = false;
@@ -81,6 +82,7 @@ void init_globals()
#ifdef GPU_FRAGMENT_SHADER
g_data.N = (FrontFacing) ? g_data.N : -g_data.N;
+ g_data.Ni = (FrontFacing) ? g_data.Ni : -g_data.Ni;
g_data.Ng = safe_normalize(cross(dFdx(g_data.P), dFdy(g_data.P)));
#endif
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_world_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_world_frag.glsl
index ed75282a550..442c2579c84 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_world_frag.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_world_frag.glsl
@@ -26,11 +26,14 @@ void main()
ivec2 out_texel = ivec2(gl_FragCoord.xy);
imageStore(rp_normal_img, out_texel, vec4(0.0, 0.0, 0.0, 1.0));
- imageStore(rp_diffuse_light_img, out_texel, vec4(0.0, 0.0, 0.0, 1.0));
+ imageStore(
+ rp_light_img, ivec3(out_texel, RENDER_PASS_LAYER_DIFFUSE_LIGHT), vec4(0.0, 0.0, 0.0, 1.0));
+ imageStore(
+ rp_light_img, ivec3(out_texel, RENDER_PASS_LAYER_SPECULAR_LIGHT), vec4(0.0, 0.0, 0.0, 1.0));
imageStore(rp_diffuse_color_img, out_texel, vec4(0.0, 0.0, 0.0, 1.0));
- imageStore(rp_specular_light_img, out_texel, vec4(0.0, 0.0, 0.0, 1.0));
imageStore(rp_specular_color_img, out_texel, vec4(0.0, 0.0, 0.0, 1.0));
imageStore(rp_emission_img, out_texel, vec4(0.0, 0.0, 0.0, 1.0));
+ imageStore(rp_cryptomatte_img, out_texel, vec4(0.0));
out_background.rgb = safe_color(g_emission) * (1.0 - g_holdout);
out_background.a = saturate(avg(g_transmittance)) * g_holdout;
diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_depth_of_field_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_depth_of_field_info.hh
index b398a6cc4e7..b689a7f53a2 100644
--- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_depth_of_field_info.hh
+++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_depth_of_field_info.hh
@@ -11,7 +11,7 @@ GPU_SHADER_CREATE_INFO(eevee_depth_of_field_bokeh_lut)
.do_static_compilation(true)
.local_group_size(DOF_BOKEH_LUT_SIZE, DOF_BOKEH_LUT_SIZE)
.additional_info("eevee_shared", "draw_view")
- .uniform_buf(1, "DepthOfFieldData", "dof_buf")
+ .uniform_buf(6, "DepthOfFieldData", "dof_buf")
.image(0, GPU_RG16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_gather_lut_img")
.image(1, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_scatter_lut_img")
.image(2, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_resolve_lut_img")
@@ -21,7 +21,7 @@ GPU_SHADER_CREATE_INFO(eevee_depth_of_field_setup)
.do_static_compilation(true)
.local_group_size(DOF_DEFAULT_GROUP_SIZE, DOF_DEFAULT_GROUP_SIZE)
.additional_info("eevee_shared", "draw_view")
- .uniform_buf(1, "DepthOfFieldData", "dof_buf")
+ .uniform_buf(6, "DepthOfFieldData", "dof_buf")
.sampler(0, ImageType::FLOAT_2D, "color_tx")
.sampler(1, ImageType::DEPTH_2D, "depth_tx")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_color_img")
@@ -32,7 +32,7 @@ GPU_SHADER_CREATE_INFO(eevee_depth_of_field_stabilize)
.do_static_compilation(true)
.local_group_size(DOF_STABILIZE_GROUP_SIZE, DOF_STABILIZE_GROUP_SIZE)
.additional_info("eevee_shared", "draw_view", "eevee_velocity_camera")
- .uniform_buf(4, "DepthOfFieldData", "dof_buf")
+ .uniform_buf(6, "DepthOfFieldData", "dof_buf")
.sampler(0, ImageType::FLOAT_2D, "coc_tx")
.sampler(1, ImageType::FLOAT_2D, "color_tx")
.sampler(2, ImageType::FLOAT_2D, "velocity_tx")
@@ -57,7 +57,7 @@ GPU_SHADER_CREATE_INFO(eevee_depth_of_field_reduce)
.do_static_compilation(true)
.local_group_size(DOF_REDUCE_GROUP_SIZE, DOF_REDUCE_GROUP_SIZE)
.additional_info("eevee_shared", "draw_view")
- .uniform_buf(1, "DepthOfFieldData", "dof_buf")
+ .uniform_buf(6, "DepthOfFieldData", "dof_buf")
.sampler(0, ImageType::FLOAT_2D, "downsample_tx")
.storage_buf(0, Qualifier::WRITE, "ScatterRect", "scatter_fg_list_buf[]")
.storage_buf(1, Qualifier::WRITE, "ScatterRect", "scatter_bg_list_buf[]")
@@ -154,7 +154,7 @@ GPU_SHADER_CREATE_INFO(eevee_depth_of_field_gather_common)
"draw_view",
"eevee_depth_of_field_tiles_common",
"eevee_sampling_data")
- .uniform_buf(2, "DepthOfFieldData", "dof_buf")
+ .uniform_buf(6, "DepthOfFieldData", "dof_buf")
.local_group_size(DOF_GATHER_GROUP_SIZE, DOF_GATHER_GROUP_SIZE)
.sampler(0, ImageType::FLOAT_2D, "color_tx")
.sampler(1, ImageType::FLOAT_2D, "color_bilinear_tx")
@@ -229,7 +229,7 @@ GPU_SHADER_CREATE_INFO(eevee_depth_of_field_resolve)
"draw_view",
"eevee_depth_of_field_tiles_common",
"eevee_sampling_data")
- .uniform_buf(2, "DepthOfFieldData", "dof_buf")
+ .uniform_buf(6, "DepthOfFieldData", "dof_buf")
.sampler(0, ImageType::DEPTH_2D, "depth_tx")
.sampler(1, ImageType::FLOAT_2D, "color_tx")
.sampler(2, ImageType::FLOAT_2D, "color_bg_tx")
diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_film_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_film_info.hh
index a5baaca51f9..4541f14d96c 100644
--- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_film_info.hh
+++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_film_info.hh
@@ -4,25 +4,24 @@
#include "gpu_shader_create_info.hh"
GPU_SHADER_CREATE_INFO(eevee_film)
- .uniform_buf(4, "FilmData", "film_buf")
+ .uniform_buf(6, "FilmData", "film_buf")
.sampler(0, ImageType::DEPTH_2D, "depth_tx")
.sampler(1, ImageType::FLOAT_2D, "combined_tx")
.sampler(2, ImageType::FLOAT_2D, "normal_tx")
.sampler(3, ImageType::FLOAT_2D, "vector_tx")
- .sampler(4, ImageType::FLOAT_2D, "diffuse_light_tx")
+ .sampler(4, ImageType::FLOAT_2D_ARRAY, "light_tx")
.sampler(5, ImageType::FLOAT_2D, "diffuse_color_tx")
- .sampler(6, ImageType::FLOAT_2D, "specular_light_tx")
- .sampler(7, ImageType::FLOAT_2D, "specular_color_tx")
- .sampler(8, ImageType::FLOAT_2D, "volume_light_tx")
- .sampler(9, ImageType::FLOAT_2D, "emission_tx")
- .sampler(10, ImageType::FLOAT_2D, "environment_tx")
- .sampler(11, ImageType::FLOAT_2D, "shadow_tx")
- .sampler(12, ImageType::FLOAT_2D, "ambient_occlusion_tx")
- .sampler(13, ImageType::FLOAT_2D_ARRAY, "aov_color_tx")
- .sampler(14, ImageType::FLOAT_2D_ARRAY, "aov_value_tx")
+ .sampler(6, ImageType::FLOAT_2D, "specular_color_tx")
+ .sampler(7, ImageType::FLOAT_2D, "volume_light_tx")
+ .sampler(8, ImageType::FLOAT_2D, "emission_tx")
+ .sampler(9, ImageType::FLOAT_2D, "environment_tx")
+ .sampler(10, ImageType::FLOAT_2D, "shadow_tx")
+ .sampler(11, ImageType::FLOAT_2D, "ambient_occlusion_tx")
+ .sampler(12, ImageType::FLOAT_2D_ARRAY, "aov_color_tx")
+ .sampler(13, ImageType::FLOAT_2D_ARRAY, "aov_value_tx")
/* Color History for TAA needs to be sampler to leverage bilinear sampling. */
- .sampler(15, ImageType::FLOAT_2D, "in_combined_tx")
- // .sampler(15, ImageType::FLOAT_2D, "cryptomatte_tx") /* TODO */
+ .sampler(14, ImageType::FLOAT_2D, "in_combined_tx")
+ .sampler(15, ImageType::FLOAT_2D, "cryptomatte_tx")
.image(0, GPU_R32F, Qualifier::READ, ImageType::FLOAT_2D_ARRAY, "in_weight_img")
.image(1, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_weight_img")
/* Color History for TAA needs to be sampler to leverage bilinear sampling. */
@@ -31,6 +30,7 @@ GPU_SHADER_CREATE_INFO(eevee_film)
.image(4, GPU_R32F, Qualifier::READ_WRITE, ImageType::FLOAT_2D, "depth_img")
.image(5, GPU_RGBA16F, Qualifier::READ_WRITE, ImageType::FLOAT_2D_ARRAY, "color_accum_img")
.image(6, GPU_R16F, Qualifier::READ_WRITE, ImageType::FLOAT_2D_ARRAY, "value_accum_img")
+ .image(7, GPU_RGBA32F, Qualifier::READ_WRITE, ImageType::FLOAT_2D_ARRAY, "cryptomatte_img")
.additional_info("eevee_shared")
.additional_info("eevee_velocity_camera")
.additional_info("draw_view");
@@ -46,3 +46,13 @@ GPU_SHADER_CREATE_INFO(eevee_film_comp)
.local_group_size(FILM_GROUP_SIZE, FILM_GROUP_SIZE)
.compute_source("eevee_film_comp.glsl")
.additional_info("eevee_film");
+
+GPU_SHADER_CREATE_INFO(eevee_film_cryptomatte_post)
+ .do_static_compilation(true)
+ .image(0, GPU_RGBA32F, Qualifier::READ_WRITE, ImageType::FLOAT_2D_ARRAY, "cryptomatte_img")
+ .image(1, GPU_R32F, Qualifier::READ, ImageType::FLOAT_2D_ARRAY, "weight_img")
+ .push_constant(Type::INT, "cryptomatte_layer_len")
+ .push_constant(Type::INT, "cryptomatte_samples_per_layer")
+ .local_group_size(FILM_GROUP_SIZE, FILM_GROUP_SIZE)
+ .compute_source("eevee_film_cryptomatte_post_comp.glsl")
+ .additional_info("eevee_shared");
diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_hiz_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_hiz_info.hh
new file mode 100644
index 00000000000..5e32631a8f8
--- /dev/null
+++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_hiz_info.hh
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "eevee_defines.hh"
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(eevee_hiz_data)
+ .sampler(15, ImageType::FLOAT_2D, "hiz_tx")
+ .uniform_buf(5, "HiZData", "hiz_buf");
+
+GPU_SHADER_CREATE_INFO(eevee_hiz_update)
+ .do_static_compilation(true)
+ .local_group_size(FILM_GROUP_SIZE, FILM_GROUP_SIZE)
+ .storage_buf(0, Qualifier::READ_WRITE, "uint", "finished_tile_counter")
+ .sampler(0, ImageType::DEPTH_2D, "depth_tx")
+ .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_mip_0")
+ .image(1, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_mip_1")
+ .image(2, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_mip_2")
+ .image(3, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_mip_3")
+ .image(4, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_mip_4")
+ .image(5, GPU_R32F, Qualifier::READ_WRITE, ImageType::FLOAT_2D, "out_mip_5")
+ .image(6, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_mip_6")
+ .image(7, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_mip_7")
+ .push_constant(Type::BOOL, "update_mip_0")
+ .compute_source("eevee_hiz_update_comp.glsl");
+
+GPU_SHADER_CREATE_INFO(eevee_hiz_debug)
+ .do_static_compilation(true)
+ .fragment_out(0, Type::VEC4, "out_debug_color_add", DualBlend::SRC_0)
+ .fragment_out(0, Type::VEC4, "out_debug_color_mul", DualBlend::SRC_1)
+ .fragment_source("eevee_hiz_debug_frag.glsl")
+ .additional_info("eevee_shared", "eevee_hiz_data", "draw_fullscreen");
diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_light_culling_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_light_culling_info.hh
index 56fda25ed13..41602426a1d 100644
--- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_light_culling_info.hh
+++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_light_culling_info.hh
@@ -8,10 +8,10 @@
* \{ */
GPU_SHADER_CREATE_INFO(eevee_light_data)
- .storage_buf(0, Qualifier::READ, "LightCullingData", "light_cull_buf")
- .storage_buf(1, Qualifier::READ, "LightData", "light_buf[]")
- .storage_buf(2, Qualifier::READ, "uint", "light_zbin_buf[]")
- .storage_buf(3, Qualifier::READ, "uint", "light_tile_buf[]");
+ .storage_buf(LIGHT_CULL_BUF_SLOT, Qualifier::READ, "LightCullingData", "light_cull_buf")
+ .storage_buf(LIGHT_BUF_SLOT, Qualifier::READ, "LightData", "light_buf[]")
+ .storage_buf(LIGHT_ZBIN_BUF_SLOT, Qualifier::READ, "uint", "light_zbin_buf[]")
+ .storage_buf(LIGHT_TILE_BUF_SLOT, Qualifier::READ, "uint", "light_tile_buf[]");
/** \} */
@@ -67,10 +67,10 @@ GPU_SHADER_CREATE_INFO(eevee_light_culling_tile)
GPU_SHADER_CREATE_INFO(eevee_light_culling_debug)
.do_static_compilation(true)
- .sampler(0, ImageType::DEPTH_2D, "depth_tx")
- .fragment_out(0, Type::VEC4, "out_debug_color")
- .additional_info("eevee_shared", "draw_view")
+ .fragment_out(0, Type::VEC4, "out_debug_color_add", DualBlend::SRC_0)
+ .fragment_out(0, Type::VEC4, "out_debug_color_mul", DualBlend::SRC_1)
.fragment_source("eevee_light_culling_debug_frag.glsl")
- .additional_info("draw_fullscreen", "eevee_light_data");
+ .additional_info(
+ "eevee_shared", "draw_view", "draw_fullscreen", "eevee_light_data", "eevee_hiz_data");
/** \} */
diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh
index 6929dec1150..78d52d4b90e 100644
--- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh
+++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "eevee_defines.hh"
#include "gpu_shader_create_info.hh"
/* -------------------------------------------------------------------- */
@@ -14,9 +15,10 @@ GPU_SHADER_CREATE_INFO(eevee_shared)
GPU_SHADER_CREATE_INFO(eevee_sampling_data)
.define("EEVEE_SAMPLING_DATA")
.additional_info("eevee_shared")
- .storage_buf(14, Qualifier::READ, "SamplingData", "sampling_buf");
+ .storage_buf(6, Qualifier::READ, "SamplingData", "sampling_buf");
-GPU_SHADER_CREATE_INFO(eevee_utility_texture).sampler(8, ImageType::FLOAT_2D_ARRAY, "utility_tx");
+GPU_SHADER_CREATE_INFO(eevee_utility_texture)
+ .sampler(RBUFS_UTILITY_TEX_SLOT, ImageType::FLOAT_2D_ARRAY, "utility_tx");
/** \} */
@@ -30,7 +32,7 @@ GPU_SHADER_CREATE_INFO(eevee_geom_mesh)
.vertex_in(0, Type::VEC3, "pos")
.vertex_in(1, Type::VEC3, "nor")
.vertex_source("eevee_geom_mesh_vert.glsl")
- .additional_info("draw_mesh", "draw_resource_id_varying", "draw_resource_handle");
+ .additional_info("draw_modelmat_new", "draw_resource_id_varying", "draw_view");
GPU_SHADER_CREATE_INFO(eevee_geom_gpencil)
.additional_info("eevee_shared")
@@ -52,7 +54,7 @@ GPU_SHADER_CREATE_INFO(eevee_geom_world)
.define("MAT_GEOM_WORLD")
.builtins(BuiltinBits::VERTEX_ID)
.vertex_source("eevee_geom_world_vert.glsl")
- .additional_info("draw_modelmat", "draw_resource_id_varying", "draw_resource_handle");
+ .additional_info("draw_modelmat_new", "draw_resource_id_varying", "draw_view");
/** \} */
@@ -78,9 +80,21 @@ GPU_SHADER_INTERFACE_INFO(eevee_surf_iface, "interp")
GPU_SHADER_CREATE_INFO(eevee_aov_out)
.define("MAT_AOV_SUPPORT")
- .image_array_out(6, Qualifier::WRITE, GPU_RGBA16F, "aov_color_img")
- .image_array_out(7, Qualifier::WRITE, GPU_R16F, "aov_value_img")
- .storage_buf(7, Qualifier::READ, "AOVsInfoData", "aov_buf");
+ .image_array_out(RBUFS_AOV_COLOR_SLOT, Qualifier::WRITE, GPU_RGBA16F, "aov_color_img")
+ .image_array_out(RBUFS_AOV_VALUE_SLOT, Qualifier::WRITE, GPU_R16F, "aov_value_img")
+ .storage_buf(RBUFS_AOV_BUF_SLOT, Qualifier::READ, "AOVsInfoData", "aov_buf");
+
+GPU_SHADER_CREATE_INFO(eevee_render_pass_out)
+ .define("MAT_RENDER_PASS_SUPPORT")
+ .image_out(RBUFS_NORMAL_SLOT, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_normal_img")
+ .image_array_out(RBUFS_LIGHT_SLOT, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_light_img")
+ .image_out(RBUFS_DIFF_COLOR_SLOT, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_diffuse_color_img")
+ .image_out(RBUFS_SPEC_COLOR_SLOT, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_specular_color_img")
+ .image_out(RBUFS_EMISSION_SLOT, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_emission_img");
+
+GPU_SHADER_CREATE_INFO(eevee_cryptomatte_out)
+ .storage_buf(7, Qualifier::READ, "vec2", "cryptomatte_object_buf[]", Frequency::PASS)
+ .image_out(7, Qualifier::WRITE, GPU_RGBA32F, "rp_cryptomatte_img");
GPU_SHADER_CREATE_INFO(eevee_surf_deferred)
.vertex_out(eevee_surf_iface)
@@ -104,7 +118,6 @@ GPU_SHADER_CREATE_INFO(eevee_surf_deferred)
;
GPU_SHADER_CREATE_INFO(eevee_surf_forward)
- .auto_resource_location(true)
.vertex_out(eevee_surf_iface)
/* Early fragment test is needed for render passes support for forward surfaces. */
/* NOTE: This removes the possibility of using gl_FragDepth. */
@@ -112,43 +125,33 @@ GPU_SHADER_CREATE_INFO(eevee_surf_forward)
.fragment_out(0, Type::VEC4, "out_radiance", DualBlend::SRC_0)
.fragment_out(0, Type::VEC4, "out_transmittance", DualBlend::SRC_1)
.fragment_source("eevee_surf_forward_frag.glsl")
- .image_out(0, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_normal_img")
- .image_out(1, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_diffuse_light_img")
- .image_out(2, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_diffuse_color_img")
- .image_out(3, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_specular_light_img")
- .image_out(4, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_specular_color_img")
- .image_out(5, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_emission_img")
- .additional_info("eevee_aov_out",
+ .additional_info("eevee_cryptomatte_out",
"eevee_light_data",
"eevee_utility_texture",
"eevee_sampling_data"
- // "eevee_lightprobe_data",
+ // "eevee_lightprobe_data",
+ // "eevee_shadow_data"
/* Optionally added depending on the material. */
// "eevee_raytrace_data",
// "eevee_transmittance_data",
- // "eevee_shadow_data"
+ // "eevee_aov_out",
+ // "eevee_render_pass_out",
);
GPU_SHADER_CREATE_INFO(eevee_surf_depth)
.vertex_out(eevee_surf_iface)
.fragment_source("eevee_surf_depth_frag.glsl")
- // .additional_info("eevee_sampling_data", "eevee_utility_texture")
- ;
+ .additional_info("eevee_sampling_data", "eevee_utility_texture");
GPU_SHADER_CREATE_INFO(eevee_surf_world)
.vertex_out(eevee_surf_iface)
- .image_out(0, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_normal_img")
- .image_out(1, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_diffuse_light_img")
- .image_out(2, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_diffuse_color_img")
- .image_out(3, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_specular_light_img")
- .image_out(4, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_specular_color_img")
- .image_out(5, Qualifier::READ_WRITE, GPU_RGBA16F, "rp_emission_img")
.push_constant(Type::FLOAT, "world_opacity_fade")
.fragment_out(0, Type::VEC4, "out_background")
.fragment_source("eevee_surf_world_frag.glsl")
- .additional_info("eevee_aov_out"
- //"eevee_utility_texture"
- );
+ .additional_info("eevee_aov_out",
+ "eevee_cryptomatte_out",
+ "eevee_render_pass_out",
+ "eevee_utility_texture");
#undef image_out
#undef image_array_out
@@ -190,10 +193,7 @@ GPU_SHADER_CREATE_INFO(eevee_volume_deferred)
GPU_SHADER_CREATE_INFO(eevee_material_stub).define("EEVEE_MATERIAL_STUBS");
# define EEVEE_MAT_FINAL_VARIATION(name, ...) \
- GPU_SHADER_CREATE_INFO(name) \
- .additional_info(__VA_ARGS__) \
- .auto_resource_location(true) \
- .do_static_compilation(true);
+ GPU_SHADER_CREATE_INFO(name).additional_info(__VA_ARGS__).do_static_compilation(true);
# define EEVEE_MAT_GEOM_VARIATIONS(prefix, ...) \
EEVEE_MAT_FINAL_VARIATION(prefix##_world, "eevee_geom_world", __VA_ARGS__) \
diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_motion_blur_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_motion_blur_info.hh
index d6ff34b0ed2..ec302ec6770 100644
--- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_motion_blur_info.hh
+++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_motion_blur_info.hh
@@ -6,7 +6,7 @@
GPU_SHADER_CREATE_INFO(eevee_motion_blur_tiles_flatten)
.local_group_size(MOTION_BLUR_GROUP_SIZE, MOTION_BLUR_GROUP_SIZE)
.additional_info("eevee_shared", "draw_view", "eevee_velocity_camera")
- .uniform_buf(4, "MotionBlurData", "motion_blur_buf")
+ .uniform_buf(6, "MotionBlurData", "motion_blur_buf")
.sampler(0, ImageType::DEPTH_2D, "depth_tx")
.image(1, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_tiles_img")
.compute_source("eevee_motion_blur_flatten_comp.glsl");
@@ -35,7 +35,7 @@ GPU_SHADER_CREATE_INFO(eevee_motion_blur_gather)
.do_static_compilation(true)
.local_group_size(MOTION_BLUR_GROUP_SIZE, MOTION_BLUR_GROUP_SIZE)
.additional_info("eevee_shared", "draw_view", "eevee_sampling_data")
- .uniform_buf(4, "MotionBlurData", "motion_blur_buf")
+ .uniform_buf(6, "MotionBlurData", "motion_blur_buf")
.sampler(0, ImageType::DEPTH_2D, "depth_tx")
.sampler(1, ImageType::FLOAT_2D, "velocity_tx")
.sampler(2, ImageType::FLOAT_2D, "in_color_tx")
diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_velocity_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_velocity_info.hh
index 6e8e8fb020a..0a1c2721c61 100644
--- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_velocity_info.hh
+++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_velocity_info.hh
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "eevee_defines.hh"
#include "gpu_shader_create_info.hh"
/* -------------------------------------------------------------------- */
@@ -17,19 +18,20 @@ GPU_SHADER_INTERFACE_INFO(eevee_velocity_surface_iface, "motion")
GPU_SHADER_CREATE_INFO(eevee_velocity_camera)
.define("VELOCITY_CAMERA")
- .uniform_buf(1, "CameraData", "camera_prev")
- .uniform_buf(2, "CameraData", "camera_curr")
- .uniform_buf(3, "CameraData", "camera_next");
+ .uniform_buf(VELOCITY_CAMERA_PREV_BUF, "CameraData", "camera_prev")
+ .uniform_buf(VELOCITY_CAMERA_CURR_BUF, "CameraData", "camera_curr")
+ .uniform_buf(VELOCITY_CAMERA_NEXT_BUF, "CameraData", "camera_next");
GPU_SHADER_CREATE_INFO(eevee_velocity_geom)
.define("MAT_VELOCITY")
- .auto_resource_location(true)
- .storage_buf(4, Qualifier::READ, "mat4", "velocity_obj_prev_buf[]", Frequency::PASS)
- .storage_buf(5, Qualifier::READ, "mat4", "velocity_obj_next_buf[]", Frequency::PASS)
- .storage_buf(6, Qualifier::READ, "vec4", "velocity_geo_prev_buf[]", Frequency::PASS)
- .storage_buf(7, Qualifier::READ, "vec4", "velocity_geo_next_buf[]", Frequency::PASS)
- .storage_buf(
- 7, Qualifier::READ, "VelocityIndex", "velocity_indirection_buf[]", Frequency::PASS)
+ .storage_buf(VELOCITY_OBJ_PREV_BUF_SLOT, Qualifier::READ, "mat4", "velocity_obj_prev_buf[]")
+ .storage_buf(VELOCITY_OBJ_NEXT_BUF_SLOT, Qualifier::READ, "mat4", "velocity_obj_next_buf[]")
+ .storage_buf(VELOCITY_GEO_PREV_BUF_SLOT, Qualifier::READ, "vec4", "velocity_geo_prev_buf[]")
+ .storage_buf(VELOCITY_GEO_NEXT_BUF_SLOT, Qualifier::READ, "vec4", "velocity_geo_next_buf[]")
+ .storage_buf(VELOCITY_INDIRECTION_BUF_SLOT,
+ Qualifier::READ,
+ "VelocityIndex",
+ "velocity_indirection_buf[]")
.vertex_out(eevee_velocity_surface_iface)
.fragment_out(0, Type::VEC4, "out_velocity")
.additional_info("eevee_velocity_camera");