MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ mill()

uint32_t MayaFlux::Portal::Graphics::PrimitiveMill::mill ( const std::shared_ptr< Buffers::VKBuffer > &  source,
std::span< const DrawRun runs,
const MillView view 
)

Mill runs out of source into the owned buffer.

Parameters
sourceVertex buffer the spans index into. Must carry a vertex layout whose stride is a multiple of four bytes and which has a word aligned position attribute.
runsSpans to mill, in output order.
viewViewpoint, consumed only by Ribbon::WorldFacing.
Returns
Vertices written, or 0 when there was nothing to mill or the source could not be used.

Does not wait on its own dispatch. It resolves the previous call's submission first, then submits this one and returns. output() is immediately valid to record a draw against; it is not valid to read from the host until a later mill() or release() has resolved the fence.

Dispatched on the graphics queue, not a compute one, which is what makes the recorded barriers mean anything: submission order spans vkQueueSubmit calls to one queue, so the trailing barrier orders this write before the draw submitted afterwards and the leading one orders the previous frame's vertex fetch before this write. Neither reaches across queues, and the destination is SharingMode::eExclusive, so a dedicated compute queue would need a semaphore and a queue family ownership transfer instead.

Waiting on the previous dispatch is not optional: the run and prefix tables are host visible and rewritten here, so the prior dispatch must have finished reading them.

The destination grows to fit and never shrinks.

Definition at line 630 of file PrimitiveMill.cpp.

634{
636
637 m_milled_count = 0;
638
639 if (!source || runs.empty()) {
640 return 0;
641 }
642
643 const auto layout = source->get_vertex_layout();
644 if (!layout.has_value()) {
645 return 0;
646 }
647
648 MillOffsets off;
649 if (!offsets_from(*layout, off)) {
651 "PrimitiveMill: layout is not millable, stride {} needs word alignment "
652 "and an addressable position attribute",
653 layout->stride_bytes);
654 return 0;
655 }
656
657 const uint32_t source_vertices = layout->vertex_count;
658 for (const auto& run : runs) {
659 if (run.vertex_count == 0) {
660 continue;
661 }
662 if (run.vertex_offset > source_vertices
663 || run.vertex_count > source_vertices - run.vertex_offset) {
665 "PrimitiveMill: run [{}, {}) exceeds the source's {} vertices",
666 run.vertex_offset, run.vertex_offset + run.vertex_count, source_vertices);
667 return 0;
668 }
669 }
670
671 build_prefix(runs, m_prefix);
672 const uint32_t total = m_prefix.back();
673 if (total == 0) {
674 return 0;
675 }
676
677 if (!ensure_kernel() || !ensure_buffers(source, *layout, total, runs.size())) {
678 return 0;
679 }
680
681 m_output_slot = (m_output_slot + 1) % m_outputs.size();
682
683 auto* run_ptr = static_cast<uint32_t*>(m_run_buf->get_mapped_ptr());
684 auto* prefix_ptr = static_cast<uint32_t*>(m_prefix_buf->get_mapped_ptr());
685 if (!run_ptr || !prefix_ptr) {
687 "PrimitiveMill: run or prefix buffer is not host mapped");
688 return 0;
689 }
690
691 for (size_t r = 0; r < runs.size(); ++r) {
692 run_ptr[r * RUN_WORDS + 0] = static_cast<uint32_t>(runs[r].topology);
693 run_ptr[r * RUN_WORDS + 1] = runs[r].vertex_offset;
694 run_ptr[r * RUN_WORDS + 2] = runs[r].vertex_count;
695 }
696 std::memcpy(prefix_ptr, m_prefix.data(), m_prefix.size() * sizeof(uint32_t));
697
698 write_descriptors(source);
699
700 const auto pc = make_pc(m_spec, view, off, total, runs.size());
701
702 auto& foundry = get_shader_foundry();
703 auto& press = get_compute_press();
704
705 const auto destination = m_outputs[m_output_slot]->get_buffer();
706
707 auto cmd_id = foundry.begin_commands(ShaderFoundry::CommandBufferType::GRAPHICS);
708
709 foundry.buffer_barrier(
710 cmd_id,
711 destination,
712 vk::AccessFlagBits::eVertexAttributeRead,
713 vk::AccessFlagBits::eShaderWrite,
714 vk::PipelineStageFlagBits::eVertexInput,
715 vk::PipelineStageFlagBits::eComputeShader);
716
717 press.bind_all(cmd_id, m_pipeline, m_sets, &pc, sizeof(MillPC));
718 press.dispatch(cmd_id, (total + WORKGROUP - 1) / WORKGROUP, 1, 1);
719
720 foundry.buffer_barrier(
721 cmd_id,
722 destination,
723 vk::AccessFlagBits::eShaderWrite,
724 vk::AccessFlagBits::eVertexAttributeRead,
725 vk::PipelineStageFlagBits::eComputeShader,
726 vk::PipelineStageFlagBits::eVertexInput);
727
728 m_pending_fence = foundry.submit_async(cmd_id);
731 "PrimitiveMill: dispatch submission failed");
732 return 0;
733 }
734
736
738 "PrimitiveMill: milled {} runs into {} vertices", runs.size(), total);
739
740 return total;
741}
#define MF_RT_ERROR(comp, ctx,...)
#define MF_RT_TRACE(comp, ctx,...)
uint32_t total
FenceID m_pending_fence
Outstanding dispatch, resolved at the start of the next mill().
bool ensure_buffers(const std::shared_ptr< Buffers::VKBuffer > &source, const Kakshya::VertexLayout &layout, uint32_t total, size_t run_count)
Grows the destination ring, run and prefix buffers to fit.
std::shared_ptr< Buffers::VKBuffer > m_prefix_buf
std::shared_ptr< Buffers::VKBuffer > m_run_buf
std::vector< DescriptorSetID > m_sets
bool ensure_kernel()
Compiles the kernel and allocates its descriptor sets, once.
std::vector< std::shared_ptr< Buffers::VKBuffer > > m_outputs
Milled buffers rotated between dispatches, all at m_output_capacity.
void resolve_pending()
Wait on and reclaim the previous dispatch, if one is outstanding.
void write_descriptors(const std::shared_ptr< Buffers::VKBuffer > &source)
Points the descriptor set at the current buffer set, on any change of source or ring slot.
void run()
Definition main.cpp:22
@ Rendering
GPU rendering operations (graphics pipeline, frame rendering)
@ Portal
High-level user-facing API layer.
Source source()
Begin a Source chain.
Definition Plot.hpp:128
constexpr FenceID INVALID_FENCE
MAYAFLUX_API ShaderFoundry & get_shader_foundry()
Get the global shader compiler instance.
MAYAFLUX_API ComputePress & get_compute_press()
std::shared_ptr< Buffers::TextBuffer > press(std::string_view text, const PressParams &params)
Composite a UTF-8 string into a new TextBuffer.
Definition InkPress.cpp:344

References ensure_buffers(), ensure_kernel(), MayaFlux::Portal::Graphics::get_compute_press(), MayaFlux::Portal::Graphics::get_shader_foundry(), MayaFlux::Portal::Graphics::ShaderFoundry::GRAPHICS, MayaFlux::Portal::Graphics::INVALID_FENCE, m_milled_count, m_output_slot, m_outputs, m_pending_fence, m_pipeline, m_prefix, m_prefix_buf, m_run_buf, m_sets, m_spec, MF_RT_ERROR, MF_RT_TRACE, MayaFlux::Journal::Portal, MayaFlux::Journal::Rendering, resolve_pending(), run(), total, and write_descriptors().

Referenced by MayaFlux::Buffers::RenderProcessor::mill_runs().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: