WIP: Draw: Thin Handles #105034
|
@ -40,8 +40,7 @@ GPU_SHADER_CREATE_INFO(workbench_next_mesh)
|
|||
.vertex_in(2, Type::VEC4, "ac")
|
||||
.vertex_in(3, Type::VEC2, "au")
|
||||
.vertex_source("workbench_prepass_vert.glsl")
|
||||
.additional_info("draw_modelmat_new")
|
||||
.additional_info("draw_resource_handle_new");
|
||||
.additional_info("draw_modelmat_new", "draw_resource_handle_new", "with_thin_handles");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(workbench_next_curves)
|
||||
/* TODO Adding workbench_next_mesh to avoid shader compilation errors */
|
||||
|
|
|
@ -16,8 +16,13 @@ void main()
|
|||
|
||||
normal_interp = normalize(normal_object_to_view(nor));
|
||||
|
||||
#ifdef WORKBENCH_NEXT
|
||||
object_id = int(uint(resource_id) & 0xFFFFu) + 1;
|
||||
workbench_material_data_get(
|
||||
int(resource_handle), ac.rgb, color_interp, alpha_interp, _roughness, metallic);
|
||||
#else
|
||||
object_id = int(uint(resource_handle) & 0xFFFFu) + 1;
|
||||
workbench_material_data_get(
|
||||
resource_handle, ac.rgb, color_interp, alpha_interp, _roughness, metallic);
|
||||
|
||||
object_id = int(uint(resource_handle) & 0xFFFFu) + 1;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -202,10 +202,8 @@ class Instance {
|
|||
if (batches[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
/* TODO(fclem): This create a cull-able instance for each sub-object. This is done
|
||||
* for simplicity to reduce complexity. But this increase the overhead per object.
|
||||
* Instead, we should use an indirection buffer to the material buffer. */
|
||||
ResourceHandle _handle = i == 0 ? handle : manager.resource_handle(ob_ref);
|
||||
|
||||
ResourceThinHandle _handle = manager.resource_thin_handle(handle);
|
||||
|
||||
Material &mat = resources.material_buf.get_or_resize(_handle.resource_index());
|
||||
|
||||
|
@ -247,7 +245,8 @@ class Instance {
|
|||
}
|
||||
|
||||
if (batch) {
|
||||
Material &mat = resources.material_buf.get_or_resize(handle.resource_index());
|
||||
ResourceThinHandle _handle = manager.resource_thin_handle(handle);
|
||||
Material &mat = resources.material_buf.get_or_resize(_handle.resource_index());
|
||||
|
||||
if (object_state.color_type == V3D_SHADING_OBJECT_COLOR) {
|
||||
mat = Material(*ob_ref.object);
|
||||
|
@ -270,7 +269,7 @@ class Instance {
|
|||
draw_mesh(ob_ref,
|
||||
mat,
|
||||
batch,
|
||||
handle,
|
||||
_handle,
|
||||
object_state.image_paint_override,
|
||||
object_state.override_sampler_state);
|
||||
}
|
||||
|
@ -285,7 +284,7 @@ class Instance {
|
|||
void draw_mesh(ObjectRef &ob_ref,
|
||||
Material &material,
|
||||
GPUBatch *batch,
|
||||
ResourceHandle handle,
|
||||
ResourceThinHandle handle,
|
||||
::Image *image = nullptr,
|
||||
eGPUSamplerState sampler_state = GPU_SAMPLER_DEFAULT,
|
||||
ImageUser *iuser = nullptr)
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace blender::workbench {
|
|||
/** \name MeshPass
|
||||
* \{ */
|
||||
|
||||
MeshPass::MeshPass(const char *name) : PassMain(name){};
|
||||
MeshPass::MeshPass(const char *name) : PassMainThin(name){};
|
||||
|
||||
/* Move to draw::Pass */
|
||||
bool MeshPass::is_empty() const
|
||||
|
@ -19,7 +19,7 @@ bool MeshPass::is_empty() const
|
|||
void MeshPass::init_pass(SceneResources &resources, DRWState state, int clip_planes)
|
||||
{
|
||||
is_empty_ = true;
|
||||
PassMain::init();
|
||||
PassMainThin::init();
|
||||
state_set(state, clip_planes);
|
||||
bind_texture(WB_MATCAP_SLOT, resources.matcap_tx);
|
||||
bind_ssbo(WB_MATERIAL_SLOT, &resources.material_buf);
|
||||
|
@ -47,7 +47,7 @@ void MeshPass::init_subpasses(ePipelineType pipeline,
|
|||
std::string(get_name(shader_type));
|
||||
}
|
||||
GPUShader *sh = shaders.prepass_shader_get(pipeline, geom_type, shader_type, lighting, clip);
|
||||
PassMain::Sub *pass = &sub(pass_names[geom][shader].c_str());
|
||||
PassMainThin::Sub *pass = &sub(pass_names[geom][shader].c_str());
|
||||
pass->shader_set(sh);
|
||||
passes_[geom][shader] = pass;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ void MeshPass::init_subpasses(ePipelineType pipeline,
|
|||
|
||||
void MeshPass::draw(ObjectRef &ref,
|
||||
GPUBatch *batch,
|
||||
ResourceHandle handle,
|
||||
ResourceThinHandle handle,
|
||||
::Image *image /* = nullptr */,
|
||||
eGPUSamplerState sampler_state /* = GPU_SAMPLER_DEFAULT */,
|
||||
ImageUser *iuser /* = nullptr */)
|
||||
|
@ -76,7 +76,7 @@ void MeshPass::draw(ObjectRef &ref,
|
|||
}
|
||||
if (texture) {
|
||||
auto add_cb = [&] {
|
||||
PassMain::Sub *sub_pass = passes_[int(geometry_type)][int(eShaderType::TEXTURE)];
|
||||
PassMainThin::Sub *sub_pass = passes_[int(geometry_type)][int(eShaderType::TEXTURE)];
|
||||
sub_pass = &sub_pass->sub(image->id.name);
|
||||
if (tilemap) {
|
||||
sub_pass->bind_texture(WB_TILE_ARRAY_SLOT, texture, sampler_state);
|
||||
|
|
|
@ -159,13 +159,13 @@ struct SceneResources {
|
|||
void load_jitter_tx(int total_samples);
|
||||
};
|
||||
|
||||
class MeshPass : public PassMain {
|
||||
class MeshPass : public PassMainThin {
|
||||
private:
|
||||
using TextureSubPassKey = std::pair<GPUTexture *, eGeometryType>;
|
||||
|
||||
Map<TextureSubPassKey, PassMain::Sub *> texture_subpass_map_ = {};
|
||||
Map<TextureSubPassKey, PassMainThin::Sub *> texture_subpass_map_ = {};
|
||||
|
||||
PassMain::Sub *passes_[geometry_type_len][shader_type_len] = {{nullptr}};
|
||||
PassMainThin::Sub *passes_[geometry_type_len][shader_type_len] = {{nullptr}};
|
||||
|
||||
bool is_empty_ = false;
|
||||
|
||||
|
@ -183,7 +183,7 @@ class MeshPass : public PassMain {
|
|||
|
||||
void draw(ObjectRef &ref,
|
||||
GPUBatch *batch,
|
||||
ResourceHandle handle,
|
||||
ResourceThinHandle handle,
|
||||
::Image *image = nullptr,
|
||||
eGPUSamplerState sampler_state = eGPUSamplerState::GPU_SAMPLER_DEFAULT,
|
||||
ImageUser *iuser = nullptr);
|
||||
|
|
|
@ -104,8 +104,8 @@ void Draw::execute(RecordingState &state) const
|
|||
|
||||
void DrawMulti::execute(RecordingState &state) const
|
||||
{
|
||||
DrawMultiBuf::DrawCommandBuf &indirect_buf = multi_draw_buf->command_buf_;
|
||||
DrawMultiBuf::DrawGroupBuf &groups = multi_draw_buf->group_buf_;
|
||||
DrawMultiBufBase::DrawCommandBuf &indirect_buf = multi_draw_buf->command_buf_;
|
||||
DrawMultiBufBase::DrawGroupBuf &groups = multi_draw_buf->group_buf_;
|
||||
|
||||
uint group_index = this->group_first;
|
||||
while (group_index != uint(-1)) {
|
||||
|
@ -397,7 +397,7 @@ std::string Draw::serialize() const
|
|||
|
||||
std::string DrawMulti::serialize(std::string line_prefix) const
|
||||
{
|
||||
DrawMultiBuf::DrawGroupBuf &groups = multi_draw_buf->group_buf_;
|
||||
DrawMultiBufBase::DrawGroupBuf &groups = multi_draw_buf->group_buf_;
|
||||
|
||||
MutableSpan<DrawPrototype> prototypes(multi_draw_buf->prototype_buf_.data(),
|
||||
multi_draw_buf->prototype_count_);
|
||||
|
@ -599,15 +599,10 @@ void DrawCommandBuf::bind(RecordingState &state,
|
|||
}
|
||||
}
|
||||
|
||||
void DrawMultiBuf::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,17 +636,8 @@ void DrawMultiBuf::bind(RecordingState &state,
|
|||
command_buf_.get_or_resize(group_count_ * 2);
|
||||
|
||||
if (prototype_count_ > 0) {
|
||||
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);
|
||||
generate_commands();
|
||||
|
||||
if (GPU_shader_draw_parameters_support() == false) {
|
||||
GPU_memory_barrier(GPU_BARRIER_VERTEX_ATTRIB_ARRAY);
|
||||
state.resource_id_buf = resource_id_buf_;
|
||||
|
@ -664,6 +650,52 @@ void DrawMultiBuf::bind(RecordingState &state,
|
|||
GPU_debug_group_end();
|
||||
}
|
||||
|
||||
void DrawMultiBuf::bind(RecordingState &state,
|
||||
Vector<Header, 0> & /*headers*/,
|
||||
Vector<Undetermined, 0> & /*commands*/,
|
||||
VisibilityBuf &visibility_buf,
|
||||
int visibility_word_per_draw,
|
||||
int view_len)
|
||||
{
|
||||
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::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)
|
||||
{
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
}; // namespace blender::draw::command
|
||||
|
|
|
@ -30,7 +30,9 @@ template<typename DrawCommandBufType> class PassBase;
|
|||
namespace blender::draw::command {
|
||||
|
||||
class DrawCommandBuf;
|
||||
class DrawMultiBuf;
|
||||
class DrawMultiBufBase;
|
||||
|
||||
using ThinMapBuf = StorageArrayBuffer<uint, 128>;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Recording State
|
||||
|
@ -297,7 +299,7 @@ struct Draw {
|
|||
|
||||
struct DrawMulti {
|
||||
GPUBatch *batch;
|
||||
DrawMultiBuf *multi_draw_buf;
|
||||
DrawMultiBufBase *multi_draw_buf;
|
||||
uint group_first;
|
||||
uint uuid;
|
||||
|
||||
|
@ -486,11 +488,11 @@ class DrawCommandBuf {
|
|||
*
|
||||
* \{ */
|
||||
|
||||
class DrawMultiBuf {
|
||||
class DrawMultiBufBase {
|
||||
friend Manager;
|
||||
friend DrawMulti;
|
||||
|
||||
private:
|
||||
protected:
|
||||
using DrawGroupBuf = StorageArrayBuffer<DrawGroup, 16>;
|
||||
using DrawPrototypeBuf = StorageArrayBuffer<DrawPrototype, 16>;
|
||||
using DrawCommandBuf = StorageArrayBuffer<DrawCommand, 16, true>;
|
||||
|
@ -518,22 +520,14 @@ class DrawMultiBuf {
|
|||
/** Used items in the resource_id_buf_. Not it's allocated length. */
|
||||
uint resource_id_count_ = 0;
|
||||
|
||||
public:
|
||||
void clear()
|
||||
{
|
||||
header_id_counter_ = 0;
|
||||
group_count_ = 0;
|
||||
prototype_count_ = 0;
|
||||
group_ids_.clear();
|
||||
}
|
||||
|
||||
void append_draw(Vector<Header, 0> &headers,
|
||||
Vector<Undetermined, 0> &commands,
|
||||
GPUBatch *batch,
|
||||
uint instance_len,
|
||||
uint vertex_len,
|
||||
uint vertex_first,
|
||||
ResourceHandle handle)
|
||||
void append_draw_base(Vector<Header, 0> &headers,
|
||||
Vector<Undetermined, 0> &commands,
|
||||
GPUBatch *batch,
|
||||
uint instance_len,
|
||||
uint vertex_len,
|
||||
uint vertex_first,
|
||||
uint handle_index,
|
||||
bool inverted_handedness)
|
||||
{
|
||||
/* Custom draw-calls cannot be batched and will produce one group per draw. */
|
||||
const bool custom_group = ((vertex_first != 0 && vertex_first != -1) || vertex_len != -1);
|
||||
|
@ -551,10 +545,8 @@ class DrawMultiBuf {
|
|||
|
||||
uint &group_id = group_ids_.lookup_or_add(DrawGroupKey(cmd.uuid, batch), uint(-1));
|
||||
|
||||
bool inverted = handle.has_inverted_handedness();
|
||||
|
||||
DrawPrototype &draw = prototype_buf_.get_or_resize(prototype_count_++);
|
||||
draw.resource_handle = handle.raw;
|
||||
draw.resource_handle = handle_index;
|
||||
draw.instance_len = instance_len;
|
||||
draw.group_id = group_id;
|
||||
|
||||
|
@ -565,7 +557,7 @@ class DrawMultiBuf {
|
|||
DrawGroup &group = group_buf_.get_or_resize(new_group_id);
|
||||
group.next = cmd.group_first;
|
||||
group.len = instance_len;
|
||||
group.front_facing_len = inverted ? 0 : instance_len;
|
||||
group.front_facing_len = inverted_handedness ? 0 : instance_len;
|
||||
group.gpu_batch = batch;
|
||||
group.front_proto_len = 0;
|
||||
group.back_proto_len = 0;
|
||||
|
@ -576,19 +568,51 @@ class DrawMultiBuf {
|
|||
group_id = new_group_id;
|
||||
}
|
||||
/* For serialization only. */
|
||||
(inverted ? group.back_proto_len : group.front_proto_len)++;
|
||||
(inverted_handedness ? group.back_proto_len : group.front_proto_len)++;
|
||||
/* Append to list. */
|
||||
cmd.group_first = new_group_id;
|
||||
}
|
||||
else {
|
||||
DrawGroup &group = group_buf_[group_id];
|
||||
group.len += instance_len;
|
||||
group.front_facing_len += inverted ? 0 : instance_len;
|
||||
group.front_facing_len += inverted_handedness ? 0 : instance_len;
|
||||
/* For serialization only. */
|
||||
(inverted ? group.back_proto_len : group.front_proto_len)++;
|
||||
(inverted_handedness ? group.back_proto_len : group.front_proto_len)++;
|
||||
}
|
||||
}
|
||||
|
||||
void bind_base(RecordingState &state, int view_len, std::function<void()> generate_commands);
|
||||
|
||||
public:
|
||||
void clear()
|
||||
{
|
||||
header_id_counter_ = 0;
|
||||
group_count_ = 0;
|
||||
prototype_count_ = 0;
|
||||
group_ids_.clear();
|
||||
}
|
||||
};
|
||||
|
||||
class DrawMultiBuf : public DrawMultiBufBase {
|
||||
public:
|
||||
void append_draw(Vector<Header, 0> &headers,
|
||||
Vector<Undetermined, 0> &commands,
|
||||
GPUBatch *batch,
|
||||
uint instance_len,
|
||||
uint vertex_len,
|
||||
uint vertex_first,
|
||||
ResourceHandle handle)
|
||||
{
|
||||
append_draw_base(headers,
|
||||
commands,
|
||||
batch,
|
||||
instance_len,
|
||||
vertex_len,
|
||||
vertex_first,
|
||||
handle.raw,
|
||||
handle.has_inverted_handedness());
|
||||
}
|
||||
|
||||
void bind(RecordingState &state,
|
||||
Vector<Header, 0> &headers,
|
||||
Vector<Undetermined, 0> &commands,
|
||||
|
@ -597,6 +621,35 @@ class DrawMultiBuf {
|
|||
int view_len);
|
||||
};
|
||||
|
||||
class DrawMultiThinBuf : public DrawMultiBufBase {
|
||||
public:
|
||||
void append_draw(Vector<Header, 0> &headers,
|
||||
Vector<Undetermined, 0> &commands,
|
||||
GPUBatch *batch,
|
||||
uint instance_len,
|
||||
uint vertex_len,
|
||||
uint vertex_first,
|
||||
ResourceThinHandle handle)
|
||||
{
|
||||
append_draw_base(headers,
|
||||
commands,
|
||||
batch,
|
||||
instance_len,
|
||||
vertex_len,
|
||||
vertex_first,
|
||||
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);
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
}; // namespace blender::draw::command
|
||||
|
|
|
@ -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,6 +47,14 @@ struct ResourceHandle {
|
|||
}
|
||||
};
|
||||
|
||||
struct ResourceThinHandle : public ResourceHandle {
|
||||
ResourceHandle object_handle;
|
||||
|
||||
ResourceThinHandle(const ResourceHandle object_handle, uint thin_index)
|
||||
: 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. */
|
||||
struct ObjectRef {
|
||||
Object *object;
|
||||
|
|
|
@ -30,6 +30,7 @@ void Manager::begin_sync()
|
|||
matrix_buf.swap();
|
||||
bounds_buf.swap();
|
||||
infos_buf.swap();
|
||||
thin_map_buf.swap();
|
||||
|
||||
/* TODO: This means the reference is kept until further redraw or manager tear-down. Instead,
|
||||
* they should be released after each draw loop. But for now, mimics old DRW behavior. */
|
||||
|
@ -52,8 +53,12 @@ void Manager::begin_sync()
|
|||
memset(infos_buf.current().data(),
|
||||
0xF0,
|
||||
matrix_buf.current().size() * sizeof(*infos_buf.current().data()));
|
||||
memset(thin_map_buf.current().data(),
|
||||
0xF0,
|
||||
thin_map_buf.current().size() * sizeof(*thin_map_buf.current().data()));
|
||||
#endif
|
||||
resource_len_ = 0;
|
||||
resource_thin_len_ = 0;
|
||||
attribute_len_ = 0;
|
||||
/* TODO(fclem): Resize buffers if too big, but with an hysteresis threshold. */
|
||||
|
||||
|
@ -101,6 +106,7 @@ void Manager::end_sync()
|
|||
matrix_buf.current().push_update();
|
||||
bounds_buf.current().push_update();
|
||||
infos_buf.current().push_update();
|
||||
thin_map_buf.current().push_update();
|
||||
attributes_buf.push_update();
|
||||
layer_attributes_buf.push_update();
|
||||
attributes_buf_legacy.push_update();
|
||||
|
@ -195,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();
|
||||
|
@ -253,6 +288,7 @@ Manager::DataDebugOutput Manager::data_debug()
|
|||
matrix_buf.current().read();
|
||||
bounds_buf.current().read();
|
||||
infos_buf.current().read();
|
||||
/* TODO (Miguel Pozo): thin_map_buf.current().read(); */
|
||||
|
||||
Manager::DataDebugOutput output;
|
||||
output.matrices = {matrix_buf.current().data(), resource_len_};
|
||||
|
|
|
@ -33,16 +33,19 @@ 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 {
|
||||
using ObjectMatricesBuf = StorageArrayBuffer<ObjectMatrices, 128>;
|
||||
using ObjectBoundsBuf = StorageArrayBuffer<ObjectBounds, 128>;
|
||||
using ObjectInfosBuf = StorageArrayBuffer<ObjectInfos, 128>;
|
||||
using ThinMapBuf = StorageArrayBuffer<uint, 128>;
|
||||
using ObjectAttributeBuf = StorageArrayBuffer<ObjectAttribute, 128>;
|
||||
using LayerAttributeBuf = UniformArrayBuffer<LayerAttribute, 512>;
|
||||
/**
|
||||
|
@ -76,6 +79,8 @@ class Manager {
|
|||
SwapChain<ObjectBoundsBuf, 2> bounds_buf;
|
||||
SwapChain<ObjectInfosBuf, 2> infos_buf;
|
||||
|
||||
SwapChain<ThinMapBuf, 2> thin_map_buf;
|
||||
|
||||
/**
|
||||
* Object Attributes are reference by indirection data inside ObjectInfos.
|
||||
* This is because attribute list is arbitrary.
|
||||
|
@ -106,6 +111,8 @@ class Manager {
|
|||
private:
|
||||
/** Number of resource handle recorded. */
|
||||
uint resource_len_ = 0;
|
||||
/** Number of resource thin handle recorded. */
|
||||
uint resource_thin_len_ = 0;
|
||||
/** Number of object attribute recorded. */
|
||||
uint attribute_len_ = 0;
|
||||
|
||||
|
@ -134,6 +141,8 @@ class Manager {
|
|||
const float3 &bounds_center,
|
||||
const float3 &bounds_half_extent);
|
||||
|
||||
ResourceThinHandle resource_thin_handle(const ResourceHandle object_handle);
|
||||
|
||||
/**
|
||||
* Populate additional per resource data on demand.
|
||||
*/
|
||||
|
@ -152,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.
|
||||
|
@ -217,6 +227,12 @@ inline ResourceHandle Manager::resource_handle(const float4x4 &model_matrix,
|
|||
return ResourceHandle(resource_len_++, false);
|
||||
}
|
||||
|
||||
inline ResourceThinHandle Manager::resource_thin_handle(const ResourceHandle object_handle)
|
||||
{
|
||||
thin_map_buf.current().get_or_resize(resource_thin_len_) = object_handle.raw;
|
||||
return ResourceThinHandle(object_handle, resource_thin_len_++);
|
||||
}
|
||||
|
||||
inline void Manager::extract_object_attributes(ResourceHandle handle,
|
||||
const ObjectRef &ref,
|
||||
Span<GPUMaterial *> materials)
|
||||
|
|
|
@ -253,6 +253,16 @@ class PassBase {
|
|||
StorageBuffer<DrawCommand, true> &indirect_buffer,
|
||||
ResourceHandle handle = {0});
|
||||
|
||||
/**
|
||||
* Thin variants.
|
||||
*/
|
||||
void draw(GPUBatch *batch,
|
||||
uint instance_len = -1,
|
||||
uint vertex_len = -1,
|
||||
uint vertex_first = -1,
|
||||
ResourceThinHandle handle = {0});
|
||||
void draw(GPUBatch *batch, ResourceThinHandle handle);
|
||||
|
||||
/**
|
||||
* Record a compute dispatch call.
|
||||
*/
|
||||
|
@ -706,6 +716,32 @@ inline void PassBase<T>::draw_procedural_indirect(
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Thin Handle draw calls
|
||||
* \{ */
|
||||
|
||||
template<class T>
|
||||
inline void PassBase<T>::draw(GPUBatch *batch,
|
||||
uint instance_len,
|
||||
uint vertex_len,
|
||||
uint vertex_first,
|
||||
ResourceThinHandle handle)
|
||||
{
|
||||
if (instance_len == 0 || vertex_len == 0) {
|
||||
return;
|
||||
}
|
||||
BLI_assert(shader_);
|
||||
draw_commands_buf_.append_draw(
|
||||
headers_, commands_, batch, instance_len, vertex_len, vertex_first, handle);
|
||||
}
|
||||
|
||||
template<class T> inline void PassBase<T>::draw(GPUBatch *batch, ResourceThinHandle handle)
|
||||
{
|
||||
this->draw(batch, -1, -1, -1, handle);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Compute Dispatch Implementation
|
||||
* \{ */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -88,9 +88,9 @@ uniform int drw_resourceChunk;
|
|||
/* This is in the case we want to do a special instance drawcall for one object but still want to
|
||||
* have the right resourceId and all the correct ubo datas. */
|
||||
uniform int drw_ResourceID;
|
||||
# define resource_id drw_ResourceID
|
||||
# define _resource_id_ drw_ResourceID
|
||||
# else
|
||||
# define resource_id (gpu_BaseInstance + instanceId)
|
||||
# define _resource_id_ (gpu_BaseInstance + instanceId)
|
||||
# endif
|
||||
|
||||
/* Use this to declare and pass the value if
|
||||
|
@ -114,23 +114,23 @@ uniform int drw_ResourceID;
|
|||
#ifdef USE_GPU_SHADER_CREATE_INFO
|
||||
/* TODO(fclem): Rename PASS_RESOURCE_ID to DRW_RESOURCE_ID_VARYING_SET */
|
||||
# if defined(UNIFORM_RESOURCE_ID)
|
||||
# define resource_id drw_ResourceID
|
||||
# define _resource_id_ drw_ResourceID
|
||||
# define PASS_RESOURCE_ID
|
||||
|
||||
# elif defined(GPU_VERTEX_SHADER)
|
||||
# if defined(UNIFORM_RESOURCE_ID_NEW)
|
||||
# define resource_id (drw_ResourceID >> DRW_VIEW_SHIFT)
|
||||
# define _resource_id_ (drw_ResourceID >> DRW_VIEW_SHIFT)
|
||||
# else
|
||||
# define resource_id gpu_InstanceIndex
|
||||
# define _resource_id_ gpu_InstanceIndex
|
||||
# endif
|
||||
# define PASS_RESOURCE_ID drw_ResourceID_iface.resource_index = resource_id;
|
||||
|
||||
# elif defined(GPU_GEOMETRY_SHADER)
|
||||
# define resource_id drw_ResourceID_iface_in[0].resource_index
|
||||
# define _resource_id_ drw_ResourceID_iface_in[0].resource_index
|
||||
# define PASS_RESOURCE_ID drw_ResourceID_iface_out.resource_index = resource_id;
|
||||
|
||||
# elif defined(GPU_FRAGMENT_SHADER)
|
||||
# define resource_id drw_ResourceID_iface.resource_index
|
||||
# define _resource_id_ drw_ResourceID_iface.resource_index
|
||||
# endif
|
||||
|
||||
/* TODO(fclem): Remove. */
|
||||
|
@ -149,7 +149,7 @@ uniform int drw_ResourceID;
|
|||
# define RESOURCE_ID_VARYING
|
||||
# endif
|
||||
|
||||
# define resource_id resourceIDGeom
|
||||
# define _resource_id_ resourceIDGeom
|
||||
# define PASS_RESOURCE_ID resourceIDFrag = resource_id[0];
|
||||
# endif
|
||||
|
||||
|
@ -157,10 +157,17 @@ uniform int drw_ResourceID;
|
|||
# if !defined(EEVEE_GENERATED_INTERFACE)
|
||||
flat in int resourceIDFrag;
|
||||
# endif
|
||||
# define resource_id resourceIDFrag
|
||||
# define _resource_id_ resourceIDFrag
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef WITH_THIN_HANDLES
|
||||
# define resource_thin_id _resource_id_
|
||||
# define resource_id thin_map_buf[_resource_id_]
|
||||
#else
|
||||
# define resource_id _resource_id_
|
||||
#endif
|
||||
|
||||
/* Breaking this across multiple lines causes issues for some older GLSL compilers. */
|
||||
/* clang-format off */
|
||||
#if !defined(GPU_INTEL) && !defined(GPU_DEPRECATED_AMD_DRIVER) && (!defined(OS_MAC) || defined(GPU_METAL)) && !defined(INSTANCED_ATTR) && !defined(DRW_LEGACY_MODEL_MATRIX)
|
||||
|
|
|
@ -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