Draw: Custom IDs #105261
|
@ -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_with_custom_id", "draw_resource_handle_new");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(workbench_next_curves)
|
||||
/* TODO Adding workbench_next_mesh to avoid shader compilation errors */
|
||||
|
|
|
@ -16,8 +16,12 @@ void main()
|
|||
|
||||
normal_interp = normalize(normal_object_to_view(nor));
|
||||
|
||||
object_id = int(uint(resource_id) & 0xFFFFu) + 1;
|
||||
#ifdef WORKBENCH_NEXT
|
||||
workbench_material_data_get(
|
||||
int(drw_CustomID), ac.rgb, color_interp, alpha_interp, _roughness, metallic);
|
||||
#else
|
||||
workbench_material_data_get(
|
||||
resource_handle, ac.rgb, color_interp, alpha_interp, _roughness, metallic);
|
||||
|
||||
object_id = int(uint(resource_handle) & 0xFFFFu) + 1;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ class Instance {
|
|||
resolution,
|
||||
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT |
|
||||
GPU_TEXTURE_USAGE_MIP_SWIZZLE_VIEW);
|
||||
resources.material_buf.clear();
|
||||
|
||||
opaque_ps.sync(scene_state, resources);
|
||||
transparent_ps.sync(scene_state, resources);
|
||||
|
@ -202,12 +203,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);
|
||||
|
||||
Material &mat = resources.material_buf.get_or_resize(_handle.resource_index());
|
||||
Material mat;
|
||||
|
||||
if (::Material *_mat = BKE_object_material_get_eval(ob_ref.object, i + 1)) {
|
||||
mat = Material(*_mat);
|
||||
|
@ -225,7 +222,7 @@ class Instance {
|
|||
get_material_image(ob_ref.object, i + 1, image, iuser, sampler_state);
|
||||
}
|
||||
|
||||
draw_mesh(ob_ref, mat, batches[i], _handle, image, sampler_state, iuser);
|
||||
draw_mesh(ob_ref, mat, batches[i], handle, image, sampler_state, iuser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -247,7 +244,7 @@ class Instance {
|
|||
}
|
||||
|
||||
if (batch) {
|
||||
Material &mat = resources.material_buf.get_or_resize(handle.resource_index());
|
||||
Material mat;
|
||||
|
||||
if (object_state.color_type == V3D_SHADING_OBJECT_COLOR) {
|
||||
mat = Material(*ob_ref.object);
|
||||
|
@ -291,9 +288,11 @@ class Instance {
|
|||
ImageUser *iuser = nullptr)
|
||||
{
|
||||
const bool in_front = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0;
|
||||
resources.material_buf.append(material);
|
||||
int material_index = resources.material_buf.size() - 1;
|
||||
|
||||
auto draw = [&](MeshPass &pass) {
|
||||
pass.draw(ob_ref, batch, handle, image, sampler_state, iuser);
|
||||
pass.draw(ob_ref, batch, handle, material_index, image, sampler_state, iuser);
|
||||
};
|
||||
|
||||
if (scene_state.xray_mode || material.is_transparent()) {
|
||||
|
|
|
@ -18,6 +18,7 @@ bool MeshPass::is_empty() const
|
|||
|
||||
void MeshPass::init_pass(SceneResources &resources, DRWState state, int clip_planes)
|
||||
{
|
||||
use_custom_ids = true;
|
||||
is_empty_ = true;
|
||||
PassMain::init();
|
||||
state_set(state, clip_planes);
|
||||
|
@ -57,6 +58,7 @@ void MeshPass::init_subpasses(ePipelineType pipeline,
|
|||
void MeshPass::draw(ObjectRef &ref,
|
||||
GPUBatch *batch,
|
||||
ResourceHandle handle,
|
||||
uint material_index,
|
||||
::Image *image /* = nullptr */,
|
||||
eGPUSamplerState sampler_state /* = GPU_SAMPLER_DEFAULT */,
|
||||
ImageUser *iuser /* = nullptr */)
|
||||
|
@ -95,11 +97,11 @@ void MeshPass::draw(ObjectRef &ref,
|
|||
};
|
||||
|
||||
texture_subpass_map_.lookup_or_add_cb(TextureSubPassKey(texture, geometry_type), add_cb)
|
||||
->draw(batch, handle);
|
||||
->draw(batch, handle, material_index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
passes_[int(geometry_type)][int(eShaderType::MATERIAL)]->draw(batch, handle);
|
||||
passes_[int(geometry_type)][int(eShaderType::MATERIAL)]->draw(batch, handle, material_index);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -184,6 +184,7 @@ class MeshPass : public PassMain {
|
|||
void draw(ObjectRef &ref,
|
||||
GPUBatch *batch,
|
||||
ResourceHandle handle,
|
||||
uint material_index,
|
||||
::Image *image = nullptr,
|
||||
eGPUSamplerState sampler_state = eGPUSamplerState::GPU_SAMPLER_DEFAULT,
|
||||
ImageUser *iuser = nullptr);
|
||||
|
|
|
@ -600,14 +600,13 @@ void DrawCommandBuf::bind(RecordingState &state,
|
|||
}
|
||||
|
||||
void DrawMultiBuf::bind(RecordingState &state,
|
||||
Vector<Header, 0> &headers,
|
||||
Vector<Undetermined, 0> &commands,
|
||||
Vector<Header, 0> & /*headers*/,
|
||||
Vector<Undetermined, 0> & /*commands*/,
|
||||
VisibilityBuf &visibility_buf,
|
||||
int visibility_word_per_draw,
|
||||
int view_len)
|
||||
int view_len,
|
||||
bool use_custom_ids)
|
||||
{
|
||||
UNUSED_VARS(headers, commands);
|
||||
|
||||
GPU_debug_group_begin("DrawMultiBuf.bind");
|
||||
|
||||
resource_id_count_ = 0u;
|
||||
|
@ -636,7 +635,7 @@ void DrawMultiBuf::bind(RecordingState &state,
|
|||
group_buf_.push_update();
|
||||
prototype_buf_.push_update();
|
||||
/* Allocate enough for the expansion pass. */
|
||||
resource_id_buf_.get_or_resize(resource_id_count_);
|
||||
resource_id_buf_.get_or_resize(resource_id_count_ * (use_custom_ids ? 2 : 1));
|
||||
/* Two command per group. */
|
||||
command_buf_.get_or_resize(group_count_ * 2);
|
||||
|
||||
|
@ -646,6 +645,7 @@ void DrawMultiBuf::bind(RecordingState &state,
|
|||
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_shader_uniform_1b(shader, "use_custom_ids", use_custom_ids);
|
||||
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"));
|
||||
|
|
|
@ -433,7 +433,8 @@ class DrawCommandBuf {
|
|||
uint instance_len,
|
||||
uint vertex_len,
|
||||
uint vertex_first,
|
||||
ResourceHandle handle)
|
||||
ResourceHandle handle,
|
||||
uint /*custom_id*/)
|
||||
{
|
||||
vertex_first = vertex_first != -1 ? vertex_first : 0;
|
||||
instance_len = instance_len != -1 ? instance_len : 1;
|
||||
|
@ -533,7 +534,8 @@ class DrawMultiBuf {
|
|||
uint instance_len,
|
||||
uint vertex_len,
|
||||
uint vertex_first,
|
||||
ResourceHandle handle)
|
||||
ResourceHandle handle,
|
||||
uint custom_id)
|
||||
{
|
||||
/* 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);
|
||||
|
@ -555,6 +557,7 @@ class DrawMultiBuf {
|
|||
|
||||
DrawPrototype &draw = prototype_buf_.get_or_resize(prototype_count_++);
|
||||
draw.resource_handle = handle.raw;
|
||||
draw.custom_id = custom_id;
|
||||
draw.instance_len = instance_len;
|
||||
draw.group_id = group_id;
|
||||
|
||||
|
@ -594,7 +597,8 @@ class DrawMultiBuf {
|
|||
Vector<Undetermined, 0> &commands,
|
||||
VisibilityBuf &visibility_buf,
|
||||
int visibility_word_per_draw,
|
||||
int view_len);
|
||||
int view_len,
|
||||
bool use_custom_ids);
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -72,9 +72,10 @@ struct DrawPrototype {
|
|||
uint group_id;
|
||||
/* Resource handle associated with this call. Also reference visibility. */
|
||||
uint resource_handle;
|
||||
/* Custom extra value to be used by the engines. */
|
||||
uint custom_id;
|
||||
/* Number of instances. */
|
||||
uint instance_len;
|
||||
uint _pad0;
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(DrawPrototype, 16)
|
||||
|
||||
|
|
|
@ -186,7 +186,8 @@ void Manager::submit(PassMain &pass, View &view)
|
|||
pass.commands_,
|
||||
view.get_visibility_buffer(),
|
||||
view.visibility_word_per_draw(),
|
||||
view.view_len_);
|
||||
view.view_len_,
|
||||
pass.use_custom_ids);
|
||||
|
||||
resource_bind();
|
||||
|
||||
|
|
|
@ -135,6 +135,8 @@ class PassBase {
|
|||
public:
|
||||
const char *debug_name;
|
||||
|
||||
bool use_custom_ids;
|
||||
|
||||
PassBase(const char *name,
|
||||
DrawCommandBufType &draw_command_buf,
|
||||
SubPassVector<PassBase<DrawCommandBufType>> &sub_passes,
|
||||
|
@ -142,7 +144,8 @@ class PassBase {
|
|||
: draw_commands_buf_(draw_command_buf),
|
||||
sub_passes_(sub_passes),
|
||||
shader_(shader),
|
||||
debug_name(name){};
|
||||
debug_name(name),
|
||||
use_custom_ids(false){};
|
||||
|
||||
/**
|
||||
* Reset the pass command pool.
|
||||
|
@ -224,13 +227,14 @@ class PassBase {
|
|||
uint instance_len = -1,
|
||||
uint vertex_len = -1,
|
||||
uint vertex_first = -1,
|
||||
ResourceHandle handle = {0});
|
||||
ResourceHandle handle = {0},
|
||||
uint custom_id = 0);
|
||||
|
||||
/**
|
||||
* Shorter version for the common case.
|
||||
* \note Implemented in derived class. Not a virtual function to avoid indirection.
|
||||
*/
|
||||
void draw(GPUBatch *batch, ResourceHandle handle);
|
||||
void draw(GPUBatch *batch, ResourceHandle handle, uint custom_id = 0);
|
||||
|
||||
/**
|
||||
* Record a procedural draw call. Geometry is **NOT** source from a GPUBatch.
|
||||
|
@ -240,7 +244,8 @@ class PassBase {
|
|||
uint instance_len,
|
||||
uint vertex_len,
|
||||
uint vertex_first = -1,
|
||||
ResourceHandle handle = {0});
|
||||
ResourceHandle handle = {0},
|
||||
uint custom_id = 0);
|
||||
|
||||
/**
|
||||
* Indirect variants.
|
||||
|
@ -654,20 +659,25 @@ template<class T> std::string PassBase<T>::serialize(std::string line_prefix) co
|
|||
* \{ */
|
||||
|
||||
template<class T>
|
||||
inline void PassBase<T>::draw(
|
||||
GPUBatch *batch, uint instance_len, uint vertex_len, uint vertex_first, ResourceHandle handle)
|
||||
inline void PassBase<T>::draw(GPUBatch *batch,
|
||||
uint instance_len,
|
||||
uint vertex_len,
|
||||
uint vertex_first,
|
||||
ResourceHandle handle,
|
||||
uint custom_id)
|
||||
{
|
||||
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);
|
||||
headers_, commands_, batch, instance_len, vertex_len, vertex_first, handle, custom_id);
|
||||
}
|
||||
|
||||
template<class T> inline void PassBase<T>::draw(GPUBatch *batch, ResourceHandle handle)
|
||||
template<class T>
|
||||
inline void PassBase<T>::draw(GPUBatch *batch, ResourceHandle handle, uint custom_id)
|
||||
{
|
||||
this->draw(batch, -1, -1, -1, handle);
|
||||
this->draw(batch, -1, -1, -1, handle, custom_id);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
@ -675,9 +685,11 @@ inline void PassBase<T>::draw_procedural(GPUPrimType primitive,
|
|||
uint instance_len,
|
||||
uint vertex_len,
|
||||
uint vertex_first,
|
||||
ResourceHandle handle)
|
||||
ResourceHandle handle,
|
||||
uint custom_id)
|
||||
{
|
||||
this->draw(procedural_batch_get(primitive), instance_len, vertex_len, vertex_first, handle);
|
||||
this->draw(
|
||||
procedural_batch_get(primitive), instance_len, vertex_len, vertex_first, handle, custom_id);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -108,7 +108,14 @@ void main()
|
|||
uint view_index = i * 32u;
|
||||
while (word != 0u) {
|
||||
if ((word & 1u) != 0u) {
|
||||
resource_id_buf[dst_index++] = view_index | (resource_index << view_shift);
|
||||
if (use_custom_ids) {
|
||||
resource_id_buf[dst_index * 2] = view_index | (resource_index << view_shift);
|
||||
resource_id_buf[dst_index * 2 + 1] = proto.custom_id;
|
||||
}
|
||||
else {
|
||||
resource_id_buf[dst_index] = view_index | (resource_index << view_shift);
|
||||
}
|
||||
dst_index++;
|
||||
}
|
||||
view_index++;
|
||||
word >>= 1u;
|
||||
|
@ -117,7 +124,13 @@ void main()
|
|||
}
|
||||
else {
|
||||
for (uint i = dst_index; i < dst_index + visible_instance_len; i++) {
|
||||
resource_id_buf[i] = resource_index;
|
||||
if (use_custom_ids) {
|
||||
resource_id_buf[i * 2] = resource_index;
|
||||
resource_id_buf[i * 2 + 1] = proto.custom_id;
|
||||
}
|
||||
else {
|
||||
resource_id_buf[i] = resource_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -189,6 +189,7 @@ GPU_SHADER_CREATE_INFO(draw_command_generate)
|
|||
.push_constant(Type::INT, "prototype_len")
|
||||
.push_constant(Type::INT, "visibility_word_per_draw")
|
||||
.push_constant(Type::INT, "view_shift")
|
||||
.push_constant(Type::BOOL, "use_custom_ids")
|
||||
.compute_source("draw_command_generate_comp.glsl");
|
||||
|
||||
/** \} */
|
||||
|
@ -200,9 +201,18 @@ GPU_SHADER_CREATE_INFO(draw_command_generate)
|
|||
|
||||
GPU_SHADER_CREATE_INFO(draw_resource_id_new)
|
||||
.define("UNIFORM_RESOURCE_ID_NEW")
|
||||
/* TODO (Miguel Pozo): This is an int for compatibility.
|
||||
* It should become uint once the "Next" ports are complete. */
|
||||
.storage_buf(DRW_RESOURCE_ID_SLOT, Qualifier::READ, "int", "resource_id_buf[]")
|
||||
.define("drw_ResourceID", "resource_id_buf[gpu_BaseInstance + gl_InstanceID]");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(draw_resource_with_custom_id_new)
|
||||
.define("UNIFORM_RESOURCE_ID_NEW")
|
||||
.define("WITH_CUSTOM_IDS")
|
||||
.storage_buf(DRW_RESOURCE_ID_SLOT, Qualifier::READ, "int2", "resource_id_buf[]")
|
||||
.define("drw_ResourceID", "resource_id_buf[gpu_BaseInstance + gl_InstanceID].x")
|
||||
.define("drw_CustomID", "resource_id_buf[gpu_BaseInstance + gl_InstanceID].y");
|
||||
|
||||
pragma37 marked this conversation as resolved
|
||||
/**
|
||||
* Workaround the lack of gl_BaseInstance by binding the resource_id_buf as vertex buf.
|
||||
*/
|
||||
|
@ -210,6 +220,13 @@ GPU_SHADER_CREATE_INFO(draw_resource_id_fallback)
|
|||
.define("UNIFORM_RESOURCE_ID_NEW")
|
||||
.vertex_in(15, Type::INT, "drw_ResourceID");
|
||||
|
||||
pragma37 marked this conversation as resolved
Clément Foucault
commented
Rename Rename `draw_resource_and_custom_id` to `draw_resource_with_custom_id`.
|
||||
GPU_SHADER_CREATE_INFO(draw_resource_with_custom_id_fallback)
|
||||
.define("UNIFORM_RESOURCE_ID_NEW")
|
||||
.define("WITH_CUSTOM_IDS")
|
||||
.vertex_in(15, Type::IVEC2, "vertex_in_drw_ResourceID")
|
||||
.define("drw_ResourceID", "vertex_in_drw_ResourceID.x")
|
||||
.define("drw_CustomID", "vertex_in_drw_ResourceID.y");
|
||||
|
||||
/** TODO mask view id bits. */
|
||||
GPU_SHADER_CREATE_INFO(draw_resource_handle_new).define("resource_handle", "drw_ResourceID");
|
||||
|
||||
|
@ -219,14 +236,19 @@ GPU_SHADER_CREATE_INFO(draw_resource_handle_new).define("resource_handle", "drw_
|
|||
/** \name Draw Object Resources
|
||||
* \{ */
|
||||
|
||||
pragma37 marked this conversation as resolved
Clément Foucault
commented
Remove the Remove the `_` suffix here.
|
||||
GPU_SHADER_CREATE_INFO(draw_modelmat_new)
|
||||
GPU_SHADER_CREATE_INFO(draw_modelmat_new_common)
|
||||
.typedef_source("draw_shader_shared.h")
|
||||
.storage_buf(DRW_OBJ_MAT_SLOT, Qualifier::READ, "ObjectMatrices", "drw_matrix_buf[]")
|
||||
.define("drw_ModelMatrixInverse", "drw_matrix_buf[resource_id].model_inverse")
|
||||
.define("drw_ModelMatrix", "drw_matrix_buf[resource_id].model")
|
||||
/* TODO For compatibility with old shaders. To be removed. */
|
||||
.define("ModelMatrixInverse", "drw_ModelMatrixInverse")
|
||||
.define("ModelMatrix", "drw_ModelMatrix")
|
||||
.additional_info("draw_resource_id_new");
|
||||
.define("ModelMatrix", "drw_ModelMatrix");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(draw_modelmat_new)
|
||||
.additional_info("draw_modelmat_new_common", "draw_resource_id_new");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(draw_modelmat_new_with_custom_id)
|
||||
.additional_info("draw_modelmat_new_common", "draw_resource_with_custom_id_new");
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -317,6 +317,7 @@ void gpu_shader_create_info_init()
|
|||
/* WORKAROUND: Replace the use of gpu_BaseInstance by an instance attribute. */
|
||||
if (GPU_shader_draw_parameters_support() == false) {
|
||||
draw_resource_id_new = draw_resource_id_fallback;
|
||||
draw_resource_with_custom_id_new = draw_resource_with_custom_id_fallback;
|
||||
}
|
||||
|
||||
#ifdef WITH_METAL_BACKEND
|
||||
|
|
|
@ -121,12 +121,18 @@ void GLVertArray::update_bindings(const GLuint vao,
|
|||
|
||||
if (batch->resource_id_buf) {
|
||||
const ShaderInput *input = interface->attr_get("drw_ResourceID");
|
||||
int component_len = 1;
|
||||
pragma37 marked this conversation as resolved
Clément Foucault
commented
Use Use `comp_len` or `component_len`.
`size` is generally reserved for size in bytes use `_len` suffix for the rest.
Try to avoid calling variable just `len` or `size`. They are always size of length of something.
|
||||
if (input == nullptr) {
|
||||
/* Uses Custom IDs */
|
||||
input = interface->attr_get("vertex_in_drw_ResourceID_");
|
||||
component_len = 2;
|
||||
}
|
||||
if (input) {
|
||||
dynamic_cast<GLStorageBuf *>(unwrap(batch->resource_id_buf))->bind_as(GL_ARRAY_BUFFER);
|
||||
glEnableVertexAttribArray(input->location);
|
||||
glVertexAttribDivisor(input->location, 1);
|
||||
glVertexAttribIPointer(
|
||||
input->location, 1, to_gl(GPU_COMP_I32), sizeof(uint32_t), (GLvoid *)nullptr);
|
||||
input->location, component_len, to_gl(GPU_COMP_I32), 0, (GLvoid *)nullptr);
|
||||
attr_mask &= ~(1 << input->location);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
It isn't
uint2
because of compatibility with older code. This should become a TODO.