diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-08-19 13:51:40 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-08-19 14:33:08 -0400 |
| commit | 154436ab88925540f86f43c0ac885c080949aa9b (patch) | |
| tree | 43a22f26286428f0d165fc1ff801cd0cb87092c6 /src/static-ui.cpp | |
| parent | ebcae77b137a759c453b89a774ece5a755078a38 (diff) | |
pke: ui box type button image
Diffstat (limited to 'src/static-ui.cpp')
| -rw-r--r-- | src/static-ui.cpp | 372 |
1 files changed, 308 insertions, 64 deletions
diff --git a/src/static-ui.cpp b/src/static-ui.cpp index 7e500d9..d8990a3 100644 --- a/src/static-ui.cpp +++ b/src/static-ui.cpp @@ -30,15 +30,18 @@ struct pke_ui_box_instance_buffer_item { glm::vec4 color_background; glm::vec2 px_scale; float depth; - float padding[1]; + float texture_layer; }; +typedef pk_bkt_arr_t<pke_ui_graphics_bindings_texture> texture_binding_bkt_arr; + struct pke_ui_master { pk_membucket *bkt; pke_ui_box **root_boxes; pke_ui_box_count_T h_root_boxes; pke_ui_box_count_T r_root_boxes; pke_ui_graphics_bindings bindings; + texture_binding_bkt_arr bindings_texture{}; bool should_update_buffer = false; glm::vec2 px_scale; pk_arr_t<pke_input_event> events_this_tick; @@ -51,6 +54,8 @@ struct pke_ui_master { } state; } pke_ui_master; +void pke_ui_teardown_box_recursive(pke_ui_box *box); + // typedef void(*pke_box_search)(pke_ui_box &box); typedef std::function<void(pke_ui_box &box)> pke_box_iterate ; @@ -75,10 +80,12 @@ void pke_ui_internal_box_iterate_top_down_recursive(pke_box_iterate *iters, int void pke_ui_init() { pke_ui_master.bkt = pk_mem_bucket_create("pke ui", PK_MEM_DEFAULT_BUCKET_SIZE, PK_MEMBUCKET_FLAG_NONE); - pke_ui_master.root_boxes = pk_new_arr<pke_ui_box*>(1, pke_ui_master.bkt); + pke_ui_master.r_root_boxes = 8; + pke_ui_master.root_boxes = pk_new_arr<pke_ui_box*>(pke_ui_master.r_root_boxes, pke_ui_master.bkt); pke_ui_master.h_root_boxes = 0; - pke_ui_master.r_root_boxes = 1; pke_ui_master.bindings = {}; + pke_ui_master.events_this_tick.bkt = pke_ui_master.bkt; + new (&pke_ui_master.bindings_texture) texture_binding_bkt_arr{ pk_bkt_arr_handle_MAX_constexpr, pke_ui_master.bkt, MemBkt_Vulkan }; pke_input_set ui_controls_set{}; ui_controls_set.title = "debug-editor-controls"; @@ -230,7 +237,7 @@ struct pke_ui_flex_params { float unit_total; }; -void pke_ui_calc_px(pk_arr_t<pke_ui_box_instance_buffer_item> &buffer, pke_ui_flex_params *flex_params, pke_ui_box *box) { +void pke_ui_calc_px(pk_arr_t<pke_ui_box_instance_buffer_item> &buffer, pk_arr_t<std::pair<pke_ui_box*,pke_ui_box_instance_buffer_item>> &tmp_txtr_buffer, pke_ui_flex_params *flex_params, pke_ui_box *box) { assert(box != nullptr); glm::vec2 px_size; glm::vec2 px_min_size; @@ -238,6 +245,8 @@ void pke_ui_calc_px(pk_arr_t<pke_ui_box_instance_buffer_item> &buffer, pke_ui_fl glm::vec2 parent_size_padded; glm::vec2 parent_pos_and_offset; + if (box->isMarkedForRemoval == true) return; + assert(box->pos_top_left.x >= 0.0); assert(box->pos_top_left.y >= 0.0); assert(box->max_size.x >= 0.0); @@ -387,17 +396,31 @@ void pke_ui_calc_px(pk_arr_t<pke_ui_box_instance_buffer_item> &buffer, pke_ui_fl tmp.px_scale.x = (2.0 / (float)Extent.width); tmp.px_scale.y = (2.0 / (float)Extent.height); tmp.depth = (float)box->layer; - pk_arr_append_t(&buffer, tmp); + tmp.texture_layer = -1; + if (PK_HAS_FLAG(box->type, PKE_UI_BOX_TYPE_BUTTON_IMAGE)) { + if (PK_HAS_FLAG(box->state_flags_mem, PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_PRESS) && PK_HAS_FLAG(box->state_flags, PKE_UI_BOX_STATE_FLAG_MOUSE_HOVER)) { + tmp.texture_layer = 2; + } else if (PK_HAS_FLAG(box->state_flags, PKE_UI_BOX_STATE_FLAG_MOUSE_HOVER)) { + tmp.texture_layer = 1; + } else { + tmp.texture_layer = 0; + } + pk_arr_append_t(&tmp_txtr_buffer, {box, tmp}); + } else { + pk_arr_append_t(&buffer, tmp); + } } -void pke_ui_recalc_sizes_recursive(pk_arr_t<pke_ui_box_instance_buffer_item> &arr, pke_ui_box *box) { +void pke_ui_recalc_sizes_recursive(pk_arr_t<pke_ui_box_instance_buffer_item> &arr, pk_arr_t<std::pair<pke_ui_box*,pke_ui_box_instance_buffer_item>> &tmp_txtr_buffer, pke_ui_box *box) { PKE_UI_BOX_FLAG_T flags_masked; uint8_t flex_count = 0; pke_ui_flex_params flex_params{}; + if (box->isMarkedForRemoval == true) return; + flags_masked = PKE_UI_BOX_FLAG_T(box->flags & PKE_UI_BOX_FLAG_POSITION_TYPE_ALL); if (flags_masked == 0b000 || flags_masked == 0b011 || flags_masked == 0b101 || flags_masked == 0b110 || flags_masked == 0b111) { - fprintf(stderr, "[%s] ui box invalid flags: position type", __FILE__); + fprintf(stderr, "[%s] ui box invalid flags: position type\n", __FILE__); return; } @@ -409,7 +432,7 @@ void pke_ui_recalc_sizes_recursive(pk_arr_t<pke_ui_box_instance_buffer_item> &ar } if (flex_count != 0 && flex_count != box->internal.h_children) { - fprintf(stderr, "[%s] ui box invalid flags: if one child is type FLEX, then all children must be type FLEX", __FILE__); + fprintf(stderr, "[%s] ui box invalid flags: if one child is type FLEX, then all children must be type FLEX\n", __FILE__); return; } if (flex_count != 0) { @@ -420,13 +443,23 @@ void pke_ui_recalc_sizes_recursive(pk_arr_t<pke_ui_box_instance_buffer_item> &ar } for (pke_ui_box_count_T i = 0; i < box->internal.h_children; ++i) { - pke_ui_calc_px(arr, &flex_params, box->internal.children[i]); - pke_ui_recalc_sizes_recursive(arr, box->internal.children[i]); + pke_ui_calc_px(arr, tmp_txtr_buffer, &flex_params, box->internal.children[i]); + pke_ui_recalc_sizes_recursive(arr, tmp_txtr_buffer, box->internal.children[i]); } } +int pke_ui_box_ibi_sort_for_buffer(const void *lhs, const void *rhs) { + const pke_ui_box_instance_buffer_item *l = reinterpret_cast<const pke_ui_box_instance_buffer_item*>(lhs); + const pke_ui_box_instance_buffer_item *r = reinterpret_cast<const pke_ui_box_instance_buffer_item*>(rhs); + return l->texture_layer > r->texture_layer; +} + void pke_ui_update_instance_buffer(pk_arr_t<pke_ui_box_instance_buffer_item> &arr) { VkResult vkResult; + if (arr.next == 0) { + pke_ui_master.bindings.instance_counter = 0; + return; + } if (arr.next > pke_ui_master.bindings.instance_buffer_max_count) { VkBuffer newBuffer; VkBufferCreateInfo bufferCI; @@ -473,51 +506,54 @@ void pke_ui_update_instance_buffer(pk_arr_t<pke_ui_box_instance_buffer_item> &ar pke_ui_master.bindings.deviceMemoryInst = new_memory; pke_ui_master.bindings.instance_buffer_max_count = arr.next; } - PKVK_TmpBufferDetails tmpBufferDetails{}; - PKVK_BeginBuffer(graphicsFamilyIndex, sizeof(pke_ui_box_instance_buffer_item) * arr.next, tmpBufferDetails); - { - VkCommandBufferBeginInfo vkCommandBufferBeginInfo; - vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - vkCommandBufferBeginInfo.pNext = nullptr; - // TODO consider single-use? - vkCommandBufferBeginInfo.flags = 0; - vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; - vkResult = vkBeginCommandBuffer(tmpBufferDetails.cmdBuffer, &vkCommandBufferBeginInfo); - assert(vkResult == VK_SUCCESS); - - memcpy(tmpBufferDetails.deviceData, arr.data, sizeof(pke_ui_box_instance_buffer_item) * arr.next); - - VkBufferCopy vk_buffer_copy{}; - vk_buffer_copy.srcOffset = 0; - vk_buffer_copy.dstOffset = 0; - vk_buffer_copy.size = sizeof(pke_ui_box_instance_buffer_item) * arr.next; - vkCmdCopyBuffer(tmpBufferDetails.cmdBuffer, tmpBufferDetails.buffer, pke_ui_master.bindings.bd_instance.buffer, 1, &vk_buffer_copy); - - vkResult = vkEndCommandBuffer(tmpBufferDetails.cmdBuffer); - assert(vkResult == VK_SUCCESS); - - VkSubmitInfo submitInfo; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.pNext = nullptr; - submitInfo.waitSemaphoreCount = 0; - submitInfo.pWaitSemaphores = nullptr; - submitInfo.pWaitDstStageMask = nullptr; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &tmpBufferDetails.cmdBuffer; - submitInfo.signalSemaphoreCount = 0; - submitInfo.pSignalSemaphores = nullptr; - vkResult = vkQueueSubmit(tmpBufferDetails.queue, 1, &submitInfo, nullptr); - assert(vkResult == VK_SUCCESS); - vkResult = vkQueueWaitIdle(tmpBufferDetails.queue); - assert(vkResult == VK_SUCCESS); + if (arr.next > 0 && arr.data != nullptr ) { + PKVK_TmpBufferDetails tmpBufferDetails{}; + PKVK_BeginBuffer(graphicsFamilyIndex, sizeof(pke_ui_box_instance_buffer_item) * arr.next, tmpBufferDetails); + { + VkCommandBufferBeginInfo vkCommandBufferBeginInfo; + vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkCommandBufferBeginInfo.pNext = nullptr; + // TODO consider single-use? + vkCommandBufferBeginInfo.flags = 0; + vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; + vkResult = vkBeginCommandBuffer(tmpBufferDetails.cmdBuffer, &vkCommandBufferBeginInfo); + assert(vkResult == VK_SUCCESS); + + memcpy(tmpBufferDetails.deviceData, arr.data, sizeof(pke_ui_box_instance_buffer_item) * arr.next); + + VkBufferCopy vk_buffer_copy{}; + vk_buffer_copy.srcOffset = 0; + vk_buffer_copy.dstOffset = 0; + vk_buffer_copy.size = sizeof(pke_ui_box_instance_buffer_item) * arr.next; + vkCmdCopyBuffer(tmpBufferDetails.cmdBuffer, tmpBufferDetails.buffer, pke_ui_master.bindings.bd_instance.buffer, 1, &vk_buffer_copy); + + vkResult = vkEndCommandBuffer(tmpBufferDetails.cmdBuffer); + assert(vkResult == VK_SUCCESS); + + VkSubmitInfo submitInfo; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.pNext = nullptr; + submitInfo.waitSemaphoreCount = 0; + submitInfo.pWaitSemaphores = nullptr; + submitInfo.pWaitDstStageMask = nullptr; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &tmpBufferDetails.cmdBuffer; + submitInfo.signalSemaphoreCount = 0; + submitInfo.pSignalSemaphores = nullptr; + vkResult = vkQueueSubmit(tmpBufferDetails.queue, 1, &submitInfo, nullptr); + assert(vkResult == VK_SUCCESS); + vkResult = vkQueueWaitIdle(tmpBufferDetails.queue); + assert(vkResult == VK_SUCCESS); + } + PKVK_EndBuffer(tmpBufferDetails); } - PKVK_EndBuffer(tmpBufferDetails); pke_ui_master.bindings.instance_counter = arr.next; } void pke_ui_tick(double delta) { (void)delta; - pke_ui_box_count_T i; + pke_ui_box_count_T i, ii; + uint32_t u; if (pke_ui_master.h_root_boxes == 0) return; pke_ui_master.state.mouse_left = pke_input_query_by_action_name(ui_ux_mouse_left); @@ -525,15 +561,50 @@ void pke_ui_tick(double delta) { pke_ui_master.state.mouse_middle = pke_input_query_by_action_name(ui_ux_mouse_middle); pke_ui_master.state.deepest_pressed = nullptr; - pk_arr_t<pke_ui_box_instance_buffer_item> arr; + pk_arr_t<pke_ui_box_instance_buffer_item> arr{}; + arr.bkt = pkeSettings.mem_bkt.game_transient; + pk_arr_t<std::pair<pke_ui_box*,pke_ui_box_instance_buffer_item>> tmp_txtr_arr; + tmp_txtr_arr.bkt = pkeSettings.mem_bkt.game_transient; pke_ui_master.px_scale = glm::vec2( 2.0 / (float)Extent.width, 2.0 / (float)Extent.height ); for (i = 0; i < pke_ui_master.h_root_boxes; ++i) { pke_ui_box *box = pke_ui_master.root_boxes[i]; - pke_ui_calc_px(arr, nullptr, box); - pke_ui_recalc_sizes_recursive(arr, box); + // 2025-08-18 JCB + // This currently only calls tear-down for boxes on the root list. + // Leaving this as-is for the time being because you can control the + // visibility of child boxes with flags and don't need to completely remove them. + for (u = 0; u < EntitiesToBeRemoved.next; ++u) { + if (EntitiesToBeRemoved[u] == box) { + pke_ui_teardown_box_recursive(box); + for (ii = 0; i + ii + 1 < pke_ui_master.r_root_boxes; ++ii) { + pke_ui_master.root_boxes[i + ii] = pke_ui_master.root_boxes[i + ii + 1]; + } + pke_ui_master.h_root_boxes -= 1; + i -= 1; + pke_ui_master.should_update_buffer = true; + goto skip_calc; + } + } + pke_ui_calc_px(arr, tmp_txtr_arr, nullptr, box); + pke_ui_recalc_sizes_recursive(arr, tmp_txtr_arr, box); +skip_calc: + continue; + } + + for (i = 0; i < tmp_txtr_arr.next; ++i) { + const std::pair<pke_ui_box*,pke_ui_box_instance_buffer_item> &pair = tmp_txtr_arr[i]; + if (pair.first->type_data->button_image.gr_binds_bkt_arr_handle == pk_bkt_arr_handle_MAX) { + continue; + } + pke_ui_graphics_bindings_texture *bindings = &pke_ui_master.bindings_texture[pair.first->type_data->button_image.gr_binds_bkt_arr_handle]; + if (bindings == nullptr || bindings->descriptor_sets == nullptr) { + continue; + } + bindings->instance_count = 1; + bindings->instance_offset = arr.next; + pk_arr_append_t(&arr, pair.second); } if (pke_ui_master.should_update_buffer || pkeSettings.rt.was_framebuffer_resized) { @@ -552,7 +623,7 @@ void pke_ui_tick(double delta) { component_event = ECS_GetEv(pke_ui_master.state.deepest_pressed->type_data->button_image.pke_event_handle); break; default: - fprintf(stderr, "[static-ui] Something was pressed but we didn't know the type and couldn't emit."); + fprintf(stderr, "[static-ui] Something was pressed but we didn't know the type and couldn't emit.\n"); } if (component_event != nullptr) { pk_ev_emit(component_event->ev_mgr_id, component_event->ev_id, nullptr); @@ -567,6 +638,37 @@ void pke_ui_teardown_box_recursive(pke_ui_box *box) { if (box->internal.children != nullptr) { pk_delete_arr<pke_ui_box *>(box->internal.children, box->internal.r_children, pke_ui_master.bkt); } + if (box->type_data != nullptr) { + if (box->type == PKE_UI_BOX_TYPE_BUTTON_IMAGE && box->type_data->button_image.gr_binds_bkt_arr_handle != pk_bkt_arr_handle_MAX) { + + pke_ui_graphics_bindings_texture *bindings = &pke_ui_master.bindings_texture[box->type_data->button_image.gr_binds_bkt_arr_handle]; + + // reminder that we are not passing the flag on the pool to manually manage descriptor sets, so all we need to do is destroy the pool + if (bindings->descriptor_pool != VK_NULL_HANDLE) { + pkvk_queue_vk_descriptor_pool_destroy(bindings->descriptor_pool); + } + if (bindings->descriptor_sets != nullptr) { + pk_delete_arr(bindings->descriptor_sets, prevSwapchainLength, MemBkt_Vulkan); + } + + if (bindings->image_view!= VK_NULL_HANDLE) { + pkvk_queue_vk_image_view_destroy(bindings->image_view); + } + if (bindings->image!= VK_NULL_HANDLE) { + pkvk_queue_vk_image_destroy(bindings->image); + } + if (bindings->image_memory != VK_NULL_HANDLE) { + pkvk_queue_vk_memory_free(bindings->image_memory); + } + + bindings->descriptor_sets = nullptr; + bindings->descriptor_pool = VK_NULL_HANDLE; + pk_bkt_arr_free_handle(&pke_ui_master.bindings_texture, box->type_data->button_image.gr_binds_bkt_arr_handle); + bindings = nullptr; + } + pk_delete<pke_ui_box_type_data>(box->type_data, pke_ui_master.bkt); + } + pk_delete<pke_ui_box>(box, pke_ui_master.bkt); pke_ui_master.should_update_buffer = true; } @@ -575,6 +677,7 @@ void pke_ui_teardown() { pke_ui_teardown_box_recursive(pke_ui_master.root_boxes[i]); } pk_delete_arr<pke_ui_box *>(pke_ui_master.root_boxes, pke_ui_master.r_root_boxes, pke_ui_master.bkt); + pke_ui_master.bindings_texture.~texture_binding_bkt_arr(); pk_mem_bucket_destroy(pke_ui_master.bkt); pke_ui_master.bkt = nullptr; pke_ui_master.root_boxes = nullptr; @@ -650,13 +753,7 @@ void pke_ui_internal_new_typed_box(pke_ui_box *box, const PKE_UI_BOX_TYPE type) break; case PKE_UI_BOX_TYPE_BUTTON_IMAGE: tp_data = pk_new<pke_ui_box_type_data>(pke_ui_master.bkt); - tp_data->button_image.image_memory = VK_NULL_HANDLE; - tp_data->button_image.image_default = VK_NULL_HANDLE; - tp_data->button_image.image_view_default = VK_NULL_HANDLE; - tp_data->button_image.image_hovered = VK_NULL_HANDLE; - tp_data->button_image.image_view_hovered = VK_NULL_HANDLE; - tp_data->button_image.image_pressed = VK_NULL_HANDLE; - tp_data->button_image.image_view_pressed = VK_NULL_HANDLE; + tp_data->button_image.gr_binds_bkt_arr_handle = pk_bkt_arr_handle_MAX; pressed_ev = ECS_CreateEv(box, pk_uuid_max); tp_data->button_image.pke_event_handle = pressed_ev->pke_event_handle; tp_data->button_image.ev_id = pressed_ev->ev_id; @@ -682,8 +779,9 @@ pke_ui_box *pke_ui_box_new_root(const PKE_UI_BOX_TYPE type, pk_uuid uuid) { if (pke_ui_master.root_boxes != nullptr) pk_delete_arr<pke_ui_box*>(pke_ui_master.root_boxes, prev_r_root_boxes, pke_ui_master.bkt); pke_ui_master.root_boxes = boxes; } + assert(pke_ui_master.h_root_boxes < pke_ui_master.r_root_boxes); pke_ui_box *box = pk_new<pke_ui_box>(pke_ui_master.bkt); - *box = {}; + new (box) pke_ui_box{}; pke_ui_master.root_boxes[pke_ui_master.h_root_boxes] = box; pke_ui_master.h_root_boxes += 1; pke_ui_master.should_update_buffer = true; @@ -701,7 +799,7 @@ pke_ui_box *pke_ui_box_new_child(pke_ui_box *parent, const PKE_UI_BOX_TYPE type, // validation if (parent->type >= PKE_UI_BOX_TYPE_TEXT) { // this might be too broad, alter if needed - fprintf(stdout, "[pke_ui_box_new_child] Validation error: PKE_UI_BOX_TYPE_TEXT cannot have children."); + fprintf(stdout, "[pke_ui_box_new_child] Validation error: PKE_UI_BOX_TYPE_TEXT cannot have children.\n"); return nullptr; } @@ -731,6 +829,152 @@ pke_ui_box *pke_ui_box_new_child(pke_ui_box *parent, const PKE_UI_BOX_TYPE type, return box; } -pke_ui_graphics_bindings *pke_ui_get_graphics_bindings() { - return &pke_ui_master.bindings; +void pke_ui_box_update_textures(pke_ui_box *box) { + uint32_t i; + pke_ui_graphics_bindings_texture *bindings = nullptr; + pkvk_texture_upload_data data{}; + pkvk_texture_upload_data_out out{}; + AssetHandle handle_default; + AssetHandle handle_hovered; + AssetHandle handle_pressed; + const Asset *asset_default = nullptr; + const Asset *asset_hovered = nullptr; + const Asset *asset_pressed = nullptr; + + if (box->type != PKE_UI_BOX_TYPE_BUTTON_IMAGE) { + fprintf(stderr, "[pke_ui_box_handle_textures] attempted to process textures on non-texture typed ui box. Got type: %hhu\n", static_cast<PKE_UI_BOX_TYPE_T>(box->type)); + return; + } + + if (box->type_data->button_image.gr_binds_bkt_arr_handle == pk_bkt_arr_handle_MAX) { + box->type_data->button_image.gr_binds_bkt_arr_handle = pk_bkt_arr_new_handle(&pke_ui_master.bindings_texture); + bindings = &pke_ui_master.bindings_texture[box->type_data->button_image.gr_binds_bkt_arr_handle]; + bindings->descriptor_sets = nullptr; + bindings->descriptor_pool = VK_NULL_HANDLE; + bindings->instance_count = 0; + bindings->instance_offset = 0; + } else { + bindings = &pke_ui_master.bindings_texture[box->type_data->button_image.gr_binds_bkt_arr_handle]; + } + assert(bindings != nullptr); + + handle_default = AM_GetHandle(box->type_data->button_image.img_key_default); + handle_hovered = AM_GetHandle(box->type_data->button_image.img_key_hovered); + handle_pressed = AM_GetHandle(box->type_data->button_image.img_key_pressed); + + if (handle_default == AssetHandle_MAX) return; + if (handle_hovered == AssetHandle_MAX) return; + if (handle_pressed == AssetHandle_MAX) return; + + asset_default = AM_Get(handle_default); + asset_hovered = AM_Get(handle_hovered); + asset_pressed = AM_Get(handle_pressed); + + if (asset_default == nullptr || asset_default->type != PKE_ASSET_TYPE_TEXTURE) { + fprintf(stderr, "[pke_ui_box_update_textures] `img_key_default` was not found or was not a texture.\n"); + return; + } + if (asset_hovered == nullptr || asset_hovered->type != PKE_ASSET_TYPE_TEXTURE) { + fprintf(stderr, "[pke_ui_box_update_textures] `img_key_hovered` was not found or was not a texture.\n"); + } + if (asset_pressed == nullptr || asset_pressed->type != PKE_ASSET_TYPE_TEXTURE) { + fprintf(stderr, "[pke_ui_box_update_textures] `img_key_pressed` was not found or was not a texture.\n"); + } + + data.n_textures = 3; + data.texture_assets[0] = asset_default; + data.texture_assets[1] = asset_hovered; + data.texture_assets[2] = asset_pressed; + + pkvk_texture_upload_array(&data, &out); + + bindings->image = out.images[0]; + bindings->image_view = out.image_views[0]; + bindings->image_memory = out.device_memory; + + if (bindings->descriptor_sets != nullptr) { + vkDestroyDescriptorPool(vkDevice, bindings->descriptor_pool, vkAllocator); + pk_delete_arr<VkDescriptorSet>(bindings->descriptor_sets, prevSwapchainLength, MemBkt_Vulkan); + } + + VkDescriptorPoolSize pool_size{}; + pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + pool_size.descriptorCount = (uint32_t)swapchainLength; + + VkDescriptorPoolCreateInfo dpci{}; + dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + dpci.pNext = VK_NULL_HANDLE; + dpci.flags = 0; + dpci.maxSets = swapchainLength; + dpci.poolSizeCount = (uint32_t)1; + dpci.pPoolSizes = &pool_size; + + VkDescriptorSetLayout *descriptorSets = pk_new_arr<VkDescriptorSetLayout>(swapchainLength, pkeSettings.mem_bkt.game_transient); + for (i = 0; i < swapchainLength; ++i) { + descriptorSets[i] = pkePipelines.descr_layouts.named.txtr; + } + + VkDescriptorSetAllocateInfo vkDescriptorSetAllocateInfo; + vkDescriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + vkDescriptorSetAllocateInfo.pNext = nullptr; + vkDescriptorSetAllocateInfo.descriptorSetCount = swapchainLength; + vkDescriptorSetAllocateInfo.pSetLayouts = descriptorSets; + + VkWriteDescriptorSet *writeDescriptorSets = pk_new_arr<VkWriteDescriptorSet>(swapchainLength, pkeSettings.mem_bkt.game_transient); + for (i = 0; i < swapchainLength; ++i) { + writeDescriptorSets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writeDescriptorSets[i].pNext = VK_NULL_HANDLE; + writeDescriptorSets[i].dstSet = VK_NULL_HANDLE; + writeDescriptorSets[i].dstBinding = 0; + writeDescriptorSets[i].dstArrayElement = 0; + writeDescriptorSets[i].descriptorCount = 1; + writeDescriptorSets[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + writeDescriptorSets[i].pImageInfo = VK_NULL_HANDLE; + writeDescriptorSets[i].pBufferInfo = VK_NULL_HANDLE; + writeDescriptorSets[i].pTexelBufferView = nullptr; + } + + VkDescriptorImageInfo textureDescriptorInfo; + textureDescriptorInfo.sampler = global_sampler; + textureDescriptorInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + textureDescriptorInfo.imageView = bindings->image_view; + + // consider making me a global pool + auto vkResult = vkCreateDescriptorPool(vkDevice, &dpci, vkAllocator, &bindings->descriptor_pool); + assert(vkResult == VK_SUCCESS); + + vkDescriptorSetAllocateInfo.descriptorPool = bindings->descriptor_pool; + + bindings->descriptor_sets = pk_new_arr<VkDescriptorSet>(swapchainLength, MemBkt_Vulkan); + + vkResult = vkAllocateDescriptorSets(vkDevice, &vkDescriptorSetAllocateInfo, bindings->descriptor_sets); + assert(vkResult == VK_SUCCESS); + + for (i = 0; i < swapchainLength; ++i) { + writeDescriptorSets[i].pImageInfo = &textureDescriptorInfo; + writeDescriptorSets[i].dstSet = bindings->descriptor_sets[i]; + } + + vkUpdateDescriptorSets(vkDevice, swapchainLength, writeDescriptorSets, 0, nullptr); + + AM_Release(handle_pressed); + AM_Release(handle_hovered); + AM_Release(handle_default); +} + +const pke_ui_graphics_bindings &pke_ui_get_graphics_bindings() { + return pke_ui_master.bindings; +} + +void pke_ui_get_graphics_bindings_texture(pk_arr *arr) { + pk_arr_t<pke_ui_graphics_bindings_texture> &arr_t = *static_cast<pk_arr_t<pke_ui_graphics_bindings_texture>*>(arr); + assert(arr_t.stride == sizeof(pke_ui_graphics_bindings_texture)); + assert(arr_t.alignment == alignof(pke_ui_graphics_bindings_texture)); + + texture_binding_bkt_arr::FN_Iter iter_fn_tmpln; + iter_fn_tmpln.func = [&arr_t](pke_ui_graphics_bindings_texture *arr_item) { + pk_arr_append_t(&arr_t, *arr_item); + }; + + pk_bkt_arr_iterate(&pke_ui_master.bindings_texture, texture_binding_bkt_arr::FN_Iter::invoke, &iter_fn_tmpln); } |
