RmlUi_Renderer_VK.cpp 114 KB

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