WIP: Draw: Thin Handles #105034

Closed
Miguel Pozo wants to merge 5 commits from pragma37/blender:pull-thin-handles into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
10 changed files with 126 additions and 58 deletions
Showing only changes of commit aaf3578995 - Show all commits

View File

@ -599,15 +599,10 @@ void DrawCommandBuf::bind(RecordingState &state,
}
}
void DrawMultiBufBase::bind(RecordingState &state,
Vector<Header, 0> &headers,
Vector<Undetermined, 0> &commands,
VisibilityBuf &visibility_buf,
int visibility_word_per_draw,
int view_len)
void DrawMultiBufBase::bind_base(RecordingState &state,
int view_len,
std::function<void()> generate_commands)
{
UNUSED_VARS(headers, commands);
GPU_debug_group_begin("DrawMultiBuf.bind");
resource_id_count_ = 0u;
@ -641,7 +636,7 @@ void DrawMultiBufBase::bind(RecordingState &state,
command_buf_.get_or_resize(group_count_ * 2);
if (prototype_count_ > 0) {
generate_commands(visibility_buf, visibility_word_per_draw, view_len);
generate_commands();
if (GPU_shader_draw_parameters_support() == false) {
GPU_memory_barrier(GPU_BARRIER_VERTEX_ATTRIB_ARRAY);
@ -655,28 +650,50 @@ void DrawMultiBufBase::bind(RecordingState &state,
GPU_debug_group_end();
}
void DrawMultiBuf::generate_commands(VisibilityBuf &visibility_buf,
int visibility_word_per_draw,
int view_len)
void DrawMultiBuf::bind(RecordingState &state,
Vector<Header, 0> & /*headers*/,
Vector<Undetermined, 0> & /*commands*/,
VisibilityBuf &visibility_buf,
int visibility_word_per_draw,
int view_len)
{
GPUShader *shader = DRW_shader_draw_command_generate_get();
GPU_shader_bind(shader);
GPU_shader_uniform_1i(shader, "prototype_len", prototype_count_);
GPU_shader_uniform_1i(shader, "visibility_word_per_draw", visibility_word_per_draw);
GPU_shader_uniform_1i(shader, "view_shift", log2_ceil_u(view_len));
GPU_storagebuf_bind(group_buf_, GPU_shader_get_ssbo_binding(shader, "group_buf"));
GPU_storagebuf_bind(visibility_buf, GPU_shader_get_ssbo_binding(shader, "visibility_buf"));
GPU_storagebuf_bind(prototype_buf_, GPU_shader_get_ssbo_binding(shader, "prototype_buf"));
GPU_storagebuf_bind(command_buf_, GPU_shader_get_ssbo_binding(shader, "command_buf"));
GPU_storagebuf_bind(resource_id_buf_, DRW_RESOURCE_ID_SLOT);
GPU_compute_dispatch(shader, divide_ceil_u(prototype_count_, DRW_COMMAND_GROUP_SIZE), 1, 1);
bind_base(state, view_len, [&]() {
GPUShader *shader = DRW_shader_draw_command_generate_get();
GPU_shader_bind(shader);
GPU_shader_uniform_1i(shader, "prototype_len", prototype_count_);
GPU_shader_uniform_1i(shader, "visibility_word_per_draw", visibility_word_per_draw);
GPU_shader_uniform_1i(shader, "view_shift", log2_ceil_u(view_len));
GPU_storagebuf_bind(group_buf_, GPU_shader_get_ssbo_binding(shader, "group_buf"));
GPU_storagebuf_bind(visibility_buf, GPU_shader_get_ssbo_binding(shader, "visibility_buf"));
GPU_storagebuf_bind(prototype_buf_, GPU_shader_get_ssbo_binding(shader, "prototype_buf"));
GPU_storagebuf_bind(command_buf_, GPU_shader_get_ssbo_binding(shader, "command_buf"));
GPU_storagebuf_bind(resource_id_buf_, DRW_RESOURCE_ID_SLOT);
GPU_compute_dispatch(shader, divide_ceil_u(prototype_count_, DRW_COMMAND_GROUP_SIZE), 1, 1);
});
}
void DrawMultiThinBuf::generate_commands(VisibilityBuf &visibility_buf,
int visibility_word_per_draw,
int view_len)
void DrawMultiThinBuf::bind(RecordingState &state,
Vector<Header, 0> & /*headers*/,
Vector<Undetermined, 0> & /*commands*/,
VisibilityBuf &visibility_buf,
int visibility_word_per_draw,
int view_len,
ThinMapBuf &thin_map_buf)
{
/*TODO (Miguel Pozo) */
bind_base(state, view_len, [&]() {
GPUShader *shader = DRW_shader_draw_command_with_thin_generate_get();
GPU_shader_bind(shader);
GPU_shader_uniform_1i(shader, "prototype_len", prototype_count_);
GPU_shader_uniform_1i(shader, "visibility_word_per_draw", visibility_word_per_draw);
GPU_shader_uniform_1i(shader, "view_shift", log2_ceil_u(view_len));
GPU_storagebuf_bind(group_buf_, GPU_shader_get_ssbo_binding(shader, "group_buf"));
GPU_storagebuf_bind(visibility_buf, GPU_shader_get_ssbo_binding(shader, "visibility_buf"));
GPU_storagebuf_bind(prototype_buf_, GPU_shader_get_ssbo_binding(shader, "prototype_buf"));
GPU_storagebuf_bind(command_buf_, GPU_shader_get_ssbo_binding(shader, "command_buf"));
GPU_storagebuf_bind(resource_id_buf_, DRW_RESOURCE_ID_SLOT);
GPU_storagebuf_bind(thin_map_buf, DRW_RESOURCE_THIN_MAP_SLOT);
GPU_compute_dispatch(shader, divide_ceil_u(prototype_count_, DRW_COMMAND_GROUP_SIZE), 1, 1);
});
}
/** \} */

View File

@ -32,6 +32,8 @@ namespace blender::draw::command {
class DrawCommandBuf;
class DrawMultiBufBase;
using ThinMapBuf = StorageArrayBuffer<uint, 128>;
/* -------------------------------------------------------------------- */
/** \name Recording State
* \{ */
@ -579,9 +581,7 @@ class DrawMultiBufBase {
}
}
virtual void generate_commands(VisibilityBuf &visibility_buf,
int visibility_word_per_draw,
int view_len) = 0;
void bind_base(RecordingState &state, int view_len, std::function<void()> generate_commands);
public:
void clear()
@ -591,21 +591,9 @@ class DrawMultiBufBase {
prototype_count_ = 0;
group_ids_.clear();
}
void bind(RecordingState &state,
Vector<Header, 0> &headers,
Vector<Undetermined, 0> &commands,
VisibilityBuf &visibility_buf,
int visibility_word_per_draw,
int view_len);
};
class DrawMultiBuf : public DrawMultiBufBase {
virtual void generate_commands(VisibilityBuf &visibility_buf,
int visibility_word_per_draw,
int view_len) override;
public:
void append_draw(Vector<Header, 0> &headers,
Vector<Undetermined, 0> &commands,
@ -624,14 +612,16 @@ class DrawMultiBuf : public DrawMultiBufBase {
handle.raw,
handle.has_inverted_handedness());
}
void bind(RecordingState &state,
Vector<Header, 0> &headers,
Vector<Undetermined, 0> &commands,
VisibilityBuf &visibility_buf,
int visibility_word_per_draw,
int view_len);
};
class DrawMultiThinBuf : public DrawMultiBufBase {
virtual void generate_commands(VisibilityBuf &visibility_buf,
int visibility_word_per_draw,
int view_len) override;
public:
void append_draw(Vector<Header, 0> &headers,
Vector<Undetermined, 0> &commands,
@ -650,6 +640,14 @@ class DrawMultiThinBuf : public DrawMultiBufBase {
handle.raw,
handle.object_handle.has_inverted_handedness());
}
void bind(RecordingState &state,
Vector<Header, 0> &headers,
Vector<Undetermined, 0> &commands,
VisibilityBuf &visibility_buf,
int visibility_word_per_draw,
int view_len,
ThinMapBuf &thin_map_buf);
};
/** \} */

View File

@ -17,6 +17,7 @@
#define DRW_LAYER_ATTR_UBO_SLOT 3
#define DRW_RESOURCE_THIN_MAP_SLOT 12
#define DRW_RESOURCE_ID_SLOT 11
#define DRW_OBJ_MAT_SLOT 10
#define DRW_OBJ_INFOS_SLOT 9

View File

@ -47,17 +47,12 @@ struct ResourceHandle {
}
};
struct ResourceThinHandle {
struct ResourceThinHandle : public ResourceHandle {
ResourceHandle object_handle;
uint raw;
ResourceThinHandle(const ResourceHandle object_handle, uint thin_index)
: object_handle(object_handle), raw(thin_index) {};
uint resource_index() const
{
return raw;
}
: ResourceHandle(thin_index, object_handle.has_inverted_handedness()),
object_handle(object_handle){};
};
/* TODO(fclem): Move to somewhere more appropriated after cleaning up the header dependencies. */

View File

@ -201,6 +201,35 @@ void Manager::submit(PassMain &pass, View &view)
state.cleanup();
}
void Manager::submit(PassMainThin &pass, View &view)
{
view.bind();
debug_bind();
bool freeze_culling = (U.experimental.use_viewport_debug && DST.draw_ctx.v3d &&
(DST.draw_ctx.v3d->debug_flag & V3D_DEBUG_FREEZE_CULLING) != 0);
view.compute_visibility(bounds_buf.current(), resource_len_, freeze_culling);
command::RecordingState state;
state.inverted_view = view.is_inverted();
pass.draw_commands_buf_.bind(state,
pass.headers_,
pass.commands_,
view.get_visibility_buffer(),
view.visibility_word_per_draw(),
view.view_len_,
thin_map_buf.current());
resource_bind();
pass.submit(state);
state.cleanup();
}
void Manager::submit(PassSortable &pass, View &view)
{
pass.sort();

View File

@ -33,10 +33,12 @@ template<typename T> class Pass;
namespace command {
class DrawCommandBuf;
class DrawMultiBuf;
class DrawMultiThinBuf;
} // namespace command
using PassSimple = detail::Pass<command::DrawCommandBuf>;
using PassMain = detail::Pass<command::DrawMultiBuf>;
using PassMainThin = detail::Pass<command::DrawMultiThinBuf>;
class PassSortable;
class Manager {
@ -159,6 +161,7 @@ class Manager {
*/
void submit(PassSimple &pass, View &view);
void submit(PassMain &pass, View &view);
void submit(PassMainThin &pass, View &view);
void submit(PassSortable &pass, View &view);
/**
* Variant without any view. Must not contain any shader using `draw_view` create info.

View File

@ -27,6 +27,7 @@ static struct {
struct GPUShader *draw_view_finalize_sh;
struct GPUShader *draw_resource_finalize_sh;
struct GPUShader *draw_command_generate_sh;
struct GPUShader *draw_command_with_thin_generate_sh;
} e_data = {{nullptr}};
/* -------------------------------------------------------------------- */
@ -146,6 +147,15 @@ GPUShader *DRW_shader_draw_command_generate_get()
return e_data.draw_command_generate_sh;
}
GPUShader *DRW_shader_draw_command_with_thin_generate_get()
{
if (e_data.draw_command_with_thin_generate_sh == nullptr) {
e_data.draw_command_with_thin_generate_sh = GPU_shader_create_from_info_name(
"draw_command_with_thin_generate");
}
return e_data.draw_command_with_thin_generate_sh;
}
/** \} */
void DRW_shaders_free()
@ -159,4 +169,5 @@ void DRW_shaders_free()
DRW_SHADER_FREE_SAFE(e_data.draw_view_finalize_sh);
DRW_SHADER_FREE_SAFE(e_data.draw_resource_finalize_sh);
DRW_SHADER_FREE_SAFE(e_data.draw_command_generate_sh);
DRW_SHADER_FREE_SAFE(e_data.draw_command_with_thin_generate_sh);
}

View File

@ -32,6 +32,7 @@ GPUShader *DRW_shader_draw_visibility_compute_get();
GPUShader *DRW_shader_draw_view_finalize_get();
GPUShader *DRW_shader_draw_resource_finalize_get();
GPUShader *DRW_shader_draw_command_generate_get();
GPUShader *DRW_shader_draw_command_with_thin_generate_get();
#endif

View File

@ -54,11 +54,15 @@ void main()
uint group_id = proto.group_id;
bool is_inverted = (proto.resource_handle & 0x80000000u) != 0;
uint resource_index = (proto.resource_handle & 0x7FFFFFFFu);
uint visibility_index = resource_index;
#ifdef WITH_THIN_HANDLES
visibility_index = thin_map_buf[resource_index] & 0x7FFFFFFFu;
#endif
/* Visibility test result. */
uint visible_instance_len = 0;
if (visibility_word_per_draw > 0) {
uint visibility_word = resource_index * visibility_word_per_draw;
uint visibility_word = visibility_index * visibility_word_per_draw;
for (uint i = 0; i < visibility_word_per_draw; i++, visibility_word++) {
/* NOTE: This assumes `proto.instance_len` is 1. */
/* TODO: Assert. */
@ -66,7 +70,7 @@ void main()
}
}
else {
if ((visibility_buf[resource_index / 32u] & (1u << (resource_index % 32u))) != 0) {
if ((visibility_buf[visibility_index / 32u] & (1u << (visibility_index % 32u))) != 0) {
visible_instance_len = proto.instance_len;
}
}
@ -102,12 +106,13 @@ void main()
/* Fill resource_id buffer for each instance of this draw. */
if (visibility_word_per_draw > 0) {
uint visibility_word = resource_index * visibility_word_per_draw;
uint visibility_word = visibility_index * visibility_word_per_draw;
for (uint i = 0; i < visibility_word_per_draw; i++, visibility_word++) {
uint word = visibility_buf[visibility_word];
uint view_index = i * 32u;
while (word != 0u) {
if ((word & 1u) != 0u) {
/* TODO (Miguel Pozo): ??? */
resource_id_buf[dst_index++] = view_index | (resource_index << view_shift);
}
view_index++;

View File

@ -191,6 +191,14 @@ GPU_SHADER_CREATE_INFO(draw_command_generate)
.push_constant(Type::INT, "view_shift")
.compute_source("draw_command_generate_comp.glsl");
GPU_SHADER_CREATE_INFO(with_thin_handles)
.define("WITH_THIN_HANDLES")
.storage_buf(DRW_RESOURCE_THIN_MAP_SLOT, Qualifier::READ, "uint", "thin_map_buf[]");
GPU_SHADER_CREATE_INFO(draw_command_with_thin_generate)
.do_static_compilation(true)
.additional_info("draw_command_generate", "with_thin_handles");
/** \} */
/* -------------------------------------------------------------------- */