7#include "gfx_pipeline_image_vulkan_intf.hpp"
8#include "gfx_device_vulkan_impl.hpp"
9#include "../macros.hpp"
10#include <vulkan/vulkan.hpp>
12hi_export_module(hikogui.GFX : gfx_pipeline_image_impl);
14hi_export
namespace hi {
inline namespace v1 {
16inline void gfx_pipeline_image::draw_in_command_buffer(vk::CommandBuffer commandBuffer, draw_context
const& context)
18 gfx_pipeline::draw_in_command_buffer(commandBuffer, context);
20 hi_axiom_not_null(device());
21 device()->flushAllocation(vertexBufferAllocation, 0, vertexBufferData.size() *
sizeof(vertex));
22 device()->image_pipeline->prepare_atlas_for_rendering();
26 hi_assert(tmpvertexBuffers.
size() == tmpOffsets.
size());
28 device()->image_pipeline->draw_in_command_buffer(commandBuffer);
30 commandBuffer.bindVertexBuffers(0, tmpvertexBuffers, tmpOffsets);
32 pushConstants.windowExtent = extent2{narrow_cast<float>(extent.width), narrow_cast<float>(extent.height)};
33 pushConstants.viewportScale = sfloat_rg32{2.0f / extent.width, 2.0f / extent.height};
34 pushConstants.atlasExtent = sfloat_rg32{device_shared::atlas_image_axis_size, device_shared::atlas_image_axis_size};
35 pushConstants.atlasScale =
36 sfloat_rg32{1.0f / device_shared::atlas_image_axis_size, 1.0f / device_shared::atlas_image_axis_size};
37 commandBuffer.pushConstants(
39 vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment,
41 sizeof(push_constants),
44 auto const numberOfRectangles = vertexBufferData.size() / 4;
45 auto const numberOfTriangles = numberOfRectangles * 2;
46 device()->cmdBeginDebugUtilsLabelEXT(commandBuffer,
"draw images");
47 commandBuffer.drawIndexed(narrow_cast<uint32_t>(numberOfTriangles * 3), 1, 0, 0, 0);
48 device()->cmdEndDebugUtilsLabelEXT(commandBuffer);
53 hi_axiom_not_null(device());
54 return device()->image_pipeline->shader_stages;
61 vk::DescriptorType::eSampler,
63 vk::ShaderStageFlagBits::eFragment},
65 vk::DescriptorType::eSampledImage,
66 narrow_cast<uint32_t>(device_shared::atlas_maximum_num_images),
67 vk::ShaderStageFlagBits::eFragment}};
72 hi_axiom_not_null(device());
73 auto const& sharedImagePipeline = device()->image_pipeline;
81 vk::DescriptorType::eSampler,
82 &sharedImagePipeline->atlas_sampler_descriptor_image_info,
90 narrow_cast<uint32_t>(sharedImagePipeline->atlas_descriptor_image_infos.size()),
91 vk::DescriptorType::eSampledImage,
92 sharedImagePipeline->atlas_descriptor_image_infos.data(),
98inline size_t gfx_pipeline_image::getDescriptorSetVersion()
const
100 hi_axiom_not_null(device());
101 return device()->image_pipeline->atlas_textures.size();
106 return push_constants::pushConstantRanges();
109inline vk::VertexInputBindingDescription gfx_pipeline_image::createVertexInputBindingDescription()
const
111 return vertex::inputBindingDescription();
116 return vertex::inputAttributeDescriptions();
119inline void gfx_pipeline_image::build_vertex_buffers()
121 using vertexIndexType = uint16_t;
122 constexpr ssize_t numberOfVertices = 1 << (
sizeof(vertexIndexType) * CHAR_BIT);
124 vk::BufferCreateInfo
const bufferCreateInfo = {
125 vk::BufferCreateFlags(),
126 sizeof(vertex) * numberOfVertices,
127 vk::BufferUsageFlagBits::eVertexBuffer,
128 vk::SharingMode::eExclusive};
129 VmaAllocationCreateInfo allocationCreateInfo = {};
130 allocationCreateInfo.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
131 allocationCreateInfo.pUserData =
const_cast<char *
>(
"image-pipeline vertex buffer");
132 allocationCreateInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
134 hi_axiom_not_null(device());
135 std::tie(vertexBuffer, vertexBufferAllocation) = device()->createBuffer(bufferCreateInfo, allocationCreateInfo);
136 device()->setDebugUtilsObjectNameEXT(vertexBuffer,
"image-pipeline vertex buffer");
137 vertexBufferData = device()->mapMemory<vertex>(vertexBufferAllocation);
140inline void gfx_pipeline_image::teardown_vertex_buffers()
142 hi_axiom_not_null(device());
143 device()->unmapMemory(vertexBufferAllocation);
144 device()->destroyBuffer(vertexBuffer, vertexBufferAllocation);
148gfx_pipeline_image::texture_map::transitionLayout(
const gfx_device& device, vk::Format format, vk::ImageLayout nextLayout)
150 if (layout != nextLayout) {
151 device.transition_layout(image, format, layout, nextLayout);
156inline gfx_pipeline_image::paged_image::paged_image(gfx_surface
const *surface,
std::size_t width,
std::size_t height) noexcept :
157 device(
nullptr), width(width), height(height), pages()
159 if (surface ==
nullptr) {
168 auto const lock = std::scoped_lock(gfx_system_mutex);
169 if ((this->device = surface->device()) !=
nullptr) {
170 auto const[num_columns, num_rows] = size_in_int_pages();
171 this->pages = device->image_pipeline->allocate_pages(num_columns * num_rows);
175inline gfx_pipeline_image::paged_image::paged_image(gfx_surface
const *surface, pixmap_span<sfloat_rgba16 const> image) noexcept :
176 paged_image(surface, narrow_cast<std::size_t>(image.width()), narrow_cast<std::size_t>(image.height()))
179 auto const lock = std::scoped_lock(gfx_system_mutex);
184inline gfx_pipeline_image::paged_image::paged_image(gfx_surface
const *surface, png
const& image) noexcept :
185 paged_image(surface, narrow_cast<std::size_t>(image.width()), narrow_cast<std::size_t>(image.height()))
188 auto const lock = std::scoped_lock(gfx_system_mutex);
193inline gfx_pipeline_image::paged_image::paged_image(paged_image&&
other) noexcept :
194 state(
other.state.exchange(state_type::uninitialized)),
195 device(std::exchange(
other.device,
nullptr)),
197 height(
other.height),
202inline gfx_pipeline_image::paged_image& gfx_pipeline_image::paged_image::operator=(paged_image&&
other)
noexcept
204 hi_return_on_self_assignment(
other);
208 device->image_pipeline->free_pages(pages);
211 state =
other.state.exchange(state_type::uninitialized);
212 device = std::exchange(
other.device,
nullptr);
214 height =
other.height;
219inline gfx_pipeline_image::paged_image::~paged_image()
222 device->image_pipeline->free_pages(pages);
228 hi_assert(image.width() == width and image.height() == height);
231 auto const lock = std::scoped_lock(gfx_system_mutex);
233 state = state_type::drawing;
235 auto staging_image = device->image_pipeline->get_staging_pixmap(image.width(), image.height());
236 image.decode_image(staging_image);
237 device->image_pipeline->update_atlas_with_staging_pixmap(*
this);
239 state = state_type::uploaded;
245 hi_assert(image.width() == width and image.height() == height);
248 auto const lock = std::scoped_lock(gfx_system_mutex);
250 state = state_type::drawing;
252 auto staging_image = device->image_pipeline->get_staging_pixmap(image.width(), image.height());
253 copy(image, staging_image);
254 device->image_pipeline->update_atlas_with_staging_pixmap(*
this);
256 state = state_type::uploaded;
260inline gfx_pipeline_image::device_shared::device_shared(gfx_device
const& device) : device(device)
266inline gfx_pipeline_image::device_shared::~device_shared() {}
270 hi_assert_not_null(old_device);
271 teardown_shaders(old_device);
272 teardown_atlas(old_device);
277 while (num_pages > _atlas_free_pages.size()) {
282 for (
int i = 0; i < num_pages; i++) {
283 auto const page = _atlas_free_pages.back();
285 _atlas_free_pages.pop_back();
292 _atlas_free_pages.insert(_atlas_free_pages.end(), pages.begin(), pages.end());
297 staging_texture.transitionLayout(device, vk::Format::eR16G16B16A16Sfloat, vk::ImageLayout::eGeneral);
299 return staging_texture.pixmap.subimage(1, 1, staging_image_width - 2, staging_image_height - 2);
310 constexpr auto page_stride = gfx_pipeline_image::paged_image::page_size + 2;
312 auto const image_nr = page / gfx_pipeline_image::device_shared::atlas_num_pages_per_image;
313 auto const image_page = page % gfx_pipeline_image::device_shared::atlas_num_pages_per_image;
316 narrow_cast<float>((image_page % gfx_pipeline_image::device_shared::atlas_num_pages_per_axis) * page_stride + 1),
317 narrow_cast<float>((image_page / gfx_pipeline_image::device_shared::atlas_num_pages_per_axis) * page_stride + 1),
318 narrow_cast<float>(image_nr)};
329 auto const width_in_pages = (image.width + gfx_pipeline_image::paged_image::page_size - 1) / gfx_pipeline_image::paged_image::page_size;
332 narrow_cast<float>((page_index % width_in_pages) * gfx_pipeline_image::paged_image::page_size + 1),
333 narrow_cast<float>((page_index / width_in_pages) * gfx_pipeline_image::paged_image::page_size + 1)};
336inline void gfx_pipeline_image::device_shared::make_staging_border_transparent(aarectangle border_rectangle)
noexcept
338 auto const width = ceil_cast<std::size_t>(border_rectangle.width());
339 auto const height = ceil_cast<std::size_t>(border_rectangle.height());
340 auto const bottom = floor_cast<std::size_t>(border_rectangle.bottom());
341 auto const top = ceil_cast<std::size_t>(border_rectangle.top());
342 auto const left = floor_cast<std::size_t>(border_rectangle.left());
343 auto const right = ceil_cast<std::size_t>(border_rectangle.right());
346 hi_assert(
left == 0);
348 hi_assert(
right >= 2);
351 auto border_bottom_row = staging_texture.pixmap[
bottom];
352 auto border_top_row = staging_texture.pixmap[
top - 1];
353 auto image_bottom_row = staging_texture.pixmap[
bottom + 1];
354 auto image_top_row = staging_texture.pixmap[
top - 2];
355 for (
auto x = 0_uz; x != width; ++x) {
356 border_bottom_row[x] = make_transparent(image_bottom_row[x]);
357 border_top_row[x] = make_transparent(image_top_row[x]);
361 for (
auto y = 0_uz; y != height; ++y) {
362 auto row = staging_texture.pixmap[y];
363 row[
left] = make_transparent(row[
left + 1]);
364 row[
right - 2] = make_transparent(row[
right - 1]);
368inline void gfx_pipeline_image::device_shared::clear_staging_between_border_and_upload(
369 aarectangle border_rectangle,
370 aarectangle upload_rectangle)
noexcept
372 hi_assert(border_rectangle.left() == 0.0f and border_rectangle.bottom() == 0.0f);
373 hi_assert(upload_rectangle.left() == 0.0f and upload_rectangle.bottom() == 0.0f);
375 auto const border_top = floor_cast<std::size_t>(border_rectangle.top());
376 auto const border_right = floor_cast<std::size_t>(border_rectangle.right());
377 auto const upload_top = floor_cast<std::size_t>(upload_rectangle.top());
378 auto const upload_right = floor_cast<std::size_t>(upload_rectangle.right());
379 hi_assert(border_right <= upload_right);
380 hi_assert(border_top <= upload_top);
383 for (
auto y = 0_uz; y != border_top; ++y) {
384 auto row = staging_texture.pixmap[y];
385 for (
auto x = border_right; x != upload_right; ++x) {
386 row[x] = sfloat_rgba16{};
391 for (
auto y = border_top; y != upload_top; ++y) {
392 auto row = staging_texture.pixmap[y];
393 for (
auto x = 0_uz; x != upload_right; ++x) {
394 row[x] = sfloat_rgba16{};
399inline void gfx_pipeline_image::device_shared::prepare_staging_for_upload(paged_image
const& image)
noexcept
401 auto const image_rectangle = aarectangle{point2{1.0f, 1.0f}, image.size()};
402 auto const border_rectangle = image_rectangle + 1;
403 auto const upload_width =
ceil(image.width, paged_image::page_size) + 2;
404 auto const upload_height =
ceil(image.height, paged_image::page_size) + 2;
405 auto const upload_rectangle = aarectangle{extent2{narrow_cast<float>(upload_width), narrow_cast<float>(upload_height)}};
407 make_staging_border_transparent(border_rectangle);
408 clear_staging_between_border_and_upload(border_rectangle, upload_rectangle);
411 static_assert(std::is_same_v<
decltype(staging_texture.pixmap)::value_type, sfloat_rgba16>);
412 device.flushAllocation(staging_texture.allocation, 0, upload_height * staging_texture.pixmap.stride() * 8);
413 staging_texture.transitionLayout(device, vk::Format::eR16G16B16A16Sfloat, vk::ImageLayout::eTransferSrcOptimal);
416inline void gfx_pipeline_image::device_shared::update_atlas_with_staging_pixmap(paged_image
const& image)
noexcept
418 prepare_staging_for_upload(image);
421 for (
std::size_t index = 0; index < size(image.pages); index++) {
422 auto const page = image.pages.
at(index);
428 constexpr auto width = narrow_cast<int32_t>(paged_image::page_size + 2);
429 constexpr auto height = narrow_cast<int32_t>(paged_image::page_size + 2);
430 auto const src_x = floor_cast<int32_t>(src_position.x() - 1.0f);
431 auto const src_y = floor_cast<int32_t>(src_position.y() - 1.0f);
432 auto const dst_x = floor_cast<int32_t>(dst_position.x() - 1.0f);
433 auto const dst_y = floor_cast<int32_t>(dst_position.y() - 1.0f);
434 auto const dst_z = floor_cast<std::size_t>(dst_position.z());
436 auto& regionsToCopy = regions_to_copy_per_atlas_texture.
at(dst_z);
437 regionsToCopy.emplace_back(
438 vk::ImageSubresourceLayers{vk::ImageAspectFlagBits::eColor, 0, 0, 1},
439 vk::Offset3D{src_x, src_y, 0},
440 vk::ImageSubresourceLayers{vk::ImageAspectFlagBits::eColor, 0, 0, 1},
441 vk::Offset3D{dst_x, dst_y, 0},
442 vk::Extent3D{width, height, 1});
445 for (
std::size_t atlas_texture_index = 0; atlas_texture_index < size(atlas_textures); atlas_texture_index++) {
446 auto const& regions_to_copy = regions_to_copy_per_atlas_texture.
at(atlas_texture_index);
447 if (regions_to_copy.empty()) {
451 auto& atlas_texture = atlas_textures.at(atlas_texture_index);
452 atlas_texture.transitionLayout(device, vk::Format::eR16G16B16A16Sfloat, vk::ImageLayout::eTransferDstOptimal);
455 staging_texture.image,
456 vk::ImageLayout::eTransferSrcOptimal,
458 vk::ImageLayout::eTransferDstOptimal,
465 for (
auto& atlas_texture : atlas_textures) {
466 atlas_texture.transitionLayout(device, vk::Format::eR16G16B16A16Sfloat, vk::ImageLayout::eShaderReadOnlyOptimal);
470inline void gfx_pipeline_image::device_shared::draw_in_command_buffer(vk::CommandBuffer
const& commandBuffer)
472 commandBuffer.bindIndexBuffer(device.quadIndexBuffer, 0, vk::IndexType::eUint16);
475inline void gfx_pipeline_image::device_shared::build_shaders()
477 vertex_shader_module = device.loadShader(
URL(
"resource:image_vulkan.vert.spv"));
478 fragment_shader_module = device.loadShader(
URL(
"resource:image_vulkan.frag.spv"));
481 {vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eVertex, vertex_shader_module,
"main"},
482 {vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eFragment, fragment_shader_module,
"main"}};
485inline void gfx_pipeline_image::device_shared::teardown_shaders(gfx_device
const *vulkanDevice)
487 hi_assert_not_null(vulkanDevice);
488 vulkanDevice->destroy(vertex_shader_module);
489 vulkanDevice->destroy(fragment_shader_module);
492inline void gfx_pipeline_image::device_shared::add_atlas_image()
494 auto const current_image_index = size(atlas_textures);
497 vk::ImageCreateInfo
const imageCreateInfo = {
498 vk::ImageCreateFlags(),
500 vk::Format::eR16G16B16A16Sfloat,
501 vk::Extent3D(atlas_image_axis_size, atlas_image_axis_size, 1),
504 vk::SampleCountFlagBits::e1,
505 vk::ImageTiling::eOptimal,
506 vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled,
507 vk::SharingMode::eExclusive,
510 vk::ImageLayout::eUndefined};
511 VmaAllocationCreateInfo allocationCreateInfo = {};
512 auto allocation_name = std::format(
"image-pipeline atlas image {}", current_image_index);
513 allocationCreateInfo.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
514 allocationCreateInfo.pUserData =
const_cast<char *
>(allocation_name.c_str());
515 allocationCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
517 auto const[atlasImage, atlasImageAllocation] = device.createImage(imageCreateInfo, allocationCreateInfo);
518 device.setDebugUtilsObjectNameEXT(atlasImage, allocation_name.c_str());
520 auto const atlasImageView = device.createImageView(
521 {vk::ImageViewCreateFlags(),
523 vk::ImageViewType::e2D,
524 imageCreateInfo.format,
525 vk::ComponentMapping(),
527 vk::ImageAspectFlagBits::eColor,
534 atlas_textures.push_back({atlasImage, atlasImageAllocation, atlasImageView});
537 auto const page_offset = current_image_index * atlas_num_pages_per_image;
538 for (
int i = 0; i < atlas_num_pages_per_image; i++) {
539 _atlas_free_pages.push_back({page_offset + i});
543 for (
std::size_t i = 0; i < size(atlas_descriptor_image_infos); i++) {
546 atlas_descriptor_image_infos.at(i) = {
548 i < atlas_textures.size() ? atlas_textures.at(i).view : atlas_textures.at(0).view,
549 vk::ImageLayout::eShaderReadOnlyOptimal};
553inline void gfx_pipeline_image::device_shared::build_atlas()
556 vk::ImageCreateInfo
const imageCreateInfo = {
557 vk::ImageCreateFlags(),
559 vk::Format::eR16G16B16A16Sfloat,
560 vk::Extent3D(staging_image_width, staging_image_height, 1),
563 vk::SampleCountFlagBits::e1,
564 vk::ImageTiling::eLinear,
565 vk::ImageUsageFlagBits::eTransferSrc,
566 vk::SharingMode::eExclusive,
569 vk::ImageLayout::ePreinitialized};
570 VmaAllocationCreateInfo allocationCreateInfo = {};
571 allocationCreateInfo.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
572 allocationCreateInfo.pUserData =
const_cast<char *
>(
"image-pipeline staging image");
573 allocationCreateInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
574 auto const[image, allocation] = device.createImage(imageCreateInfo, allocationCreateInfo);
575 device.setDebugUtilsObjectNameEXT(image,
"image-pipeline staging image");
576 auto const data = device.mapMemory<sfloat_rgba16>(allocation);
584 vk::SamplerCreateInfo
const samplerCreateInfo = {
585 vk::SamplerCreateFlags(),
588 vk::SamplerMipmapMode::eNearest,
589 vk::SamplerAddressMode::eRepeat,
590 vk::SamplerAddressMode::eRepeat,
591 vk::SamplerAddressMode::eRepeat,
596 vk::CompareOp::eNever,
599 vk::BorderColor::eFloatTransparentBlack,
602 atlas_sampler = device.createSampler(samplerCreateInfo);
604 atlas_sampler_descriptor_image_info = {atlas_sampler, vk::ImageView(), vk::ImageLayout::eUndefined};
611inline void gfx_pipeline_image::device_shared::teardown_atlas(gfx_device
const *old_device)
613 hi_assert_not_null(old_device);
614 old_device->destroy(atlas_sampler);
616 for (
const auto& atlas_texture : atlas_textures) {
617 old_device->destroy(atlas_texture.view);
618 old_device->destroyImage(atlas_texture.image, atlas_texture.allocation);
620 atlas_textures.clear();
622 old_device->unmapMemory(staging_texture.allocation);
623 old_device->destroyImage(staging_texture.image, staging_texture.allocation);
627 vector_span<vertex>& vertices,
632 hi_assert(image.state == paged_image::state_type::uploaded);
634 constexpr auto page_size2 =
635 f32x4{narrow_cast<float>(paged_image::page_size), narrow_cast<float>(paged_image::page_size), 0.0f, 0.0f};
637 auto const image_size = image.
size();
638 auto const size_in_float_pages =
f32x4{image.size_in_float_pages()};
639 auto const size_in_int_pages =
i32x4{ceil(size_in_float_pages)};
640 auto const num_columns = narrow_cast<std::size_t>(size_in_int_pages.x());
641 auto const num_rows = narrow_cast<std::size_t>(size_in_int_pages.y());
643 auto const page_to_quad_ratio = rcp(size_in_float_pages);
644 auto const page_to_quad_ratio_x =
scale3{page_to_quad_ratio.xxx1()};
645 auto const page_to_quad_ratio_y =
scale3{page_to_quad_ratio.yyy1()};
646 auto const left_increment = page_to_quad_ratio_y * box.left();
647 auto const right_increment = page_to_quad_ratio_y * box.right();
649 auto left_bottom = box.p0;
650 auto right_bottom = box.p1;
651 auto bottom_increment = page_to_quad_ratio_x * (right_bottom - left_bottom);
652 auto it = image.pages.begin();
653 for (
std::size_t page_index = 0, row_nr = 0; row_nr != num_rows; ++row_nr) {
654 auto const left_top = left_bottom + left_increment;
655 auto const right_top = right_bottom + right_increment;
656 auto const top_increment = page_to_quad_ratio_x * (right_top - left_top);
658 auto new_p0 = left_bottom;
659 auto new_p2 = left_top;
660 for (
std::size_t column_nr = 0; column_nr != num_columns; ++column_nr, ++page_index, ++it) {
661 auto const new_p1 = new_p0 + bottom_increment;
662 auto const new_p3 = new_p2 + top_increment;
667 auto const xy =
f32x4{narrow_cast<float>(column_nr), narrow_cast<float>(row_nr * paged_image::page_size), 0.0f, 0.0f};
670 vertices.emplace_back(new_p0, clipping_rectangle, get<0>(uv_rectangle));
671 vertices.emplace_back(new_p1, clipping_rectangle, get<1>(uv_rectangle));
672 vertices.emplace_back(new_p2, clipping_rectangle, get<2>(uv_rectangle));
673 vertices.emplace_back(new_p3, clipping_rectangle, get<3>(uv_rectangle));
679 left_bottom = left_top;
680 right_bottom = right_top;
681 bottom_increment = top_increment;
@ bottom
Align to the bottom.
@ right
Align the text to the right side.
@ left
Align the text to the left side.
@ other
The gui_event does not have associated data.
The HikoGUI namespace.
Definition array_generic.hpp:20
point2 get_staging_position(const gfx_pipeline_image::paged_image &image, std::size_t page_index)
Get the position in the staging texture map to copy from.
Definition gfx_pipeline_image_vulkan_impl.hpp:327
point3 get_atlas_position(std::size_t page) noexcept
Get the coordinate in the atlas from a page index.
Definition gfx_pipeline_image_vulkan_impl.hpp:307
std::ptrdiff_t ssize_t
Signed size/index into an array.
Definition misc.hpp:32
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Class which represents an axis-aligned rectangle.
Definition aarectangle.hpp:33
A high-level geometric extent.
Definition extent2.hpp:32
A rectangle / parallelogram in 3D space.
Definition rectangle.hpp:25
This is a image that is uploaded into the texture atlas.
Definition gfx_pipeline_image_vulkan_intf.hpp:83
void upload(pixmap_span< sfloat_rgba16 const > image) noexcept
Upload image to atlas.
Definition gfx_pipeline_image_vulkan_impl.hpp:243
void destroy(gfx_device const *vulkanDevice)
Definition gfx_pipeline_image_vulkan_impl.hpp:268
void place_vertices(vector_span< vertex > &vertices, aarectangle const &clipping_rectangle, quad const &box, paged_image const &image) noexcept
Place vertices for a single image.
Definition gfx_pipeline_image_vulkan_impl.hpp:626
std::vector< std::size_t > allocate_pages(std::size_t num_pages) noexcept
Allocate pages from the atlas.
Definition gfx_pipeline_image_vulkan_impl.hpp:275
void prepare_atlas_for_rendering()
Prepare the atlas so that it can be used as a texture map by the shaders.
Definition gfx_pipeline_image_vulkan_impl.hpp:463
hi::pixmap_span< sfloat_rgba16 > get_staging_pixmap()
Get the full staging pixel map excluding border.
Definition gfx_pipeline_image_vulkan_impl.hpp:295
void free_pages(std::vector< std::size_t > const &pages) noexcept
Deallocate pages back to the atlas.
Definition gfx_pipeline_image_vulkan_impl.hpp:290
A non-owning 2D pixel-based image.
Definition pixmap_span.hpp:34
Universal Resource Locator.
Definition URL.hpp:58