20 const glm::vec3& bounds_min,
21 const glm::vec3& bounds_max,
27 , m_field(
std::move(field))
28 , m_bounds_min(bounds_min)
29 , m_bounds_max(bounds_max)
30 , m_res_x(
std::max(res_x, 1U))
31 , m_res_y(
std::max(res_y, 1U))
32 , m_res_z(
std::max(res_z, 1U))
33 , m_iso_level(iso_level)
47 std::shared_ptr<VKBuffer> grid_buf,
48 std::shared_ptr<VKBuffer> counter_buf,
49 const glm::vec3& bounds_min,
50 const glm::vec3& bounds_max,
56 , m_bounds_min(bounds_min)
57 , m_bounds_max(bounds_max)
58 , m_res_x(
std::max(res_x, 1U))
59 , m_res_y(
std::max(res_y, 1U))
60 , m_res_z(
std::max(res_z, 1U))
61 , m_iso_level(iso_level)
62 , m_grid_buf(
std::move(grid_buf))
63 , m_counter_buf(
std::move(counter_buf))
64 , m_owns_buffers(false)
126 auto vk_buf = std::dynamic_pointer_cast<VKBuffer>(buffer);
129 "SDFMeshProcessor requires a VKBuffer");
145 std::vector<uint32_t> edge_flat(256);
146 for (
size_t i = 0; i < 256; ++i)
149 std::vector<int32_t> tri_flat(
static_cast<long>(256) * 16);
150 for (
size_t i = 0; i < 256; ++i) {
151 for (
size_t j = 0; j < 16; ++j)
155 std::memcpy(
m_edge_buf->get_mapped_ptr(), edge_flat.data(),
156 edge_flat.size() *
sizeof(uint32_t));
157 std::memcpy(
m_tri_buf->get_mapped_ptr(), tri_flat.data(),
158 tri_flat.size() *
sizeof(int32_t));
163 const std::shared_ptr<VKBuffer>& )
171 std::memset(
m_counter_buf->get_mapped_ptr(), 0,
sizeof(uint32_t));
178 extent.x /
static_cast<float>(
m_res_x),
179 extent.y /
static_cast<float>(
m_res_y),
180 extent.z /
static_cast<float>(
m_res_z),
194 const uint32_t groups = (
voxel_count() + 63U) / 64U;
202 const std::shared_ptr<VKBuffer>& buffer)
204 const auto n = *
static_cast<const uint32_t*
>(
m_counter_buf->get_mapped_ptr());
206 if (
auto rp = buffer->get_render_processor()) {
207 buffer->get_render_processor()->set_vertex_range(0, n);
210 "SDFMeshProcessor: no render processor attached to buffer, cannot set vertex count");
217 "SDFMeshProcessor: {} vertices extracted", n);
231 VKBuffer::Usage::HOST_STORAGE,
236 256 *
sizeof(uint32_t),
237 VKBuffer::Usage::HOST_STORAGE,
242 static_cast<long>(256) * 16 *
sizeof(int32_t),
243 VKBuffer::Usage::HOST_STORAGE,
249 VKBuffer::Usage::HOST_STORAGE,
256 const uint32_t nx =
m_res_x + 1;
257 const uint32_t ny =
m_res_y + 1;
258 const uint32_t nz =
m_res_z + 1;
259 const size_t total =
static_cast<size_t>(nx) * ny * nz;
262 const glm::vec3 step {
263 extent.x /
static_cast<float>(
m_res_x),
264 extent.y /
static_cast<float>(
m_res_y),
265 extent.z /
static_cast<float>(
m_res_z),
268 auto* grid =
static_cast<float*
>(
m_grid_buf->get_mapped_ptr());
270 MayaFlux::Parallel::for_each(std::execution::par_unseq,
271 std::views::iota(0UZ, total).begin(),
272 std::views::iota(0UZ, total).end(),
274 const uint32_t gix = idx % nx;
275 const uint32_t giy = (idx / nx) % ny;
276 const uint32_t giz = idx / (
static_cast<size_t>(nx) * ny);
290 256 *
sizeof(uint32_t),
291 VKBuffer::Usage::HOST_STORAGE,
296 static_cast<long>(256) * 16 *
sizeof(int32_t),
297 VKBuffer::Usage::HOST_STORAGE,
#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 set_axis_palette(const glm::vec3 &x, const glm::vec3 &y, const glm::vec3 &z)
Color each triangle by the dominant axis of its surface normal.
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
std::array< glm::vec3, 3 > m_palette
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.
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.