22 const glm::vec3& bounds_min,
23 const glm::vec3& bounds_max,
29 , m_field(
std::move(field))
30 , m_bounds_min(bounds_min)
31 , m_bounds_max(bounds_max)
32 , m_res_x(
std::max(res_x, 1U))
33 , m_res_y(
std::max(res_y, 1U))
34 , m_res_z(
std::max(res_z, 1U))
35 , m_iso_level(iso_level)
49 std::shared_ptr<VKBuffer> grid_buf,
50 std::shared_ptr<VKBuffer> counter_buf,
51 const glm::vec3& bounds_min,
52 const glm::vec3& bounds_max,
58 , m_bounds_min(bounds_min)
59 , m_bounds_max(bounds_max)
60 , m_res_x(
std::max(res_x, 1U))
61 , m_res_y(
std::max(res_y, 1U))
62 , m_res_z(
std::max(res_z, 1U))
63 , m_iso_level(iso_level)
64 , m_grid_buf(
std::move(grid_buf))
65 , m_counter_buf(
std::move(counter_buf))
66 , m_owns_buffers(false)
122 auto vk_buf = std::dynamic_pointer_cast<VKBuffer>(buffer);
125 "SDFMeshProcessor requires a VKBuffer");
141 std::vector<uint32_t> edge_flat(256);
142 for (
size_t i = 0; i < 256; ++i)
145 std::vector<int32_t> tri_flat(
static_cast<long>(256) * 16);
146 for (
size_t i = 0; i < 256; ++i) {
147 for (
size_t j = 0; j < 16; ++j)
151 std::memcpy(
m_edge_buf->get_mapped_ptr(), edge_flat.data(),
152 edge_flat.size() *
sizeof(uint32_t));
153 std::memcpy(
m_tri_buf->get_mapped_ptr(), tri_flat.data(),
154 tri_flat.size() *
sizeof(int32_t));
159 const std::shared_ptr<VKBuffer>& )
167 std::memset(
m_counter_buf->get_mapped_ptr(), 0,
sizeof(uint32_t));
174 extent.x /
static_cast<float>(
m_res_x),
175 extent.y /
static_cast<float>(
m_res_y),
176 extent.z /
static_cast<float>(
m_res_z),
184 const uint32_t groups = (
voxel_count() + 63U) / 64U;
192 const std::shared_ptr<VKBuffer>& buffer)
194 const auto n = *
static_cast<const uint32_t*
>(
m_counter_buf->get_mapped_ptr());
196 if (
auto rp = buffer->get_render_processor()) {
197 buffer->get_render_processor()->set_vertex_range(0, n);
200 "SDFMeshProcessor: no render processor attached to buffer, cannot set vertex count");
207 "SDFMeshProcessor: {} vertices extracted", n);
226 256 *
sizeof(uint32_t),
232 static_cast<long>(256) * 16 *
sizeof(int32_t),
246 const uint32_t nx =
m_res_x + 1;
247 const uint32_t ny =
m_res_y + 1;
248 const uint32_t nz =
m_res_z + 1;
249 const size_t total =
static_cast<size_t>(nx) * ny * nz;
252 const glm::vec3 step {
253 extent.x /
static_cast<float>(
m_res_x),
254 extent.y /
static_cast<float>(
m_res_y),
255 extent.z /
static_cast<float>(
m_res_z),
258 auto* grid =
static_cast<float*
>(
m_grid_buf->get_mapped_ptr());
260 MayaFlux::Parallel::for_each(std::execution::par_unseq,
261 std::views::iota(0UZ, total).begin(),
262 std::views::iota(0UZ, total).end(),
264 const uint32_t gix = idx % nx;
265 const uint32_t giy = (idx / nx) % ny;
266 const uint32_t giz = idx / (
static_cast<size_t>(nx) * ny);
280 256 *
sizeof(uint32_t),
286 static_cast<long>(256) * 16 *
sizeof(int32_t),
#define MF_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
virtual void on_attach(const std::shared_ptr< Buffer > &)
Called when this processor is attached to a buffer.
void set_dispatch_mode(ShaderDispatchConfig::DispatchMode mode)
Set dispatch mode.
void set_manual_dispatch(uint32_t x, uint32_t y=1, uint32_t z=1)
Set manual dispatch group counts.
Specialized ShaderProcessor for Compute Pipelines.
void rebuild_owned_buffers()
void set_bounds(const glm::vec3 &bounds_min, const glm::vec3 &bounds_max)
Replace the evaluation volume and mark dirty.
std::shared_ptr< VKBuffer > m_grid_buf
bool on_before_execute(Portal::Graphics::CommandBufferID cmd_id, const std::shared_ptr< VKBuffer > &buffer) override
Called before each process callback.
bool m_owns_buffers
false in GPU-field mode; buffers owned by SdfPrepProcessor.
void set_field(Kinesis::SpatialField field)
Replace the scalar field and mark dirty.
uint32_t corner_count() const noexcept
void on_descriptors_created() override
Called after descriptor sets are created.
std::shared_ptr< VKBuffer > m_tri_buf
Kinesis::SpatialField m_field
SDFMeshProcessor(Kinesis::SpatialField field, const glm::vec3 &bounds_min, const glm::vec3 &bounds_max, uint32_t res_x, uint32_t res_y, uint32_t res_z, float iso_level)
std::shared_ptr< VKBuffer > m_counter_buf
uint32_t voxel_count() const noexcept
std::shared_ptr< VKBuffer > m_edge_buf
void on_attach(const std::shared_ptr< Buffer > &buffer) override
Called when this processor is attached to a buffer.
void on_after_execute(Portal::Graphics::CommandBufferID cmd_id, const std::shared_ptr< VKBuffer > &buffer) override
Called after each process callback.
void rebuild_lookup_buffers()
void set_resolution(uint32_t res_x, uint32_t res_y, uint32_t res_z)
Replace the grid resolution and mark dirty.
void set_iso_level(float iso_level)
Replace the iso_level threshold and mark dirty.
bool m_needs_descriptor_rebuild
void set_push_constant_data(const T &data)
Update push constant data (type-safe)
void bind_buffer(const std::string &descriptor_name, const std::shared_ptr< VKBuffer > &buffer)
Bind a VKBuffer to a named shader descriptor.
@ HOST_STORAGE
Host-visible storage buffer (eStorageBuffer + eHostVisible|eHostCoherent)
Interface * get_service()
Query for a backend service.
static BackendRegistry & instance()
Get the global registry instance.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.
@ UNKNOWN
Unknown or undefined modality.
constexpr std::array< uint16_t, 256 > k_edge_table
constexpr std::array< std::array< int8_t, 16 >, 256 > k_tri_table
Describes how a VKBuffer binds to a shader descriptor.
std::unordered_map< std::string, ShaderBinding > bindings
size_t push_constant_size
@ MANUAL
Use explicit group counts.
Typed, composable, stateless callable from domain D to range R.
Backend buffer management service interface.