Overlay Next: Refactor #107734
@ -597,6 +597,8 @@ set(GLSL_SRC
|
||||
engines/select/shaders/select_id_frag.glsl
|
||||
engines/select/shaders/select_lib.glsl
|
||||
|
||||
engines/select/select_shader_shared.hh
|
||||
|
||||
engines/basic/shaders/basic_conservative_depth_geom.glsl
|
||||
engines/basic/shaders/basic_depth_vert.glsl
|
||||
engines/basic/shaders/basic_depth_vert_conservative_no_geom.glsl
|
||||
|
@ -15,8 +15,7 @@
|
||||
#include "overlay_prepass.hh"
|
||||
#include "overlay_shape.hh"
|
||||
|
||||
#include "../select/select_empty.hh"
|
||||
#include "../select/select_object.hh"
|
||||
#include "../select/select_instance.hh"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
@ -25,7 +24,7 @@ template<
|
||||
* selectable component and using a special shaders for drawing.
|
||||
* Making the select engine templated makes it easier to phase out any overhead of the
|
||||
* selection for the regular non-selection case.*/
|
||||
typename SelectEngineT = select::EngineEmpty>
|
||||
typename SelectEngineT = select::Instance>
|
||||
class Instance {
|
||||
public:
|
||||
/* WORKAROUND: Legacy. Move to grid pass. */
|
||||
|
@ -88,6 +88,8 @@ template<typename SelectEngineT> class Metaballs {
|
||||
pass.init();
|
||||
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
|
||||
state.clipping_state);
|
||||
/* NOTE: Use armature sphere outline shader to have perspective correct outline instead of
|
||||
* just a circle facing the camera. */
|
||||
pass.shader_set(res.shaders.armature_sphere_outline);
|
||||
pass.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
res.select_bind(pass);
|
||||
|
@ -46,7 +46,7 @@ template<typename SelectEngineT> class Prepass {
|
||||
GPUBatch *geom = DRW_cache_object_surface_get(ob_ref.object);
|
||||
if (geom) {
|
||||
ResourceHandle res_handle = manager.resource_handle(ob_ref);
|
||||
pass.draw(geom, res_handle, res.select_id(ob_ref).value);
|
||||
pass.draw(geom, res_handle, res.select_id(ob_ref).get());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1236,15 +1236,16 @@ void OVERLAY_shader_free(void)
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
template<>
|
||||
ShaderModule<select::EngineEmpty> *ShaderModule<select::EngineEmpty>::g_shader_module = nullptr;
|
||||
ShaderModule<select::Instance> *ShaderModule<select::Instance>::g_shader_module = nullptr;
|
||||
|
||||
template<>
|
||||
ShaderModule<select::EngineObject> *ShaderModule<select::EngineObject>::g_shader_module = nullptr;
|
||||
ShaderModule<select::InstanceDummy> *ShaderModule<select::InstanceDummy>::g_shader_module =
|
||||
nullptr;
|
||||
|
||||
void shader_module_free()
|
||||
{
|
||||
ShaderModule<select::EngineEmpty>::module_free();
|
||||
ShaderModule<select::EngineObject>::module_free();
|
||||
ShaderModule<select::Instance>::module_free();
|
||||
ShaderModule<select::InstanceDummy>::module_free();
|
||||
}
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
|
@ -10,8 +10,7 @@
|
||||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
#include "../select/select_empty.hh"
|
||||
#include "../select/select_object.hh"
|
||||
#include "../select/select_instance.hh"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
|
@ -6,5 +6,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define SELECT_DATA 4
|
||||
#define SELECT_ID_IN 5
|
||||
#define SELECT_ID_OUT 6
|
||||
|
@ -1,50 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2023 Blender Foundation. */
|
||||
|
||||
/** \file
|
||||
* \ingroup draw_engine
|
||||
*
|
||||
* Dummy implementation of the select engine types to avoid any overhead.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "draw_manager.hh"
|
||||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
namespace blender::draw::select {
|
||||
|
||||
struct EngineEmpty {
|
||||
/* Add type safety to selection ID. Only the select engine should provide them. */
|
||||
struct ID {};
|
||||
|
||||
struct SelectShader {
|
||||
static void patch(gpu::shader::ShaderCreateInfo &){};
|
||||
};
|
||||
|
||||
struct SelectBuf {
|
||||
void select_clear(){};
|
||||
void select_append(ID){};
|
||||
void select_bind(PassSimple &){};
|
||||
};
|
||||
|
||||
struct SelectMap {
|
||||
[[nodiscard]] const ID select_id(const ObjectRef &, uint = 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void begin_sync(){};
|
||||
|
||||
void select_bind(PassSimple &){};
|
||||
|
||||
void select_bind(PassMain &){};
|
||||
|
||||
void end_sync(){};
|
||||
|
||||
void read_result(){};
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace blender::draw::select
|
@ -4,8 +4,6 @@
|
||||
/** \file
|
||||
* \ingroup draw_engine
|
||||
*
|
||||
* This is an implementation of the Select engine specialized for selecting object.
|
||||
* Should plug seamlessly inside the overlay engine logic.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -18,19 +16,72 @@
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
#include "select_defines.h"
|
||||
#include "select_shader_shared.hh"
|
||||
|
||||
namespace blender::draw::select {
|
||||
|
||||
struct EngineObject {
|
||||
/**
|
||||
* Dummy implementation of the select engine types to avoid any overhead.
|
||||
* Bypass any selection logic.
|
||||
*/
|
||||
struct InstanceDummy {
|
||||
pragma37 marked this conversation as resolved
Outdated
|
||||
/* Add type safety to selection ID. Only the select engine should provide them. */
|
||||
struct ID {
|
||||
class ID {
|
||||
public:
|
||||
constexpr uint32_t get() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct SelectShader {
|
||||
static void patch(gpu::shader::ShaderCreateInfo &){};
|
||||
};
|
||||
|
||||
struct SelectBuf {
|
||||
void select_clear(){};
|
||||
void select_append(ID){};
|
||||
void select_bind(PassSimple &){};
|
||||
};
|
||||
|
||||
struct SelectMap {
|
||||
[[nodiscard]] const ID select_id(const ObjectRef &, uint = 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void begin_sync(){};
|
||||
|
||||
void select_bind(PassSimple &){};
|
||||
|
||||
void select_bind(PassMain &){};
|
||||
|
||||
void end_sync(){};
|
||||
|
||||
void read_result(){};
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* This is an implementation of the Select engine specialized for selecting object.
|
||||
* Should plug seamlessly inside the overlay engine logic.
|
||||
*/
|
||||
struct Instance {
|
||||
/* Add type safety to selection ID. Only the select engine should provide them. */
|
||||
class ID {
|
||||
public:
|
||||
uint32_t value;
|
||||
|
||||
uint32_t get() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
struct SelectShader {
|
||||
static void patch(gpu::shader::ShaderCreateInfo &info)
|
||||
{
|
||||
info.define("SELECT_UNORDERED");
|
||||
info.define("SELECT_ENABLE");
|
||||
/* Replace additional info. */
|
||||
for (StringRefNull &str : info.additional_infos_) {
|
||||
if (str == "draw_modelmat_new") {
|
||||
@ -43,7 +94,7 @@ struct EngineObject {
|
||||
|
||||
/**
|
||||
* Add a dedicated selection id buffer to a pass.
|
||||
* Use this when not using a #PassMain which can pass the select ID via CustomID.
|
||||
* To be used when not using a #PassMain which can pass the select ID via CustomID.
|
||||
*/
|
||||
struct SelectBuf {
|
||||
StorageVectorBuffer<uint32_t> select_buf = {"select_buf"};
|
||||
@ -55,7 +106,7 @@ struct EngineObject {
|
||||
|
||||
void select_append(ID select_id)
|
||||
{
|
||||
select_buf.append(select_id.value);
|
||||
select_buf.append(select_id.get());
|
||||
}
|
||||
|
||||
void select_bind(PassSimple &pass)
|
||||
@ -80,6 +131,8 @@ struct EngineObject {
|
||||
StorageArrayBuffer<uint> select_output_buf = {"select_output_buf"};
|
||||
/** Dummy buffer. Might be better to remove, but simplify the shader create info patching. */
|
||||
StorageArrayBuffer<uint, 4, true> dummy_select_buf = {"dummy_select_buf"};
|
||||
/** Uniform buffer to bind to all passes to pass information about the selection state. */
|
||||
UniformBuffer<SelectInfoData> info_buf;
|
||||
|
||||
/* TODO(fclem): The sub_object_id id should eventually become some enum or take a sub-object
|
||||
* reference directly. This would isolate the selection logic to this class. */
|
||||
@ -93,6 +146,12 @@ struct EngineObject {
|
||||
return {id};
|
||||
}
|
||||
|
||||
/* Load an invalid index that will not write to the output (not selectable). */
|
||||
[[nodiscard]] const ID select_invalid_id()
|
||||
{
|
||||
return {uint32_t(-1)};
|
||||
}
|
||||
|
||||
void begin_sync()
|
||||
{
|
||||
select_id_map.clear();
|
||||
@ -101,14 +160,18 @@ struct EngineObject {
|
||||
#endif
|
||||
}
|
||||
|
||||
/** IMPORTANT: Changes the draw state. Need to be called after the pass own state. */
|
||||
void select_bind(PassSimple &pass)
|
||||
{
|
||||
pass.bind_ubo(SELECT_DATA, &info_buf);
|
||||
pass.bind_ssbo(SELECT_ID_OUT, &select_output_buf);
|
||||
}
|
||||
|
||||
/** IMPORTANT: Changes the draw state. Need to be called after the pass own state. */
|
||||
void select_bind(PassMain &pass)
|
||||
{
|
||||
pass.use_custom_ids = true;
|
||||
pass.bind_ubo(SELECT_DATA, &info_buf);
|
||||
/* IMPORTANT: This binds a dummy buffer `in_select_buf` but it is not supposed to be used. */
|
||||
pass.bind_ssbo(SELECT_ID_IN, &dummy_select_buf);
|
||||
pass.bind_ssbo(SELECT_ID_OUT, &select_output_buf);
|
||||
@ -116,6 +179,11 @@ struct EngineObject {
|
||||
|
||||
void end_sync()
|
||||
{
|
||||
info_buf.mode = SelectType::SELECT_ALL;
|
||||
/* TODO: Should be select rect center. */
|
||||
info_buf.cursor = int2(512, 512);
|
||||
info_buf.push_update();
|
||||
|
||||
select_output_buf.resize(ceil_to_multiple_u(select_id_map.size(), 4));
|
||||
select_output_buf.push_update();
|
||||
select_output_buf.clear_to_zero();
|
28
source/blender/draw/engines/select/select_shader_shared.hh
Normal file
28
source/blender/draw/engines/select/select_shader_shared.hh
Normal file
@ -0,0 +1,28 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef GPU_SHADER
|
||||
# pragma once
|
||||
|
||||
# include "GPU_shader_shared_utils.h"
|
||||
|
||||
namespace blender::draw::select {
|
||||
|
||||
#endif
|
||||
|
||||
/* Matches eV3DSelectMode */
|
||||
enum SelectType : uint32_t {
|
||||
SELECT_ALL = 0u,
|
||||
SELECT_PICK_ALL = 1u,
|
||||
SELECT_PICK_NEAREST = 2u,
|
||||
};
|
||||
|
||||
struct SelectInfoData {
|
||||
int2 cursor;
|
||||
SelectType mode;
|
||||
uint _pad0;
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(SelectInfoData, 16)
|
||||
|
||||
#ifndef GPU_SHADER
|
||||
} // namespace blender::draw::select
|
||||
#endif
|
@ -44,7 +44,11 @@ GPU_SHADER_CREATE_INFO(select_id_uniform_clipped)
|
||||
|
||||
/* Used to patch overlay shaders. */
|
||||
GPU_SHADER_CREATE_INFO(select_id_patch)
|
||||
.typedef_source("select_shader_shared.hh")
|
||||
.vertex_out(select_id_iface)
|
||||
/* Need to make sure the depth & stencil comparison runs before the fragment shader. */
|
||||
.early_fragment_test(true)
|
||||
.uniform_buf(SELECT_DATA, "SelectInfoData", "select_info_buf")
|
||||
/* Select IDs for instanced draw-calls not using #PassMain. */
|
||||
.storage_buf(SELECT_ID_IN, Qualifier::READ, "int", "in_select_buf[]")
|
||||
/* Stores the result of the whole selection drawing. Content depends on selection mode. */
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
#if !(defined(SELECT_UNORDERED) || defined(SELECT_DEPTH_PICKING))
|
||||
#ifndef SELECT_ENABLE
|
||||
/* Avoid requesting the select_id when not in selection mode. */
|
||||
# define select_id_set(select_id)
|
||||
# define select_id_output(select_id)
|
||||
@ -16,19 +16,34 @@ void select_id_set(int id)
|
||||
|
||||
void select_id_output(int id)
|
||||
{
|
||||
# if defined(SELECT_UNORDERED)
|
||||
/* Used by rectangle selection.
|
||||
* Set the bit of the select id in the bitmap. */
|
||||
atomicOr(out_select_buf[id / 32u], 1u << (uint(id) % 32u));
|
||||
if (id == -1) {
|
||||
/* Invalid index */
|
||||
return;
|
||||
}
|
||||
|
||||
# elif defined(SELECT_DEPTH_PICKING)
|
||||
/* Used by mouse-clicking selection.
|
||||
* Stores the nearest depth for this select id. */
|
||||
atomicMin(out_select_buf[id], floatBitsToUint(gl_FragCoord.z));
|
||||
if (select_info_buf.mode == SELECT_ALL) {
|
||||
/* Set the bit of the select id in the bitmap. */
|
||||
atomicOr(out_select_buf[id / 32u], 1u << (uint(id) % 32u));
|
||||
}
|
||||
else if (select_info_buf.mode == SELECT_PICK_ALL) {
|
||||
/* Stores the nearest depth for this select id. */
|
||||
atomicMin(out_select_buf[id], floatBitsToUint(gl_FragCoord.z));
|
||||
}
|
||||
else if (select_info_buf.mode == SELECT_PICK_NEAREST) {
|
||||
/* Stores the nearest depth with the distance to the cursor. */
|
||||
|
||||
# else
|
||||
# error
|
||||
# endif
|
||||
/* Distance function to the cursor. Currently a simple pixel ring distance. */
|
||||
ivec2 coord = abs(ivec2(gl_FragCoord.xy) - select_info_buf.cursor);
|
||||
uint dist = uint(max(coord.x, coord.y));
|
||||
|
||||
uint depth = uint(gl_FragCoord.z * float(0x00FFFFFFu));
|
||||
|
||||
/* Reject hits outside of valid range. */
|
||||
if (dist < 0xFFu) {
|
||||
/* Packed values to ensure the atomicMin is performed on the whole result. */
|
||||
atomicMin(out_select_buf[id], (depth << 8u) | dist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user
remove
e
prefixWhat's the rule here?
All the enums (at least most of them?) in the code base have the
e
prefix.There was a decision (or discussion, I cannot find it at the moment) not so long ago to not use that prefix as it isn't clear and enums are usually called
Types
or something else that indicates they are enums.This hasn't been applied to the whole codebase that's why most of them remains.
Ok, good to know!