RmlUi_Renderer_VK.cpp 114 KB

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