Overlay-Next: Initial implementation #107045
|
@ -191,6 +191,7 @@ set(SRC
|
|||
engines/gpencil/gpencil_shader_fx.c
|
||||
engines/select/select_draw_utils.c
|
||||
engines/select/select_engine.c
|
||||
engines/select/select_instance.cc
|
||||
engines/overlay/overlay_antialiasing.cc
|
||||
engines/overlay/overlay_armature.cc
|
||||
engines/overlay/overlay_background.cc
|
||||
|
|
|
@ -12,11 +12,6 @@ namespace blender::draw::overlay {
|
|||
|
||||
template<typename T> void Instance<T>::init()
|
||||
{
|
||||
resources.depth_tx.wrap(DRW_viewport_texture_list_get()->depth);
|
||||
resources.depth_in_front_tx.wrap(DRW_viewport_texture_list_get()->depth_in_front);
|
||||
resources.color_overlay_tx.wrap(DRW_viewport_texture_list_get()->color_overlay);
|
||||
resources.color_render_tx.wrap(DRW_viewport_texture_list_get()->color);
|
||||
|
||||
/* TODO(fclem): Remove DRW global usage. */
|
||||
const DRWContextState *ctx = DRW_context_state_get();
|
||||
/* Was needed by `object_wire_theme_id()` when doing the port. Not sure if needed nowadays. */
|
||||
|
@ -146,26 +141,41 @@ template<typename T> void Instance<T>::end_sync()
|
|||
|
||||
template<typename T> void Instance<T>::draw(Manager &manager)
|
||||
{
|
||||
/* WORKAROUND: This is to prevent crashes when using depth picking or selection.
|
||||
* The selection engine should handle theses cases instead. */
|
||||
if (!DRW_state_is_fbo()) {
|
||||
return;
|
||||
}
|
||||
resources.depth_tx.wrap(DRW_viewport_texture_list_get()->depth);
|
||||
resources.depth_in_front_tx.wrap(DRW_viewport_texture_list_get()->depth_in_front);
|
||||
resources.color_overlay_tx.wrap(DRW_viewport_texture_list_get()->color_overlay);
|
||||
resources.color_render_tx.wrap(DRW_viewport_texture_list_get()->color);
|
||||
|
||||
int2 render_size = int2(resources.depth_tx.size());
|
||||
|
||||
const DRWView *view_legacy = DRW_view_default_get();
|
||||
View view("OverlayView", view_legacy);
|
||||
|
||||
resources.line_tx.acquire(render_size, GPU_RGBA8);
|
||||
/* TODO: Better semantical switch? */
|
||||
if (!resources.color_overlay_tx.is_valid()) {
|
||||
/* Likely to be the selection case. Allocate dummy texture and bind only depth buffer. */
|
||||
resources.line_tx.acquire(int2(1, 1), GPU_RGBA8);
|
||||
resources.color_overlay_alloc_tx.acquire(int2(1, 1), GPU_SRGB8_A8);
|
||||
resources.color_render_alloc_tx.acquire(int2(1, 1), GPU_SRGB8_A8);
|
||||
|
||||
resources.overlay_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(resources.color_overlay_tx));
|
||||
resources.overlay_line_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(resources.color_overlay_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(resources.line_tx));
|
||||
resources.overlay_color_only_fb.ensure(GPU_ATTACHMENT_NONE,
|
||||
GPU_ATTACHMENT_TEXTURE(resources.color_overlay_tx));
|
||||
resources.color_overlay_tx.wrap(resources.color_overlay_alloc_tx);
|
||||
resources.color_render_tx.wrap(resources.color_render_alloc_tx);
|
||||
|
||||
resources.overlay_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx));
|
||||
resources.overlay_line_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx));
|
||||
resources.overlay_color_only_fb.ensure(GPU_ATTACHMENT_NONE);
|
||||
}
|
||||
else {
|
||||
resources.line_tx.acquire(render_size, GPU_RGBA8);
|
||||
|
||||
resources.overlay_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(resources.color_overlay_tx));
|
||||
resources.overlay_line_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(resources.color_overlay_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(resources.line_tx));
|
||||
resources.overlay_color_only_fb.ensure(GPU_ATTACHMENT_NONE,
|
||||
GPU_ATTACHMENT_TEXTURE(resources.color_overlay_tx));
|
||||
}
|
||||
|
||||
/* TODO(fclem): Remove mandatory allocation. */
|
||||
if (!resources.depth_in_front_tx.is_valid()) {
|
||||
|
@ -201,6 +211,8 @@ template<typename T> void Instance<T>::draw(Manager &manager)
|
|||
|
||||
resources.line_tx.release();
|
||||
resources.depth_in_front_alloc_tx.release();
|
||||
resources.color_overlay_alloc_tx.release();
|
||||
resources.color_render_alloc_tx.release();
|
||||
|
||||
resources.read_result();
|
||||
}
|
||||
|
@ -212,6 +224,12 @@ template void Instance<>::object_sync(ObjectRef &ob_ref, Manager &manager);
|
|||
template void Instance<>::end_sync();
|
||||
template void Instance<>::draw(Manager &manager);
|
||||
|
||||
template void Instance<select::Instance>::init();
|
||||
template void Instance<select::Instance>::begin_sync();
|
||||
template void Instance<select::Instance>::object_sync(ObjectRef &ob_ref, Manager &manager);
|
||||
template void Instance<select::Instance>::end_sync();
|
||||
template void Instance<select::Instance>::draw(Manager &manager);
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
|
||||
/* TODO(fclem): Move elsewhere. */
|
||||
|
|
|
@ -24,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::Instance>
|
||||
typename SelectEngineT = select::InstanceDummy>
|
||||
class Instance {
|
||||
public:
|
||||
/* WORKAROUND: Legacy. Move to grid pass. */
|
||||
|
@ -93,4 +93,10 @@ extern template void Instance<>::object_sync(ObjectRef &ob_ref, Manager &manager
|
|||
extern template void Instance<>::end_sync();
|
||||
extern template void Instance<>::draw(Manager &manager);
|
||||
|
||||
extern template void Instance<select::Instance>::init();
|
||||
extern template void Instance<select::Instance>::begin_sync();
|
||||
extern template void Instance<select::Instance>::object_sync(ObjectRef &ob_ref, Manager &manager);
|
||||
extern template void Instance<select::Instance>::end_sync();
|
||||
extern template void Instance<select::Instance>::draw(Manager &manager);
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
|
|
|
@ -75,6 +75,8 @@ template<typename SelectEngineT> struct Resources : public SelectEngineT::Select
|
|||
|
||||
TextureFromPool line_tx = {"line_tx"};
|
||||
TextureFromPool depth_in_front_alloc_tx = {"overlay_depth_in_front_tx"};
|
||||
TextureFromPool color_overlay_alloc_tx = {"overlay_color_overlay_alloc_tx"};
|
||||
TextureFromPool color_render_alloc_tx = {"overlay_color_render_alloc_tx"};
|
||||
|
||||
/** TODO(fclem): Copy of G_data.block that should become theme colors only and managed by the
|
||||
* engine. */
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* select_engine.c */
|
||||
|
||||
extern DrawEngineType draw_engine_select_type;
|
||||
|
@ -22,3 +26,11 @@ struct SELECTID_Context *DRW_select_engine_context_get(void);
|
|||
|
||||
struct GPUFrameBuffer *DRW_engine_select_framebuffer_get(void);
|
||||
struct GPUTexture *DRW_engine_select_texture_get(void);
|
||||
|
||||
/* select_instance.cc */
|
||||
|
||||
extern DrawEngineType draw_engine_select_next_type;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup select
|
||||
*/
|
||||
|
||||
#include "DRW_render.h"
|
||||
|
||||
#include "GPU_capabilities.h"
|
||||
|
||||
#include "select_engine.h"
|
||||
|
||||
#include "../overlay/overlay_instance.hh"
|
||||
#include "select_instance.hh"
|
||||
|
||||
using namespace blender::draw;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Select-Next Engine
|
||||
* \{ */
|
||||
|
||||
using Instance = overlay::Instance<select::Instance>;
|
||||
|
||||
typedef struct SELECT_NextData {
|
||||
void *engine_type;
|
||||
DRWViewportEmptyList *fbl;
|
||||
DRWViewportEmptyList *txl;
|
||||
DRWViewportEmptyList *psl;
|
||||
DRWViewportEmptyList *stl;
|
||||
|
||||
Instance *instance;
|
||||
} SELECT_NextData;
|
||||
|
||||
static void SELECT_next_engine_init(void *vedata)
|
||||
{
|
||||
if (!GPU_shader_storage_buffer_objects_support()) {
|
||||
return;
|
||||
}
|
||||
|
||||
OVERLAY_Data *ved = reinterpret_cast<OVERLAY_Data *>(vedata);
|
||||
|
||||
if (ved->instance == nullptr) {
|
||||
ved->instance = new Instance();
|
||||
}
|
||||
|
||||
reinterpret_cast<Instance *>(ved->instance)->init();
|
||||
}
|
||||
|
||||
static void SELECT_next_cache_init(void *vedata)
|
||||
{
|
||||
if (!GPU_shader_storage_buffer_objects_support()) {
|
||||
return;
|
||||
}
|
||||
reinterpret_cast<Instance *>(reinterpret_cast<OVERLAY_Data *>(vedata)->instance)->begin_sync();
|
||||
}
|
||||
|
||||
static void SELECT_next_cache_populate(void *vedata, Object *object)
|
||||
{
|
||||
if (!GPU_shader_storage_buffer_objects_support()) {
|
||||
return;
|
||||
}
|
||||
ObjectRef ref;
|
||||
ref.object = object;
|
||||
ref.dupli_object = DRW_object_get_dupli(object);
|
||||
ref.dupli_parent = DRW_object_get_dupli_parent(object);
|
||||
|
||||
reinterpret_cast<Instance *>(reinterpret_cast<OVERLAY_Data *>(vedata)->instance)
|
||||
->object_sync(ref, *DRW_manager_get());
|
||||
}
|
||||
|
||||
static void SELECT_next_cache_finish(void *vedata)
|
||||
{
|
||||
if (!GPU_shader_storage_buffer_objects_support()) {
|
||||
return;
|
||||
}
|
||||
reinterpret_cast<Instance *>(reinterpret_cast<OVERLAY_Data *>(vedata)->instance)->end_sync();
|
||||
}
|
||||
|
||||
static void SELECT_next_draw_scene(void *vedata)
|
||||
{
|
||||
if (!GPU_shader_storage_buffer_objects_support()) {
|
||||
return;
|
||||
}
|
||||
|
||||
reinterpret_cast<Instance *>(reinterpret_cast<OVERLAY_Data *>(vedata)->instance)
|
||||
->draw(*DRW_manager_get());
|
||||
}
|
||||
|
||||
static void SELECT_next_instance_free(void *instance_)
|
||||
{
|
||||
auto *instance = (Instance *)instance_;
|
||||
if (instance != nullptr) {
|
||||
delete instance;
|
||||
}
|
||||
}
|
||||
|
||||
static const DrawEngineDataSize SELECT_next_data_size = DRW_VIEWPORT_DATA_SIZE(SELECT_NextData);
|
||||
|
||||
DrawEngineType draw_engine_select_next_type = {
|
||||
NULL,
|
||||
NULL,
|
||||
N_("Select-Next"),
|
||||
&SELECT_next_data_size,
|
||||
&SELECT_next_engine_init,
|
||||
NULL,
|
||||
&SELECT_next_instance_free,
|
||||
&SELECT_next_cache_init,
|
||||
&SELECT_next_cache_populate,
|
||||
&SELECT_next_cache_finish,
|
||||
&SELECT_next_draw_scene,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/** \} */
|
|
@ -10,6 +10,10 @@
|
|||
|
||||
#include "DRW_gpu_wrapper.hh"
|
||||
|
||||
#include "GPU_select.h"
|
||||
|
||||
#include "../intern/gpu_select_private.h"
|
||||
|
||||
#include "draw_manager.hh"
|
||||
#include "draw_pass.hh"
|
||||
|
||||
|
@ -133,6 +137,8 @@ struct Instance {
|
|||
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;
|
||||
/** Will remove the depth test state from any pass drawing objects with select id. */
|
||||
bool disable_depth_test;
|
||||
|
||||
/* 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. */
|
||||
|
@ -154,23 +160,52 @@ struct Instance {
|
|||
|
||||
void begin_sync()
|
||||
{
|
||||
switch (gpu_select_next_get_mode()) {
|
||||
case GPU_SELECT_ALL:
|
||||
info_buf.mode = SelectType::SELECT_ALL;
|
||||
disable_depth_test = true;
|
||||
break;
|
||||
/* Not sure if these 2 NEAREST are mapped to the right algorithm. */
|
||||
case GPU_SELECT_NEAREST_FIRST_PASS:
|
||||
case GPU_SELECT_NEAREST_SECOND_PASS:
|
||||
case GPU_SELECT_PICK_ALL:
|
||||
info_buf.mode = SelectType::SELECT_PICK_ALL;
|
||||
info_buf.cursor = int2(gpu_select_next_get_pick_area_center());
|
||||
disable_depth_test = true;
|
||||
break;
|
||||
case GPU_SELECT_PICK_NEAREST:
|
||||
info_buf.mode = SelectType::SELECT_PICK_NEAREST;
|
||||
info_buf.cursor = int2(gpu_select_next_get_pick_area_center());
|
||||
disable_depth_test = true;
|
||||
break;
|
||||
}
|
||||
info_buf.push_update();
|
||||
|
||||
select_id_map.clear();
|
||||
#ifdef DEBUG
|
||||
map_names.clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** IMPORTANT: Changes the draw state. Need to be called after the pass own state. */
|
||||
/** IMPORTANT: Changes the draw state. Need to be called after the pass own state_set. */
|
||||
void select_bind(PassSimple &pass)
|
||||
{
|
||||
if (disable_depth_test) {
|
||||
/* TODO: clipping state. */
|
||||
pass.state_set(DRW_STATE_WRITE_COLOR);
|
||||
}
|
||||
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. */
|
||||
/** IMPORTANT: Changes the draw state. Need to be called after the pass own state_set. */
|
||||
void select_bind(PassMain &pass)
|
||||
{
|
||||
pass.use_custom_ids = true;
|
||||
if (disable_depth_test) {
|
||||
/* TODO: clipping state. */
|
||||
pass.state_set(DRW_STATE_WRITE_COLOR);
|
||||
}
|
||||
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);
|
||||
|
@ -179,11 +214,6 @@ struct Instance {
|
|||
|
||||
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();
|
||||
|
@ -195,18 +225,31 @@ struct Instance {
|
|||
GPU_finish();
|
||||
select_output_buf.read();
|
||||
|
||||
#ifdef DEBUG
|
||||
for (auto i : IndexRange(select_output_buf.size())) {
|
||||
uint32_t word = select_output_buf[i];
|
||||
for (auto bit : IndexRange(32)) {
|
||||
if ((word & 1) != 0) {
|
||||
uint index = i * 32 + bit;
|
||||
std::cout << index << map_names[index] << std::endl;
|
||||
Vector<GPUSelectResult> result;
|
||||
|
||||
/* Convert raw data from GPU to #GPUSelectResult. */
|
||||
switch (info_buf.mode) {
|
||||
case SelectType::SELECT_ALL:
|
||||
for (auto i : IndexRange(select_id_map.size())) {
|
||||
if (((select_output_buf[i / 32] >> (i % 32)) & 1) != 0) {
|
||||
result.append({select_id_map[i], 0xFFFFu});
|
||||
}
|
||||
}
|
||||
word >>= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SelectType::SELECT_PICK_ALL:
|
||||
case SelectType::SELECT_PICK_NEAREST:
|
||||
for (auto i : IndexRange(select_id_map.size())) {
|
||||
if (select_output_buf[i] != 0) {
|
||||
/* NOTE: For `SELECT_PICK_NEAREST`, `select_output_buf` also contains the screen
|
||||
* distance to cursor in the lowest bits. */
|
||||
result.append({select_id_map[i], select_output_buf[i]});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
gpu_select_next_set_result(result.data(), result.size());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -2457,7 +2457,10 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
|
|||
DST.options.is_material_select = do_material_sub_selection;
|
||||
drw_task_graph_init();
|
||||
/* Get list of enabled engines */
|
||||
if (use_obedit) {
|
||||
if (U.experimental.enable_overlay_next) {
|
||||
use_drw_engine(&draw_engine_select_next_type);
|
||||
}
|
||||
else if (use_obedit) {
|
||||
drw_engines_enable_overlays();
|
||||
}
|
||||
else if (!draw_surface) {
|
||||
|
@ -2566,6 +2569,9 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
|
|||
draw_select_framebuffer_depth_only_setup(viewport_size);
|
||||
GPU_framebuffer_bind(g_select_buffer.framebuffer_depth_only);
|
||||
GPU_framebuffer_clear_depth(g_select_buffer.framebuffer_depth_only, 1.0f);
|
||||
/* WORKAROUND: Needed for Select-Next for keeping the same codeflow as Overlay-Next. */
|
||||
BLI_assert(DRW_viewport_texture_list_get()->depth == NULL);
|
||||
DRW_viewport_texture_list_get()->depth = g_select_buffer.texture_depth;
|
||||
|
||||
/* Start Drawing */
|
||||
DRW_state_reset();
|
||||
|
@ -2578,11 +2584,15 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
|
|||
if (!select_pass_fn(DRW_SELECT_PASS_PRE, select_pass_user_data)) {
|
||||
break;
|
||||
}
|
||||
DRW_state_lock(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_TEST_ENABLED);
|
||||
if (!U.experimental.enable_overlay_next) {
|
||||
DRW_state_lock(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_TEST_ENABLED);
|
||||
}
|
||||
|
||||
drw_engines_draw_scene();
|
||||
|
||||
DRW_state_lock(0);
|
||||
if (!U.experimental.enable_overlay_next) {
|
||||
DRW_state_lock(0);
|
||||
}
|
||||
|
||||
if (!select_pass_fn(DRW_SELECT_PASS_POST, select_pass_user_data)) {
|
||||
break;
|
||||
|
@ -2591,6 +2601,9 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
|
|||
|
||||
DRW_smoke_exit(DST.vmempool);
|
||||
|
||||
/* WORKAROUND: Do not leave ownership to the viewport list. */
|
||||
DRW_viewport_texture_list_get()->depth = NULL;
|
||||
|
||||
DRW_state_reset();
|
||||
drw_engines_disable();
|
||||
|
||||
|
@ -3012,6 +3025,7 @@ void DRW_engines_register(void)
|
|||
|
||||
DRW_engine_register(&draw_engine_overlay_type);
|
||||
DRW_engine_register(&draw_engine_overlay_next_type);
|
||||
DRW_engine_register(&draw_engine_select_next_type);
|
||||
DRW_engine_register(&draw_engine_select_type);
|
||||
DRW_engine_register(&draw_engine_basic_type);
|
||||
DRW_engine_register(&draw_engine_compositor_type);
|
||||
|
|
|
@ -485,7 +485,7 @@ static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
|
|||
bool continue_pass = false;
|
||||
struct DrawSelectLoopUserData *data = user_data;
|
||||
if (stage == DRW_SELECT_PASS_PRE) {
|
||||
GPU_select_begin(
|
||||
GPU_select_begin_next(
|
||||
data->buffer, data->buffer_len, data->rect, data->gpu_select_mode, data->hits);
|
||||
/* always run POST after PRE. */
|
||||
continue_pass = true;
|
||||
|
@ -596,7 +596,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
|
|||
/* Re-use cache (rect must be smaller than the cached)
|
||||
* other context is assumed to be unchanged */
|
||||
if (GPU_select_is_cached()) {
|
||||
GPU_select_begin(buffer, buffer_len, &rect, gpu_select_mode, 0);
|
||||
GPU_select_begin_next(buffer, buffer_len, &rect, gpu_select_mode, 0);
|
||||
GPU_select_cache_load_id();
|
||||
hits = GPU_select_end();
|
||||
goto finally;
|
||||
|
|
|
@ -68,6 +68,7 @@ set(SRC
|
|||
intern/gpu_platform.cc
|
||||
intern/gpu_query.cc
|
||||
intern/gpu_select.c
|
||||
intern/gpu_select_next.cc
|
||||
intern/gpu_select_pick.c
|
||||
intern/gpu_select_sample_query.cc
|
||||
intern/gpu_shader.cc
|
||||
|
|
|
@ -50,6 +50,15 @@ void GPU_select_begin(GPUSelectResult *buffer,
|
|||
const struct rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits);
|
||||
/**
|
||||
* Initialize and provide buffer for results.
|
||||
* Uses the new Select-Next engine if enabled.
|
||||
*/
|
||||
void GPU_select_begin_next(GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
const struct rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits);
|
||||
/**
|
||||
* Loads a new selection id and ends previous query, if any.
|
||||
* In second pass of selection it also returns
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "GPU_select.h"
|
||||
|
||||
#include "BLI_rect.h"
|
||||
|
@ -30,6 +32,8 @@ typedef enum eGPUSelectAlgo {
|
|||
/** Read depth buffer for every drawing pass and extract depths, `gpu_select_pick.c`
|
||||
* Only sets 4th component (ID) correctly. */
|
||||
ALGO_GL_PICK = 2,
|
||||
/** Use Select-Next draw engine. */
|
||||
ALGO_SELECT_NEXT = 3,
|
||||
} eGPUSelectAlgo;
|
||||
|
||||
typedef struct GPUSelectState {
|
||||
|
@ -60,11 +64,12 @@ static GPUSelectState g_select_state = {0};
|
|||
/** \name Public API
|
||||
* \{ */
|
||||
|
||||
void GPU_select_begin(GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits)
|
||||
static void gpu_select_begin_ex(GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits,
|
||||
bool use_select_next)
|
||||
{
|
||||
if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
|
||||
/* In the case hits was '-1',
|
||||
|
@ -76,7 +81,10 @@ void GPU_select_begin(GPUSelectResult *buffer,
|
|||
g_select_state.select_is_active = true;
|
||||
g_select_state.mode = mode;
|
||||
|
||||
if (ELEM(g_select_state.mode, GPU_SELECT_PICK_ALL, GPU_SELECT_PICK_NEAREST)) {
|
||||
if (use_select_next) {
|
||||
g_select_state.algorithm = ALGO_SELECT_NEXT;
|
||||
}
|
||||
else if (ELEM(g_select_state.mode, GPU_SELECT_PICK_ALL, GPU_SELECT_PICK_NEAREST)) {
|
||||
g_select_state.algorithm = ALGO_GL_PICK;
|
||||
}
|
||||
else {
|
||||
|
@ -89,6 +97,7 @@ void GPU_select_begin(GPUSelectResult *buffer,
|
|||
g_select_state.use_cache_needs_init = false;
|
||||
|
||||
switch (g_select_state.algorithm) {
|
||||
case ALGO_SELECT_NEXT:
|
||||
case ALGO_GL_QUERY: {
|
||||
g_select_state.use_cache = false;
|
||||
break;
|
||||
|
@ -102,6 +111,10 @@ void GPU_select_begin(GPUSelectResult *buffer,
|
|||
}
|
||||
|
||||
switch (g_select_state.algorithm) {
|
||||
case ALGO_SELECT_NEXT: {
|
||||
gpu_select_next_begin(buffer, buffer_len, input, mode);
|
||||
break;
|
||||
}
|
||||
case ALGO_GL_QUERY: {
|
||||
gpu_select_query_begin(buffer, buffer_len, input, mode, oldhits);
|
||||
break;
|
||||
|
@ -114,6 +127,25 @@ void GPU_select_begin(GPUSelectResult *buffer,
|
|||
}
|
||||
}
|
||||
|
||||
void GPU_select_begin_next(GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits)
|
||||
{
|
||||
gpu_select_begin_ex(
|
||||
buffer, buffer_len, input, mode, oldhits, U.experimental.enable_overlay_next);
|
||||
}
|
||||
|
||||
void GPU_select_begin(GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits)
|
||||
{
|
||||
gpu_select_begin_ex(buffer, buffer_len, input, mode, oldhits, false);
|
||||
}
|
||||
|
||||
bool GPU_select_load_id(uint id)
|
||||
{
|
||||
/* if no selection mode active, ignore */
|
||||
|
@ -122,6 +154,11 @@ bool GPU_select_load_id(uint id)
|
|||
}
|
||||
|
||||
switch (g_select_state.algorithm) {
|
||||
case ALGO_SELECT_NEXT:
|
||||
/* This shouldn't use this pipeline. */
|
||||
BLI_assert_unreachable();
|
||||
return 0;
|
||||
|
||||
case ALGO_GL_QUERY: {
|
||||
return gpu_select_query_load_id(id);
|
||||
}
|
||||
|
@ -137,6 +174,10 @@ uint GPU_select_end(void)
|
|||
uint hits = 0;
|
||||
|
||||
switch (g_select_state.algorithm) {
|
||||
case ALGO_SELECT_NEXT: {
|
||||
hits = gpu_select_next_end();
|
||||
break;
|
||||
}
|
||||
case ALGO_GL_QUERY: {
|
||||
hits = gpu_select_query_end();
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2017 Blender Foundation. All rights reserved. */
|
||||
|
||||
/** \file
|
||||
* \ingroup gpu
|
||||
*
|
||||
* Glue to make the new Select-Next engine work with the old GPU select API.
|
||||
*/
|
||||
#include <float.h>
|
||||
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_span.hh"
|
||||
|
||||
#include "GPU_select.h"
|
||||
|
||||
#include "gpu_select_private.h"
|
||||
|
||||
struct GPUSelectNextState {
|
||||
/** Result buffer set on initialization. */
|
||||
GPUSelectResult *buffer;
|
||||
uint buffer_len;
|
||||
/** Area of the viewport to render / select from. */
|
||||
rcti rect;
|
||||
/** Number of hits. Set to -1 if it overflows buffer_len. */
|
||||
uint hits;
|
||||
/** Mode of operation. */
|
||||
eGPUSelectMode mode;
|
||||
};
|
||||
|
||||
static GPUSelectNextState g_state = {};
|
||||
|
||||
void gpu_select_next_begin(GPUSelectResult *buffer,
|
||||
uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode)
|
||||
|
||||
{
|
||||
g_state.buffer = buffer;
|
||||
g_state.rect = *input;
|
||||
g_state.buffer_len = buffer_len;
|
||||
g_state.mode = mode;
|
||||
}
|
||||
|
||||
int gpu_select_next_get_pick_area_center()
|
||||
{
|
||||
BLI_assert(BLI_rcti_size_x(&g_state.rect) == BLI_rcti_size_y(&g_state.rect));
|
||||
return BLI_rcti_size_x(&g_state.rect) / 2;
|
||||
}
|
||||
|
||||
eGPUSelectMode gpu_select_next_get_mode()
|
||||
{
|
||||
return g_state.mode;
|
||||
}
|
||||
|
||||
void gpu_select_next_set_result(GPUSelectResult *hit_buf, uint hit_len)
|
||||
|
||||
{
|
||||
if (hit_len > g_state.buffer_len) {
|
||||
g_state.hits = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
blender::MutableSpan<GPUSelectResult> result(g_state.buffer, g_state.buffer_len);
|
||||
blender::Span<GPUSelectResult> hits(hit_buf, hit_len);
|
||||
|
||||
/* TODO(fclem): There might be some conversion to do to align to the other APIs output. */
|
||||
switch (g_state.mode) {
|
||||
case eGPUSelectMode::GPU_SELECT_ALL:
|
||||
result.take_front(hit_len).copy_from(hits);
|
||||
break;
|
||||
case eGPUSelectMode::GPU_SELECT_NEAREST_FIRST_PASS:
|
||||
result.take_front(hit_len).copy_from(hits);
|
||||
break;
|
||||
case eGPUSelectMode::GPU_SELECT_NEAREST_SECOND_PASS:
|
||||
result.take_front(hit_len).copy_from(hits);
|
||||
break;
|
||||
case eGPUSelectMode::GPU_SELECT_PICK_ALL:
|
||||
result.take_front(hit_len).copy_from(hits);
|
||||
break;
|
||||
case eGPUSelectMode::GPU_SELECT_PICK_NEAREST:
|
||||
result.take_front(hit_len).copy_from(hits);
|
||||
break;
|
||||
}
|
||||
|
||||
g_state.hits = hit_len;
|
||||
}
|
||||
|
||||
uint gpu_select_next_end()
|
||||
{
|
||||
return g_state.hits;
|
||||
}
|
|
@ -37,6 +37,19 @@ void gpu_select_query_begin(
|
|||
bool gpu_select_query_load_id(uint id);
|
||||
uint gpu_select_query_end(void);
|
||||
|
||||
/* gpu_select_next */
|
||||
|
||||
void gpu_select_next_begin(GPUSelectResult *buffer,
|
||||
uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode);
|
||||
uint gpu_select_next_end(void);
|
||||
|
||||
/* Return a single offset since picking uses squared viewport. */
|
||||
int gpu_select_next_get_pick_area_center(void);
|
||||
eGPUSelectMode gpu_select_next_get_mode(void);
|
||||
void gpu_select_next_set_result(GPUSelectResult *buffer, uint buffer_len);
|
||||
|
||||
#define SELECT_ID_NONE ((uint)0xffffffff)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
Loading…
Reference in New Issue