WIP: Draw: Thin Handles #105034
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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");
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
Loading…
Reference in New Issue