RmlUi_Renderer_VK.cpp 114 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043
  1. /*
  2. * This source file is part of RmlUi, the HTML/CSS Interface Middleware
  3. *
  4. * For the latest information, see http://github.com/mikke89/RmlUi
  5. *
  6. * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
  7. * Copyright (c) 2019-2023 The RmlUi Team, and contributors
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. *
  27. */
  28. #include "RmlUi_Renderer_VK.h"
  29. #include "RmlUi_Vulkan/ShadersCompiledSPV.h"
  30. #include <RmlUi/Core/Core.h>
  31. #include <RmlUi/Core/FileInterface.h>
  32. #include <RmlUi/Core/Log.h>
  33. #include <RmlUi/Core/Math.h>
  34. #include <RmlUi/Core/Platform.h>
  35. #include <RmlUi/Core/Profiling.h>
  36. #include <algorithm>
  37. #include <string.h>
  38. // AlignUp(314, 256) = 512
  39. template <typename T>
  40. static T AlignUp(T val, T alignment)
  41. {
  42. return (val + alignment - (T)1) & ~(alignment - (T)1);
  43. }
  44. VkValidationFeaturesEXT debug_validation_features_ext = {};
  45. VkValidationFeatureEnableEXT debug_validation_features_ext_requested[] = {
  46. VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,
  47. VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
  48. VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
  49. };
  50. #ifdef RMLUI_VK_DEBUG
  51. static Rml::String FormatByteSize(VkDeviceSize size) noexcept
  52. {
  53. constexpr VkDeviceSize K = VkDeviceSize(1024);
  54. if (size < K)
  55. return Rml::CreateString("%zu B", size);
  56. else if (size < K * K)
  57. return Rml::CreateString("%g KB", double(size) / double(K));
  58. return Rml::CreateString("%g MB", double(size) / double(K * K));
  59. }
  60. static VKAPI_ATTR VkBool32 VKAPI_CALL MyDebugReportCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severityFlags,
  61. VkDebugUtilsMessageTypeFlagsEXT /*messageTypeFlags*/, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* /*pUserData*/)
  62. {
  63. if (severityFlags & VkDebugUtilsMessageSeverityFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT)
  64. {
  65. return VK_FALSE;
  66. }
  67. #ifdef RMLUI_PLATFORM_WIN32
  68. if (severityFlags & VkDebugUtilsMessageSeverityFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
  69. {
  70. // some logs are not passed to our UI, because of early calling for explicity I put native log output
  71. OutputDebugString(TEXT("\n"));
  72. OutputDebugStringA(pCallbackData->pMessage);
  73. }
  74. #endif
  75. Rml::Log::Message(Rml::Log::LT_ERROR, "[Vulkan][VALIDATION] %s ", pCallbackData->pMessage);
  76. return VK_FALSE;
  77. }
  78. #endif
  79. RenderInterface_VK::RenderInterface_VK() :
  80. m_is_transform_enabled{false}, m_is_apply_to_regular_geometry_stencil{false}, m_is_use_scissor_specified{false}, m_is_use_stencil_pipeline{false},
  81. m_width{}, m_height{}, m_queue_index_present{}, m_queue_index_graphics{}, m_queue_index_compute{}, m_semaphore_index{},
  82. m_semaphore_index_previous{}, m_image_index{}, m_p_instance{}, m_p_device{}, m_p_physical_device{}, m_p_surface{}, m_p_swapchain{},
  83. m_p_allocator{}, m_p_current_command_buffer{}, m_p_descriptor_set_layout_vertex_transform{}, m_p_descriptor_set_layout_texture{},
  84. m_p_pipeline_layout{}, m_p_pipeline_with_textures{}, m_p_pipeline_without_textures{},
  85. m_p_pipeline_stencil_for_region_where_geometry_will_be_drawn{}, m_p_pipeline_stencil_for_regular_geometry_that_applied_to_region_with_textures{},
  86. m_p_pipeline_stencil_for_regular_geometry_that_applied_to_region_without_textures{}, m_p_descriptor_set{}, m_p_render_pass{},
  87. m_p_sampler_linear{}, m_scissor{}, m_scissor_original{}, m_viewport{}, m_p_queue_present{}, m_p_queue_graphics{}, m_p_queue_compute{},
  88. #ifdef RMLUI_VK_DEBUG
  89. m_debug_messenger{},
  90. #endif
  91. m_swapchain_format{}, m_texture_depthstencil{}, m_pending_for_deletion_textures_by_frames{}
  92. {}
  93. RenderInterface_VK::~RenderInterface_VK() {}
  94. Rml::CompiledGeometryHandle RenderInterface_VK::CompileGeometry(Rml::Span<const Rml::Vertex> vertices, Rml::Span<const int> indices)
  95. {
  96. RMLUI_ZoneScopedN("Vulkan - CompileGeometry");
  97. VkDescriptorSet p_current_descriptor_set = nullptr;
  98. p_current_descriptor_set = m_p_descriptor_set;
  99. RMLUI_VK_ASSERTMSG(p_current_descriptor_set,
  100. "you can't have here an invalid pointer of VkDescriptorSet. Two reason might be. 1. - you didn't allocate it "
  101. "at all or 2. - Somehing is wrong with allocation and somehow it was corrupted by something.");
  102. auto* p_geometry_handle = new geometry_handle_t{};
  103. uint32_t* pCopyDataToBuffer = nullptr;
  104. const void* pData = reinterpret_cast<const void*>(vertices.data());
  105. bool status = m_memory_pool.Alloc_VertexBuffer((uint32_t)vertices.size(), sizeof(Rml::Vertex), reinterpret_cast<void**>(&pCopyDataToBuffer),
  106. &p_geometry_handle->m_p_vertex, &p_geometry_handle->m_p_vertex_allocation);
  107. RMLUI_VK_ASSERTMSG(status, "failed to AllocVertexBuffer");
  108. memcpy(pCopyDataToBuffer, pData, sizeof(Rml::Vertex) * vertices.size());
  109. status = m_memory_pool.Alloc_IndexBuffer((uint32_t)indices.size(), sizeof(int), reinterpret_cast<void**>(&pCopyDataToBuffer),
  110. &p_geometry_handle->m_p_index, &p_geometry_handle->m_p_index_allocation);
  111. RMLUI_VK_ASSERTMSG(status, "failed to AllocIndexBuffer");
  112. memcpy(pCopyDataToBuffer, indices.data(), sizeof(int) * indices.size());
  113. p_geometry_handle->m_num_indices = (int)indices.size();
  114. return Rml::CompiledGeometryHandle(p_geometry_handle);
  115. }
  116. void RenderInterface_VK::RenderGeometry(Rml::CompiledGeometryHandle geometry, Rml::Vector2f translation, Rml::TextureHandle texture)
  117. {
  118. RMLUI_ZoneScopedN("Vulkan - RenderCompiledGeometry");
  119. if (m_p_current_command_buffer == nullptr)
  120. return;
  121. RMLUI_VK_ASSERTMSG(m_p_current_command_buffer, "must be valid otherwise you can't render now!!! (can't be)");
  122. texture_data_t* p_texture = reinterpret_cast<texture_data_t*>(texture);
  123. VkDescriptorImageInfo info_descriptor_image = {};
  124. if (p_texture && p_texture->m_p_vk_descriptor_set == nullptr)
  125. {
  126. VkDescriptorSet p_texture_set = nullptr;
  127. m_manager_descriptors.Alloc_Descriptor(m_p_device, &m_p_descriptor_set_layout_texture, &p_texture_set);
  128. info_descriptor_image.imageView = p_texture->m_p_vk_image_view;
  129. info_descriptor_image.sampler = p_texture->m_p_vk_sampler;
  130. info_descriptor_image.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  131. VkWriteDescriptorSet info_write = {};
  132. info_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  133. info_write.dstSet = p_texture_set;
  134. info_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  135. info_write.dstBinding = 2;
  136. info_write.pImageInfo = &info_descriptor_image;
  137. info_write.descriptorCount = 1;
  138. vkUpdateDescriptorSets(m_p_device, 1, &info_write, 0, nullptr);
  139. p_texture->m_p_vk_descriptor_set = p_texture_set;
  140. }
  141. geometry_handle_t* p_casted_compiled_geometry = reinterpret_cast<geometry_handle_t*>(geometry);
  142. m_user_data_for_vertex_shader.m_translate = translation;
  143. VkDescriptorSet p_current_descriptor_set = nullptr;
  144. p_current_descriptor_set = m_p_descriptor_set;
  145. RMLUI_VK_ASSERTMSG(p_current_descriptor_set,
  146. "you can't have here an invalid pointer of VkDescriptorSet. Two reason might be. 1. - you didn't allocate it "
  147. "at all or 2. - Somehing is wrong with allocation and somehow it was corrupted by something.");
  148. shader_vertex_user_data_t* p_data = nullptr;
  149. if (p_casted_compiled_geometry->m_p_shader_allocation == nullptr)
  150. {
  151. // it means it was freed in ReleaseCompiledGeometry method
  152. bool status = m_memory_pool.Alloc_GeneralBuffer(sizeof(m_user_data_for_vertex_shader), reinterpret_cast<void**>(&p_data),
  153. &p_casted_compiled_geometry->m_p_shader, &p_casted_compiled_geometry->m_p_shader_allocation);
  154. RMLUI_VK_ASSERTMSG(status, "failed to allocate VkDescriptorBufferInfo for uniform data to shaders");
  155. }
  156. else
  157. {
  158. // it means our state is dirty and we need to update data, but it is not right in terms of architecture, for real better experience would
  159. // be great to free all "compiled" geometries and "re-build" them in one general way, but here I got only three callings for
  160. // font-face-layer textures (load_document example) and that shit. So better to think how to make it right, if it is fine okay, if it is
  161. // not okay and like we really expect that ReleaseCompiledGeometry for all objects that needs to be rebuilt so better to implement that,
  162. // but still it is a big architectural thing (or at least you need to do something big commits here to implement a such feature), so my
  163. // implementation doesn't break anything what we had, but still it looks strange. If I get callings for releasing maybe I need to use it
  164. // for all objects not separately????? Otherwise it is better to provide method for resizing (or some kind of "resizing" callback) for
  165. // recalculating all geometry IDK, so it means you pass the existed geometry that wasn't pass to ReleaseCompiledGeometry, but from another
  166. // hand you need to re-build compiled geometry again so we have two kinds of geometry one is compiled and never changes and one is dynamic
  167. // and it goes through pipeline InitializationOfProgram...->Compile->Render->Release->Compile->Render->Release...
  168. m_memory_pool.Free_GeometryHandle_ShaderDataOnly(p_casted_compiled_geometry);
  169. bool status = m_memory_pool.Alloc_GeneralBuffer(sizeof(m_user_data_for_vertex_shader), reinterpret_cast<void**>(&p_data),
  170. &p_casted_compiled_geometry->m_p_shader, &p_casted_compiled_geometry->m_p_shader_allocation);
  171. RMLUI_VK_ASSERTMSG(status, "failed to allocate VkDescriptorBufferInfo for uniform data to shaders");
  172. }
  173. if (p_data)
  174. {
  175. p_data->m_transform = m_user_data_for_vertex_shader.m_transform;
  176. p_data->m_translate = m_user_data_for_vertex_shader.m_translate;
  177. }
  178. else
  179. {
  180. RMLUI_VK_ASSERTMSG(p_data, "you can't reach this zone, it means something bad");
  181. }
  182. const uint32_t pDescriptorOffsets = static_cast<uint32_t>(p_casted_compiled_geometry->m_p_shader.offset);
  183. VkDescriptorSet p_texture_descriptor_set = nullptr;
  184. if (p_texture)
  185. {
  186. p_texture_descriptor_set = p_texture->m_p_vk_descriptor_set;
  187. }
  188. VkDescriptorSet p_sets[] = {p_current_descriptor_set, p_texture_descriptor_set};
  189. int real_size_of_sets = 2;
  190. if (p_texture == nullptr)
  191. real_size_of_sets = 1;
  192. vkCmdBindDescriptorSets(m_p_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_p_pipeline_layout, 0, real_size_of_sets, p_sets, 1,
  193. &pDescriptorOffsets);
  194. if (m_is_use_stencil_pipeline)
  195. {
  196. vkCmdBindPipeline(m_p_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_p_pipeline_stencil_for_region_where_geometry_will_be_drawn);
  197. }
  198. else
  199. {
  200. if (p_texture)
  201. {
  202. if (m_is_apply_to_regular_geometry_stencil)
  203. {
  204. vkCmdBindPipeline(m_p_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
  205. m_p_pipeline_stencil_for_regular_geometry_that_applied_to_region_with_textures);
  206. }
  207. else
  208. {
  209. vkCmdBindPipeline(m_p_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_p_pipeline_with_textures);
  210. }
  211. }
  212. else
  213. {
  214. if (m_is_apply_to_regular_geometry_stencil)
  215. {
  216. vkCmdBindPipeline(m_p_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
  217. m_p_pipeline_stencil_for_regular_geometry_that_applied_to_region_without_textures);
  218. }
  219. else
  220. {
  221. vkCmdBindPipeline(m_p_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_p_pipeline_without_textures);
  222. }
  223. }
  224. }
  225. vkCmdBindVertexBuffers(m_p_current_command_buffer, 0, 1, &p_casted_compiled_geometry->m_p_vertex.buffer,
  226. &p_casted_compiled_geometry->m_p_vertex.offset);
  227. vkCmdBindIndexBuffer(m_p_current_command_buffer, p_casted_compiled_geometry->m_p_index.buffer, p_casted_compiled_geometry->m_p_index.offset,
  228. VK_INDEX_TYPE_UINT32);
  229. vkCmdDrawIndexed(m_p_current_command_buffer, p_casted_compiled_geometry->m_num_indices, 1, 0, 0, 0);
  230. }
  231. void RenderInterface_VK::ReleaseGeometry(Rml::CompiledGeometryHandle geometry)
  232. {
  233. RMLUI_ZoneScopedN("Vulkan - ReleaseCompiledGeometry");
  234. geometry_handle_t* p_casted_geometry = reinterpret_cast<geometry_handle_t*>(geometry);
  235. m_pending_for_deletion_geometries.push_back(p_casted_geometry);
  236. }
  237. void RenderInterface_VK::EnableScissorRegion(bool enable)
  238. {
  239. if (m_p_current_command_buffer == nullptr)
  240. return;
  241. if (m_is_transform_enabled)
  242. {
  243. m_is_apply_to_regular_geometry_stencil = true;
  244. }
  245. m_is_use_scissor_specified = enable;
  246. if (m_is_use_scissor_specified == false)
  247. {
  248. m_is_apply_to_regular_geometry_stencil = false;
  249. vkCmdSetScissor(m_p_current_command_buffer, 0, 1, &m_scissor_original);
  250. }
  251. }
  252. void RenderInterface_VK::SetScissorRegion(Rml::Rectanglei region)
  253. {
  254. if (m_is_use_scissor_specified)
  255. {
  256. if (m_is_transform_enabled)
  257. {
  258. Rml::Vertex vertices[4];
  259. vertices[0].position = Rml::Vector2f(region.TopLeft());
  260. vertices[1].position = Rml::Vector2f(region.TopRight());
  261. vertices[2].position = Rml::Vector2f(region.BottomRight());
  262. vertices[3].position = Rml::Vector2f(region.BottomLeft());
  263. int indices[6] = {0, 2, 1, 0, 3, 2};
  264. m_is_use_stencil_pipeline = true;
  265. #ifdef RMLUI_DEBUG
  266. VkDebugUtilsLabelEXT info{};
  267. info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
  268. info.color[0] = 1.0f;
  269. info.color[1] = 1.0f;
  270. info.color[2] = 0.0f;
  271. info.color[3] = 1.0f;
  272. info.pLabelName = "SetScissorRegion (generated region)";
  273. vkCmdInsertDebugUtilsLabelEXT(m_p_current_command_buffer, &info);
  274. #endif
  275. VkClearDepthStencilValue info_clear_color{};
  276. info_clear_color.depth = 1.0f;
  277. info_clear_color.stencil = 0;
  278. VkClearAttachment clear_attachment = {};
  279. clear_attachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
  280. clear_attachment.clearValue.depthStencil = info_clear_color;
  281. clear_attachment.colorAttachment = 1;
  282. VkClearRect clear_rect = {};
  283. clear_rect.layerCount = 1;
  284. clear_rect.rect.extent.width = m_width;
  285. clear_rect.rect.extent.height = m_height;
  286. vkCmdClearAttachments(m_p_current_command_buffer, 1, &clear_attachment, 1, &clear_rect);
  287. if (Rml::CompiledGeometryHandle handle = CompileGeometry({vertices, 4}, {indices, 6}))
  288. {
  289. RenderGeometry(handle, {}, {});
  290. ReleaseGeometry(handle);
  291. }
  292. m_is_use_stencil_pipeline = false;
  293. m_is_apply_to_regular_geometry_stencil = true;
  294. }
  295. else
  296. {
  297. m_scissor.extent.width = region.Width();
  298. m_scissor.extent.height = region.Height();
  299. m_scissor.offset.x = Rml::Math::Clamp(region.Left(), 0, m_width);
  300. m_scissor.offset.y = Rml::Math::Clamp(region.Top(), 0, m_height);
  301. #ifdef RMLUI_DEBUG
  302. VkDebugUtilsLabelEXT info{};
  303. info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
  304. info.color[0] = 1.0f;
  305. info.color[1] = 0.0f;
  306. info.color[2] = 0.0f;
  307. info.color[3] = 1.0f;
  308. info.pLabelName = "SetScissorRegion (offset)";
  309. vkCmdInsertDebugUtilsLabelEXT(m_p_current_command_buffer, &info);
  310. #endif
  311. vkCmdSetScissor(m_p_current_command_buffer, 0, 1, &m_scissor);
  312. }
  313. }
  314. }
  315. // Set to byte packing, or the compiler will expand our struct, which means it won't read correctly from file
  316. #pragma pack(1)
  317. struct TGAHeader {
  318. char idLength;
  319. char colourMapType;
  320. char dataType;
  321. short int colourMapOrigin;
  322. short int colourMapLength;
  323. char colourMapDepth;
  324. short int xOrigin;
  325. short int yOrigin;
  326. short int width;
  327. short int height;
  328. char bitsPerPixel;
  329. char imageDescriptor;
  330. };
  331. // Restore packing
  332. #pragma pack()
  333. Rml::TextureHandle RenderInterface_VK::LoadTexture(Rml::Vector2i& texture_dimensions, const Rml::String& source)
  334. {
  335. Rml::FileInterface* file_interface = Rml::GetFileInterface();
  336. Rml::FileHandle file_handle = file_interface->Open(source);
  337. if (!file_handle)
  338. {
  339. return false;
  340. }
  341. file_interface->Seek(file_handle, 0, SEEK_END);
  342. size_t buffer_size = file_interface->Tell(file_handle);
  343. file_interface->Seek(file_handle, 0, SEEK_SET);
  344. if (buffer_size <= sizeof(TGAHeader))
  345. {
  346. Rml::Log::Message(Rml::Log::LT_ERROR, "Texture file size is smaller than TGAHeader, file is not a valid TGA image.");
  347. file_interface->Close(file_handle);
  348. return false;
  349. }
  350. using Rml::byte;
  351. Rml::UniquePtr<byte[]> buffer(new byte[buffer_size]);
  352. file_interface->Read(buffer.get(), buffer_size, file_handle);
  353. file_interface->Close(file_handle);
  354. TGAHeader header;
  355. memcpy(&header, buffer.get(), sizeof(TGAHeader));
  356. int color_mode = header.bitsPerPixel / 8;
  357. const size_t image_size = header.width * header.height * 4; // We always make 32bit textures
  358. if (header.dataType != 2)
  359. {
  360. Rml::Log::Message(Rml::Log::LT_ERROR, "Only 24/32bit uncompressed TGAs are supported.");
  361. return false;
  362. }
  363. // Ensure we have at least 3 colors
  364. if (color_mode < 3)
  365. {
  366. Rml::Log::Message(Rml::Log::LT_ERROR, "Only 24 and 32bit textures are supported.");
  367. return false;
  368. }
  369. const byte* image_src = buffer.get() + sizeof(TGAHeader);
  370. Rml::UniquePtr<byte[]> image_dest_buffer(new byte[image_size]);
  371. byte* image_dest = image_dest_buffer.get();
  372. // Targa is BGR, swap to RGB, flip Y axis, and convert to premultiplied alpha.
  373. for (long y = 0; y < header.height; y++)
  374. {
  375. long read_index = y * header.width * color_mode;
  376. long write_index = ((header.imageDescriptor & 32) != 0) ? read_index : (header.height - y - 1) * header.width * 4;
  377. for (long x = 0; x < header.width; x++)
  378. {
  379. image_dest[write_index] = image_src[read_index + 2];
  380. image_dest[write_index + 1] = image_src[read_index + 1];
  381. image_dest[write_index + 2] = image_src[read_index];
  382. if (color_mode == 4)
  383. {
  384. const byte alpha = image_src[read_index + 3];
  385. for (size_t j = 0; j < 3; j++)
  386. image_dest[write_index + j] = byte((image_dest[write_index + j] * alpha) / 255);
  387. image_dest[write_index + 3] = alpha;
  388. }
  389. else
  390. image_dest[write_index + 3] = 255;
  391. write_index += 4;
  392. read_index += color_mode;
  393. }
  394. }
  395. texture_dimensions.x = header.width;
  396. texture_dimensions.y = header.height;
  397. return GenerateTexture({image_dest, image_size}, texture_dimensions);
  398. }
  399. Rml::TextureHandle RenderInterface_VK::GenerateTexture(Rml::Span<const Rml::byte> source_data, Rml::Vector2i source_dimensions)
  400. {
  401. Rml::String source_name = "generated-texture";
  402. return CreateTexture(source_data, source_dimensions, source_name);
  403. }
  404. /*
  405. How vulkan works with textures efficiently?
  406. You need to create buffer that has CPU memory accessibility it means it uses your RAM memory for storing data and it has only CPU visibility (RAM)
  407. After you create buffer that has GPU memory accessibility it means it uses by your video hardware and it has only VRAM (Video RAM) visibility
  408. So you copy data to CPU_buffer and after you copy that thing to GPU_buffer, but delete CPU_buffer
  409. So it means you "uploaded" data to GPU
  410. Again, you need to "write" data into CPU buffer after you need to copy that data from buffer to GPU buffer and after that buffer go to GPU.
  411. RAW_POINTER_DATA_BYTES_LITERALLY->COPY_TO->CPU->COPY_TO->GPU->Releasing_CPU <= that's how works uploading textures in Vulkan if you want to have
  412. efficient handling otherwise it is cpu_to_gpu visibility and it means you create only ONE buffer that is accessible for CPU and for GPU, but it
  413. will cause the worst performance...
  414. */
  415. Rml::TextureHandle RenderInterface_VK::CreateTexture(Rml::Span<const Rml::byte> source, Rml::Vector2i dimensions, const Rml::String& name)
  416. {
  417. RMLUI_ZoneScopedN("Vulkan - GenerateTexture");
  418. RMLUI_VK_ASSERTMSG(!source.empty(), "you pushed not valid data for copying to buffer");
  419. RMLUI_VK_ASSERTMSG(m_p_allocator, "you have to initialize Vma Allocator for this method");
  420. (void)name;
  421. int width = dimensions.x;
  422. int height = dimensions.y;
  423. RMLUI_VK_ASSERTMSG(width, "invalid width");
  424. RMLUI_VK_ASSERTMSG(height, "invalid height");
  425. VkDeviceSize image_size = source.size();
  426. VkFormat format = VkFormat::VK_FORMAT_R8G8B8A8_UNORM;
  427. buffer_data_t cpu_buffer = CreateResource_StagingBuffer(image_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
  428. void* data;
  429. vmaMapMemory(m_p_allocator, cpu_buffer.m_p_vma_allocation, &data);
  430. memcpy(data, source.data(), static_cast<size_t>(image_size));
  431. vmaUnmapMemory(m_p_allocator, cpu_buffer.m_p_vma_allocation);
  432. VkExtent3D extent_image = {};
  433. extent_image.width = static_cast<uint32_t>(width);
  434. extent_image.height = static_cast<uint32_t>(height);
  435. extent_image.depth = 1;
  436. auto* p_texture = new texture_data_t{};
  437. VkImageCreateInfo info = {};
  438. info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  439. info.pNext = nullptr;
  440. info.imageType = VK_IMAGE_TYPE_2D;
  441. info.format = format;
  442. info.extent = extent_image;
  443. info.mipLevels = 1;
  444. info.arrayLayers = 1;
  445. info.samples = VK_SAMPLE_COUNT_1_BIT;
  446. info.tiling = VK_IMAGE_TILING_OPTIMAL;
  447. info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
  448. VmaAllocationCreateInfo info_allocation = {};
  449. info_allocation.usage = VMA_MEMORY_USAGE_GPU_ONLY;
  450. VkImage p_image = nullptr;
  451. VmaAllocation p_allocation = nullptr;
  452. VmaAllocationInfo info_stats = {};
  453. VkResult status = vmaCreateImage(m_p_allocator, &info, &info_allocation, &p_image, &p_allocation, &info_stats);
  454. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vmaCreateImage");
  455. #ifdef RMLUI_VK_DEBUG
  456. Rml::Log::Message(Rml::Log::LT_DEBUG, "Created texture '%s' [%dx%d, %s]", name.c_str(), dimensions.x, dimensions.y,
  457. FormatByteSize(info_stats.size).c_str());
  458. #endif
  459. p_texture->m_p_vk_image = p_image;
  460. p_texture->m_p_vma_allocation = p_allocation;
  461. #ifdef RMLUI_VK_DEBUG
  462. vmaSetAllocationName(m_p_allocator, p_allocation, name.c_str());
  463. #endif
  464. /*
  465. * So Vulkan works only through VkCommandBuffer, it is for remembering API commands what you want to call from GPU
  466. * So on CPU side you need to create a scope that consists of two things
  467. * vkBeginCommandBuffer
  468. * ... <= here your commands what you want to place into your command buffer and send it to GPU through vkQueueSubmit function
  469. * vkEndCommandBuffer
  470. *
  471. * So commands start to work ONLY when you called the vkQueueSubmit otherwise you just "place" commands into your command buffer but you
  472. * didn't issue any thing in order to start the work on GPU side. ALWAYS remember that just sumbit means execute async mode, so you have to wait
  473. * operations before they exeecute fully otherwise you will get some errors or write/read concurrent state and all other stuff, vulkan validation
  474. * will notify you :) (in most cases)
  475. *
  476. * BUT you need always sync what you have done when you called your vkQueueSubmit function, so it is wait method, but generally you can create
  477. * another queue and isolate all stuff tbh
  478. *
  479. * So understing these principles you understand how to work with API and your GPU
  480. *
  481. * There's nothing hard, but it makes all stuff on programmer side if you remember OpenGL and how it was easy to load texture upload it and create
  482. * buffers and it In OpenGL all stuff is handled by driver and other things, not a programmer definitely
  483. *
  484. * What we do here? We need to change the layout of our image. it means where we want to use it. So in our case we want to see that this image
  485. * will be in shaders Because the initial state of create object is VK_IMAGE_LAYOUT_UNDEFINED means you can't just pass that VkImage handle to
  486. * your functions and wait that it comes to shaders for exmaple No it doesn't work like that you have to have the explicit states of your resource
  487. * and where it goes
  488. *
  489. * In our case we want to see in our pixel shader so we need to change transfer into this flag VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, because we
  490. * want to copy so it means some transfer thing, but after we say it goes to pixel after our copying operation
  491. */
  492. m_upload_manager.UploadToGPU([p_image, extent_image, cpu_buffer](VkCommandBuffer p_cmd) {
  493. VkImageSubresourceRange range = {};
  494. range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  495. range.baseMipLevel = 0;
  496. range.baseArrayLayer = 0;
  497. range.levelCount = 1;
  498. range.layerCount = 1;
  499. VkImageMemoryBarrier info_barrier = {};
  500. info_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  501. info_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  502. info_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  503. info_barrier.image = p_image;
  504. info_barrier.subresourceRange = range;
  505. info_barrier.srcAccessMask = 0;
  506. info_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  507. vkCmdPipelineBarrier(p_cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &info_barrier);
  508. VkBufferImageCopy region = {};
  509. region.bufferOffset = 0;
  510. region.bufferRowLength = 0;
  511. region.bufferImageHeight = 0;
  512. region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  513. region.imageSubresource.mipLevel = 0;
  514. region.imageSubresource.baseArrayLayer = 0;
  515. region.imageSubresource.layerCount = 1;
  516. region.imageExtent = extent_image;
  517. vkCmdCopyBufferToImage(p_cmd, cpu_buffer.m_p_vk_buffer, p_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
  518. VkImageMemoryBarrier info_barrier_shader_read = {};
  519. info_barrier_shader_read.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  520. info_barrier_shader_read.pNext = nullptr;
  521. info_barrier_shader_read.image = p_image;
  522. info_barrier_shader_read.subresourceRange = range;
  523. info_barrier_shader_read.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  524. info_barrier_shader_read.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  525. info_barrier_shader_read.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  526. info_barrier_shader_read.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
  527. vkCmdPipelineBarrier(p_cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1,
  528. &info_barrier_shader_read);
  529. });
  530. DestroyResource_StagingBuffer(cpu_buffer);
  531. VkImageViewCreateInfo info_image_view = {};
  532. info_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  533. info_image_view.pNext = nullptr;
  534. info_image_view.image = p_texture->m_p_vk_image;
  535. info_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D;
  536. info_image_view.format = format;
  537. info_image_view.subresourceRange.baseMipLevel = 0;
  538. info_image_view.subresourceRange.levelCount = 1;
  539. info_image_view.subresourceRange.baseArrayLayer = 0;
  540. info_image_view.subresourceRange.layerCount = 1;
  541. info_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  542. VkImageView p_image_view = nullptr;
  543. status = vkCreateImageView(m_p_device, &info_image_view, nullptr, &p_image_view);
  544. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkCreateImageView");
  545. p_texture->m_p_vk_image_view = p_image_view;
  546. p_texture->m_p_vk_sampler = m_p_sampler_linear;
  547. return reinterpret_cast<Rml::TextureHandle>(p_texture);
  548. }
  549. void RenderInterface_VK::ReleaseTexture(Rml::TextureHandle texture_handle)
  550. {
  551. texture_data_t* p_texture = reinterpret_cast<texture_data_t*>(texture_handle);
  552. if (p_texture)
  553. {
  554. m_pending_for_deletion_textures_by_frames[m_semaphore_index_previous].push_back(p_texture);
  555. }
  556. }
  557. void RenderInterface_VK::SetTransform(const Rml::Matrix4f* transform)
  558. {
  559. m_is_transform_enabled = !!(transform);
  560. m_user_data_for_vertex_shader.m_transform = m_projection * (transform ? *transform : Rml::Matrix4f::Identity());
  561. }
  562. void RenderInterface_VK::BeginFrame()
  563. {
  564. Wait();
  565. Update_PendingForDeletion_Textures_By_Frames();
  566. Update_PendingForDeletion_Geometries();
  567. m_command_buffer_ring.OnBeginFrame();
  568. m_p_current_command_buffer = m_command_buffer_ring.GetCommandBufferForActiveFrame(CommandBufferName::Primary);
  569. VkCommandBufferBeginInfo info = {};
  570. info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  571. info.pInheritanceInfo = nullptr;
  572. info.pNext = nullptr;
  573. info.flags = VkCommandBufferUsageFlagBits::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
  574. auto status = vkBeginCommandBuffer(m_p_current_command_buffer, &info);
  575. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkBeginCommandBuffer");
  576. VkClearValue for_filling_back_buffer_color;
  577. VkClearValue for_stencil_depth;
  578. for_stencil_depth.depthStencil = {1.0f, 0};
  579. for_filling_back_buffer_color.color = {{0.0f, 0.0f, 0.0f, 1.0f}};
  580. const VkClearValue p_color_rt[] = {for_filling_back_buffer_color, for_stencil_depth};
  581. VkRenderPassBeginInfo info_pass = {};
  582. info_pass.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  583. info_pass.pNext = nullptr;
  584. info_pass.renderPass = m_p_render_pass;
  585. info_pass.framebuffer = m_swapchain_frame_buffers[m_image_index];
  586. info_pass.pClearValues = p_color_rt;
  587. info_pass.clearValueCount = 2;
  588. info_pass.renderArea.offset.x = 0;
  589. info_pass.renderArea.offset.y = 0;
  590. info_pass.renderArea.extent.width = m_width;
  591. info_pass.renderArea.extent.height = m_height;
  592. vkCmdBeginRenderPass(m_p_current_command_buffer, &info_pass, VkSubpassContents::VK_SUBPASS_CONTENTS_INLINE);
  593. vkCmdSetViewport(m_p_current_command_buffer, 0, 1, &m_viewport);
  594. m_is_apply_to_regular_geometry_stencil = false;
  595. }
  596. void RenderInterface_VK::EndFrame()
  597. {
  598. if (m_p_current_command_buffer == nullptr)
  599. return;
  600. vkCmdEndRenderPass(m_p_current_command_buffer);
  601. auto status = vkEndCommandBuffer(m_p_current_command_buffer);
  602. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkEndCommandBuffer");
  603. Submit();
  604. Present();
  605. m_p_current_command_buffer = nullptr;
  606. }
  607. void RenderInterface_VK::SetViewport(int width, int height)
  608. {
  609. auto status = vkDeviceWaitIdle(m_p_device);
  610. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkDeviceWaitIdle");
  611. if (width > 0 && height > 0)
  612. {
  613. m_width = width;
  614. m_height = height;
  615. }
  616. if (m_p_swapchain)
  617. {
  618. Destroy_Swapchain();
  619. DestroyResourcesDependentOnSize();
  620. m_p_swapchain = {};
  621. }
  622. VkExtent2D window_extent = GetValidSurfaceExtent();
  623. if (window_extent.width == 0 || window_extent.height == 0)
  624. return;
  625. #ifdef RMLUI_VK_DEBUG
  626. Rml::Log::Message(Rml::Log::Type::LT_DEBUG, "Rml width: %d height: %d | Vulkan width: %d height: %d", m_width, m_height, window_extent.width,
  627. window_extent.height);
  628. #endif
  629. // we need to sync the data from Vulkan so we can't use native Rml's data about width and height so be careful otherwise we create framebuffer
  630. // with Rml's width and height but they're different to what Vulkan determines for our window (e.g. device/swapchain)
  631. m_width = window_extent.width;
  632. m_height = window_extent.height;
  633. Initialize_Swapchain(window_extent);
  634. CreateResourcesDependentOnSize(window_extent);
  635. }
  636. bool RenderInterface_VK::IsSwapchainValid()
  637. {
  638. return m_p_swapchain != nullptr;
  639. }
  640. void RenderInterface_VK::RecreateSwapchain()
  641. {
  642. SetViewport(m_width, m_height);
  643. }
  644. bool RenderInterface_VK::Initialize(Rml::Vector<const char*> required_extensions, CreateSurfaceCallback create_surface_callback)
  645. {
  646. RMLUI_ZoneScopedN("Vulkan - Initialize");
  647. int glad_result = 0;
  648. glad_result = gladLoaderLoadVulkan(VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE);
  649. RMLUI_VK_ASSERTMSG(glad_result != 0, "Vulkan loader failed - Global functions");
  650. Initialize_Instance(std::move(required_extensions));
  651. VkPhysicalDeviceProperties physical_device_properties = {};
  652. Initialize_PhysicalDevice(physical_device_properties);
  653. glad_result = gladLoaderLoadVulkan(m_p_instance, m_p_physical_device, VK_NULL_HANDLE);
  654. RMLUI_VK_ASSERTMSG(glad_result != 0, "Vulkan loader failed - Instance functions");
  655. Initialize_Surface(create_surface_callback);
  656. Initialize_QueueIndecies();
  657. Initialize_Device();
  658. glad_result = gladLoaderLoadVulkan(m_p_instance, m_p_physical_device, m_p_device);
  659. RMLUI_VK_ASSERTMSG(glad_result != 0, "Vulkan loader failed - Device functions");
  660. Initialize_Queues();
  661. Initialize_SyncPrimitives();
  662. Initialize_Allocator();
  663. Initialize_Resources(physical_device_properties);
  664. return true;
  665. }
  666. void RenderInterface_VK::Shutdown()
  667. {
  668. RMLUI_ZoneScopedN("Vulkan - Shutdown");
  669. auto status = vkDeviceWaitIdle(m_p_device);
  670. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "you must have a valid status here");
  671. DestroyResourcesDependentOnSize();
  672. Destroy_Resources();
  673. Destroy_Allocator();
  674. Destroy_SyncPrimitives();
  675. Destroy_Swapchain();
  676. Destroy_Surface();
  677. Destroy_Device();
  678. Destroy_ReportDebugCallback();
  679. Destroy_Instance();
  680. gladLoaderUnloadVulkan();
  681. }
  682. void RenderInterface_VK::Initialize_Instance(Rml::Vector<const char*> required_extensions) noexcept
  683. {
  684. uint32_t required_version = GetRequiredVersionAndValidateMachine();
  685. VkApplicationInfo info = {};
  686. info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  687. info.pNext = nullptr;
  688. info.pApplicationName = "RmlUi Shell";
  689. info.applicationVersion = 50;
  690. info.pEngineName = "RmlUi";
  691. info.apiVersion = required_version;
  692. Rml::Vector<const char*> instance_layer_names;
  693. Rml::Vector<const char*> instance_extension_names = std::move(required_extensions);
  694. CreatePropertiesFor_Instance(instance_layer_names, instance_extension_names);
  695. VkInstanceCreateInfo info_instance = {};
  696. info_instance.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  697. info_instance.pNext = &debug_validation_features_ext;
  698. info_instance.flags = 0;
  699. info_instance.pApplicationInfo = &info;
  700. info_instance.enabledExtensionCount = static_cast<uint32_t>(instance_extension_names.size());
  701. info_instance.ppEnabledExtensionNames = instance_extension_names.data();
  702. info_instance.enabledLayerCount = static_cast<uint32_t>(instance_layer_names.size());
  703. info_instance.ppEnabledLayerNames = instance_layer_names.data();
  704. VkResult status = vkCreateInstance(&info_instance, nullptr, &m_p_instance);
  705. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkCreateInstance");
  706. CreateReportDebugCallback();
  707. }
  708. void RenderInterface_VK::Initialize_Device() noexcept
  709. {
  710. ExtensionPropertiesList device_extension_properties;
  711. CreatePropertiesFor_Device(device_extension_properties);
  712. Rml::Vector<const char*> device_extension_names;
  713. AddExtensionToDevice(device_extension_names, device_extension_properties, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
  714. AddExtensionToDevice(device_extension_names, device_extension_properties, VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME);
  715. #ifdef RMLUI_DEBUG
  716. AddExtensionToDevice(device_extension_names, device_extension_properties, VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
  717. #endif
  718. float queue_priorities[1] = {0.0f};
  719. VkDeviceQueueCreateInfo info_queue[2] = {};
  720. info_queue[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  721. info_queue[0].pNext = nullptr;
  722. info_queue[0].queueCount = 1;
  723. info_queue[0].pQueuePriorities = queue_priorities;
  724. info_queue[0].queueFamilyIndex = m_queue_index_graphics;
  725. info_queue[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  726. info_queue[1].pNext = nullptr;
  727. info_queue[1].queueCount = 1;
  728. info_queue[1].pQueuePriorities = queue_priorities;
  729. info_queue[1].queueFamilyIndex = m_queue_index_compute;
  730. VkPhysicalDeviceFeatures features_physical_device = {};
  731. features_physical_device.fillModeNonSolid = true;
  732. features_physical_device.pipelineStatisticsQuery = true;
  733. features_physical_device.fragmentStoresAndAtomics = true;
  734. features_physical_device.vertexPipelineStoresAndAtomics = true;
  735. features_physical_device.shaderImageGatherExtended = true;
  736. features_physical_device.wideLines = true;
  737. VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR shader_subgroup_extended_type = {};
  738. shader_subgroup_extended_type.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR;
  739. shader_subgroup_extended_type.pNext = nullptr;
  740. shader_subgroup_extended_type.shaderSubgroupExtendedTypes = VK_TRUE;
  741. VkPhysicalDeviceFeatures2 features_physical_device2 = {};
  742. features_physical_device2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
  743. features_physical_device2.features = features_physical_device;
  744. features_physical_device2.pNext = &shader_subgroup_extended_type;
  745. VkDeviceCreateInfo info_device = {};
  746. info_device.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  747. info_device.pNext = &features_physical_device2;
  748. info_device.queueCreateInfoCount = m_queue_index_compute != m_queue_index_graphics ? 2 : 1;
  749. info_device.pQueueCreateInfos = info_queue;
  750. info_device.enabledExtensionCount = static_cast<uint32_t>(device_extension_names.size());
  751. info_device.ppEnabledExtensionNames = info_device.enabledExtensionCount ? device_extension_names.data() : nullptr;
  752. info_device.pEnabledFeatures = nullptr;
  753. VkResult status = vkCreateDevice(m_p_physical_device, &info_device, nullptr, &m_p_device);
  754. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkCreateDevice");
  755. }
  756. void RenderInterface_VK::Initialize_PhysicalDevice(VkPhysicalDeviceProperties& out_physical_device_properties) noexcept
  757. {
  758. PhysicalDeviceWrapperList physical_devices;
  759. CollectPhysicalDevices(physical_devices);
  760. const PhysicalDeviceWrapper* selected_physical_device =
  761. ChoosePhysicalDevice(physical_devices, VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
  762. if (!selected_physical_device)
  763. {
  764. Rml::Log::Message(Rml::Log::LT_WARNING, "Failed to pick the discrete gpu, now trying to pick integrated GPU");
  765. selected_physical_device = ChoosePhysicalDevice(physical_devices, VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
  766. if (!selected_physical_device)
  767. {
  768. Rml::Log::Message(Rml::Log::LT_WARNING, "Failed to pick the integrated gpu, now trying to pick the CPU");
  769. selected_physical_device = ChoosePhysicalDevice(physical_devices, VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_CPU);
  770. }
  771. }
  772. RMLUI_VK_ASSERTMSG(selected_physical_device, "there's no suitable physical device for rendering, abort this application");
  773. m_p_physical_device = selected_physical_device->m_p_physical_device;
  774. vkGetPhysicalDeviceProperties(m_p_physical_device, &out_physical_device_properties);
  775. #ifdef RMLUI_VK_DEBUG
  776. const auto& properties = selected_physical_device->m_physical_device_properties;
  777. Rml::Log::Message(Rml::Log::LT_DEBUG, "Picked physical device: %s", properties.deviceName);
  778. #endif
  779. }
  780. void RenderInterface_VK::Initialize_Swapchain(VkExtent2D window_extent) noexcept
  781. {
  782. m_swapchain_format = ChooseSwapchainFormat();
  783. VkSwapchainCreateInfoKHR info = {};
  784. info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  785. info.pNext = nullptr;
  786. info.surface = m_p_surface;
  787. info.imageFormat = m_swapchain_format.format;
  788. info.minImageCount = Choose_SwapchainImageCount();
  789. info.imageColorSpace = m_swapchain_format.colorSpace;
  790. info.imageExtent = window_extent;
  791. info.preTransform = CreatePretransformSwapchain();
  792. info.compositeAlpha = ChooseSwapchainCompositeAlpha();
  793. info.imageArrayLayers = 1;
  794. info.presentMode = GetPresentMode();
  795. info.oldSwapchain = nullptr;
  796. info.clipped = true;
  797. info.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  798. info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  799. info.queueFamilyIndexCount = 0;
  800. info.pQueueFamilyIndices = nullptr;
  801. uint32_t queue_family_index_present = m_queue_index_present;
  802. uint32_t queue_family_index_graphics = m_queue_index_graphics;
  803. if (queue_family_index_graphics != queue_family_index_present)
  804. {
  805. uint32_t p_indecies[2] = {queue_family_index_graphics, queue_family_index_present};
  806. info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
  807. info.queueFamilyIndexCount = sizeof(p_indecies) / sizeof(p_indecies[0]);
  808. info.pQueueFamilyIndices = p_indecies;
  809. }
  810. VkResult status = vkCreateSwapchainKHR(m_p_device, &info, nullptr, &m_p_swapchain);
  811. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkCreateSwapchainKHR");
  812. }
  813. void RenderInterface_VK::Initialize_Surface(CreateSurfaceCallback create_surface_callback) noexcept
  814. {
  815. RMLUI_VK_ASSERTMSG(m_p_instance, "you must initialize your VkInstance");
  816. bool result = create_surface_callback(m_p_instance, &m_p_surface);
  817. RMLUI_VK_ASSERTMSG(result && m_p_surface, "failed to call create_surface_callback");
  818. }
  819. void RenderInterface_VK::Initialize_QueueIndecies() noexcept
  820. {
  821. RMLUI_VK_ASSERTMSG(m_p_physical_device, "you must initialize your physical device");
  822. RMLUI_VK_ASSERTMSG(m_p_surface, "you must initialize VkSurfaceKHR before calling this method");
  823. uint32_t queue_family_count = 0;
  824. vkGetPhysicalDeviceQueueFamilyProperties(m_p_physical_device, &queue_family_count, nullptr);
  825. RMLUI_VK_ASSERTMSG(queue_family_count >= 1, "failed to vkGetPhysicalDeviceQueueFamilyProperties (getting count)");
  826. Rml::Vector<VkQueueFamilyProperties> queue_props;
  827. queue_props.resize(queue_family_count);
  828. vkGetPhysicalDeviceQueueFamilyProperties(m_p_physical_device, &queue_family_count, queue_props.data());
  829. RMLUI_VK_ASSERTMSG(queue_family_count >= 1, "failed to vkGetPhysicalDeviceQueueFamilyProperties (filling vector of VkQueueFamilyProperties)");
  830. constexpr uint32_t kUint32Undefined = uint32_t(-1);
  831. m_queue_index_compute = kUint32Undefined;
  832. m_queue_index_graphics = kUint32Undefined;
  833. m_queue_index_present = kUint32Undefined;
  834. for (uint32_t i = 0; i < queue_family_count; ++i)
  835. {
  836. if ((queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
  837. {
  838. if (m_queue_index_graphics == kUint32Undefined)
  839. m_queue_index_graphics = i;
  840. VkBool32 is_support_present;
  841. vkGetPhysicalDeviceSurfaceSupportKHR(m_p_physical_device, i, m_p_surface, &is_support_present);
  842. // User's videocard may have same index for two queues like graphics and present
  843. if (is_support_present == VK_TRUE)
  844. {
  845. m_queue_index_graphics = i;
  846. m_queue_index_present = m_queue_index_graphics;
  847. break;
  848. }
  849. }
  850. }
  851. if (m_queue_index_present == static_cast<uint32_t>(-1))
  852. {
  853. Rml::Log::Message(Rml::Log::LT_WARNING, "[Vulkan] User doesn't have one index for two queues, so we need to find for present queue index");
  854. for (uint32_t i = 0; i < queue_family_count; ++i)
  855. {
  856. VkBool32 is_support_present;
  857. vkGetPhysicalDeviceSurfaceSupportKHR(m_p_physical_device, i, m_p_surface, &is_support_present);
  858. if (is_support_present == VK_TRUE)
  859. {
  860. m_queue_index_present = i;
  861. break;
  862. }
  863. }
  864. }
  865. for (uint32_t i = 0; i < queue_family_count; ++i)
  866. {
  867. if ((queue_props[i].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)
  868. {
  869. if (m_queue_index_compute == kUint32Undefined)
  870. m_queue_index_compute = i;
  871. if (i != m_queue_index_graphics)
  872. {
  873. m_queue_index_compute = i;
  874. break;
  875. }
  876. }
  877. }
  878. #ifdef RMLUI_VK_DEBUG
  879. Rml::Log::Message(Rml::Log::LT_DEBUG, "[Vulkan] User family queues indecies: Graphics[%d] Present[%d] Compute[%d]", m_queue_index_graphics,
  880. m_queue_index_present, m_queue_index_compute);
  881. #endif
  882. }
  883. void RenderInterface_VK::Initialize_Queues() noexcept
  884. {
  885. RMLUI_VK_ASSERTMSG(m_p_device, "you must initialize VkDevice before using this method");
  886. vkGetDeviceQueue(m_p_device, m_queue_index_graphics, 0, &m_p_queue_graphics);
  887. if (m_queue_index_graphics == m_queue_index_present)
  888. {
  889. m_p_queue_present = m_p_queue_graphics;
  890. }
  891. else
  892. {
  893. vkGetDeviceQueue(m_p_device, m_queue_index_present, 0, &m_p_queue_present);
  894. }
  895. constexpr uint32_t kUint32Undefined = uint32_t(-1);
  896. if (m_queue_index_compute != kUint32Undefined)
  897. {
  898. vkGetDeviceQueue(m_p_device, m_queue_index_compute, 0, &m_p_queue_compute);
  899. }
  900. }
  901. void RenderInterface_VK::Initialize_SyncPrimitives() noexcept
  902. {
  903. RMLUI_VK_ASSERTMSG(m_p_device, "you must initialize your device");
  904. m_executed_fences.resize(kSwapchainBackBufferCount);
  905. m_semaphores_finished_render.resize(kSwapchainBackBufferCount);
  906. m_semaphores_image_available.resize(kSwapchainBackBufferCount);
  907. VkResult status = VK_SUCCESS;
  908. for (uint32_t i = 0; i < kSwapchainBackBufferCount; ++i)
  909. {
  910. VkFenceCreateInfo info_fence = {};
  911. info_fence.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
  912. info_fence.pNext = nullptr;
  913. info_fence.flags = VK_FENCE_CREATE_SIGNALED_BIT;
  914. status = vkCreateFence(m_p_device, &info_fence, nullptr, &m_executed_fences[i]);
  915. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkCreateFence");
  916. VkSemaphoreCreateInfo info_semaphore = {};
  917. info_semaphore.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
  918. info_semaphore.pNext = nullptr;
  919. info_semaphore.flags = 0;
  920. status = vkCreateSemaphore(m_p_device, &info_semaphore, nullptr, &m_semaphores_image_available[i]);
  921. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkCreateSemaphore");
  922. status = vkCreateSemaphore(m_p_device, &info_semaphore, nullptr, &m_semaphores_finished_render[i]);
  923. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkCreateSemaphore");
  924. }
  925. }
  926. void RenderInterface_VK::Initialize_Resources(const VkPhysicalDeviceProperties& physical_device_properties) noexcept
  927. {
  928. m_command_buffer_ring.Initialize(m_p_device, m_queue_index_graphics);
  929. const VkDeviceSize min_buffer_alignment = physical_device_properties.limits.minUniformBufferOffsetAlignment;
  930. m_memory_pool.Initialize(kVideoMemoryForAllocation, min_buffer_alignment, m_p_allocator, m_p_device);
  931. m_upload_manager.Initialize(m_p_device, m_p_queue_graphics, m_queue_index_graphics);
  932. m_manager_descriptors.Initialize(m_p_device, 100, 100, 10, 10);
  933. CreateShaders();
  934. CreateDescriptorSetLayout();
  935. CreatePipelineLayout();
  936. CreateSamplers();
  937. CreateDescriptorSets();
  938. }
  939. void RenderInterface_VK::Initialize_Allocator() noexcept
  940. {
  941. RMLUI_VK_ASSERTMSG(m_p_device, "you must have a valid VkDevice here");
  942. RMLUI_VK_ASSERTMSG(m_p_physical_device, "you must have a valid VkPhysicalDevice here");
  943. RMLUI_VK_ASSERTMSG(m_p_instance, "you must have a valid VkInstance here");
  944. VmaVulkanFunctions vulkanFunctions = {};
  945. vulkanFunctions.vkGetInstanceProcAddr = vkGetInstanceProcAddr;
  946. vulkanFunctions.vkGetDeviceProcAddr = vkGetDeviceProcAddr;
  947. VmaAllocatorCreateInfo info = {};
  948. info.vulkanApiVersion = RMLUI_VK_API_VERSION;
  949. info.device = m_p_device;
  950. info.instance = m_p_instance;
  951. info.physicalDevice = m_p_physical_device;
  952. info.pVulkanFunctions = &vulkanFunctions;
  953. auto status = vmaCreateAllocator(&info, &m_p_allocator);
  954. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vmaCreateAllocator");
  955. }
  956. void RenderInterface_VK::Destroy_Instance() noexcept
  957. {
  958. vkDestroyInstance(m_p_instance, nullptr);
  959. }
  960. void RenderInterface_VK::Destroy_Device() noexcept
  961. {
  962. vkDestroyDevice(m_p_device, nullptr);
  963. }
  964. void RenderInterface_VK::Destroy_Swapchain() noexcept
  965. {
  966. RMLUI_VK_ASSERTMSG(m_p_device, "you must initialize device");
  967. vkDestroySwapchainKHR(m_p_device, m_p_swapchain, nullptr);
  968. }
  969. void RenderInterface_VK::Destroy_Surface() noexcept
  970. {
  971. vkDestroySurfaceKHR(m_p_instance, m_p_surface, nullptr);
  972. }
  973. void RenderInterface_VK::Destroy_SyncPrimitives() noexcept
  974. {
  975. for (auto& p_fence : m_executed_fences)
  976. {
  977. vkDestroyFence(m_p_device, p_fence, nullptr);
  978. }
  979. for (auto& p_semaphore : m_semaphores_image_available)
  980. {
  981. vkDestroySemaphore(m_p_device, p_semaphore, nullptr);
  982. }
  983. for (auto& p_semaphore : m_semaphores_finished_render)
  984. {
  985. vkDestroySemaphore(m_p_device, p_semaphore, nullptr);
  986. }
  987. }
  988. void RenderInterface_VK::Destroy_Resources() noexcept
  989. {
  990. m_command_buffer_ring.Shutdown();
  991. m_upload_manager.Shutdown();
  992. if (m_p_descriptor_set)
  993. {
  994. m_manager_descriptors.Free_Descriptors(m_p_device, &m_p_descriptor_set);
  995. }
  996. vkDestroyDescriptorSetLayout(m_p_device, m_p_descriptor_set_layout_vertex_transform, nullptr);
  997. vkDestroyDescriptorSetLayout(m_p_device, m_p_descriptor_set_layout_texture, nullptr);
  998. vkDestroyPipelineLayout(m_p_device, m_p_pipeline_layout, nullptr);
  999. for (const auto& p_module : m_shaders)
  1000. {
  1001. vkDestroyShaderModule(m_p_device, p_module, nullptr);
  1002. }
  1003. DestroySamplers();
  1004. Destroy_Textures();
  1005. Destroy_Geometries();
  1006. m_manager_descriptors.Shutdown(m_p_device);
  1007. }
  1008. void RenderInterface_VK::Destroy_Allocator() noexcept
  1009. {
  1010. RMLUI_VK_ASSERTMSG(m_p_allocator, "you must have an initialized allocator for deleting");
  1011. vmaDestroyAllocator(m_p_allocator);
  1012. m_p_allocator = nullptr;
  1013. }
  1014. void RenderInterface_VK::QueryInstanceLayers(LayerPropertiesList& result) noexcept
  1015. {
  1016. uint32_t instance_layer_properties_count = 0;
  1017. VkResult status = vkEnumerateInstanceLayerProperties(&instance_layer_properties_count, nullptr);
  1018. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkEnumerateInstanceLayerProperties (getting count)");
  1019. if (instance_layer_properties_count)
  1020. {
  1021. result.resize(instance_layer_properties_count);
  1022. status = vkEnumerateInstanceLayerProperties(&instance_layer_properties_count, result.data());
  1023. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkEnumerateInstanceLayerProperties (filling vector of VkLayerProperties)");
  1024. }
  1025. }
  1026. void RenderInterface_VK::QueryInstanceExtensions(ExtensionPropertiesList& result, const LayerPropertiesList& instance_layer_properties) noexcept
  1027. {
  1028. uint32_t instance_extension_property_count = 0;
  1029. VkResult status = vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_property_count, nullptr);
  1030. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkEnumerateInstanceExtensionProperties (getting count)");
  1031. if (instance_extension_property_count)
  1032. {
  1033. result.resize(instance_extension_property_count);
  1034. status = vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_property_count, result.data());
  1035. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkEnumerateInstanceExtensionProperties (filling vector of VkExtensionProperties)");
  1036. }
  1037. uint32_t count = 0;
  1038. // without first argument in vkEnumerateInstanceExtensionProperties
  1039. // it doesn't collect information well so we need brute-force
  1040. // and pass through everything what use has
  1041. for (const auto& layer_property : instance_layer_properties)
  1042. {
  1043. status = vkEnumerateInstanceExtensionProperties(layer_property.layerName, &count, nullptr);
  1044. if (status == VK_SUCCESS)
  1045. {
  1046. if (count)
  1047. {
  1048. ExtensionPropertiesList props;
  1049. props.resize(count);
  1050. status = vkEnumerateInstanceExtensionProperties(layer_property.layerName, &count, props.data());
  1051. if (status == VK_SUCCESS)
  1052. {
  1053. #ifdef RMLUI_VK_DEBUG
  1054. Rml::Log::Message(Rml::Log::LT_DEBUG, "[Vulkan] obtained extensions for layer: %s, count: %zu", layer_property.layerName,
  1055. props.size());
  1056. #endif
  1057. for (const auto& extension : props)
  1058. {
  1059. if (IsExtensionPresent(result, extension.extensionName) == false)
  1060. {
  1061. #ifdef RMLUI_VK_DEBUG
  1062. Rml::Log::Message(Rml::Log::LT_DEBUG, "[Vulkan] new extension is added: %s", extension.extensionName);
  1063. #endif
  1064. result.push_back(extension);
  1065. }
  1066. }
  1067. }
  1068. }
  1069. }
  1070. }
  1071. }
  1072. bool RenderInterface_VK::AddLayerToInstance(Rml::Vector<const char*>& result, const LayerPropertiesList& instance_layer_properties,
  1073. const char* p_instance_layer_name) noexcept
  1074. {
  1075. if (p_instance_layer_name == nullptr)
  1076. {
  1077. RMLUI_VK_ASSERTMSG(p_instance_layer_name, "you have an invalid layer");
  1078. return false;
  1079. }
  1080. if (IsLayerPresent(instance_layer_properties, p_instance_layer_name))
  1081. {
  1082. result.push_back(p_instance_layer_name);
  1083. return true;
  1084. }
  1085. Rml::Log::Message(Rml::Log::LT_WARNING, "[Vulkan] can't add layer %s", p_instance_layer_name);
  1086. return false;
  1087. }
  1088. bool RenderInterface_VK::AddExtensionToInstance(Rml::Vector<const char*>& result, const ExtensionPropertiesList& instance_extension_properties,
  1089. const char* p_instance_extension_name) noexcept
  1090. {
  1091. if (p_instance_extension_name == nullptr)
  1092. {
  1093. RMLUI_VK_ASSERTMSG(p_instance_extension_name, "you have an invalid extension");
  1094. return false;
  1095. }
  1096. if (IsExtensionPresent(instance_extension_properties, p_instance_extension_name))
  1097. {
  1098. result.push_back(p_instance_extension_name);
  1099. return true;
  1100. }
  1101. Rml::Log::Message(Rml::Log::LT_WARNING, "[Vulkan] can't add extension %s", p_instance_extension_name);
  1102. return false;
  1103. }
  1104. void RenderInterface_VK::CreatePropertiesFor_Instance(Rml::Vector<const char*>& instance_layer_names,
  1105. Rml::Vector<const char*>& instance_extension_names) noexcept
  1106. {
  1107. ExtensionPropertiesList instance_extension_properties;
  1108. LayerPropertiesList instance_layer_properties;
  1109. QueryInstanceLayers(instance_layer_properties);
  1110. QueryInstanceExtensions(instance_extension_properties, instance_layer_properties);
  1111. AddExtensionToInstance(instance_extension_names, instance_extension_properties, "VK_EXT_debug_utils");
  1112. AddExtensionToInstance(instance_extension_names, instance_extension_properties, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
  1113. #ifdef RMLUI_VK_DEBUG
  1114. AddLayerToInstance(instance_layer_names, instance_layer_properties, "VK_LAYER_LUNARG_monitor");
  1115. bool is_cpu_validation = AddLayerToInstance(instance_layer_names, instance_layer_properties, "VK_LAYER_KHRONOS_validation") &&
  1116. AddExtensionToInstance(instance_extension_names, instance_extension_properties, VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
  1117. if (is_cpu_validation)
  1118. {
  1119. Rml::Log::Message(Rml::Log::LT_DEBUG, "[Vulkan] CPU validation is enabled");
  1120. Rml::Array<const char*, 1> requested_extensions_for_gpu = {VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME};
  1121. for (const auto& extension_name : requested_extensions_for_gpu)
  1122. {
  1123. AddExtensionToInstance(instance_extension_names, instance_extension_properties, extension_name);
  1124. }
  1125. debug_validation_features_ext.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
  1126. debug_validation_features_ext.pNext = nullptr;
  1127. debug_validation_features_ext.enabledValidationFeatureCount =
  1128. sizeof(debug_validation_features_ext_requested) / sizeof(debug_validation_features_ext_requested[0]);
  1129. debug_validation_features_ext.pEnabledValidationFeatures = debug_validation_features_ext_requested;
  1130. }
  1131. #else
  1132. (void)instance_layer_names;
  1133. #endif
  1134. }
  1135. bool RenderInterface_VK::IsLayerPresent(const LayerPropertiesList& properties, const char* p_layer_name) noexcept
  1136. {
  1137. if (properties.empty())
  1138. return false;
  1139. if (p_layer_name == nullptr)
  1140. return false;
  1141. return std::find_if(properties.cbegin(), properties.cend(),
  1142. [p_layer_name](const VkLayerProperties& prop) -> bool { return strcmp(prop.layerName, p_layer_name) == 0; }) != properties.cend();
  1143. }
  1144. bool RenderInterface_VK::IsExtensionPresent(const ExtensionPropertiesList& properties, const char* p_extension_name) noexcept
  1145. {
  1146. if (properties.empty())
  1147. return false;
  1148. if (p_extension_name == nullptr)
  1149. return false;
  1150. return std::find_if(properties.cbegin(), properties.cend(), [p_extension_name](const VkExtensionProperties& prop) -> bool {
  1151. return strcmp(prop.extensionName, p_extension_name) == 0;
  1152. }) != properties.cend();
  1153. }
  1154. bool RenderInterface_VK::AddExtensionToDevice(Rml::Vector<const char*>& result, const ExtensionPropertiesList& device_extension_properties,
  1155. const char* p_device_extension_name) noexcept
  1156. {
  1157. if (IsExtensionPresent(device_extension_properties, p_device_extension_name))
  1158. {
  1159. result.push_back(p_device_extension_name);
  1160. return true;
  1161. }
  1162. return false;
  1163. }
  1164. void RenderInterface_VK::CreatePropertiesFor_Device(ExtensionPropertiesList& result) noexcept
  1165. {
  1166. RMLUI_VK_ASSERTMSG(m_p_physical_device, "you must initialize your physical device. Call InitializePhysicalDevice first");
  1167. uint32_t extension_count = 0;
  1168. VkResult status = vkEnumerateDeviceExtensionProperties(m_p_physical_device, nullptr, &extension_count, nullptr);
  1169. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkEnumerateDeviceExtensionProperties (getting count)");
  1170. result.resize(extension_count);
  1171. status = vkEnumerateDeviceExtensionProperties(m_p_physical_device, nullptr, &extension_count, result.data());
  1172. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkEnumerateDeviceExtensionProperties (filling vector of VkExtensionProperties)");
  1173. uint32_t instance_layer_property_count = 0;
  1174. status = vkEnumerateInstanceLayerProperties(&instance_layer_property_count, nullptr);
  1175. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkEnumerateInstanceLayerProperties (getting count)");
  1176. LayerPropertiesList layers;
  1177. layers.resize(instance_layer_property_count);
  1178. // On different OS Vulkan acts strange, so we can't get our extensions to just iterate through default functions
  1179. // We need to deeply analyze our layers and get specified extensions which pass user
  1180. // So we collect all extensions that are presented in physical device
  1181. // And add when they exist to extension_names so we don't pass properties
  1182. if (instance_layer_property_count)
  1183. {
  1184. status = vkEnumerateInstanceLayerProperties(&instance_layer_property_count, layers.data());
  1185. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkEnumerateInstanceLayerProperties (filling vector of VkLayerProperties)");
  1186. for (const auto& layer : layers)
  1187. {
  1188. extension_count = 0;
  1189. status = vkEnumerateDeviceExtensionProperties(m_p_physical_device, layer.layerName, &extension_count, nullptr);
  1190. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkEnumerateDeviceExtensionProperties (getting count)");
  1191. if (extension_count)
  1192. {
  1193. ExtensionPropertiesList new_extensions;
  1194. new_extensions.resize(extension_count);
  1195. status = vkEnumerateDeviceExtensionProperties(m_p_physical_device, layer.layerName, &extension_count, new_extensions.data());
  1196. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkEnumerateDeviceExtensionProperties (filling vector of VkExtensionProperties)");
  1197. for (const auto& extension : new_extensions)
  1198. {
  1199. if (IsExtensionPresent(result, extension.extensionName) == false)
  1200. {
  1201. #ifdef RMLUI_VK_DEBUG
  1202. Rml::Log::Message(Rml::Log::LT_DEBUG, "[Vulkan] obtained new device extension from layer[%s]: %s", layer.layerName,
  1203. extension.extensionName);
  1204. #endif
  1205. result.push_back(extension);
  1206. }
  1207. }
  1208. }
  1209. }
  1210. }
  1211. }
  1212. void RenderInterface_VK::CreateReportDebugCallback() noexcept
  1213. {
  1214. #ifdef RMLUI_VK_DEBUG
  1215. VkDebugUtilsMessengerCreateInfoEXT info = {};
  1216. info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
  1217. info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
  1218. VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
  1219. info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
  1220. VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
  1221. info.pfnUserCallback = MyDebugReportCallback;
  1222. PFN_vkCreateDebugUtilsMessengerEXT p_callback_creation = VK_NULL_HANDLE;
  1223. p_callback_creation = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>(vkGetInstanceProcAddr(m_p_instance, "vkCreateDebugUtilsMessengerEXT"));
  1224. VkResult status = p_callback_creation(m_p_instance, &info, nullptr, &m_debug_messenger);
  1225. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkCreateDebugUtilsMessengerEXT");
  1226. #endif
  1227. }
  1228. void RenderInterface_VK::Destroy_ReportDebugCallback() noexcept
  1229. {
  1230. #ifdef RMLUI_VK_DEBUG
  1231. PFN_vkDestroyDebugUtilsMessengerEXT p_destroy_callback =
  1232. reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT>(vkGetInstanceProcAddr(m_p_instance, "vkDestroyDebugUtilsMessengerEXT"));
  1233. if (m_debug_messenger)
  1234. {
  1235. p_destroy_callback(m_p_instance, m_debug_messenger, nullptr);
  1236. m_debug_messenger = VK_NULL_HANDLE;
  1237. }
  1238. #endif
  1239. }
  1240. uint32_t RenderInterface_VK::GetUserAPIVersion() const noexcept
  1241. {
  1242. uint32_t result = RMLUI_VK_API_VERSION;
  1243. #if defined VK_VERSION_1_1
  1244. VkResult status = vkEnumerateInstanceVersion(&result);
  1245. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkEnumerateInstanceVersion, See Status");
  1246. #endif
  1247. return result;
  1248. }
  1249. uint32_t RenderInterface_VK::GetRequiredVersionAndValidateMachine() noexcept
  1250. {
  1251. constexpr uint32_t kRequiredVersion = RMLUI_VK_API_VERSION;
  1252. const uint32_t user_version = GetUserAPIVersion();
  1253. RMLUI_VK_ASSERTMSG(kRequiredVersion <= user_version, "Your machine doesn't support Vulkan");
  1254. return kRequiredVersion;
  1255. }
  1256. void RenderInterface_VK::CollectPhysicalDevices(PhysicalDeviceWrapperList& out_physical_devices) noexcept
  1257. {
  1258. uint32_t gpu_count = 1;
  1259. Rml::Vector<VkPhysicalDevice> temp_devices;
  1260. VkResult status = vkEnumeratePhysicalDevices(m_p_instance, &gpu_count, nullptr);
  1261. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkEnumeratePhysicalDevices (getting count)");
  1262. temp_devices.resize(gpu_count);
  1263. status = vkEnumeratePhysicalDevices(m_p_instance, &gpu_count, temp_devices.data());
  1264. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkEnumeratePhysicalDevices (filling the vector of VkPhysicalDevice)");
  1265. RMLUI_VK_ASSERTMSG(temp_devices.empty() == false, "you must have one videocard at least!");
  1266. out_physical_devices.resize(temp_devices.size());
  1267. for (size_t i = 0; i < out_physical_devices.size(); i++)
  1268. {
  1269. out_physical_devices[i].m_p_physical_device = temp_devices[i];
  1270. vkGetPhysicalDeviceProperties(out_physical_devices[i].m_p_physical_device, &out_physical_devices[i].m_physical_device_properties);
  1271. }
  1272. }
  1273. const RenderInterface_VK::PhysicalDeviceWrapper* RenderInterface_VK::ChoosePhysicalDevice(const PhysicalDeviceWrapperList& physical_devices,
  1274. VkPhysicalDeviceType device_type) noexcept
  1275. {
  1276. RMLUI_VK_ASSERTMSG(physical_devices.empty() == false,
  1277. "you must have one videocard at least or early calling of this method, try call this after CollectPhysicalDevices");
  1278. for (const auto& device : physical_devices)
  1279. {
  1280. if (device.m_physical_device_properties.deviceType == device_type)
  1281. return &device;
  1282. }
  1283. return nullptr;
  1284. }
  1285. VkSurfaceFormatKHR RenderInterface_VK::ChooseSwapchainFormat() noexcept
  1286. {
  1287. static constexpr VkFormat UNORM_FORMATS[] = {
  1288. VK_FORMAT_R4G4_UNORM_PACK8,
  1289. VK_FORMAT_R4G4B4A4_UNORM_PACK16,
  1290. VK_FORMAT_B4G4R4A4_UNORM_PACK16,
  1291. VK_FORMAT_R5G6B5_UNORM_PACK16,
  1292. VK_FORMAT_B5G6R5_UNORM_PACK16,
  1293. VK_FORMAT_R5G5B5A1_UNORM_PACK16,
  1294. VK_FORMAT_B5G5R5A1_UNORM_PACK16,
  1295. VK_FORMAT_A1R5G5B5_UNORM_PACK16,
  1296. VK_FORMAT_R8_UNORM,
  1297. VK_FORMAT_R8G8_UNORM,
  1298. VK_FORMAT_R8G8B8_UNORM,
  1299. VK_FORMAT_B8G8R8_UNORM,
  1300. VK_FORMAT_R8G8B8A8_UNORM,
  1301. VK_FORMAT_B8G8R8A8_UNORM,
  1302. VK_FORMAT_A8B8G8R8_UNORM_PACK32,
  1303. VK_FORMAT_A2R10G10B10_UNORM_PACK32,
  1304. VK_FORMAT_A2B10G10R10_UNORM_PACK32,
  1305. VK_FORMAT_R16_UNORM,
  1306. VK_FORMAT_R16G16_UNORM,
  1307. VK_FORMAT_R16G16B16_UNORM,
  1308. VK_FORMAT_R16G16B16A16_UNORM,
  1309. VK_FORMAT_D16_UNORM,
  1310. VK_FORMAT_X8_D24_UNORM_PACK32,
  1311. VK_FORMAT_D16_UNORM_S8_UINT,
  1312. VK_FORMAT_D24_UNORM_S8_UINT,
  1313. VK_FORMAT_BC1_RGB_UNORM_BLOCK,
  1314. VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
  1315. VK_FORMAT_BC2_UNORM_BLOCK,
  1316. VK_FORMAT_BC3_UNORM_BLOCK,
  1317. VK_FORMAT_BC4_UNORM_BLOCK,
  1318. VK_FORMAT_BC5_UNORM_BLOCK,
  1319. VK_FORMAT_BC7_UNORM_BLOCK,
  1320. VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
  1321. VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
  1322. VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
  1323. VK_FORMAT_EAC_R11_UNORM_BLOCK,
  1324. VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
  1325. VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
  1326. VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
  1327. VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
  1328. VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
  1329. VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
  1330. VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
  1331. VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
  1332. VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
  1333. VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
  1334. VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
  1335. VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
  1336. VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
  1337. VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
  1338. VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
  1339. };
  1340. RMLUI_VK_ASSERTMSG(m_p_physical_device, "you must initialize your physical device, before calling this method");
  1341. RMLUI_VK_ASSERTMSG(m_p_surface, "you must initialize your surface, before calling this method");
  1342. uint32_t surface_count = 0;
  1343. VkResult status = vkGetPhysicalDeviceSurfaceFormatsKHR(m_p_physical_device, m_p_surface, &surface_count, nullptr);
  1344. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkGetPhysicalDeviceSurfaceFormatsKHR (getting count)");
  1345. Rml::Vector<VkSurfaceFormatKHR> formats(surface_count);
  1346. status = vkGetPhysicalDeviceSurfaceFormatsKHR(m_p_physical_device, m_p_surface, &surface_count, formats.data());
  1347. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkGetPhysicalDeviceSurfaceFormatsKHR (filling vector of VkSurfaceFormatKHR)");
  1348. // Prefer UNORM formats
  1349. for (auto& format : formats)
  1350. {
  1351. for (auto ufmt : UNORM_FORMATS)
  1352. {
  1353. if (ufmt == format.format)
  1354. return format;
  1355. }
  1356. }
  1357. return formats.front();
  1358. }
  1359. VkExtent2D RenderInterface_VK::GetValidSurfaceExtent() noexcept
  1360. {
  1361. VkSurfaceCapabilitiesKHR caps = GetSurfaceCapabilities();
  1362. VkExtent2D result = {(uint32_t)m_width, (uint32_t)m_height};
  1363. /*
  1364. https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkSurfaceCapabilitiesKHR.html
  1365. */
  1366. if (caps.currentExtent.width == 0xFFFFFFFF)
  1367. {
  1368. result.width = Rml::Math::Clamp(result.width, caps.minImageExtent.width, caps.maxImageExtent.width);
  1369. result.height = Rml::Math::Clamp(result.height, caps.minImageExtent.height, caps.maxImageExtent.height);
  1370. }
  1371. else
  1372. {
  1373. result = caps.currentExtent;
  1374. }
  1375. return result;
  1376. }
  1377. VkSurfaceTransformFlagBitsKHR RenderInterface_VK::CreatePretransformSwapchain() noexcept
  1378. {
  1379. auto caps = GetSurfaceCapabilities();
  1380. VkSurfaceTransformFlagBitsKHR result =
  1381. (caps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : caps.currentTransform;
  1382. return result;
  1383. }
  1384. VkCompositeAlphaFlagBitsKHR RenderInterface_VK::ChooseSwapchainCompositeAlpha() noexcept
  1385. {
  1386. auto caps = GetSurfaceCapabilities();
  1387. VkCompositeAlphaFlagBitsKHR result = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
  1388. VkCompositeAlphaFlagBitsKHR composite_alpha_flags[4] = {VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
  1389. VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR};
  1390. for (uint32_t i = 0; i < sizeof(composite_alpha_flags); ++i)
  1391. {
  1392. if (caps.supportedCompositeAlpha & composite_alpha_flags[i])
  1393. {
  1394. result = composite_alpha_flags[i];
  1395. break;
  1396. }
  1397. }
  1398. return result;
  1399. }
  1400. int RenderInterface_VK::Choose_SwapchainImageCount(uint32_t user_swapchain_count_for_creation, bool if_failed_choose_min) noexcept
  1401. {
  1402. auto caps = GetSurfaceCapabilities();
  1403. // don't worry if you get this assert just ignore it the method will fix the count ;)
  1404. RMLUI_VK_ASSERTMSG(user_swapchain_count_for_creation >= caps.minImageCount,
  1405. "can't be, you must have a valid count that bounds from minImageCount to maxImageCount! Otherwise you will get a validation error that "
  1406. "specifies that you created a swapchain with invalid image count");
  1407. RMLUI_VK_ASSERTMSG(user_swapchain_count_for_creation <= caps.maxImageCount,
  1408. "can't be, you must have a valid count that bounds from minImageCount to maxImageCount! Otherwise you will get a validation error that "
  1409. "specifies that you created a swapchain with invalid image count");
  1410. int result = 0;
  1411. if (user_swapchain_count_for_creation < caps.minImageCount || user_swapchain_count_for_creation > caps.maxImageCount)
  1412. result = if_failed_choose_min ? caps.minImageCount : caps.maxImageCount;
  1413. else
  1414. result = user_swapchain_count_for_creation;
  1415. return result;
  1416. }
  1417. // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkPresentModeKHR.html
  1418. // VK_PRESENT_MODE_FIFO_KHR system must support this mode at least so by default we want to use it otherwise user can specify his mode
  1419. VkPresentModeKHR RenderInterface_VK::GetPresentMode(VkPresentModeKHR required) noexcept
  1420. {
  1421. RMLUI_VK_ASSERTMSG(m_p_device, "[Vulkan] you must initialize your device, before calling this method");
  1422. RMLUI_VK_ASSERTMSG(m_p_physical_device, "[Vulkan] you must initialize your physical device, before calling this method");
  1423. RMLUI_VK_ASSERTMSG(m_p_surface, "[Vulkan] you must initialize your surface, before calling this method");
  1424. VkPresentModeKHR result = required;
  1425. uint32_t present_modes_count = 0;
  1426. VkResult status = vkGetPhysicalDeviceSurfacePresentModesKHR(m_p_physical_device, m_p_surface, &present_modes_count, nullptr);
  1427. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "[Vulkan] failed to vkGetPhysicalDeviceSurfacePresentModesKHR (getting count)");
  1428. Rml::Vector<VkPresentModeKHR> present_modes(present_modes_count);
  1429. status = vkGetPhysicalDeviceSurfacePresentModesKHR(m_p_physical_device, m_p_surface, &present_modes_count, present_modes.data());
  1430. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "[Vulkan] failed to vkGetPhysicalDeviceSurfacePresentModesKHR (filling vector of VkPresentModeKHR)");
  1431. for (const auto& mode : present_modes)
  1432. {
  1433. if (mode == required)
  1434. return result;
  1435. }
  1436. Rml::Log::Message(Rml::Log::LT_WARNING,
  1437. "[Vulkan] WARNING system can't detect your type of present mode so we choose the first from vector front");
  1438. return present_modes.front();
  1439. }
  1440. VkSurfaceCapabilitiesKHR RenderInterface_VK::GetSurfaceCapabilities() noexcept
  1441. {
  1442. RMLUI_VK_ASSERTMSG(m_p_device, "[Vulkan] you must initialize your device, before calling this method");
  1443. RMLUI_VK_ASSERTMSG(m_p_physical_device, "[Vulkan] you must initialize your physical device, before calling this method");
  1444. RMLUI_VK_ASSERTMSG(m_p_surface, "[Vulkan] you must initialize your surface, before calling this method");
  1445. VkSurfaceCapabilitiesKHR result;
  1446. VkResult status = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_p_physical_device, m_p_surface, &result);
  1447. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "[Vulkan] failed to vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
  1448. return result;
  1449. }
  1450. void RenderInterface_VK::CreateShaders() noexcept
  1451. {
  1452. RMLUI_VK_ASSERTMSG(m_p_device, "[Vulkan] you must initialize VkDevice before calling this method");
  1453. struct shader_data_t {
  1454. const uint32_t* m_data;
  1455. size_t m_data_size;
  1456. VkShaderStageFlagBits m_shader_type;
  1457. };
  1458. const Rml::Vector<shader_data_t> shaders = {
  1459. {reinterpret_cast<const uint32_t*>(shader_vert), sizeof(shader_vert), VK_SHADER_STAGE_VERTEX_BIT},
  1460. {reinterpret_cast<const uint32_t*>(shader_frag_color), sizeof(shader_frag_color), VK_SHADER_STAGE_FRAGMENT_BIT},
  1461. {reinterpret_cast<const uint32_t*>(shader_frag_texture), sizeof(shader_frag_texture), VK_SHADER_STAGE_FRAGMENT_BIT},
  1462. };
  1463. for (const shader_data_t& shader_data : shaders)
  1464. {
  1465. VkShaderModuleCreateInfo info = {};
  1466. info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  1467. info.pCode = shader_data.m_data;
  1468. info.codeSize = shader_data.m_data_size;
  1469. VkShaderModule p_module = nullptr;
  1470. VkResult status = vkCreateShaderModule(m_p_device, &info, nullptr, &p_module);
  1471. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "[Vulkan] failed to vkCreateShaderModule");
  1472. m_shaders.push_back(p_module);
  1473. }
  1474. }
  1475. void RenderInterface_VK::CreateDescriptorSetLayout() noexcept
  1476. {
  1477. RMLUI_VK_ASSERTMSG(m_p_device, "[Vulkan] you must initialize VkDevice before calling this method");
  1478. RMLUI_VK_ASSERTMSG(!m_p_descriptor_set_layout_vertex_transform && !m_p_descriptor_set_layout_texture, "[Vulkan] Already initialized");
  1479. {
  1480. VkDescriptorSetLayoutBinding binding_for_vertex_transform = {};
  1481. binding_for_vertex_transform.binding = 1;
  1482. binding_for_vertex_transform.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
  1483. binding_for_vertex_transform.descriptorCount = 1;
  1484. binding_for_vertex_transform.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
  1485. VkDescriptorSetLayoutCreateInfo info = {};
  1486. info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  1487. info.pBindings = &binding_for_vertex_transform;
  1488. info.bindingCount = 1;
  1489. VkResult status = vkCreateDescriptorSetLayout(m_p_device, &info, nullptr, &m_p_descriptor_set_layout_vertex_transform);
  1490. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "[Vulkan] failed to vkCreateDescriptorSetLayout");
  1491. }
  1492. {
  1493. VkDescriptorSetLayoutBinding binding_for_fragment_texture = {};
  1494. binding_for_fragment_texture.binding = 2;
  1495. binding_for_fragment_texture.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  1496. binding_for_fragment_texture.descriptorCount = 1;
  1497. binding_for_fragment_texture.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  1498. VkDescriptorSetLayoutCreateInfo info = {};
  1499. info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  1500. info.pBindings = &binding_for_fragment_texture;
  1501. info.bindingCount = 1;
  1502. VkResult status = vkCreateDescriptorSetLayout(m_p_device, &info, nullptr, &m_p_descriptor_set_layout_texture);
  1503. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "[Vulkan] failed to vkCreateDescriptorSetLayout");
  1504. }
  1505. }
  1506. void RenderInterface_VK::CreatePipelineLayout() noexcept
  1507. {
  1508. RMLUI_VK_ASSERTMSG(m_p_descriptor_set_layout_vertex_transform, "[Vulkan] You must initialize VkDescriptorSetLayout before calling this method");
  1509. RMLUI_VK_ASSERTMSG(m_p_descriptor_set_layout_texture,
  1510. "[Vulkan] you must initialize VkDescriptorSetLayout for textures before calling this method!");
  1511. RMLUI_VK_ASSERTMSG(m_p_device, "[Vulkan] you must initialize VkDevice before calling this method");
  1512. VkDescriptorSetLayout p_layouts[] = {m_p_descriptor_set_layout_vertex_transform, m_p_descriptor_set_layout_texture};
  1513. VkPipelineLayoutCreateInfo info = {};
  1514. info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
  1515. info.pNext = nullptr;
  1516. info.pSetLayouts = p_layouts;
  1517. info.setLayoutCount = 2;
  1518. auto status = vkCreatePipelineLayout(m_p_device, &info, nullptr, &m_p_pipeline_layout);
  1519. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "[Vulkan] failed to vkCreatePipelineLayout");
  1520. }
  1521. void RenderInterface_VK::CreateDescriptorSets() noexcept
  1522. {
  1523. RMLUI_VK_ASSERTMSG(m_p_device, "[Vulkan] you have to initialize your VkDevice before calling this method");
  1524. RMLUI_VK_ASSERTMSG(m_p_descriptor_set_layout_vertex_transform,
  1525. "[Vulkan] you have to initialize your VkDescriptorSetLayout before calling this method");
  1526. m_manager_descriptors.Alloc_Descriptor(m_p_device, &m_p_descriptor_set_layout_vertex_transform, &m_p_descriptor_set);
  1527. m_memory_pool.SetDescriptorSet(1, sizeof(shader_vertex_user_data_t), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, m_p_descriptor_set);
  1528. }
  1529. void RenderInterface_VK::CreateSamplers() noexcept
  1530. {
  1531. VkSamplerCreateInfo info = {};
  1532. info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
  1533. info.pNext = nullptr;
  1534. info.magFilter = VK_FILTER_LINEAR;
  1535. info.minFilter = VK_FILTER_LINEAR;
  1536. info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  1537. info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  1538. info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  1539. vkCreateSampler(m_p_device, &info, nullptr, &m_p_sampler_linear);
  1540. }
  1541. void RenderInterface_VK::Create_Pipelines() noexcept
  1542. {
  1543. RMLUI_VK_ASSERTMSG(m_p_pipeline_layout, "must be initialized");
  1544. RMLUI_VK_ASSERTMSG(m_p_render_pass, "must be initialized");
  1545. VkPipelineInputAssemblyStateCreateInfo info_assembly_state = {};
  1546. info_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
  1547. info_assembly_state.pNext = nullptr;
  1548. info_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
  1549. info_assembly_state.primitiveRestartEnable = VK_FALSE;
  1550. info_assembly_state.flags = 0;
  1551. VkPipelineRasterizationStateCreateInfo info_raster_state = {};
  1552. info_raster_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
  1553. info_raster_state.pNext = nullptr;
  1554. info_raster_state.polygonMode = VK_POLYGON_MODE_FILL;
  1555. info_raster_state.cullMode = VK_CULL_MODE_NONE;
  1556. info_raster_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
  1557. info_raster_state.rasterizerDiscardEnable = VK_FALSE;
  1558. info_raster_state.depthBiasEnable = VK_FALSE;
  1559. info_raster_state.lineWidth = 1.0f;
  1560. VkPipelineColorBlendAttachmentState info_color_blend_att = {};
  1561. info_color_blend_att.colorWriteMask = 0xf;
  1562. info_color_blend_att.blendEnable = VK_TRUE;
  1563. info_color_blend_att.srcColorBlendFactor = VkBlendFactor::VK_BLEND_FACTOR_ONE;
  1564. info_color_blend_att.dstColorBlendFactor = VkBlendFactor::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
  1565. info_color_blend_att.colorBlendOp = VkBlendOp::VK_BLEND_OP_ADD;
  1566. info_color_blend_att.srcAlphaBlendFactor = VkBlendFactor::VK_BLEND_FACTOR_ONE;
  1567. info_color_blend_att.dstAlphaBlendFactor = VkBlendFactor::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
  1568. info_color_blend_att.alphaBlendOp = VkBlendOp::VK_BLEND_OP_SUBTRACT;
  1569. VkPipelineColorBlendStateCreateInfo info_color_blend_state = {};
  1570. info_color_blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  1571. info_color_blend_state.pNext = nullptr;
  1572. info_color_blend_state.attachmentCount = 1;
  1573. info_color_blend_state.pAttachments = &info_color_blend_att;
  1574. VkPipelineDepthStencilStateCreateInfo info_depth = {};
  1575. info_depth.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
  1576. info_depth.pNext = nullptr;
  1577. info_depth.depthTestEnable = VK_FALSE;
  1578. info_depth.depthWriteEnable = VK_TRUE;
  1579. info_depth.depthBoundsTestEnable = VK_FALSE;
  1580. info_depth.maxDepthBounds = 1.0f;
  1581. info_depth.depthCompareOp = VK_COMPARE_OP_ALWAYS;
  1582. info_depth.stencilTestEnable = VK_TRUE;
  1583. info_depth.back.compareOp = VK_COMPARE_OP_ALWAYS;
  1584. info_depth.back.failOp = VK_STENCIL_OP_KEEP;
  1585. info_depth.back.depthFailOp = VK_STENCIL_OP_KEEP;
  1586. info_depth.back.passOp = VK_STENCIL_OP_KEEP;
  1587. info_depth.back.compareMask = 1;
  1588. info_depth.back.writeMask = 1;
  1589. info_depth.back.reference = 1;
  1590. info_depth.front = info_depth.back;
  1591. VkPipelineViewportStateCreateInfo info_viewport = {};
  1592. info_viewport.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
  1593. info_viewport.pNext = nullptr;
  1594. info_viewport.viewportCount = 1;
  1595. info_viewport.scissorCount = 1;
  1596. info_viewport.flags = 0;
  1597. VkPipelineMultisampleStateCreateInfo info_multisample = {};
  1598. info_multisample.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
  1599. info_multisample.pNext = nullptr;
  1600. info_multisample.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
  1601. info_multisample.flags = 0;
  1602. Rml::Array<VkDynamicState, 2> dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
  1603. VkPipelineDynamicStateCreateInfo info_dynamic_state = {};
  1604. info_dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
  1605. info_dynamic_state.pNext = nullptr;
  1606. info_dynamic_state.pDynamicStates = dynamicStateEnables.data();
  1607. info_dynamic_state.dynamicStateCount = static_cast<uint32_t>(dynamicStateEnables.size());
  1608. info_dynamic_state.flags = 0;
  1609. Rml::Array<VkPipelineShaderStageCreateInfo, 2> shaders_that_will_be_used_in_pipeline;
  1610. VkPipelineShaderStageCreateInfo info_shader = {};
  1611. info_shader.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  1612. info_shader.pNext = nullptr;
  1613. info_shader.pName = "main";
  1614. info_shader.stage = VK_SHADER_STAGE_VERTEX_BIT;
  1615. info_shader.module = m_shaders[static_cast<int>(shader_id_t::Vertex)];
  1616. shaders_that_will_be_used_in_pipeline[0] = info_shader;
  1617. info_shader.module = m_shaders[static_cast<int>(shader_id_t::Fragment_WithTextures)];
  1618. info_shader.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
  1619. shaders_that_will_be_used_in_pipeline[1] = info_shader;
  1620. VkPipelineVertexInputStateCreateInfo info_vertex = {};
  1621. info_vertex.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
  1622. info_vertex.pNext = nullptr;
  1623. info_vertex.flags = 0;
  1624. Rml::Array<VkVertexInputAttributeDescription, 3> info_shader_vertex_attributes;
  1625. // describe info about our vertex and what is used in vertex shader as "layout(location = X) in"
  1626. VkVertexInputBindingDescription info_vertex_input_binding = {};
  1627. info_vertex_input_binding.binding = 0;
  1628. info_vertex_input_binding.stride = sizeof(Rml::Vertex);
  1629. info_vertex_input_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
  1630. info_shader_vertex_attributes[0].binding = 0;
  1631. info_shader_vertex_attributes[0].location = 0;
  1632. info_shader_vertex_attributes[0].format = VK_FORMAT_R32G32_SFLOAT;
  1633. info_shader_vertex_attributes[0].offset = offsetof(Rml::Vertex, position);
  1634. info_shader_vertex_attributes[1].binding = 0;
  1635. info_shader_vertex_attributes[1].location = 1;
  1636. info_shader_vertex_attributes[1].format = VK_FORMAT_R8G8B8A8_UNORM;
  1637. info_shader_vertex_attributes[1].offset = offsetof(Rml::Vertex, colour);
  1638. info_shader_vertex_attributes[2].binding = 0;
  1639. info_shader_vertex_attributes[2].location = 2;
  1640. info_shader_vertex_attributes[2].format = VK_FORMAT_R32G32_SFLOAT;
  1641. info_shader_vertex_attributes[2].offset = offsetof(Rml::Vertex, tex_coord);
  1642. info_vertex.pVertexAttributeDescriptions = info_shader_vertex_attributes.data();
  1643. info_vertex.vertexAttributeDescriptionCount = static_cast<uint32_t>(info_shader_vertex_attributes.size());
  1644. info_vertex.pVertexBindingDescriptions = &info_vertex_input_binding;
  1645. info_vertex.vertexBindingDescriptionCount = 1;
  1646. VkGraphicsPipelineCreateInfo info = {};
  1647. info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
  1648. info.pNext = nullptr;
  1649. info.pInputAssemblyState = &info_assembly_state;
  1650. info.pRasterizationState = &info_raster_state;
  1651. info.pColorBlendState = &info_color_blend_state;
  1652. info.pMultisampleState = &info_multisample;
  1653. info.pViewportState = &info_viewport;
  1654. info.pDepthStencilState = &info_depth;
  1655. info.pDynamicState = &info_dynamic_state;
  1656. info.stageCount = static_cast<uint32_t>(shaders_that_will_be_used_in_pipeline.size());
  1657. info.pStages = shaders_that_will_be_used_in_pipeline.data();
  1658. info.pVertexInputState = &info_vertex;
  1659. info.layout = m_p_pipeline_layout;
  1660. info.renderPass = m_p_render_pass;
  1661. info.subpass = 0;
  1662. auto status = vkCreateGraphicsPipelines(m_p_device, nullptr, 1, &info, nullptr, &m_p_pipeline_with_textures);
  1663. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkCreateGraphicsPipelines");
  1664. info_depth.back.passOp = VK_STENCIL_OP_KEEP;
  1665. info_depth.back.failOp = VK_STENCIL_OP_KEEP;
  1666. info_depth.back.depthFailOp = VK_STENCIL_OP_KEEP;
  1667. info_depth.back.compareOp = VK_COMPARE_OP_EQUAL;
  1668. info_depth.back.compareMask = 1;
  1669. info_depth.back.writeMask = 1;
  1670. info_depth.back.reference = 1;
  1671. info_depth.front = info_depth.back;
  1672. status = vkCreateGraphicsPipelines(m_p_device, nullptr, 1, &info, nullptr,
  1673. &m_p_pipeline_stencil_for_regular_geometry_that_applied_to_region_with_textures);
  1674. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkCreateGraphicsPipelines");
  1675. info_shader.module = m_shaders[static_cast<int>(shader_id_t::Fragment_WithoutTextures)];
  1676. shaders_that_will_be_used_in_pipeline[1] = info_shader;
  1677. info_depth.back.compareOp = VK_COMPARE_OP_ALWAYS;
  1678. info_depth.back.failOp = VK_STENCIL_OP_KEEP;
  1679. info_depth.back.depthFailOp = VK_STENCIL_OP_KEEP;
  1680. info_depth.back.passOp = VK_STENCIL_OP_KEEP;
  1681. info_depth.back.compareMask = 1;
  1682. info_depth.back.writeMask = 1;
  1683. info_depth.back.reference = 1;
  1684. info_depth.front = info_depth.back;
  1685. status = vkCreateGraphicsPipelines(m_p_device, nullptr, 1, &info, nullptr, &m_p_pipeline_without_textures);
  1686. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkCreateGraphicsPipelines");
  1687. info_depth.back.passOp = VK_STENCIL_OP_KEEP;
  1688. info_depth.back.failOp = VK_STENCIL_OP_KEEP;
  1689. info_depth.back.depthFailOp = VK_STENCIL_OP_KEEP;
  1690. info_depth.back.compareOp = VK_COMPARE_OP_EQUAL;
  1691. info_depth.back.compareMask = 1;
  1692. info_depth.back.writeMask = 1;
  1693. info_depth.back.reference = 1;
  1694. info_depth.front = info_depth.back;
  1695. status = vkCreateGraphicsPipelines(m_p_device, nullptr, 1, &info, nullptr,
  1696. &m_p_pipeline_stencil_for_regular_geometry_that_applied_to_region_without_textures);
  1697. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkCreateGraphicsPipelines");
  1698. info_color_blend_att.colorWriteMask = 0x0;
  1699. info_depth.back.passOp = VK_STENCIL_OP_REPLACE;
  1700. info_depth.back.failOp = VK_STENCIL_OP_KEEP;
  1701. info_depth.back.depthFailOp = VK_STENCIL_OP_KEEP;
  1702. info_depth.back.compareOp = VK_COMPARE_OP_ALWAYS;
  1703. info_depth.back.compareMask = 1;
  1704. info_depth.back.writeMask = 1;
  1705. info_depth.back.reference = 1;
  1706. info_depth.front = info_depth.back;
  1707. status = vkCreateGraphicsPipelines(m_p_device, nullptr, 1, &info, nullptr, &m_p_pipeline_stencil_for_region_where_geometry_will_be_drawn);
  1708. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkCreateGraphicsPipelines");
  1709. #ifdef RMLUI_DEBUG
  1710. VkDebugUtilsObjectNameInfoEXT info_debug = {};
  1711. info_debug.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
  1712. info_debug.pObjectName = "pipeline_stencil for region where geometry will be drawn";
  1713. info_debug.objectType = VkObjectType::VK_OBJECT_TYPE_PIPELINE;
  1714. info_debug.objectHandle = (uint64_t)m_p_pipeline_stencil_for_region_where_geometry_will_be_drawn;
  1715. vkSetDebugUtilsObjectNameEXT(m_p_device, &info_debug);
  1716. info_debug.pObjectName = "pipeline_stencil_for_regular_geometry_that_applied_to_region_without_textures";
  1717. info_debug.objectHandle = (uint64_t)m_p_pipeline_stencil_for_regular_geometry_that_applied_to_region_without_textures;
  1718. vkSetDebugUtilsObjectNameEXT(m_p_device, &info_debug);
  1719. info_debug.pObjectName = "pipeline_without_textures";
  1720. info_debug.objectHandle = (uint64_t)m_p_pipeline_without_textures;
  1721. vkSetDebugUtilsObjectNameEXT(m_p_device, &info_debug);
  1722. info_debug.pObjectName = "pipeline_stencil_for_regular_geometry_that_applied_to_region_with_textures";
  1723. info_debug.objectHandle = (uint64_t)m_p_pipeline_stencil_for_regular_geometry_that_applied_to_region_with_textures;
  1724. vkSetDebugUtilsObjectNameEXT(m_p_device, &info_debug);
  1725. info_debug.pObjectName = "pipeline_with_textures";
  1726. info_debug.objectHandle = (uint64_t)m_p_pipeline_with_textures;
  1727. vkSetDebugUtilsObjectNameEXT(m_p_device, &info_debug);
  1728. #endif
  1729. }
  1730. void RenderInterface_VK::CreateSwapchainFrameBuffers(const VkExtent2D& real_render_image_size) noexcept
  1731. {
  1732. RMLUI_VK_ASSERTMSG(m_p_render_pass, "you must create a VkRenderPass before calling this method");
  1733. RMLUI_VK_ASSERTMSG(m_p_device, "you must have a valid VkDevice here");
  1734. CreateSwapchainImageViews();
  1735. Create_DepthStencilImage();
  1736. Create_DepthStencilImageViews();
  1737. m_swapchain_frame_buffers.resize(m_swapchain_image_views.size());
  1738. Rml::Array<VkImageView, 2> attachments;
  1739. VkFramebufferCreateInfo info = {};
  1740. info.sType = VkStructureType::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  1741. info.pNext = nullptr;
  1742. info.renderPass = m_p_render_pass;
  1743. info.attachmentCount = static_cast<uint32_t>(attachments.size());
  1744. info.pAttachments = attachments.data();
  1745. info.width = real_render_image_size.width;
  1746. info.height = real_render_image_size.height;
  1747. info.layers = 1;
  1748. int index = 0;
  1749. VkResult status = VkResult::VK_SUCCESS;
  1750. attachments[1] = m_texture_depthstencil.m_p_vk_image_view;
  1751. for (auto p_view : m_swapchain_image_views)
  1752. {
  1753. attachments[0] = p_view;
  1754. status = vkCreateFramebuffer(m_p_device, &info, nullptr, &m_swapchain_frame_buffers[index]);
  1755. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkCreateFramebuffer");
  1756. ++index;
  1757. }
  1758. }
  1759. void RenderInterface_VK::CreateSwapchainImages() noexcept
  1760. {
  1761. RMLUI_VK_ASSERTMSG(m_p_device, "[Vulkan] you must initialize VkDevice before calling this method");
  1762. RMLUI_VK_ASSERTMSG(m_p_swapchain, "[Vulkan] you must initialize VkSwapchainKHR before calling this method");
  1763. uint32_t count = 0;
  1764. auto status = vkGetSwapchainImagesKHR(m_p_device, m_p_swapchain, &count, nullptr);
  1765. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "[Vulkan] failed to vkGetSwapchainImagesKHR (get count)");
  1766. m_swapchain_images.resize(count);
  1767. status = vkGetSwapchainImagesKHR(m_p_device, m_p_swapchain, &count, m_swapchain_images.data());
  1768. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "[Vulkan] failed to vkGetSwapchainImagesKHR (filling vector)");
  1769. }
  1770. void RenderInterface_VK::CreateSwapchainImageViews() noexcept
  1771. {
  1772. CreateSwapchainImages();
  1773. m_swapchain_image_views.resize(m_swapchain_images.size());
  1774. uint32_t index = 0;
  1775. VkImageViewCreateInfo info = {};
  1776. VkResult status = VkResult::VK_SUCCESS;
  1777. for (auto p_image : m_swapchain_images)
  1778. {
  1779. info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  1780. info.pNext = nullptr;
  1781. info.format = m_swapchain_format.format;
  1782. info.components.r = VK_COMPONENT_SWIZZLE_R;
  1783. info.components.g = VK_COMPONENT_SWIZZLE_G;
  1784. info.components.b = VK_COMPONENT_SWIZZLE_B;
  1785. info.components.a = VK_COMPONENT_SWIZZLE_A;
  1786. info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  1787. info.subresourceRange.baseMipLevel = 0;
  1788. info.subresourceRange.levelCount = 1;
  1789. info.subresourceRange.baseArrayLayer = 0;
  1790. info.subresourceRange.layerCount = 1;
  1791. info.viewType = VK_IMAGE_VIEW_TYPE_2D;
  1792. info.flags = 0;
  1793. info.image = p_image;
  1794. status = vkCreateImageView(m_p_device, &info, nullptr, &m_swapchain_image_views[index]);
  1795. ++index;
  1796. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "[Vulkan] failed to vkCreateImageView (creating swapchain views)");
  1797. }
  1798. }
  1799. void RenderInterface_VK::Create_DepthStencilImage() noexcept
  1800. {
  1801. RMLUI_VK_ASSERTMSG(m_p_device, "you must initialize your VkDevice here");
  1802. RMLUI_VK_ASSERTMSG(m_p_allocator, "you must initialize your VMA allcator");
  1803. RMLUI_VK_ASSERTMSG(m_texture_depthstencil.m_p_vk_image == nullptr, "you should delete texture before create it");
  1804. VkImageCreateInfo info = {};
  1805. info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  1806. info.imageType = VK_IMAGE_TYPE_2D;
  1807. info.format = Get_SupportedDepthFormat();
  1808. info.extent = {static_cast<uint32_t>(m_width), static_cast<uint32_t>(m_height), 1};
  1809. info.mipLevels = 1;
  1810. info.arrayLayers = 1;
  1811. info.samples = VK_SAMPLE_COUNT_1_BIT;
  1812. info.tiling = VK_IMAGE_TILING_OPTIMAL;
  1813. info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
  1814. VmaAllocation p_allocation = {};
  1815. VkImage p_image = {};
  1816. VmaAllocationCreateInfo info_alloc = {};
  1817. auto p_commentary = "our depth stencil image";
  1818. info_alloc.usage = VMA_MEMORY_USAGE_GPU_ONLY;
  1819. info_alloc.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
  1820. info_alloc.pUserData = const_cast<char*>(p_commentary);
  1821. VkResult status = vmaCreateImage(m_p_allocator, &info, &info_alloc, &p_image, &p_allocation, nullptr);
  1822. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vmaCreateImage");
  1823. m_texture_depthstencil.m_p_vk_image = p_image;
  1824. m_texture_depthstencil.m_p_vma_allocation = p_allocation;
  1825. }
  1826. void RenderInterface_VK::Create_DepthStencilImageViews() noexcept
  1827. {
  1828. RMLUI_VK_ASSERTMSG(m_p_device, "you must initialize your VkDevice here");
  1829. RMLUI_VK_ASSERTMSG(m_texture_depthstencil.m_p_vk_image_view == nullptr, "you should delete it before creating");
  1830. RMLUI_VK_ASSERTMSG(m_texture_depthstencil.m_p_vk_image, "you must initialize VkImage before create this");
  1831. VkImageViewCreateInfo info = {};
  1832. info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  1833. info.viewType = VK_IMAGE_VIEW_TYPE_2D;
  1834. info.image = m_texture_depthstencil.m_p_vk_image;
  1835. info.format = Get_SupportedDepthFormat();
  1836. info.subresourceRange.baseMipLevel = 0;
  1837. info.subresourceRange.levelCount = 1;
  1838. info.subresourceRange.baseArrayLayer = 0;
  1839. info.subresourceRange.layerCount = 1;
  1840. info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
  1841. if (Get_SupportedDepthFormat() >= VK_FORMAT_D16_UNORM_S8_UINT)
  1842. {
  1843. info.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
  1844. }
  1845. VkImageView p_image_view = {};
  1846. VkResult status = vkCreateImageView(m_p_device, &info, nullptr, &p_image_view);
  1847. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkCreateImageView");
  1848. m_texture_depthstencil.m_p_vk_image_view = p_image_view;
  1849. }
  1850. void RenderInterface_VK::CreateResourcesDependentOnSize(const VkExtent2D& real_render_image_size) noexcept
  1851. {
  1852. m_viewport.height = static_cast<float>(real_render_image_size.height);
  1853. m_viewport.width = static_cast<float>(real_render_image_size.width);
  1854. m_viewport.minDepth = 0.0f;
  1855. m_viewport.maxDepth = 1.0f;
  1856. m_viewport.x = 0.0f;
  1857. m_viewport.y = 0.0f;
  1858. m_scissor.extent.width = real_render_image_size.width;
  1859. m_scissor.extent.height = real_render_image_size.height;
  1860. m_scissor.offset.x = 0;
  1861. m_scissor.offset.y = 0;
  1862. m_scissor_original = m_scissor;
  1863. m_projection = Rml::Matrix4f::ProjectOrtho(0.0f, static_cast<float>(m_width), static_cast<float>(m_height), 0.0f, -10000, 10000);
  1864. // https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/
  1865. Rml::Matrix4f correction_matrix;
  1866. correction_matrix.SetColumns(Rml::Vector4f(1.0f, 0.0f, 0.0f, 0.0f), Rml::Vector4f(0.0f, -1.0f, 0.0f, 0.0f), Rml::Vector4f(0.0f, 0.0f, 0.5f, 0.0f),
  1867. Rml::Vector4f(0.0f, 0.0f, 0.5f, 1.0f));
  1868. m_projection = correction_matrix * m_projection;
  1869. SetTransform(nullptr);
  1870. CreateRenderPass();
  1871. CreateSwapchainFrameBuffers(real_render_image_size);
  1872. Create_Pipelines();
  1873. }
  1874. RenderInterface_VK::buffer_data_t RenderInterface_VK::CreateResource_StagingBuffer(VkDeviceSize size, VkBufferUsageFlags flags) noexcept
  1875. {
  1876. VkBufferCreateInfo info = {};
  1877. info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
  1878. info.pNext = nullptr;
  1879. info.size = size;
  1880. info.usage = flags;
  1881. VmaAllocationCreateInfo info_allocation = {};
  1882. info_allocation.usage = VMA_MEMORY_USAGE_CPU_ONLY;
  1883. VkBuffer p_buffer = nullptr;
  1884. VmaAllocation p_allocation = nullptr;
  1885. VmaAllocationInfo info_stats = {};
  1886. VkResult status = vmaCreateBuffer(m_p_allocator, &info, &info_allocation, &p_buffer, &p_allocation, &info_stats);
  1887. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vmaCreateBuffer");
  1888. #ifdef RMLUI_VK_DEBUG
  1889. Rml::Log::Message(Rml::Log::LT_DEBUG, "Allocated buffer [%s]", FormatByteSize(info_stats.size).c_str());
  1890. #endif
  1891. buffer_data_t result = {};
  1892. result.m_p_vk_buffer = p_buffer;
  1893. result.m_p_vma_allocation = p_allocation;
  1894. return result;
  1895. }
  1896. void RenderInterface_VK::DestroyResource_StagingBuffer(const buffer_data_t& data) noexcept
  1897. {
  1898. if (m_p_allocator)
  1899. {
  1900. if (data.m_p_vk_buffer && data.m_p_vma_allocation)
  1901. {
  1902. vmaDestroyBuffer(m_p_allocator, data.m_p_vk_buffer, data.m_p_vma_allocation);
  1903. }
  1904. }
  1905. }
  1906. void RenderInterface_VK::Destroy_Textures() noexcept
  1907. {
  1908. for (auto& textures : m_pending_for_deletion_textures_by_frames)
  1909. {
  1910. for (texture_data_t* p_data : textures)
  1911. {
  1912. Destroy_Texture(*p_data);
  1913. delete p_data;
  1914. }
  1915. textures.clear();
  1916. }
  1917. }
  1918. void RenderInterface_VK::Destroy_Geometries() noexcept
  1919. {
  1920. Update_PendingForDeletion_Geometries();
  1921. m_memory_pool.Shutdown();
  1922. }
  1923. void RenderInterface_VK::Destroy_Texture(const texture_data_t& texture) noexcept
  1924. {
  1925. RMLUI_VK_ASSERTMSG(m_p_allocator, "you must have initialized VmaAllocator");
  1926. RMLUI_VK_ASSERTMSG(m_p_device, "you must have initialized VkDevice");
  1927. if (texture.m_p_vma_allocation)
  1928. {
  1929. vmaDestroyImage(m_p_allocator, texture.m_p_vk_image, texture.m_p_vma_allocation);
  1930. vkDestroyImageView(m_p_device, texture.m_p_vk_image_view, nullptr);
  1931. VkDescriptorSet p_set = texture.m_p_vk_descriptor_set;
  1932. if (p_set)
  1933. {
  1934. m_manager_descriptors.Free_Descriptors(m_p_device, &p_set);
  1935. }
  1936. }
  1937. }
  1938. void RenderInterface_VK::DestroyResourcesDependentOnSize() noexcept
  1939. {
  1940. Destroy_Pipelines();
  1941. DestroySwapchainFrameBuffers();
  1942. DestroyRenderPass();
  1943. }
  1944. void RenderInterface_VK::DestroySwapchainImageViews() noexcept
  1945. {
  1946. RMLUI_VK_ASSERTMSG(m_p_device, "[Vulkan] you must initialize VkDevice before calling this method");
  1947. m_swapchain_images.clear();
  1948. for (auto p_view : m_swapchain_image_views)
  1949. {
  1950. vkDestroyImageView(m_p_device, p_view, nullptr);
  1951. }
  1952. m_swapchain_image_views.clear();
  1953. }
  1954. void RenderInterface_VK::DestroySwapchainFrameBuffers() noexcept
  1955. {
  1956. DestroySwapchainImageViews();
  1957. Destroy_Texture(m_texture_depthstencil);
  1958. m_texture_depthstencil.m_p_vk_image = nullptr;
  1959. m_texture_depthstencil.m_p_vk_image_view = nullptr;
  1960. for (auto p_frame_buffer : m_swapchain_frame_buffers)
  1961. {
  1962. vkDestroyFramebuffer(m_p_device, p_frame_buffer, nullptr);
  1963. }
  1964. m_swapchain_frame_buffers.clear();
  1965. }
  1966. void RenderInterface_VK::DestroyRenderPass() noexcept
  1967. {
  1968. RMLUI_VK_ASSERTMSG(m_p_device, "you must have a valid VkDevice here");
  1969. if (m_p_render_pass)
  1970. {
  1971. vkDestroyRenderPass(m_p_device, m_p_render_pass, nullptr);
  1972. m_p_render_pass = nullptr;
  1973. }
  1974. }
  1975. void RenderInterface_VK::Destroy_Pipelines() noexcept
  1976. {
  1977. RMLUI_VK_ASSERTMSG(m_p_device, "must exist here");
  1978. vkDestroyPipeline(m_p_device, m_p_pipeline_with_textures, nullptr);
  1979. vkDestroyPipeline(m_p_device, m_p_pipeline_without_textures, nullptr);
  1980. vkDestroyPipeline(m_p_device, m_p_pipeline_stencil_for_region_where_geometry_will_be_drawn, nullptr);
  1981. vkDestroyPipeline(m_p_device, m_p_pipeline_stencil_for_regular_geometry_that_applied_to_region_with_textures, nullptr);
  1982. vkDestroyPipeline(m_p_device, m_p_pipeline_stencil_for_regular_geometry_that_applied_to_region_without_textures, nullptr);
  1983. }
  1984. void RenderInterface_VK::DestroyDescriptorSets() noexcept {}
  1985. void RenderInterface_VK::DestroyPipelineLayout() noexcept {}
  1986. void RenderInterface_VK::DestroySamplers() noexcept
  1987. {
  1988. RMLUI_VK_ASSERTMSG(m_p_device, "must exist here");
  1989. vkDestroySampler(m_p_device, m_p_sampler_linear, nullptr);
  1990. }
  1991. void RenderInterface_VK::CreateRenderPass() noexcept
  1992. {
  1993. RMLUI_VK_ASSERTMSG(m_p_device, "you must have a valid VkDevice here");
  1994. Rml::Array<VkAttachmentDescription, 2> attachments = {};
  1995. attachments[0].format = m_swapchain_format.format;
  1996. attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
  1997. attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  1998. attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  1999. attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  2000. attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  2001. attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  2002. attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  2003. attachments[1].format = Get_SupportedDepthFormat();
  2004. attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
  2005. attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  2006. attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  2007. attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  2008. attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  2009. attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  2010. attachments[1].finalLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  2011. RMLUI_VK_ASSERTMSG(attachments[1].format != VkFormat::VK_FORMAT_UNDEFINED,
  2012. "can't obtain depth format, your device doesn't support depth/stencil operations");
  2013. Rml::Array<VkAttachmentReference, 2> color_references;
  2014. // swapchain
  2015. color_references[0].attachment = 0;
  2016. color_references[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  2017. // depth stencil
  2018. color_references[1].attachment = 1;
  2019. color_references[1].layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  2020. VkSubpassDescription subpass = {};
  2021. subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  2022. subpass.flags = 0;
  2023. subpass.inputAttachmentCount = 0;
  2024. subpass.pInputAttachments = nullptr;
  2025. subpass.colorAttachmentCount = 1;
  2026. subpass.pColorAttachments = &color_references[0];
  2027. subpass.pResolveAttachments = nullptr;
  2028. subpass.pDepthStencilAttachment = &color_references[1];
  2029. subpass.preserveAttachmentCount = 0;
  2030. subpass.pPreserveAttachments = nullptr;
  2031. Rml::Array<VkSubpassDependency, 2> dependencies = {};
  2032. dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
  2033. dependencies[0].dstSubpass = 0;
  2034. dependencies[0].srcAccessMask = 0;
  2035. dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  2036. dependencies[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  2037. dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  2038. dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
  2039. dependencies[1].srcSubpass = VK_SUBPASS_EXTERNAL;
  2040. dependencies[1].dstSubpass = 0;
  2041. dependencies[1].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
  2042. dependencies[1].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
  2043. dependencies[1].srcAccessMask = 0;
  2044. dependencies[1].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
  2045. dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
  2046. VkRenderPassCreateInfo info = {};
  2047. info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  2048. info.pNext = nullptr;
  2049. info.attachmentCount = static_cast<uint32_t>(attachments.size());
  2050. info.pAttachments = attachments.data();
  2051. info.subpassCount = 1;
  2052. info.pSubpasses = &subpass;
  2053. info.dependencyCount = static_cast<uint32_t>(dependencies.size());
  2054. info.pDependencies = dependencies.data();
  2055. VkResult status = vkCreateRenderPass(m_p_device, &info, nullptr, &m_p_render_pass);
  2056. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkCreateRenderPass");
  2057. }
  2058. void RenderInterface_VK::Wait() noexcept
  2059. {
  2060. RMLUI_VK_ASSERTMSG(m_p_device, "you must initialize device");
  2061. RMLUI_VK_ASSERTMSG(m_p_swapchain, "you must initialize swapchain");
  2062. constexpr uint64_t kMaxUint64 = std::numeric_limits<uint64_t>::max();
  2063. auto status =
  2064. vkAcquireNextImageKHR(m_p_device, m_p_swapchain, kMaxUint64, m_semaphores_image_available[m_semaphore_index], nullptr, &m_image_index);
  2065. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkAcquireNextImageKHR (see status)");
  2066. m_semaphore_index_previous = m_semaphore_index;
  2067. m_semaphore_index = ((m_semaphore_index + 1) % kSwapchainBackBufferCount);
  2068. status = vkWaitForFences(m_p_device, 1, &m_executed_fences[m_semaphore_index_previous], VK_TRUE, kMaxUint64);
  2069. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkWaitForFences (see status)");
  2070. status = vkResetFences(m_p_device, 1, &m_executed_fences[m_semaphore_index_previous]);
  2071. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkResetFences (see status)");
  2072. }
  2073. void RenderInterface_VK::Update_PendingForDeletion_Textures_By_Frames() noexcept
  2074. {
  2075. auto& textures_for_previous_frame = m_pending_for_deletion_textures_by_frames[m_semaphore_index_previous];
  2076. for (texture_data_t* p_data : textures_for_previous_frame)
  2077. {
  2078. Destroy_Texture(*p_data);
  2079. delete p_data;
  2080. }
  2081. textures_for_previous_frame.clear();
  2082. }
  2083. void RenderInterface_VK::Update_PendingForDeletion_Geometries() noexcept
  2084. {
  2085. for (geometry_handle_t* p_geometry_handle : m_pending_for_deletion_geometries)
  2086. {
  2087. m_memory_pool.Free_GeometryHandle(p_geometry_handle);
  2088. delete p_geometry_handle;
  2089. }
  2090. m_pending_for_deletion_geometries.clear();
  2091. }
  2092. void RenderInterface_VK::Submit() noexcept
  2093. {
  2094. const VkSemaphore p_semaphores_wait[] = {m_semaphores_image_available[m_semaphore_index]};
  2095. const VkSemaphore p_semaphores_signal[] = {m_semaphores_finished_render[m_semaphore_index]};
  2096. VkFence p_fence = m_executed_fences[m_semaphore_index];
  2097. VkPipelineStageFlags submit_wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  2098. VkSubmitInfo info = {};
  2099. info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  2100. info.pNext = nullptr;
  2101. info.waitSemaphoreCount = 1;
  2102. info.pWaitSemaphores = p_semaphores_wait;
  2103. info.pWaitDstStageMask = &submit_wait_stage;
  2104. info.signalSemaphoreCount = 1;
  2105. info.pSignalSemaphores = p_semaphores_signal;
  2106. info.commandBufferCount = 1;
  2107. info.pCommandBuffers = &m_p_current_command_buffer;
  2108. VkResult status = vkQueueSubmit(m_p_queue_graphics, 1, &info, p_fence);
  2109. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkQueueSubmit");
  2110. }
  2111. void RenderInterface_VK::Present() noexcept
  2112. {
  2113. VkPresentInfoKHR info = {};
  2114. info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  2115. info.pNext = nullptr;
  2116. info.waitSemaphoreCount = 1;
  2117. info.pWaitSemaphores = &(m_semaphores_finished_render[m_semaphore_index]);
  2118. info.swapchainCount = 1;
  2119. info.pSwapchains = &m_p_swapchain;
  2120. info.pImageIndices = &m_image_index;
  2121. info.pResults = nullptr;
  2122. VkResult status = vkQueuePresentKHR(m_p_queue_present, &info);
  2123. if (!(status == VK_SUCCESS))
  2124. {
  2125. if (status == VK_ERROR_OUT_OF_DATE_KHR || status == VK_SUBOPTIMAL_KHR)
  2126. {
  2127. RecreateSwapchain();
  2128. }
  2129. else
  2130. {
  2131. RMLUI_VK_ASSERTMSG(status == VK_SUCCESS, "failed to vkQueuePresentKHR");
  2132. }
  2133. }
  2134. }
  2135. VkFormat RenderInterface_VK::Get_SupportedDepthFormat()
  2136. {
  2137. RMLUI_VK_ASSERTMSG(m_p_physical_device, "you must initialize and pick physical device for your renderer");
  2138. Rml::Array<VkFormat, 5> formats = {VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT,
  2139. VK_FORMAT_D16_UNORM};
  2140. VkFormatProperties properties;
  2141. for (const auto& format : formats)
  2142. {
  2143. vkGetPhysicalDeviceFormatProperties(m_p_physical_device, format, &properties);
  2144. if (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
  2145. {
  2146. return format;
  2147. }
  2148. }
  2149. return VkFormat::VK_FORMAT_UNDEFINED;
  2150. }
  2151. RenderInterface_VK::CommandBufferRing::CommandBufferRing() : m_p_device{}, m_frame_index{}, m_p_current_frame{}, m_frames{} {}
  2152. void RenderInterface_VK::CommandBufferRing::Initialize(VkDevice p_device, uint32_t queue_index_graphics) noexcept
  2153. {
  2154. RMLUI_VK_ASSERTMSG(p_device, "you can't pass an invalid VkDevice here");
  2155. RMLUI_VK_ASSERTMSG(!m_p_device, "already initialized");
  2156. m_p_device = p_device;
  2157. for (CommandBuffersPerFrame& current_buffer : m_frames)
  2158. {
  2159. for (uint32_t command_buffer_index = 0; command_buffer_index < kNumCommandBuffersPerFrame; ++command_buffer_index)
  2160. {
  2161. VkCommandPoolCreateInfo info_pool = {};
  2162. info_pool.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  2163. info_pool.pNext = nullptr;
  2164. info_pool.queueFamilyIndex = queue_index_graphics;
  2165. info_pool.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
  2166. VkCommandPool p_pool = nullptr;
  2167. auto status = vkCreateCommandPool(p_device, &info_pool, nullptr, &p_pool);
  2168. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "can't create command pool");
  2169. current_buffer.m_command_pools[command_buffer_index] = p_pool;
  2170. VkCommandBufferAllocateInfo info_buffer = {};
  2171. info_buffer.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  2172. info_buffer.pNext = nullptr;
  2173. info_buffer.commandPool = p_pool;
  2174. info_buffer.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  2175. info_buffer.commandBufferCount = 1;
  2176. VkCommandBuffer p_buffer = nullptr;
  2177. status = vkAllocateCommandBuffers(p_device, &info_buffer, &p_buffer);
  2178. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to fill command buffers");
  2179. current_buffer.m_command_buffers[command_buffer_index] = p_buffer;
  2180. }
  2181. }
  2182. m_frame_index = 0;
  2183. m_p_current_frame = &m_frames[m_frame_index];
  2184. }
  2185. void RenderInterface_VK::CommandBufferRing::Shutdown()
  2186. {
  2187. RMLUI_VK_ASSERTMSG(m_p_device, "you can't have an uninitialized VkDevice");
  2188. for (CommandBuffersPerFrame& current_buffer : m_frames)
  2189. {
  2190. for (uint32_t i = 0; i < kNumCommandBuffersPerFrame; ++i)
  2191. {
  2192. vkFreeCommandBuffers(m_p_device, current_buffer.m_command_pools[i], 1, &current_buffer.m_command_buffers[i]);
  2193. vkDestroyCommandPool(m_p_device, current_buffer.m_command_pools[i], nullptr);
  2194. }
  2195. }
  2196. }
  2197. void RenderInterface_VK::CommandBufferRing::OnBeginFrame()
  2198. {
  2199. m_frame_index = ((m_frame_index + 1) % kNumFramesToBuffer);
  2200. m_p_current_frame = &m_frames[m_frame_index];
  2201. // Reset all command pools of the current frame.
  2202. for (VkCommandPool command_pool : m_p_current_frame->m_command_pools)
  2203. {
  2204. auto status = vkResetCommandPool(m_p_device, command_pool, 0);
  2205. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vkResetCommandPool");
  2206. }
  2207. }
  2208. VkCommandBuffer RenderInterface_VK::CommandBufferRing::GetCommandBufferForActiveFrame(CommandBufferName named_command_buffer)
  2209. {
  2210. RMLUI_VK_ASSERTMSG(m_p_current_frame, "must be valid");
  2211. RMLUI_VK_ASSERTMSG(m_p_device, "you must initialize your VkDevice field with valid pointer or it's uninitialized field");
  2212. RMLUI_VK_ASSERTMSG((int)named_command_buffer < (int)CommandBufferName::Count, "overflow, please use one of the named command lists");
  2213. const uint32_t list_index = static_cast<uint32_t>(named_command_buffer);
  2214. VkCommandBuffer result = m_p_current_frame->m_command_buffers[list_index];
  2215. RMLUI_VK_ASSERTMSG(result, "your VkCommandBuffer must be valid otherwise debug your command list class for frame");
  2216. return result;
  2217. }
  2218. RenderInterface_VK::MemoryPool::MemoryPool() :
  2219. m_memory_total_size{}, m_device_min_uniform_alignment{}, m_p_data{}, m_p_buffer{}, m_p_buffer_alloc{}, m_p_device{}, m_p_vk_allocator{},
  2220. m_p_block{}
  2221. {}
  2222. RenderInterface_VK::MemoryPool::~MemoryPool() {}
  2223. void RenderInterface_VK::MemoryPool::Initialize(VkDeviceSize byte_size, VkDeviceSize device_min_uniform_alignment, VmaAllocator p_allocator,
  2224. VkDevice p_device) noexcept
  2225. {
  2226. RMLUI_VK_ASSERTMSG(byte_size > 0, "size must be valid");
  2227. RMLUI_VK_ASSERTMSG(device_min_uniform_alignment > 0, "uniform alignment must be valid");
  2228. RMLUI_VK_ASSERTMSG(p_device, "you must pass a valid VkDevice");
  2229. RMLUI_VK_ASSERTMSG(p_allocator, "you must pass a valid VmaAllocator");
  2230. m_p_device = p_device;
  2231. m_p_vk_allocator = p_allocator;
  2232. m_device_min_uniform_alignment = device_min_uniform_alignment;
  2233. #ifdef RMLUI_VK_DEBUG
  2234. Rml::Log::Message(Rml::Log::LT_DEBUG, "[Vulkan][Debug] the alignment for uniform buffer is: %zu", m_device_min_uniform_alignment);
  2235. #endif
  2236. m_memory_total_size = AlignUp<VkDeviceSize>(static_cast<VkDeviceSize>(byte_size), m_device_min_uniform_alignment);
  2237. VkBufferCreateInfo info = {};
  2238. info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
  2239. info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
  2240. info.size = m_memory_total_size;
  2241. VmaAllocationCreateInfo info_alloc = {};
  2242. auto p_commentary = "our pool buffer that manages all memory in vulkan (dynamic)";
  2243. info_alloc.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
  2244. info_alloc.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
  2245. info_alloc.pUserData = const_cast<char*>(p_commentary);
  2246. VmaAllocationInfo info_stats = {};
  2247. auto status = vmaCreateBuffer(m_p_vk_allocator, &info, &info_alloc, &m_p_buffer, &m_p_buffer_alloc, &info_stats);
  2248. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vmaCreateBuffer");
  2249. VmaVirtualBlockCreateInfo info_virtual_block = {};
  2250. info_virtual_block.size = m_memory_total_size;
  2251. status = vmaCreateVirtualBlock(&info_virtual_block, &m_p_block);
  2252. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vmaCreateVirtualBlock");
  2253. #ifdef RMLUI_VK_DEBUG
  2254. Rml::Log::Message(Rml::Log::LT_DEBUG, "[Vulkan][Debug] Allocated memory pool [%s]", FormatByteSize(info_stats.size).c_str());
  2255. #endif
  2256. status = vmaMapMemory(m_p_vk_allocator, m_p_buffer_alloc, (void**)&m_p_data);
  2257. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vmaMapMemory");
  2258. }
  2259. void RenderInterface_VK::MemoryPool::Shutdown() noexcept
  2260. {
  2261. RMLUI_VK_ASSERTMSG(m_p_vk_allocator, "you must have a valid VmaAllocator");
  2262. RMLUI_VK_ASSERTMSG(m_p_buffer, "you must allocate VkBuffer for deleting");
  2263. RMLUI_VK_ASSERTMSG(m_p_buffer_alloc, "you must allocate VmaAllocation for deleting");
  2264. #ifdef RMLUI_VK_DEBUG
  2265. Rml::Log::Message(Rml::Log::LT_DEBUG, "[Vulkan][Debug] Destroyed memory pool [%s]", FormatByteSize(m_memory_total_size).c_str());
  2266. #endif
  2267. vmaUnmapMemory(m_p_vk_allocator, m_p_buffer_alloc);
  2268. vmaDestroyVirtualBlock(m_p_block);
  2269. vmaDestroyBuffer(m_p_vk_allocator, m_p_buffer, m_p_buffer_alloc);
  2270. }
  2271. bool RenderInterface_VK::MemoryPool::Alloc_GeneralBuffer(VkDeviceSize size, void** p_data, VkDescriptorBufferInfo* p_out,
  2272. VmaVirtualAllocation* p_alloc) noexcept
  2273. {
  2274. RMLUI_VK_ASSERTMSG(p_out, "you must pass a valid pointer");
  2275. RMLUI_VK_ASSERTMSG(m_p_buffer, "you must have a valid VkBuffer");
  2276. RMLUI_VK_ASSERTMSG(*p_alloc == nullptr,
  2277. "you can't pass a VALID object, because it is for initialization. So it means you passed the already allocated "
  2278. "VmaVirtualAllocation and it means you did something wrong, like you wanted to allocate into the same object...");
  2279. size = AlignUp<VkDeviceSize>(static_cast<VkDeviceSize>(size), m_device_min_uniform_alignment);
  2280. VkDeviceSize offset_memory{};
  2281. VmaVirtualAllocationCreateInfo info = {};
  2282. info.size = size;
  2283. info.alignment = m_device_min_uniform_alignment;
  2284. auto status = vmaVirtualAllocate(m_p_block, &info, p_alloc, &offset_memory);
  2285. RMLUI_VK_ASSERTMSG(status == VkResult::VK_SUCCESS, "failed to vmaVirtualAllocate");
  2286. *p_data = (void*)(m_p_data + offset_memory);
  2287. p_out->buffer = m_p_buffer;
  2288. p_out->offset = offset_memory;
  2289. p_out->range = size;
  2290. return true;
  2291. }
  2292. bool RenderInterface_VK::MemoryPool::Alloc_VertexBuffer(uint32_t number_of_elements, uint32_t stride_in_bytes, void** p_data,
  2293. VkDescriptorBufferInfo* p_out, VmaVirtualAllocation* p_alloc) noexcept
  2294. {
  2295. return Alloc_GeneralBuffer(number_of_elements * stride_in_bytes, p_data, p_out, p_alloc);
  2296. }
  2297. bool RenderInterface_VK::MemoryPool::Alloc_IndexBuffer(uint32_t number_of_elements, uint32_t stride_in_bytes, void** p_data,
  2298. VkDescriptorBufferInfo* p_out, VmaVirtualAllocation* p_alloc) noexcept
  2299. {
  2300. return Alloc_GeneralBuffer(number_of_elements * stride_in_bytes, p_data, p_out, p_alloc);
  2301. }
  2302. void RenderInterface_VK::MemoryPool::SetDescriptorSet(uint32_t binding_index, uint32_t size, VkDescriptorType descriptor_type,
  2303. VkDescriptorSet p_set) noexcept
  2304. {
  2305. RMLUI_VK_ASSERTMSG(m_p_device, "you must have a valid VkDevice here");
  2306. RMLUI_VK_ASSERTMSG(p_set, "you must have a valid VkDescriptorSet here");
  2307. RMLUI_VK_ASSERTMSG(m_p_buffer, "you must have a valid VkBuffer here");
  2308. VkDescriptorBufferInfo info = {};
  2309. info.buffer = m_p_buffer;
  2310. info.offset = 0;
  2311. info.range = size;
  2312. VkWriteDescriptorSet info_write = {};
  2313. info_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  2314. info_write.pNext = nullptr;
  2315. info_write.dstSet = p_set;
  2316. info_write.descriptorCount = 1;
  2317. info_write.descriptorType = descriptor_type;
  2318. info_write.dstArrayElement = 0;
  2319. info_write.dstBinding = binding_index;
  2320. info_write.pBufferInfo = &info;
  2321. vkUpdateDescriptorSets(m_p_device, 1, &info_write, 0, nullptr);
  2322. }
  2323. void RenderInterface_VK::MemoryPool::SetDescriptorSet(uint32_t binding_index, VkDescriptorBufferInfo* p_info, VkDescriptorType descriptor_type,
  2324. VkDescriptorSet p_set) noexcept
  2325. {
  2326. RMLUI_VK_ASSERTMSG(m_p_device, "you must have a valid VkDevice here");
  2327. RMLUI_VK_ASSERTMSG(p_set, "you must have a valid VkDescriptorSet here");
  2328. RMLUI_VK_ASSERTMSG(m_p_buffer, "you must have a valid VkBuffer here");
  2329. RMLUI_VK_ASSERTMSG(p_info, "must be valid pointer");
  2330. VkWriteDescriptorSet info_write = {};
  2331. info_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  2332. info_write.pNext = nullptr;
  2333. info_write.dstSet = p_set;
  2334. info_write.descriptorCount = 1;
  2335. info_write.descriptorType = descriptor_type;
  2336. info_write.dstArrayElement = 0;
  2337. info_write.dstBinding = binding_index;
  2338. info_write.pBufferInfo = p_info;
  2339. vkUpdateDescriptorSets(m_p_device, 1, &info_write, 0, nullptr);
  2340. }
  2341. void RenderInterface_VK::MemoryPool::SetDescriptorSet(uint32_t binding_index, VkSampler p_sampler, VkImageLayout layout, VkImageView p_view,
  2342. VkDescriptorType descriptor_type, VkDescriptorSet p_set) noexcept
  2343. {
  2344. RMLUI_VK_ASSERTMSG(m_p_device, "you must have a valid VkDevice here");
  2345. RMLUI_VK_ASSERTMSG(p_set, "you must have a valid VkDescriptorSet here");
  2346. RMLUI_VK_ASSERTMSG(m_p_buffer, "you must have a valid VkBuffer here");
  2347. RMLUI_VK_ASSERTMSG(p_view, "you must have a valid VkImageView");
  2348. RMLUI_VK_ASSERTMSG(p_sampler, "you must have a valid VkSampler here");
  2349. VkDescriptorImageInfo info = {};
  2350. info.imageLayout = layout;
  2351. info.imageView = p_view;
  2352. info.sampler = p_sampler;
  2353. VkWriteDescriptorSet info_write = {};
  2354. info_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  2355. info_write.pNext = nullptr;
  2356. info_write.dstSet = p_set;
  2357. info_write.descriptorCount = 1;
  2358. info_write.descriptorType = descriptor_type;
  2359. info_write.dstArrayElement = 0;
  2360. info_write.dstBinding = binding_index;
  2361. info_write.pImageInfo = &info;
  2362. vkUpdateDescriptorSets(m_p_device, 1, &info_write, 0, nullptr);
  2363. }
  2364. void RenderInterface_VK::MemoryPool::Free_GeometryHandle(geometry_handle_t* p_valid_geometry_handle) noexcept
  2365. {
  2366. RMLUI_VK_ASSERTMSG(p_valid_geometry_handle,
  2367. "you must pass a VALID pointer to geometry_handle_t, otherwise something is wrong and debug your code");
  2368. RMLUI_VK_ASSERTMSG(p_valid_geometry_handle->m_p_vertex_allocation, "you must have a VALID pointer of VmaAllocation for vertex buffer");
  2369. RMLUI_VK_ASSERTMSG(p_valid_geometry_handle->m_p_index_allocation, "you must have a VALID pointer of VmaAllocation for index buffer");
  2370. // TODO: The following assertion is disabled for now. The shader allocation pointer is only set once the geometry
  2371. // handle is rendered with. However, currently the Vulkan renderer does not handle all draw calls from RmlUi, so
  2372. // this pointer may never be set if the geometry was only used in a unsupported draw calls. This can then trigger
  2373. // the following assertion. The free call below gracefully handles zero pointers so this should be safe regardless.
  2374. // RMLUI_VK_ASSERTMSG(p_valid_geometry_handle->m_p_shader_allocation,
  2375. // "you must have a VALID pointer of VmaAllocation for shader operations (like uniforms and etc)");
  2376. RMLUI_VK_ASSERTMSG(m_p_block, "you have to allocate the virtual block before do this operation...");
  2377. vmaVirtualFree(m_p_block, p_valid_geometry_handle->m_p_vertex_allocation);
  2378. vmaVirtualFree(m_p_block, p_valid_geometry_handle->m_p_index_allocation);
  2379. vmaVirtualFree(m_p_block, p_valid_geometry_handle->m_p_shader_allocation);
  2380. p_valid_geometry_handle->m_p_vertex_allocation = nullptr;
  2381. p_valid_geometry_handle->m_p_shader_allocation = nullptr;
  2382. p_valid_geometry_handle->m_p_index_allocation = nullptr;
  2383. p_valid_geometry_handle->m_num_indices = 0;
  2384. }
  2385. void RenderInterface_VK::MemoryPool::Free_GeometryHandle_ShaderDataOnly(geometry_handle_t* p_valid_geometry_handle) noexcept
  2386. {
  2387. RMLUI_VK_ASSERTMSG(p_valid_geometry_handle,
  2388. "you must pass a VALID pointer to geometry_handle_t, otherwise something is wrong and debug your code");
  2389. RMLUI_VK_ASSERTMSG(p_valid_geometry_handle->m_p_vertex_allocation, "you must have a VALID pointer of VmaAllocation for vertex buffer");
  2390. RMLUI_VK_ASSERTMSG(p_valid_geometry_handle->m_p_index_allocation, "you must have a VALID pointer of VmaAllocation for index buffer");
  2391. RMLUI_VK_ASSERTMSG(p_valid_geometry_handle->m_p_shader_allocation,
  2392. "you must have a VALID pointer of VmaAllocation for shader operations (like uniforms and etc)");
  2393. RMLUI_VK_ASSERTMSG(m_p_block, "you have to allocate the virtual block before do this operation...");
  2394. vmaVirtualFree(m_p_block, p_valid_geometry_handle->m_p_shader_allocation);
  2395. p_valid_geometry_handle->m_p_shader_allocation = nullptr;
  2396. }
  2397. #define GLAD_VULKAN_IMPLEMENTATION
  2398. #define VMA_IMPLEMENTATION
  2399. #include "RmlUi_Include_Vulkan.h"