Skip to content

Commit

Permalink
ex 8 fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
martty committed Apr 23, 2024
1 parent 8c09410 commit 5307d0f
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 99 deletions.
183 changes: 89 additions & 94 deletions examples/08_pipelined_compute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ namespace {
auto box = util::generate_cube();
int x, y;
uint32_t speed_count = 1;
std::optional<vuk::Texture> texture_of_doge;
vuk::Unique<vuk::Image> image_of_doge;
vuk::Unique<vuk::ImageView> image_view_of_doge;
vuk::ImageAttachment texture_of_doge;
vuk::Unique<vuk::Buffer> scramble_buf;
std::random_device rd;
std::mt19937 g(rd());
vuk::Future scramble_buf_fut;
vuk::Future texture_of_doge_fut;
vuk::Value<vuk::Buffer> scramble_buf_fut;
vuk::Value<vuk::ImageAttachment> texture_of_doge_fut;

vuk::Example xample{
.name = "08_pipelined_compute",
Expand All @@ -44,7 +46,8 @@ namespace {
{
vuk::PipelineBaseCreateInfo pci;
pci.add_glsl(util::read_entire_file((root / "examples/fullscreen.vert").generic_string()), (root / "examples/fullscreen.vert").generic_string());
pci.add_glsl(util::read_entire_file((root / "examples/scrambled_draw.frag").generic_string()), (root / "examples/scrambled_draw.frag").generic_string());
pci.add_glsl(util::read_entire_file((root / "examples/scrambled_draw.frag").generic_string()),
(root / "examples/scrambled_draw.frag").generic_string());
runner.runtime->create_named_pipeline("scrambled_draw", pci);
}

Expand All @@ -58,9 +61,14 @@ namespace {
int chans;
auto doge_image = stbi_load((root / "examples/doge.png").generic_string().c_str(), &x, &y, &chans, 4);

auto [tex, tex_fut] = create_texture(allocator, vuk::Format::eR8G8B8A8Srgb, vuk::Extent3D{ (unsigned)x, (unsigned)y, 1u }, doge_image, true);
texture_of_doge = std::move(tex);
runner.enqueue_setup(std::move(tex_fut));
texture_of_doge = vuk::ImageAttachment::from_preset(
vuk::ImageAttachment::Preset::eMap2D, vuk::Format::eR8G8B8A8Srgb, vuk::Extent3D{ (unsigned)x, (unsigned)y, 1u }, vuk::Samples::e1);
texture_of_doge.level_count = 1;
auto [image, view, future] = vuk::create_image_and_view_with_data(allocator, vuk::DomainFlagBits::eTransferOnTransfer, texture_of_doge, doge_image);
image_of_doge = std::move(image);
image_view_of_doge = std::move(view);
runner.enqueue_setup(future.as_released(vuk::Access::eFragmentSampled, vuk::DomainFlagBits::eGraphicsQueue));
stbi_image_free(doge_image);

// init scrambling buffer
std::vector<unsigned> indices(x * y);
Expand All @@ -71,107 +79,94 @@ namespace {

// make a GPU future
scramble_buf_fut = vuk::host_data_to_buffer(allocator, vuk::DomainFlagBits::eTransferOnTransfer, scramble_buf.get(), std::span(indices));

stbi_image_free(doge_image);
},
.render =
[](vuk::ExampleRunner& runner, vuk::Allocator& frame_allocator, vuk::Future target) {
std::shared_ptr<vuk::RenderGraph> rgx = std::make_shared<vuk::RenderGraph>("RTT");

rgx->attach_and_clear_image(
"08_rttf",
{ .extent = vuk::Dimension3D::absolute((unsigned)x, (unsigned)y), .format = runner.swapchain->format, .sample_count = vuk::Samples::e1 },
[](vuk::ExampleRunner& runner, vuk::Allocator& frame_allocator, vuk::Value<vuk::ImageAttachment> target) {
auto rttf = vuk::clear_image(
vuk::declare_ia(
"08_rttf",
{ .extent = { (unsigned)x, (unsigned)y }, .format = runner.swapchain->images[0].format, .sample_count = vuk::Samples::e1, .layer_count = 1 }),
vuk::ClearColor{ 0.f, 0.f, 0.f, 1.f });

// standard render to texture
rgx->add_pass({ .name = "rtt",
.execute_on = vuk::DomainFlagBits::eGraphicsQueue,
.resources = { "08_rttf"_image >> vuk::eColorWrite },
.execute = [](vuk::CommandBuffer& command_buffer) {
command_buffer.set_viewport(0, vuk::Rect2D::framebuffer())
.set_scissor(0, vuk::Rect2D::framebuffer())
.set_rasterization({}) // Set the default rasterization state
.broadcast_color_blend({}) // Set the default color blend state
.bind_image(0, 0, *texture_of_doge->view)
.bind_sampler(0, 0, {})
.bind_graphics_pipeline("rtt")
.draw(3, 1, 0, 0);
} });

// make a gpu future of the above graph (render to texture) and bind to an output (rttf)
vuk::Future rttf{ rgx, "08_rttf+" };

std::shared_ptr<vuk::RenderGraph> rgp = std::make_shared<vuk::RenderGraph>("08");
rgp->attach_in("08_pipelined_compute", std::move(target));
auto rtt_pass = vuk::make_pass(
"rtt",
[](vuk::CommandBuffer& command_buffer, VUK_IA(vuk::eColorWrite) target) {
command_buffer.set_viewport(0, vuk::Rect2D::framebuffer())
.set_scissor(0, vuk::Rect2D::framebuffer())
.set_rasterization({}) // Set the default rasterization state
.broadcast_color_blend({}) // Set the default color blend state
.bind_image(0, 0, texture_of_doge.image_view)
.bind_sampler(0, 0, {})
.bind_graphics_pipeline("rtt")
.draw(3, 1, 0, 0);

return target;
},
vuk::DomainFlagBits::eGraphicsQueue);

rttf = rtt_pass(rttf);

// this pass executes outside of a renderpass
// we declare a buffer dependency and dispatch a compute shader
rgp->add_pass({ .name = "sort",
.execute_on = vuk::DomainFlagBits::eGraphicsQueue,
.resources = { "08_scramble"_buffer >> vuk::eComputeRW >> "08_scramble+" },
.execute = [](vuk::CommandBuffer& command_buffer) {
command_buffer.bind_buffer(0, 0, *command_buffer.get_resource_buffer("08_scramble"));
command_buffer.bind_compute_pipeline("stupidsort").specialize_constants(0, speed_count).dispatch(1);
// We can also customize pipelines by using specialization constants
// Here we will apply a tint based on the current frame
auto current_frame = command_buffer.get_context().get_frame_count();
auto mod_frame = current_frame % 100;
if (mod_frame == 99) {
speed_count += 256;
}
} });

rgp->add_pass({ .name = "copy",
.execute_on = vuk::DomainFlagBits::eTransferQueue,
.resources = { "08_scramble+"_buffer >> vuk::eTransferRead, "08_scramble++"_buffer >> vuk::eTransferWrite >> "08_scramble+++" },
.execute = [](vuk::CommandBuffer& command_buffer) {
command_buffer.copy_buffer("08_scramble+", "08_scramble++", sizeof(unsigned) * x * y);
} });
// put it back into the persistent buffer
rgp->add_pass({ .name = "copy_2",
.execute_on = vuk::DomainFlagBits::eTransferQueue,
.resources = { "08_scramble+++"_buffer >> vuk::eTransferRead, "08_scramble++++"_buffer >> vuk::eTransferWrite >> "08_scramble+++++" },
.execute = [](vuk::CommandBuffer& command_buffer) {
command_buffer.copy_buffer("08_scramble+++", "08_scramble++++", sizeof(unsigned) * x * y);
} });
auto sort_pass = vuk::make_pass(
"sort",
[](vuk::CommandBuffer& command_buffer, VUK_BA(vuk::eComputeRW) scramble) {
command_buffer.bind_buffer(0, 0, scramble);
command_buffer.bind_compute_pipeline("stupidsort").specialize_constants(0, speed_count).dispatch(1);
// We can also customize pipelines by using specialization constants
// Here we will apply a tint based on the current frame
auto current_frame = command_buffer.get_context().get_frame_count();
auto mod_frame = current_frame % 100;
if (mod_frame == 99) {
speed_count += 256;
}

return scramble;
},
vuk::DomainFlagBits::eGraphicsQueue);

auto copy_pass = vuk::make_pass(
"copy",
[](vuk::CommandBuffer& command_buffer, VUK_BA(vuk::eTransferRead) src, VUK_BA(vuk::eTransferWrite) dst) {
command_buffer.copy_buffer(src, dst);
return dst;
},
vuk::DomainFlagBits::eTransferQueue);

auto scramble_temp = vuk::declare_buf("scramble temporary");
scramble_temp->memory_usage = vuk::MemoryUsage::eGPUonly;
scramble_temp.same_size(scramble_buf_fut);
auto sorted = sort_pass(scramble_buf_fut);
auto in_temp = copy_pass(sorted, scramble_temp);
scramble_buf_fut = copy_pass(in_temp, scramble_buf_fut);

// draw the scrambled image, with a buffer dependency on the scramble buffer
rgp->add_pass({ .name = "draw",
.execute_on = vuk::DomainFlagBits::eGraphicsQueue,
.resources = { "08_scramble+++"_buffer >> vuk::eFragmentRead,
"08_rtt"_image >> vuk::eFragmentSampled,
"08_pipelined_compute"_image >> vuk::eColorWrite >> "08_pipelined_compute_final" },
.execute = [](vuk::CommandBuffer& command_buffer) {
command_buffer.set_viewport(0, vuk::Rect2D::framebuffer())
.set_scissor(0, vuk::Rect2D::framebuffer())
.set_rasterization({}) // Set the default rasterization state
.broadcast_color_blend({}) // Set the default color blend state
.bind_image(0, 0, "08_rtt")
.bind_sampler(0, 0, {})
.bind_buffer(0, 1, *command_buffer.get_resource_buffer("08_scramble+++"))
.bind_graphics_pipeline("scrambled_draw")
.draw(3, 1, 0, 0);
} });
auto draw_pass = vuk::make_pass(
"draw",
[](vuk::CommandBuffer& command_buffer, VUK_BA(vuk::eFragmentRead) scramble, VUK_IA(vuk::eFragmentSampled) rtt, VUK_IA(vuk::eColorWrite) final) {
command_buffer.set_viewport(0, vuk::Rect2D::framebuffer())
.set_scissor(0, vuk::Rect2D::framebuffer())
.set_rasterization({}) // Set the default rasterization state
.broadcast_color_blend({}) // Set the default color blend state
.bind_image(0, 0, rtt)
.bind_sampler(0, 0, {})
.bind_buffer(0, 1, scramble)
.bind_graphics_pipeline("scrambled_draw")
.draw(3, 1, 0, 0);

return final;
},
vuk::DomainFlagBits::eGraphicsQueue);

time += ImGui::GetIO().DeltaTime;
// make the main rendergraph
// our two inputs are the futures - they compile into the main rendergraph
rgp->attach_in("08_rtt", std::move(rttf));
// the copy here in addition will execute on the transfer queue, and will signal the graphics to execute the rest
// we created this future in the setup code, so on the first frame it will append the computation
// but on the subsequent frames the future becomes ready (on the gpu) and this will only attach a buffer
rgp->attach_in("08_scramble", std::move(scramble_buf_fut));
// temporary buffer used for copying
rgp->attach_buffer(
"08_scramble++", **allocate_buffer(frame_allocator, { vuk::MemoryUsage::eGPUonly, sizeof(unsigned) * x * y, 1 }), vuk::Access::eNone);
// permanent buffer to keep state
rgp->attach_buffer("08_scramble++++", *scramble_buf, vuk::Access::eNone);
scramble_buf_fut = { rgp, "08_scramble+++++" };

return vuk::Future{ rgp, "08_pipelined_compute_final" };

return draw_pass(in_temp, rttf, target);
},
.cleanup =
[](vuk::ExampleRunner& runner, vuk::Allocator& frame_allocator) {
texture_of_doge.reset();
image_of_doge.reset();
image_view_of_doge.reset();
scramble_buf.reset();
}

Expand Down
2 changes: 1 addition & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ ADD_EXAMPLE(04_texture)
ADD_EXAMPLE(05_deferred)
ADD_EXAMPLE(06_msaa)
ADD_EXAMPLE(07_commands)
#ADD_EXAMPLE(08_pipelined_compute)
ADD_EXAMPLE(08_pipelined_compute)
ADD_EXAMPLE(09_persistent_descriptorset)
ADD_EXAMPLE(10_baby_renderer)
ADD_EXAMPLE(11_composition)
Expand Down
2 changes: 1 addition & 1 deletion include/vuk/RenderGraph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ private:
(rg->subgraphs.push_back(args.get_render_graph()), ...);
std::array refs = { arg.get_head(), args.get_head()... };
std::array defs = { arg.get_def(), args.get_def()... };
deps = { args.node... };
deps = { arg.node, args.node... };
Ref ref = rg->make_declare_array(Type::stripped(refs[0].type()), refs, defs);
rg->name_output(ref, name.c_str());
return { make_ext_ref(rg, ref, deps), ref };
Expand Down
6 changes: 3 additions & 3 deletions include/vuk/vsl/Core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ namespace vuk {

inline std::pair<Unique<Image>, Value<ImageAttachment>> create_image_with_data(Allocator& allocator,
DomainFlagBits copy_domain,
ImageAttachment ia,
ImageAttachment& ia,
const void* data,
VUK_CALLSTACK) {
auto image = allocate_image(allocator, ia, VUK_CALL);
Expand All @@ -185,7 +185,7 @@ namespace vuk {
template<class T>
std::pair<Unique<Image>, Value<ImageAttachment>> create_image_with_data(Allocator& allocator,
DomainFlagBits copy_domain,
ImageAttachment ia,
ImageAttachment& ia,
std::span<T> data,
VUK_CALLSTACK) {
return create_image_with_data(allocator, copy_domain, ia, data.data(), VUK_CALL);
Expand All @@ -194,7 +194,7 @@ namespace vuk {
inline std::tuple<Unique<Image>, Unique<ImageView>, Value<ImageAttachment>>
create_image_and_view_with_data(Allocator& allocator,
DomainFlagBits copy_domain,
ImageAttachment ia,
ImageAttachment& ia,
const void* data,
VUK_CALLSTACK) {
auto image = allocate_image(allocator, ia, VUK_CALL);
Expand Down
1 change: 1 addition & 0 deletions src/runtime/vk/Backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,7 @@ namespace vuk {
#endif
if (bound.buffer == VK_NULL_HANDLE) {
assert(bound.size != ~(0u));
assert(bound.memory_usage != (MemoryUsage)0);
BufferCreateInfo bci{ .mem_usage = bound.memory_usage, .size = bound.size, .alignment = 1 }; // TODO: alignment?
auto allocator = node->construct.allocator ? *node->construct.allocator : alloc;
auto buf = allocate_buffer(allocator, bci);
Expand Down

0 comments on commit 5307d0f

Please sign in to comment.