diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-02-04 19:17:59 -0500 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-02-04 19:17:59 -0500 |
| commit | 61e179f9580c985cb5ca80ea732fc7572d31c489 (patch) | |
| tree | 122ff15c6d94ce5aebff4ff6f1fc6d13317abe16 | |
| parent | a3fb454f9935960dc2d367455f891d8fedfb9016 (diff) | |
pke: chkpt: text rendering, no errors but blank
| -rw-r--r-- | assets/shaders/glyph.vert | 2 | ||||
| -rw-r--r-- | editor/editor.cpp | 163 | ||||
| -rw-r--r-- | src/font.cpp | 430 | ||||
| -rw-r--r-- | src/font.hpp | 7 | ||||
| -rw-r--r-- | src/game.cpp | 6 | ||||
| -rw-r--r-- | src/window.cpp | 366 | ||||
| -rw-r--r-- | src/window.hpp | 24 |
7 files changed, 700 insertions, 298 deletions
diff --git a/assets/shaders/glyph.vert b/assets/shaders/glyph.vert index 52981c2..f48056d 100644 --- a/assets/shaders/glyph.vert +++ b/assets/shaders/glyph.vert @@ -7,7 +7,7 @@ layout(location = 1) in vec2 in_uv; // instance layout(location = 2) in vec4 in_fg_color; layout(location = 3) in vec4 in_bg_color; -layout(location = 4) in vec4 in_sprite_region; +layout(location = 4) in ivec4 in_sprite_region; layout(location = 5) in float in_width; layout(location = 0) out vec4 out_fg_color; diff --git a/editor/editor.cpp b/editor/editor.cpp index 5cb6a9d..c0eafcb 100644 --- a/editor/editor.cpp +++ b/editor/editor.cpp @@ -715,80 +715,103 @@ void RecordImGuiEntityTypes() { ImGui::End(); } +int SortFontGlyphChar(const void *a, const void *b) { + return ((FontGlyphChar*)a)->unicode > ((FontGlyphChar*)b)->unicode; +} + void GenerateMTSDF(const Asset *a) { assert(PK_HAS_FLAG(a->type, PKE_ASSET_TYPE_FONT)); + NULL_CHAR_ARR(path_txtr, 128); + NULL_CHAR_ARR(path_glyphs, 128); std::error_code e; - std::filesystem::create_directory("./cache", e); + std::filesystem::create_directory("./font", e); + AssetHandle ah_image = AssetHandle_MAX; + AssetHandle ah_glyphs = AssetHandle_MAX; + snprintf(path_txtr, 128, "%s/%s.%s", "./font", a->key, "png"); + snprintf(path_glyphs, 128, "%s/%s.%s", "./font", a->key, "glyph"); if (msdfgen::FreetypeHandle *ft = msdfgen::initializeFreetype()) { - // Load font file - if (msdfgen::FontHandle *font = msdfgen::loadFont(ft, a->basePath)) { - // Storage for glyph geometry and their coordinates in the atlas - std::vector<msdf_atlas::GlyphGeometry> glyphs; - // FontGeometry is a helper class that loads a set of glyphs from a single font. - // It can also be used to get additional font metrics, kerning information, etc. - msdf_atlas::FontGeometry fontGeometry(&glyphs); - // Load a set of character glyphs: - // The second argument can be ignored unless you mix different font sizes in one atlas. - // In the last argument, you can specify a charset other than ASCII. - // To load specific glyph indices, use loadGlyphs instead. - fontGeometry.loadCharset(font, 1.0, msdf_atlas::Charset::ASCII); - // Apply MSDF edge coloring. See edge-coloring.h for other coloring strategies. - const double maxCornerAngle = 3.0; - for (msdf_atlas::GlyphGeometry &glyph : glyphs) - glyph.edgeColoring(&msdfgen::edgeColoringInkTrap, maxCornerAngle, 0); - // TightAtlasPacker class computes the layout of the atlas. - msdf_atlas::TightAtlasPacker packer; - // Set atlas parameters: - // setDimensions or setDimensionsConstraint to find the best value - packer.setDimensionsConstraint(msdf_atlas::DimensionsConstraint::SQUARE); - // setScale for a fixed size or setMinimumScale to use the largest that fits - packer.setMinimumScale(24.0); - // setPixelRange or setUnitRange - packer.setPixelRange(2.0); - packer.setMiterLimit(1.0); - // Compute atlas layout - pack glyphs - packer.pack(glyphs.data(), glyphs.size()); - // Get final atlas dimensions - int width = 0, height = 0; - packer.getDimensions(width, height); - // The ImmediateAtlasGenerator class facilitates the generation of the atlas bitmap. - msdf_atlas::ImmediateAtlasGenerator< - float, // pixel type of buffer for individual glyphs depends on generator function - 4, // number of atlas color channels - &msdf_atlas::mtsdfGenerator, // function to generate bitmaps for individual glyphs - msdf_atlas::BitmapAtlasStorage<float, 4> // class that stores the atlas bitmap - // For example, a custom atlas storage class that stores it in VRAM can be used. - > generator(width, height); - // GeneratorAttributes can be modified to change the generator's default settings. - msdf_atlas::GeneratorAttributes attributes; - generator.setAttributes(attributes); - // generator.setThreadCount(4); - // Generate atlas bitmap - generator.generate(glyphs.data(), glyphs.size()); - // The atlas bitmap can now be retrieved via atlasStorage as a BitmapConstRef. - // The glyphs array (or fontGeometry) contains positioning data for typesetting text. - msdf_atlas::BitmapAtlasStorage<float, 4> storage = generator.atlasStorage(); - msdf_atlas::saveImage<4>(storage, msdf_atlas::ImageFormat::PNG, "cache/test-font.png", msdf_atlas::YDirection::TOP_DOWN); - - auto f = fopen("cache/test-font.glyphs", "w"); - pk_arr arr_glyphs = {}; - arr_glyphs.alignment = 8; - arr_glyphs.stride = sizeof(FontGlyphChar); - pk_arr_resize(&arr_glyphs, glyphs.size()); - FontGlyphChar *arr = reinterpret_cast<FontGlyphChar *>(arr_glyphs.data); - for (uint64_t i = 0; i < glyphs.size(); ++i) { - arr[i].unicode = glyphs[i].getCodepoint(); - glyphs[i].getBoxRect(arr[i].bounds.x, arr[i].bounds.y, arr[i].bounds.z, arr[i].bounds.a); - } - - fwrite(glyphs.data(), sizeof(msdf_atlas::GlyphGeometry) * glyphs.size(), 1, f); - fclose(f); - // _ = myProject::submitAtlasBitmapAndLayout(generator.atlasStorage(), glyphs); - // Cleanup - msdfgen::destroyFont(font); - } - msdfgen::deinitializeFreetype(ft); - } + // Load font file + if (msdfgen::FontHandle *font = msdfgen::loadFont(ft, a->basePath)) { + // Storage for glyph geometry and their coordinates in the atlas + std::vector<msdf_atlas::GlyphGeometry> glyphs; + // FontGeometry is a helper class that loads a set of glyphs from a single font. + // It can also be used to get additional font metrics, kerning information, etc. + msdf_atlas::FontGeometry fontGeometry(&glyphs); + // Load a set of character glyphs: + // The second argument can be ignored unless you mix different font sizes in one atlas. + // In the last argument, you can specify a charset other than ASCII. + // To load specific glyph indices, use loadGlyphs instead. + fontGeometry.loadCharset(font, 1.0, msdf_atlas::Charset::ASCII); + // Apply MSDF edge coloring. See edge-coloring.h for other coloring strategies. + const double maxCornerAngle = 3.0; + for (msdf_atlas::GlyphGeometry &glyph : glyphs) + glyph.edgeColoring(&msdfgen::edgeColoringInkTrap, maxCornerAngle, 0); + // TightAtlasPacker class computes the layout of the atlas. + msdf_atlas::TightAtlasPacker packer; + // Set atlas parameters: + // setDimensions or setDimensionsConstraint to find the best value + packer.setDimensionsConstraint(msdf_atlas::DimensionsConstraint::SQUARE); + // setScale for a fixed size or setMinimumScale to use the largest that fits + packer.setMinimumScale(24.0); + // setPixelRange or setUnitRange + packer.setPixelRange(2.0); + packer.setMiterLimit(1.0); + // Compute atlas layout - pack glyphs + packer.pack(glyphs.data(), glyphs.size()); + // Get final atlas dimensions + int width = 0, height = 0; + packer.getDimensions(width, height); + // The ImmediateAtlasGenerator class facilitates the generation of the atlas bitmap. + msdf_atlas::ImmediateAtlasGenerator< + float, // pixel type of buffer for individual glyphs depends on generator function + 4, // number of atlas color channels + &msdf_atlas::mtsdfGenerator, // function to generate bitmaps for individual glyphs + msdf_atlas::BitmapAtlasStorage<float, 4> // class that stores the atlas bitmap + // For example, a custom atlas storage class that stores it in VRAM can be used. + > generator(width, height); + // GeneratorAttributes can be modified to change the generator's default settings. + msdf_atlas::GeneratorAttributes attributes; + generator.setAttributes(attributes); + // generator.setThreadCount(4); + // Generate atlas bitmap + generator.generate(glyphs.data(), glyphs.size()); + // The atlas bitmap can now be retrieved via atlasStorage as a BitmapConstRef. + // The glyphs array (or fontGeometry) contains positioning data for typesetting text. + msdf_atlas::BitmapAtlasStorage<float, 4> storage = generator.atlasStorage(); + msdf_atlas::saveImage<4>(storage, msdf_atlas::ImageFormat::PNG, path_txtr, msdf_atlas::YDirection::TOP_DOWN); + ah_image = AM_Register(path_txtr, PKE_ASSET_TYPE_UNSET); + + auto f = fopen(path_glyphs, "w+"); + pk_arr arr_glyphs = {}; + arr_glyphs.alignment = 8; + arr_glyphs.stride = sizeof(FontGlyphChar); + pk_arr_resize(&arr_glyphs, glyphs.size()); + FontGlyphChar *arr = reinterpret_cast<FontGlyphChar *>(arr_glyphs.data); + for (uint64_t i = 0; i < glyphs.size(); ++i) { + arr[i].unicode = glyphs[i].getCodepoint(); + glyphs[i].getBoxRect(arr[i].bounds.x, arr[i].bounds.y, arr[i].bounds.z, arr[i].bounds.a); + } + qsort(arr_glyphs.data, arr_glyphs.next, arr_glyphs.stride, SortFontGlyphChar); + fwrite(arr_glyphs.data, arr_glyphs.stride, arr_glyphs.next, f); + fclose(f); + ah_glyphs = AM_Register(path_glyphs, PKE_ASSET_TYPE_UNSET); + + // Cleanup + msdfgen::destroyFont(font); + } else { + fprintf(stderr, "failed to load font"); + return; + } + msdfgen::deinitializeFreetype(ft); + } + pk_cstr font_title; + font_title.length = strlen(a->key); + font_title.reserved = font_title.length + 1; + // TODO specific bucket? + font_title.val = pk_new<char>(font_title.reserved); + snprintf((char *)font_title.val, AssetKeyLength, "%s", a->key); + assert(ah_image != ah_glyphs && ah_image != AssetHandle_MAX); + FontType_RegisterFont(font_title, ah_image, ah_glyphs); } void RecordImGuiAssets() { diff --git a/src/font.cpp b/src/font.cpp index 45569cb..6292039 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -1,12 +1,13 @@ #include "font.hpp" #include "asset-manager.hpp" -#include "helpers.hpp" +#include "dynamic-array.hpp" #include "pk.h" #include "window.hpp" #include "static-plane.hpp" #include "vendor-stb-image-include.h" #include "game-settings.hpp" +#include <vulkan/vulkan_core.h> // TODO threading @@ -23,11 +24,62 @@ struct FontTypeData { FontTypeIndex h_ft{0}; } ftd; +struct FontInstanceBufferItem { + glm::vec4 bg_color; + glm::vec4 fg_color; + glm::ivec4 bounds; + float width; +}; + +const VkDeviceSize instance_buffer_item_size = (sizeof(glm::vec4) * 3) + sizeof(float); + // BucketContainer<FontType, TextRenderHandle, 2> bktFont; +uint32_t utf8_to_unicode(const char* str, uint32_t &out) { + uint32_t i = 0; + out = 0; + + // Check the leading byte to determine the number of bytes in the character + if ((str[i] & 0x80) == 0) { + // 1 byte character (ASCII) + out = str[i]; + i = 1; + } else if ((str[i] & 0xE0) == 0xC0) { + // 2 byte character + out = str[i] & 0x1F; + out <<= 6; + out |= (str[i + 1] & 0x3F); + i = 2; + } else if ((str[i] & 0xF0) == 0xE0) { + // 3 byte character + out = str[i] & 0x0F; + out <<= 6; + out |= (str[i + 1] & 0x3F); + out <<= 6; + out |= (str[i + 2] & 0x3F); + i = 3; + } else if ((str[i] & 0xF8) == 0xF0) { + // 4 byte character + out = str[i] & 0x07; + out <<= 6; + out |= (str[i + 1] & 0x3F); + out <<= 6; + out |= (str[i + 2] & 0x3F); + out <<= 6; + out |= (str[i + 3] & 0x3F); + i = 4; + } else { + // Invalid UTF-8 byte sequence + out = 0; + return 0; + } + return i; +} + void FontType_Init() { - ftd.h_ft = FontTypeIndex{5}; + ftd.n_ft = FontTypeIndex{5}; ftd.arr_ft = pk_new<FontType>(5); + // memset(ftd.arr_ft, 0, sizeof(FontType) * 5); } void FontType_Teardown() { @@ -36,28 +88,33 @@ void FontType_Teardown() { for (i = FontTypeIndex{0}; i < ftd.h_ft; ++i) { FontType_Unload(i); ft = &ftd.arr_ft[(FontTypeIndex_T)i]; - pk_delete<FontRender>(ft->renders, (FontTypeIndex_T)ft->n_render); + if (ft->renders != nullptr) pk_delete<FontRender>(ft->renders, (FontTypeIndex_T)ft->n_render); } pk_delete(ftd.arr_ft, (FontTypeIndex_T)ftd.n_ft); } void FontType_Serialize(std::ofstream &stream, FontType *ft) { - NULL_CHAR_ARR(handleStr, 23); + NULL_CHAR_ARR(handleStr, AssetKeyLength + 2); + const Asset *txtr = AM_Get(ft->fontTextureAssetHandle); + const Asset *glyphs = AM_Get(ft->glyphDetailsAssetHandle); stream << PKE_PROJECT_FONT_TITLE << ft->title.val << std::endl; - snprintf(handleStr, 22, "0x%08X 0x%08X", ft->fontTextureAssetHandle.bucketIndex, ft->fontTextureAssetHandle.itemIndex); + snprintf(handleStr, AssetKeyLength + 1, "%s", txtr->key); stream << PKE_PROJECT_FONT_TEXTURE_HANDLE << handleStr << std::endl; - snprintf(handleStr, 22, "0x%08X 0x%08X", ft->fontTextureAssetHandle.bucketIndex, ft->glyphDetailsAssetHandle.itemIndex); + snprintf(handleStr, AssetKeyLength + 1, "%s", glyphs->key); stream << PKE_PROJECT_FONT_GLYPH_DETAILS_HANDLE << handleStr << std::endl; + AM_Release(ft->glyphDetailsAssetHandle); + AM_Release(ft->fontTextureAssetHandle); } void FontType_Deserialize(std::ifstream &stream) { + uint64_t i; NULL_CHAR_ARR(readLine, 128); pk_cstr title; - AssetHandle fontTextureHandle; - AssetHandle glyphDetailsHandle; + AssetKey fontTextureKey; + AssetKey glyphDetailsKey; while (memset(readLine, 0, 128), stream.getline(readLine, 128)) { if (strcmp("", readLine) == 0) { - FontType_RegisterFont(title, fontTextureHandle, glyphDetailsHandle); + FontType_RegisterFont(title, AM_GetHandle(fontTextureKey), AM_GetHandle(glyphDetailsKey)); return; } if (strstr(readLine, PKE_PROJECT_FONT_TITLE)) { @@ -70,22 +127,16 @@ void FontType_Deserialize(std::ifstream &stream) { } if (strstr(readLine, PKE_PROJECT_FONT_TEXTURE_HANDLE)) { uint64_t prefixLen = strlen(PKE_PROJECT_FONT_TEXTURE_HANDLE); - // 0x00000000 0x00000000 - readLine[prefixLen + 10] = '\0'; - STR2NUM_ERROR result1 = str2num(fontTextureHandle.bucketIndex, readLine + prefixLen + 2, 16); - STR2NUM_ERROR result2 = str2num(fontTextureHandle.itemIndex, readLine + prefixLen + 11, 16); - assert(result1 == STR2NUM_ERROR::SUCCESS); - assert(result2 == STR2NUM_ERROR::SUCCESS); + for (i = 0; i < AssetKeyLength; ++i) { + fontTextureKey[i] = readLine[prefixLen + i]; + } continue; } if (strstr(readLine, PKE_PROJECT_FONT_GLYPH_DETAILS_HANDLE)) { uint64_t prefixLen = strlen(PKE_PROJECT_FONT_GLYPH_DETAILS_HANDLE); - // 0x00000000 0x00000000 - readLine[prefixLen + 10] = '\0'; - STR2NUM_ERROR result1 = str2num(glyphDetailsHandle.bucketIndex, readLine + prefixLen + 2, 16); - STR2NUM_ERROR result2 = str2num(glyphDetailsHandle.itemIndex, readLine + prefixLen + 11, 16); - assert(result1 == STR2NUM_ERROR::SUCCESS); - assert(result2 == STR2NUM_ERROR::SUCCESS); + for (i = 0; i < AssetKeyLength; ++i) { + glyphDetailsKey[i] = readLine[prefixLen + i]; + } continue; } } @@ -108,23 +159,23 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle VkDeviceSize index; constexpr VkDeviceSize expectedBufferCount = 3; constexpr VkDeviceSize startingGlyphCount = 4; + assert(fontTextureHandle != AssetHandle_MAX); + assert(glyphsHandle != AssetHandle_MAX); VkMemoryRequirements combined_vert_mem_reqs; - VkMemoryRequirements combined_inst_mem_reqs; VkMemoryRequirements combined_texture_mem_reqs; const Asset *fontTexture = AM_Get(fontTextureHandle); - const Asset *glyphs = AM_Get(glyphsHandle); - if (ftd.h_ft > ftd.n_ft) { - index = (VkDeviceSize)ftd.n_ft; + FontTypeIndex idx = ftd.h_ft; + ftd.h_ft += FontTypeIndex{1}; + if (ftd.h_ft > ftd.n_ft && idx > FontTypeIndex{0}) { ftd.n_ft += FontTypeIndex{5}; FontType *arr = pk_new<FontType>((FontTypeIndex_T)ftd.n_ft); - memcpy(arr, ftd.arr_ft, sizeof(FontType) * index); - pk_delete<FontType>(ftd.arr_ft, index); + memcpy(arr, ftd.arr_ft, sizeof(FontType) * (FontTypeIndex_T)idx); + if (ftd.arr_ft != nullptr && ftd.arr_ft != CAFE_BABE(FontType)) pk_delete<FontType>(ftd.arr_ft, (FontTypeIndex_T)idx); ftd.arr_ft = arr; } - FontTypeIndex idx = ftd.h_ft++; FontTypeIndex_T idx_t = (FontTypeIndex_T)idx; FontType *ft = &ftd.arr_ft[idx_t]; ft->title = title; @@ -133,9 +184,15 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle ft->renders = pk_new<FontRender>(startingGlyphCount); ft->n_render = FontRenderIndex{startingGlyphCount}; + const Asset *glyphs = AM_Get(glyphsHandle); + ft->n_glyphs = glyphs->size / sizeof(FontGlyphChar); + ft->glyphs = (FontGlyphChar*)glyphs->ptr; + int txtr_x, txtr_y, txtr_chan; stbi_uc *txtr_bytes = stbi_load_from_memory((unsigned char*)fontTexture->ptr, fontTexture->size, &txtr_x, &txtr_y, &txtr_chan, 4); + assert(txtr_bytes != nullptr); assert(txtr_chan == 4); + uint32_t imageSizeBytes = txtr_x * txtr_y * txtr_chan; /* * vulkan setup @@ -154,15 +211,15 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle */ // vertex { - for (uint64_t index = 0; index < expectedBufferCount; ++index) { - if (index == 0) { + for (uint64_t idx = 0; idx < expectedBufferCount; ++idx) { + if (idx == 0) { bufferCI.size = sizeof(glm::vec2) * 4; - } else if (index == 1) { + } else if (idx == 1) { bufferCI.size = sizeof(glm::vec2) * 4; - } else if (index == 2) { + } else if (idx == 2) { bufferCI.size = sizeof(uint16_t) * 6; } - if (index == 2) { + if (idx == 2) { bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT; } else { bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; @@ -203,7 +260,7 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle imageCreateInfo.extent.depth = 1; imageCreateInfo.mipLevels = 1; imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = global_sample_count; + imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -217,21 +274,6 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle vkImageSubresourceRange.baseArrayLayer = 0u; vkImageSubresourceRange.layerCount = 1u; - VkImageViewCreateInfo vkImageViewCreateInfo; - vkImageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - vkImageViewCreateInfo.pNext = nullptr; - vkImageViewCreateInfo.flags = 0; - vkImageViewCreateInfo.image = ft->textureImage; - vkImageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - vkImageViewCreateInfo.format = imageCreateInfo.format; - vkImageViewCreateInfo.components = VkComponentMapping { - .r = VK_COMPONENT_SWIZZLE_IDENTITY, - .g = VK_COMPONENT_SWIZZLE_IDENTITY, - .b = VK_COMPONENT_SWIZZLE_IDENTITY, - .a = VK_COMPONENT_SWIZZLE_IDENTITY, - }; - vkImageViewCreateInfo.subresourceRange = vkImageSubresourceRange; - VkImage tmpImage; vkResult = vkCreateImage(vkDevice, &imageCreateInfo, vkAllocator, &tmpImage); assert(vkResult == VK_SUCCESS); @@ -239,29 +281,9 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle VkMemoryRequirements imageMemoryRequirements; vkGetImageMemoryRequirements(vkDevice, tmpImage, &imageMemoryRequirements); - VkDeviceSize paddedImageSize = imageMemoryRequirements.size + (imageMemoryRequirements.alignment - (imageMemoryRequirements.size % imageMemoryRequirements.alignment)); - assert(paddedImageSize % imageMemoryRequirements.alignment == 0); + pk_arr_append(&arr_texture_mem_reqs, &imageMemoryRequirements); vkDestroyImage(vkDevice, tmpImage, vkAllocator); - - VkMemoryAllocateInfo vkMemoryAllocateInfo{}; - vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - vkMemoryAllocateInfo.pNext = nullptr; - vkMemoryAllocateInfo.allocationSize = paddedImageSize * swapchainLength; - vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(imageMemoryRequirements.memoryTypeBits, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - vkResult = vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &ft->deviceMemoryTexture); - assert(vkResult == VK_SUCCESS); - - vkResult = vkCreateImage(vkDevice, &imageCreateInfo, vkAllocator, &ft->textureImage); - assert(vkResult == VK_SUCCESS); - vkResult = vkBindImageMemory(vkDevice, ft->textureImage, ft->deviceMemoryTexture, 0); - assert(vkResult == VK_SUCCESS); - - vkImageViewCreateInfo.image = ft->textureImage; - vkResult = vkCreateImageView(vkDevice, &vkImageViewCreateInfo, vkAllocator, &ft->textureImageView); - assert(vkResult == VK_SUCCESS); } /* @@ -278,14 +300,9 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(combined_vert_mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &ft->deviceMemoryVert); - // inst - CalculateCombinedMemReqs(arr_inst_mem_reqs.next, (VkMemoryRequirements*)arr_inst_mem_reqs.data, combined_inst_mem_reqs); - vkMemoryAllocateInfo.allocationSize = combined_inst_mem_reqs.size; - vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(combined_inst_mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &ft->deviceMemoryInst); - // texture CalculateCombinedMemReqs(arr_texture_mem_reqs.next, (VkMemoryRequirements*)arr_texture_mem_reqs.data, combined_texture_mem_reqs); + // assert(combined_texture_mem_reqs.size == fontTexture->size && "Size of image texture shouldn't change?"); vkMemoryAllocateInfo.allocationSize = combined_texture_mem_reqs.size; vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(combined_texture_mem_reqs.memoryTypeBits, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); if (vkMemoryAllocateInfo.memoryTypeIndex == 0) { @@ -420,18 +437,39 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle vkQueueWaitIdle(tmpBufferDetails.queue); } PKVK_EndBuffer(tmpBufferDetails); - // set up instance buffer - { - ft->bindings.instanceBufferMaxCount = startingGlyphCount; - bufferCI.size = combined_inst_mem_reqs.size; - bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &ft->bindings.instanceBD.buffer); - vkBindBufferMemory(vkDevice, ft->bindings.instanceBD.buffer, ft->deviceMemoryInst, 0); - } // texture // transition image layout and copy to buffer + tmpBufferDetails = {}; PKVK_BeginBuffer(transferFamilyIndex, combined_texture_mem_reqs.size, tmpBufferDetails); - memcpy(tmpBufferDetails.deviceData, txtr_bytes, combined_texture_mem_reqs.size); + memcpy(tmpBufferDetails.deviceData, txtr_bytes, imageSizeBytes); + free(txtr_bytes); { + VkDeviceSize paddedImageSize = combined_texture_mem_reqs.size + (combined_texture_mem_reqs.alignment - (combined_texture_mem_reqs.size % combined_texture_mem_reqs.alignment)); + assert(paddedImageSize % combined_texture_mem_reqs.alignment == 0); + + VkImageViewCreateInfo vkImageViewCreateInfo; + vkImageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + vkImageViewCreateInfo.pNext = nullptr; + vkImageViewCreateInfo.flags = 0; + vkImageViewCreateInfo.image = ft->textureImage; + vkImageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + vkImageViewCreateInfo.format = imageCreateInfo.format; + vkImageViewCreateInfo.components = VkComponentMapping { + .r = VK_COMPONENT_SWIZZLE_IDENTITY, + .g = VK_COMPONENT_SWIZZLE_IDENTITY, + .b = VK_COMPONENT_SWIZZLE_IDENTITY, + .a = VK_COMPONENT_SWIZZLE_IDENTITY, + }; + vkImageViewCreateInfo.subresourceRange = vkImageSubresourceRange; + + vkResult = vkCreateImage(vkDevice, &imageCreateInfo, vkAllocator, &ft->textureImage); + assert(vkResult == VK_SUCCESS); + vkResult = vkBindImageMemory(vkDevice, ft->textureImage, ft->deviceMemoryTexture, 0); + assert(vkResult == VK_SUCCESS); + + vkImageViewCreateInfo.image = ft->textureImage; + vkResult = vkCreateImageView(vkDevice, &vkImageViewCreateInfo, vkAllocator, &ft->textureImageView); + assert(vkResult == VK_SUCCESS); + VkImageMemoryBarrier vkImageMemoryBarrier; vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; vkImageMemoryBarrier.pNext = nullptr; @@ -587,11 +625,11 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle assert(vkResult == VK_SUCCESS); VkWriteDescriptorSet *writeDescriptorSets = pk_new<VkWriteDescriptorSet>(swapchainLength); - for (long i = 0; i < 1 * swapchainLength; ++i) { + for (long i = 0; i < swapchainLength; ++i) { writeDescriptorSets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writeDescriptorSets[i].pNext = nullptr; writeDescriptorSets[i].dstSet = nullptr; - writeDescriptorSets[i].dstBinding = i; + writeDescriptorSets[i].dstBinding = 0; writeDescriptorSets[i].dstArrayElement = 0; writeDescriptorSets[i].descriptorCount = 1; writeDescriptorSets[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; @@ -612,20 +650,17 @@ FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle vkDescriptorBufferInfo[i].offset = 0; vkDescriptorBufferInfo[i].range = sizeof(UniformBufferObject); - long uboIndex = i * 2; - long samplerIndex = uboIndex + 1; - - writeDescriptorSets[uboIndex].pBufferInfo = &vkDescriptorBufferInfo[i]; - writeDescriptorSets[uboIndex].dstSet = ft->vkDescriptorSets[i]; - - writeDescriptorSets[samplerIndex].pImageInfo = &textureDescriptorInfo; - writeDescriptorSets[samplerIndex].dstSet = ft->vkDescriptorSets[i]; + writeDescriptorSets[i].pImageInfo = &textureDescriptorInfo; + writeDescriptorSets[i].dstSet = ft->vkDescriptorSets[i]; } - vkUpdateDescriptorSets(vkDevice, 2 * swapchainLength, writeDescriptorSets, 0, nullptr); + vkUpdateDescriptorSets(vkDevice, swapchainLength, writeDescriptorSets, 0, nullptr); pk_delete<VkDescriptorBufferInfo>(vkDescriptorBufferInfo, swapchainLength); pk_delete<VkWriteDescriptorSet>(writeDescriptorSets, swapchainLength); + AM_Release(fontTextureHandle); + AM_Release(glyphsHandle); + return idx; } @@ -698,3 +733,206 @@ void FontType_Unload(FontTypeIndex idx) { pk_delete<char>(ft->title.val, ft->title.reserved); } } + +// TODO perf? +// Every time new text is added, we're creating a new buffer and shuffling data +// This could probably be shortened or deferred by creating a larger-than-needed +// buffer. +// TODO threading +FontRender FontType_AddStringRender(FontTypeIndex idx_ft, pk_cstr cstr) { + VkResult vkResult; + FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)idx_ft]; + FontRender *fr; + FontGlyphChar *fgc; + FontRenderIndex idx_fr = ft->n_render; + DynArray<FontInstanceBufferItem> instance_buffer_items; + uint32_t i, ii, u, count; + int32_t l, m, r; + + if (ft->n_render > ft->h_render) { + ft->n_render += FontRenderIndex{5}; + FontRender *arr = pk_new<FontRender>((FontRenderIndex_T)ft->n_render); + memcpy(arr, ft->renders, sizeof(FontRender) * (FontRenderIndex_T)idx_fr); + pk_delete<FontRender>(ft->renders, (FontRenderIndex_T)idx_fr); + ft->renders = arr; + } + fr = &ft->renders[(FontRenderIndex_T)idx_fr]; + fr->len = cstr.length; + fr->index_ft = idx_ft; + fr->index_fr = idx_fr; + + // insert new characters into tmp buffer + instance_buffer_items.Reserve(cstr.length); + { + count = 0; + FontInstanceBufferItem *buf_item; + for (i = 0; i < cstr.length;) { + fgc = nullptr; + u = 0; + // determine unicode char + ii = utf8_to_unicode(&cstr.val[i], u); + if (ii == 0) { + fprintf(stderr, "failed to determine unicode for character: '%c'\n", cstr.val[i]); + i += 1; + continue; + } + i += ii; + count += 1; + + // binary search for glyph details + l = 0; + r = ft->n_glyphs - 1; + do { + m = l + (r-l)/2; + fgc = &ft->glyphs[m]; + if (fgc->unicode < u) + l = m + 1; + else + r = m - 1; + } while (fgc->unicode != u && l <= r); + + if (fgc->unicode != u) { + fprintf(stderr, "font: '%s' doesn't contain unicode character: '%u'\n", ft->title.val, u); + continue; + } + + buf_item = &instance_buffer_items.Push(); + buf_item->fg_color = glm::vec4(0.4, 0.5, 0.4, 0); + buf_item->bg_color = glm::vec4(1.0, 1.0, 1.0, 0); + buf_item->bounds = fgc->bounds; + buf_item->width = 10; + } + } + VkDeviceSize item_count_orig = ft->bindings.instanceBufferMaxCount; + VkDeviceSize item_count_new = ft->bindings.instanceBufferMaxCount + count; + + // copy existing buffer to new buffer + VkDeviceSize byteCount = instance_buffer_item_size * item_count_new; + PKVK_TmpBufferDetails tmpBufferDetails{}; + { + VkBuffer newBuffer; + VkBufferCreateInfo bufferCI; + bufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferCI.pNext = nullptr; + bufferCI.flags = {}; + bufferCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + bufferCI.queueFamilyIndexCount = 1; + bufferCI.pQueueFamilyIndices = &graphicsFamilyIndex; + bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + bufferCI.size = byteCount; + vkResult = vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &newBuffer); + assert(vkResult == VK_SUCCESS); + + VkMemoryRequirements vkMemReqs; + vkGetBufferMemoryRequirements(vkDevice, newBuffer, &vkMemReqs); + + vkDestroyBuffer(vkDevice, newBuffer, vkAllocator); + newBuffer = VK_NULL_HANDLE; + + bufferCI.size = vkMemReqs.size + (vkMemReqs.alignment - (vkMemReqs.size & vkMemReqs.alignment)); + vkResult = vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &newBuffer); + assert(vkResult == VK_SUCCESS); + + VkDeviceMemory new_memory; + VkMemoryAllocateInfo vkMemoryAllocateInfo; + vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + vkMemoryAllocateInfo.pNext = nullptr; + vkMemoryAllocateInfo.allocationSize = bufferCI.size; + vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(vkMemReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + vkResult = vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &new_memory); + assert(vkResult == VK_SUCCESS); + + vkResult = vkBindBufferMemory(vkDevice, newBuffer, new_memory, 0); + assert(vkResult == VK_SUCCESS); + + PKVK_BeginBuffer(transferFamilyIndex, byteCount, tmpBufferDetails, PKVK_TmpBufferFlags_NONE); + if (ft->bindings.instanceBD.buffer != VK_NULL_HANDLE) { + + VkCommandBufferBeginInfo vkCommandBufferBeginInfo; + vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkCommandBufferBeginInfo.pNext = nullptr; + // TODO consider single-use? + vkCommandBufferBeginInfo.flags = 0; + vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; + vkBeginCommandBuffer(tmpBufferDetails.cmdBuffer, &vkCommandBufferBeginInfo); + + VkBufferCopy vk_buffer_copy{}; + vk_buffer_copy.srcOffset = 0; + vk_buffer_copy.dstOffset = 0; + vk_buffer_copy.size = instance_buffer_item_size * item_count_orig; + vkCmdCopyBuffer(tmpBufferDetails.cmdBuffer, ft->bindings.instanceBD.buffer, newBuffer, 1, &vk_buffer_copy); + + vkEndCommandBuffer(tmpBufferDetails.cmdBuffer); + + VkSubmitInfo submitInfo; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.pNext = nullptr; + submitInfo.waitSemaphoreCount = 0; + submitInfo.pWaitSemaphores = nullptr; + submitInfo.pWaitDstStageMask = nullptr; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &tmpBufferDetails.cmdBuffer; + submitInfo.signalSemaphoreCount = 0; + submitInfo.pSignalSemaphores = nullptr; + vkQueueSubmit(tmpBufferDetails.queue, 1, &submitInfo, nullptr); + vkQueueWaitIdle(tmpBufferDetails.queue); + + } + PKVK_EndBuffer(tmpBufferDetails, PKVK_TmpBufferFlags_NONE); + if (ft->bindings.instanceBD.buffer != VK_NULL_HANDLE) + vkDestroyBuffer(vkDevice, ft->bindings.instanceBD.buffer, vkAllocator); + if (ft->deviceMemoryInst != VK_NULL_HANDLE) + vkFreeMemory(vkDevice, ft->deviceMemoryInst, vkAllocator); + + ft->deviceMemoryInst = new_memory; + ft->bindings.instanceBD.buffer = newBuffer; + ft->bindings.instanceBufferMaxCount = item_count_new; + } + + // create tmp local buffer & copy data to graphics card + byteCount = instance_buffer_item_size * count; + PKVK_BeginBuffer(transferFamilyIndex, byteCount, tmpBufferDetails); + { + + VkCommandBufferBeginInfo vkCommandBufferBeginInfo; + vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkCommandBufferBeginInfo.pNext = nullptr; + // TODO consider single-use? + vkCommandBufferBeginInfo.flags = 0; + vkCommandBufferBeginInfo.pInheritanceInfo = nullptr; + vkBeginCommandBuffer(tmpBufferDetails.cmdBuffer, &vkCommandBufferBeginInfo); + + memcpy(tmpBufferDetails.deviceData, instance_buffer_items.GetPtr(), instance_buffer_items.Count() * instance_buffer_item_size); + + VkBufferCopy vk_buffer_copy{}; + vk_buffer_copy.srcOffset = 0; + vk_buffer_copy.dstOffset = instance_buffer_item_size * item_count_orig; + vk_buffer_copy.size = instance_buffer_item_size * count; + vkCmdCopyBuffer(tmpBufferDetails.cmdBuffer, tmpBufferDetails.buffer, ft->bindings.instanceBD.buffer, 1, &vk_buffer_copy); + + vkEndCommandBuffer(tmpBufferDetails.cmdBuffer); + + VkSubmitInfo submitInfo; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.pNext = nullptr; + submitInfo.waitSemaphoreCount = 0; + submitInfo.pWaitSemaphores = nullptr; + submitInfo.pWaitDstStageMask = nullptr; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &tmpBufferDetails.cmdBuffer; + submitInfo.signalSemaphoreCount = 0; + submitInfo.pSignalSemaphores = nullptr; + vkQueueSubmit(tmpBufferDetails.queue, 1, &submitInfo, nullptr); + vkQueueWaitIdle(tmpBufferDetails.queue); + } + PKVK_EndBuffer(tmpBufferDetails); + + return *fr; +} + +void FontType_RemoveStringRender(FontRender fr) { + (void)fr; + // TODO + // FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)fr.index_ft]; +} diff --git a/src/font.hpp b/src/font.hpp index 494c365..116ac06 100644 --- a/src/font.hpp +++ b/src/font.hpp @@ -6,8 +6,6 @@ #include "pk.h" #include <glm/vec4.hpp> -#include <ostream> -#include <istream> /* Vert: (two triangles) @@ -47,7 +45,9 @@ struct FontType : public Entity_Base { VkImageView textureImageView = VK_NULL_HANDLE; VkDescriptorPool vkDescriptorPool = VK_NULL_HANDLE; VkDescriptorSet *vkDescriptorSets = nullptr; + FontGlyphChar *glyphs; FontRender *renders = nullptr; + uint32_t n_glyphs; FontRenderIndex n_render = FontRenderIndex{0}; FontRenderIndex h_render = FontRenderIndex{0}; FontTypeIndex index_ft = FontTypeIndex{0}; @@ -64,10 +64,11 @@ struct FontType : public Entity_Base { void FontType_Init(); void FontType_Teardown(); +void FontType_Tick(); void FontType_Serialize(std::ofstream &stream, FontType *ft); void FontType_Deserialize(std::ifstream &stream); FontType* FontType_GetFonts(FontTypeIndex &count); -FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTexture, AssetHandle glyphs); +FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle, AssetHandle glyphsHandle); void FontType_Unload(FontTypeIndex idx); FontRender FontType_AddStringRender(FontTypeIndex idx_ft, pk_cstr cstr); void FontType_RemoveStringRender(FontRender fr); diff --git a/src/game.cpp b/src/game.cpp index a95d2fd..d65afc6 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -8,6 +8,7 @@ #include "ecs.hpp" #include "entities.hpp" #include "event.hpp" +#include "font.hpp" #include "game-settings.hpp" #include "game-type-defs.hpp" #include "helpers.hpp" @@ -595,6 +596,7 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) { CreateWindow(windowProps); EntityType_Init(); PkeInput_Init(); + FontType_Init(); PkeProject_Load(pkeSettings.args.projectPath); if (pkeSettings.args.pluginPath != nullptr) { PkePlugin_Load(pkeSettings.args.pluginPath); @@ -606,6 +608,9 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) { } } + // pk_cstr test_text = cstring_to_pk_cstr("this is a test string"); + // FontRender fr = FontType_AddStringRender(FontTypeIndex{0}, test_text); + GameTimePoint lastTimePoint = pkeSettings.steadyClock.now(); double deltaTillNextRender = pkeSettings.deltaPerFrame; GameTimePoint lastLogTimePoint = pkeSettings.steadyClock.now(); @@ -702,6 +707,7 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) { Game_Teardown(); Event_Teardown(); EntityType_Teardown(); + FontType_Teardown(); PkeInput_Teardown(); PkeCamera_Teardown(); Physics_Teardown(); diff --git a/src/window.cpp b/src/window.cpp index 0cefba9..da4062c 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1,3 +1,5 @@ +#include "pk.h" +#include <vulkan/vulkan_core.h> #define GLFW_INCLUDE_NONE #define GLFW_INCLUDE_VULKAN @@ -149,7 +151,7 @@ VkDeviceSize paddedUboBufferSize; // public VkBuffer *UniformBuffers; DebugHitbox pkeDebugHitbox{}; -ImplementedPipelines pkePipelines{}; +ImplementedPKVK pkePipelines{}; /* * ImGui @@ -224,7 +226,7 @@ VkCommandBuffer GetCommandBuffer_Transfer() { return pkvk_shared.command_buffer.transfer; } -void PKVK_BeginBuffer(unsigned int family_index, VkDeviceSize requestedMemorySize, PKVK_TmpBufferDetails &tmpBufferDetails) { +void PKVK_BeginBuffer(unsigned int family_index, VkDeviceSize requestedMemorySize, PKVK_TmpBufferDetails &tmpBufferDetails, PKVK_TmpBufferFlags flags) { if (family_index == graphicsFamilyIndex) { tmpBufferDetails.queue = pkvk_shared.queue.graphics; tmpBufferDetails.cmdBuffer = pkvk_shared.command_buffer.graphics; @@ -262,12 +264,17 @@ void PKVK_BeginBuffer(unsigned int family_index, VkDeviceSize requestedMemorySiz vkResult = vkBindBufferMemory(vkDevice, tmpBufferDetails.buffer, tmpBufferDetails.deviceMemory, 0); assert(vkResult == VK_SUCCESS); + + if (!PK_HAS_FLAG(flags, PKVK_TmpBufferFlags_MAP_MEMORY)) return; + vkResult = vkMapMemory(vkDevice, tmpBufferDetails.deviceMemory, 0, transferMemAllocInfo.allocationSize, 0, &tmpBufferDetails.deviceData); assert(vkResult == VK_SUCCESS); } -void PKVK_EndBuffer(PKVK_TmpBufferDetails &tmpBufferDetails) { - if (tmpBufferDetails.deviceMemory != VK_NULL_HANDLE) vkUnmapMemory(vkDevice, tmpBufferDetails.deviceMemory); +void PKVK_EndBuffer(PKVK_TmpBufferDetails &tmpBufferDetails, PKVK_TmpBufferFlags flags) { + if (PK_HAS_FLAG(flags, PKVK_TmpBufferFlags_MAP_MEMORY)) { + if (tmpBufferDetails.deviceMemory != VK_NULL_HANDLE) vkUnmapMemory(vkDevice, tmpBufferDetails.deviceMemory); + } if (tmpBufferDetails.buffer != VK_NULL_HANDLE) vkDestroyBuffer(vkDevice, tmpBufferDetails.buffer, vkAllocator); if (tmpBufferDetails.deviceMemory != VK_NULL_HANDLE) vkFreeMemory(vkDevice, tmpBufferDetails.deviceMemory, vkAllocator); tmpBufferDetails = {}; @@ -1063,7 +1070,7 @@ void CreateRenderPass() { */ VkAttachmentDescription attachment_descriptions[3]; memset(attachment_descriptions, 0, sizeof(VkAttachmentDescription) * 3); - VkAttachmentReference attachment_refs[3];; + VkAttachmentReference attachment_refs[3]; memset(attachment_refs, 0, sizeof(VkAttachmentReference) * 3); VkSubpassDependency subpass_dependencies[2]; memset(subpass_dependencies, 0, sizeof(VkSubpassDependency) * 2); @@ -1157,7 +1164,7 @@ void CreateRenderPass() { renderPassInfo.attachmentCount = 2; if (vkCreateRenderPass(vkDevice, &renderPassInfo, vkAllocator, &pkvk_2d.render_pass) != VK_SUCCESS) { - throw "failed to create render pass!"; + throw "failed to create 2d render pass!"; } // color @@ -1191,7 +1198,7 @@ void CreateRenderPass() { renderPassInfo.attachmentCount = 3; if (vkCreateRenderPass(vkDevice, &renderPassInfo, vkAllocator, &pkvk_3d.render_pass) != VK_SUCCESS) { - throw "failed to create render pass!"; + throw "failed to create 3d render pass!"; } } @@ -1615,6 +1622,7 @@ void CreateSyncObjects() { } void CreateGraphicsPipelines() { + VkResult vkResult; PKVK_TmpBufferDetails tmpBufferDetails{}; // layouts & sampler { @@ -1637,24 +1645,33 @@ void CreateGraphicsPipelines() { .bindingCount = 2, .pBindings = vkDescriptorSetLayoutBindings, }; - vkCreateDescriptorSetLayout(vkDevice, &vkDescriptorSetLayoutCreateInfo, vkAllocator, &pkePipelines.descr_layouts.named.texture); + vkResult = vkCreateDescriptorSetLayout(vkDevice, &vkDescriptorSetLayoutCreateInfo, vkAllocator, &pkePipelines.descr_layouts.named.texture); + assert(vkResult == VK_SUCCESS); + assert(pkePipelines.descr_layouts.named.texture != VK_NULL_HANDLE); // no UBO on glyph vkDescriptorSetLayoutBindings[0] = vkDescriptorSetLayoutBindings[1]; vkDescriptorSetLayoutBindings[0].binding = 0; vkDescriptorSetLayoutCreateInfo.bindingCount = 1; - vkCreateDescriptorSetLayout(vkDevice, &vkDescriptorSetLayoutCreateInfo, vkAllocator, &pkePipelines.descr_layouts.named.glyph); + vkResult = vkCreateDescriptorSetLayout(vkDevice, &vkDescriptorSetLayoutCreateInfo, vkAllocator, &pkePipelines.descr_layouts.named.glyph); + assert(vkResult == VK_SUCCESS); + assert(pkePipelines.descr_layouts.named.glyph != VK_NULL_HANDLE); VkPipelineLayoutCreateInfo vkPipelineLayoutCreateInfo { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .pNext = nullptr, .flags = 0, - .setLayoutCount = 2, - .pSetLayouts = pkePipelines.descr_layouts.arr, + .setLayoutCount = 1, + .pSetLayouts = &pkePipelines.descr_layouts.named.texture, .pushConstantRangeCount = 0, .pPushConstantRanges = nullptr, }; - vkCreatePipelineLayout(vkDevice, &vkPipelineLayoutCreateInfo, vkAllocator, pkePipelines.pipe_layouts.arr); + vkCreatePipelineLayout(vkDevice, &vkPipelineLayoutCreateInfo, vkAllocator, &pkePipelines.pipe_layouts.named.texture); + assert(pkePipelines.pipe_layouts.named.texture != VK_NULL_HANDLE); + + vkPipelineLayoutCreateInfo.pSetLayouts = &pkePipelines.descr_layouts.named.glyph; + vkCreatePipelineLayout(vkDevice, &vkPipelineLayoutCreateInfo, vkAllocator, &pkePipelines.pipe_layouts.named.glyph); + assert(pkePipelines.pipe_layouts.named.glyph != VK_NULL_HANDLE); } // pipelines @@ -1662,83 +1679,157 @@ void CreateGraphicsPipelines() { // enqueue asset loading AssetHandle vertShaderAssetHandle{AM_GetHandle(AssetKey{"pke_txtr_vrt\0\0\0"})}; AssetHandle textureFragShaderAssetHandle { AM_GetHandle(AssetKey{"pke_txtr_frg\0\0\0"})}; + AssetHandle vertGlyphAssetHandle{AM_GetHandle(AssetKey{"pke_glyph_vrt\0\0"})}; + AssetHandle fragGlyphAssetHandle { AM_GetHandle(AssetKey{"pke_glyph_frg\0\0"})}; const long vertexBindingCount = 4; long index = 0; - VkVertexInputBindingDescription vertInputBD[vertexBindingCount]; - // model vertex - vertInputBD[index].binding = index; - vertInputBD[index].stride = sizeof(glm::vec3); - vertInputBD[index].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - index += 1; - // model normals - vertInputBD[index].binding = index; - vertInputBD[index].stride = sizeof(glm::vec3); - vertInputBD[index].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - index += 1; - // model UV - vertInputBD[index].binding = index; - vertInputBD[index].stride = sizeof(glm::vec2); - vertInputBD[index].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - index += 1; - // model index - // vertInputBD[index].binding = index; - // vertInputBD[index].stride = sizeof(uint16_t); - // vertInputBD[index].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - // index += 1; - // instance - vertInputBD[index].binding = index; - vertInputBD[index].stride = sizeof(glm::mat4); - vertInputBD[index].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE; - + VkVertexInputBindingDescription vertInputBD_txtr[vertexBindingCount]; const long vertexAttrDescCount = 7; - index = 0; - VkVertexInputAttributeDescription vertAttrDesc[vertexAttrDescCount]; - for (long i = 0; i < vertexAttrDescCount; ++i) { - vertAttrDesc[i].location = i; - } + VkVertexInputAttributeDescription vertAttrDesc_txtr[vertexAttrDescCount]; + VkPipelineVertexInputStateCreateInfo vkPipelineVertexInputStateCreateInfo_txtr; + { + // model vertex + vertInputBD_txtr[index].binding = index; + vertInputBD_txtr[index].stride = sizeof(glm::vec3); + vertInputBD_txtr[index].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + index += 1; + // model normals + vertInputBD_txtr[index].binding = index; + vertInputBD_txtr[index].stride = sizeof(glm::vec3); + vertInputBD_txtr[index].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + index += 1; + // model UV + vertInputBD_txtr[index].binding = index; + vertInputBD_txtr[index].stride = sizeof(glm::vec2); + vertInputBD_txtr[index].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + index += 1; + // instance + vertInputBD_txtr[index].binding = index; + vertInputBD_txtr[index].stride = sizeof(glm::mat4); + vertInputBD_txtr[index].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE; + // index += 1; - // model vertex - vertAttrDesc[index].binding = 0; - vertAttrDesc[index].format = VK_FORMAT_R32G32B32_SFLOAT; - vertAttrDesc[index].offset = 0; - index += 1; - - // model normals - vertAttrDesc[index].binding = 1; - vertAttrDesc[index].format = VK_FORMAT_R32G32B32_SFLOAT; - vertAttrDesc[index].offset = 0; - index += 1; - - // model UV - vertAttrDesc[index].binding = 2; - vertAttrDesc[index].format = VK_FORMAT_R32G32_SFLOAT; - vertAttrDesc[index].offset = 0; - index += 1; - - // instPosRotScale - for (long i = 0; i < 4; ++i) { - vertAttrDesc[index].binding = 3; - vertAttrDesc[index].format = VK_FORMAT_R32G32B32A32_SFLOAT; - vertAttrDesc[index].offset = sizeof(glm::vec4) * i; + index = 0; + for (long i = 0; i < vertexAttrDescCount; ++i) { + vertAttrDesc_txtr[i].location = i; + } + + // model vertex + vertAttrDesc_txtr[index].binding = 0; + vertAttrDesc_txtr[index].format = VK_FORMAT_R32G32B32_SFLOAT; + vertAttrDesc_txtr[index].offset = 0; + index += 1; + + // model normals + vertAttrDesc_txtr[index].binding = 1; + vertAttrDesc_txtr[index].format = VK_FORMAT_R32G32B32_SFLOAT; + vertAttrDesc_txtr[index].offset = 0; + index += 1; + + // model UV + vertAttrDesc_txtr[index].binding = 2; + vertAttrDesc_txtr[index].format = VK_FORMAT_R32G32_SFLOAT; + vertAttrDesc_txtr[index].offset = 0; index += 1; + + // instPosRotScale + for (long i = 0; i < 4; ++i) { + vertAttrDesc_txtr[index].binding = 3; + vertAttrDesc_txtr[index].format = VK_FORMAT_R32G32B32A32_SFLOAT; + vertAttrDesc_txtr[index].offset = sizeof(glm::vec4) * i; + index += 1; + } + + vkPipelineVertexInputStateCreateInfo_txtr.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vkPipelineVertexInputStateCreateInfo_txtr.pNext = nullptr; + vkPipelineVertexInputStateCreateInfo_txtr.flags = {}; + vkPipelineVertexInputStateCreateInfo_txtr.vertexBindingDescriptionCount = vertexBindingCount; + vkPipelineVertexInputStateCreateInfo_txtr.pVertexBindingDescriptions = vertInputBD_txtr; + vkPipelineVertexInputStateCreateInfo_txtr.vertexAttributeDescriptionCount = vertexAttrDescCount; + vkPipelineVertexInputStateCreateInfo_txtr.pVertexAttributeDescriptions = vertAttrDesc_txtr; } - // instance texture index - // vertAttrDesc[index].binding = 3; - // vertAttrDesc[index].format = VK_FORMAT_R32_SFLOAT; - // vertAttrDesc[index].offset = runningOffset; - // runningOffset += sizeof(float); - // index += 1; - - VkPipelineVertexInputStateCreateInfo vkPipelineVertexInputStateCreateInfo; - vkPipelineVertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vkPipelineVertexInputStateCreateInfo.pNext = nullptr; - vkPipelineVertexInputStateCreateInfo.flags = {}; - vkPipelineVertexInputStateCreateInfo.vertexBindingDescriptionCount = vertexBindingCount; - vkPipelineVertexInputStateCreateInfo.pVertexBindingDescriptions = vertInputBD; - vkPipelineVertexInputStateCreateInfo.vertexAttributeDescriptionCount = vertexAttrDescCount; - vkPipelineVertexInputStateCreateInfo.pVertexAttributeDescriptions = vertAttrDesc; + index = 0; + long offset = 0; + const long vertexBindingCount_glyph = 3; + VkVertexInputBindingDescription vertInputBD_glyph[vertexBindingCount_glyph]; + const long vertexAttrDescCount_glyph = 6; + VkVertexInputAttributeDescription vertAttrDesc_glyph[vertexAttrDescCount_glyph]; + VkPipelineVertexInputStateCreateInfo vkPipelineVertexInputStateCreateInfo_glyph{vkPipelineVertexInputStateCreateInfo_txtr}; + { + // model vertex + vertInputBD_glyph[index].binding = index; + vertInputBD_glyph[index].stride = sizeof(glm::vec2); + vertInputBD_glyph[index].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + index += 1; + + // model UV + vertInputBD_glyph[index].binding = index; + vertInputBD_glyph[index].stride = sizeof(glm::vec2); + vertInputBD_glyph[index].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + index += 1; + + // instance - total + vertInputBD_glyph[index].binding = index; + vertInputBD_glyph[index].stride = 0 + + sizeof(glm::vec4) + + sizeof(glm::vec4) + + sizeof(glm::ivec4) + + sizeof(float); + vertInputBD_glyph[index].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE; + // index += 1; + + index = 0; + for (long i = 0; i < vertexAttrDescCount_glyph; ++i) { + vertAttrDesc_glyph[i].location = i; + } + + // model vertex + vertAttrDesc_glyph[index].binding = 0; + vertAttrDesc_glyph[index].format = VK_FORMAT_R32G32_SFLOAT; + vertAttrDesc_glyph[index].offset = 0; + index += 1; + + // model UV + vertAttrDesc_glyph[index].binding = 1; + vertAttrDesc_glyph[index].format = VK_FORMAT_R32G32_SFLOAT; + vertAttrDesc_glyph[index].offset = 0; + index += 1; + + // instance - in_fg_color + vertAttrDesc_glyph[index].binding = 2; + vertAttrDesc_glyph[index].format = VK_FORMAT_R32G32B32A32_SFLOAT; + vertAttrDesc_glyph[index].offset = 0; + offset += sizeof(glm::vec4); + index += 1; + + // instance - in_bg_color + vertAttrDesc_glyph[index].binding = 2; + vertAttrDesc_glyph[index].format = VK_FORMAT_R32G32B32A32_SFLOAT; + vertAttrDesc_glyph[index].offset = offset; + offset += sizeof(glm::vec4); + index += 1; + + // instance - in_sprite_region + vertAttrDesc_glyph[index].binding = 2; + vertAttrDesc_glyph[index].format = VK_FORMAT_R32G32B32A32_SINT; + vertAttrDesc_glyph[index].offset = offset; + offset += sizeof(glm::ivec4); + index += 1; + + // instance - in_sprite_region + vertAttrDesc_glyph[index].binding = 2; + vertAttrDesc_glyph[index].format = VK_FORMAT_R32_SFLOAT; + vertAttrDesc_glyph[index].offset = offset; + // offset += sizeof(float); + // index += 1; + + vkPipelineVertexInputStateCreateInfo_glyph.vertexBindingDescriptionCount = vertexBindingCount_glyph; + vkPipelineVertexInputStateCreateInfo_glyph.pVertexBindingDescriptions = vertInputBD_glyph; + vkPipelineVertexInputStateCreateInfo_glyph.vertexAttributeDescriptionCount = vertexAttrDescCount_glyph; + vkPipelineVertexInputStateCreateInfo_glyph.pVertexAttributeDescriptions = vertAttrDesc_glyph; + } VkPipelineInputAssemblyStateCreateInfo vkPipelineInputAssemblyStateCreateInfo; vkPipelineInputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; @@ -1841,31 +1932,40 @@ void CreateGraphicsPipelines() { const Asset *textureVertShaderAsset = AM_Get(vertShaderAssetHandle); const Asset *textureFragShaderAsset = AM_Get(textureFragShaderAssetHandle); + const Asset *glyphVertShaderAsset = AM_Get(vertGlyphAssetHandle); + const Asset *glyphFragShaderAsset = AM_Get(fragGlyphAssetHandle); assert(textureVertShaderAsset != nullptr && textureVertShaderAsset->state == PKE_ASSET_LOADING_STATE_LOADED); assert(textureFragShaderAsset != nullptr && textureFragShaderAsset->state == PKE_ASSET_LOADING_STATE_LOADED); + assert(glyphVertShaderAsset != nullptr && glyphVertShaderAsset->state == PKE_ASSET_LOADING_STATE_LOADED); + assert(glyphFragShaderAsset != nullptr && glyphFragShaderAsset->state == PKE_ASSET_LOADING_STATE_LOADED); - VkPipelineShaderStageCreateInfo vkPipelineShaderStageCreateInfo[2]; + VkPipelineShaderStageCreateInfo vkPipelineShaderStageCreateInfo_txtr[2]; for (long i = 0; i < 2; ++i) { - vkPipelineShaderStageCreateInfo[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - vkPipelineShaderStageCreateInfo[i].pNext = nullptr; - vkPipelineShaderStageCreateInfo[i].flags = {}; - vkPipelineShaderStageCreateInfo[i].pName = "main"; - vkPipelineShaderStageCreateInfo[i].pSpecializationInfo = nullptr; + vkPipelineShaderStageCreateInfo_txtr[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vkPipelineShaderStageCreateInfo_txtr[i].pNext = nullptr; + vkPipelineShaderStageCreateInfo_txtr[i].flags = {}; + vkPipelineShaderStageCreateInfo_txtr[i].pName = "main"; + vkPipelineShaderStageCreateInfo_txtr[i].pSpecializationInfo = nullptr; } - - vkPipelineShaderStageCreateInfo[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - vkPipelineShaderStageCreateInfo[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - // vkPipelineShaderStageCreateInfo[0].module = // deferred - // vkPipelineShaderStageCreateInfo[1].module = // deferred - - VkGraphicsPipelineCreateInfo vkGraphicsPipelineCreateInfo[2]; + vkPipelineShaderStageCreateInfo_txtr[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + vkPipelineShaderStageCreateInfo_txtr[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + VkPipelineShaderStageCreateInfo vkPipelineShaderStageCreateInfo_glyph[2]; for (long i = 0; i < 2; ++i) { + vkPipelineShaderStageCreateInfo_glyph[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vkPipelineShaderStageCreateInfo_glyph[i].pNext = nullptr; + vkPipelineShaderStageCreateInfo_glyph[i].flags = {}; + vkPipelineShaderStageCreateInfo_glyph[i].pName = "main"; + vkPipelineShaderStageCreateInfo_glyph[i].pSpecializationInfo = nullptr; + } + vkPipelineShaderStageCreateInfo_glyph[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + vkPipelineShaderStageCreateInfo_glyph[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + + VkGraphicsPipelineCreateInfo vkGraphicsPipelineCreateInfo[3]; + for (long i = 0; i < 3; ++i) { vkGraphicsPipelineCreateInfo[i].sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; vkGraphicsPipelineCreateInfo[i].pNext = nullptr; vkGraphicsPipelineCreateInfo[i].flags = {}; vkGraphicsPipelineCreateInfo[i].stageCount = 2; - vkGraphicsPipelineCreateInfo[i].pStages = vkPipelineShaderStageCreateInfo; - vkGraphicsPipelineCreateInfo[i].pVertexInputState = &vkPipelineVertexInputStateCreateInfo; vkGraphicsPipelineCreateInfo[i].pInputAssemblyState = &vkPipelineInputAssemblyStateCreateInfo; vkGraphicsPipelineCreateInfo[i].pTessellationState = nullptr; vkGraphicsPipelineCreateInfo[i].pViewportState = &vkPipelineViewportStateCreateInfo; @@ -1873,28 +1973,57 @@ void CreateGraphicsPipelines() { vkGraphicsPipelineCreateInfo[i].pDepthStencilState = &vkPipelineDepthStencilStateCreateInfo; vkGraphicsPipelineCreateInfo[i].pColorBlendState = &vkPipelineColorBlendStateCreateInfo; vkGraphicsPipelineCreateInfo[i].pDynamicState = &vkPipelineDynamicStateCreateInfo; - vkGraphicsPipelineCreateInfo[i].layout = pkePipelines.pipe_layouts.named.texture; - vkGraphicsPipelineCreateInfo[i].renderPass = pkvk_3d.render_pass; vkGraphicsPipelineCreateInfo[i].subpass = 0; vkGraphicsPipelineCreateInfo[i].basePipelineHandle = VK_NULL_HANDLE; vkGraphicsPipelineCreateInfo[i].basePipelineIndex = {}; } + vkGraphicsPipelineCreateInfo[0].layout = pkePipelines.pipe_layouts.named.texture; + vkGraphicsPipelineCreateInfo[1].layout = pkePipelines.pipe_layouts.named.texture; + vkGraphicsPipelineCreateInfo[2].layout = pkePipelines.pipe_layouts.named.glyph; + + vkGraphicsPipelineCreateInfo[0].renderPass = pkvk_3d.render_pass; + vkGraphicsPipelineCreateInfo[1].renderPass = pkvk_3d.render_pass; + vkGraphicsPipelineCreateInfo[2].renderPass = pkvk_2d.render_pass; + + vkGraphicsPipelineCreateInfo[0].pVertexInputState = &vkPipelineVertexInputStateCreateInfo_txtr; + vkGraphicsPipelineCreateInfo[1].pVertexInputState = &vkPipelineVertexInputStateCreateInfo_txtr; + vkGraphicsPipelineCreateInfo[2].pVertexInputState = &vkPipelineVertexInputStateCreateInfo_glyph; + vkGraphicsPipelineCreateInfo[0].pRasterizationState = &vkPipelineRasterizationStateCreateInfoFill; vkGraphicsPipelineCreateInfo[1].pRasterizationState = &vkPipelineRasterizationStateCreateInfoLine; + vkGraphicsPipelineCreateInfo[2].pRasterizationState = &vkPipelineRasterizationStateCreateInfoFill; + + vkGraphicsPipelineCreateInfo[0].pStages = vkPipelineShaderStageCreateInfo_txtr; + vkGraphicsPipelineCreateInfo[1].pStages = vkPipelineShaderStageCreateInfo_txtr; + vkGraphicsPipelineCreateInfo[2].pStages = vkPipelineShaderStageCreateInfo_glyph; // deffered shader creation - vkPipelineShaderStageCreateInfo[0].module = UploadShader(vertShaderAssetHandle); - vkPipelineShaderStageCreateInfo[1].module = UploadShader(textureFragShaderAssetHandle); + vkPipelineShaderStageCreateInfo_txtr[0].module = UploadShader(vertShaderAssetHandle); + vkPipelineShaderStageCreateInfo_txtr[1].module = UploadShader(textureFragShaderAssetHandle); + vkPipelineShaderStageCreateInfo_glyph[0].module = UploadShader(vertGlyphAssetHandle); + vkPipelineShaderStageCreateInfo_glyph[1].module = UploadShader(fragGlyphAssetHandle); - vkCreateGraphicsPipelines(vkDevice, VK_NULL_HANDLE, 2, vkGraphicsPipelineCreateInfo, vkAllocator, pkePipelines.pipelines.arr); + vkResult = vkCreateGraphicsPipelines(vkDevice, VK_NULL_HANDLE, 1, &vkGraphicsPipelineCreateInfo[0], vkAllocator, &pkePipelines.pipelines.named.texture); + assert(vkResult == VK_SUCCESS); + vkResult = vkCreateGraphicsPipelines(vkDevice, VK_NULL_HANDLE, 1, &vkGraphicsPipelineCreateInfo[1], vkAllocator, &pkePipelines.pipelines.named.texture_wireframe); + assert(vkResult == VK_SUCCESS); + vkResult = vkCreateGraphicsPipelines(vkDevice, VK_NULL_HANDLE, 1, &vkGraphicsPipelineCreateInfo[2], vkAllocator, &pkePipelines.pipelines.named.glyph); + assert(vkResult == VK_SUCCESS); + assert(pkePipelines.pipelines.named.texture != VK_NULL_HANDLE); + assert(pkePipelines.pipelines.named.texture_wireframe != VK_NULL_HANDLE); + assert(pkePipelines.pipelines.named.glyph != VK_NULL_HANDLE); for (long i = 0; i < 2; ++i) { - vkDestroyShaderModule(vkDevice, vkPipelineShaderStageCreateInfo[i].module, vkAllocator); + vkDestroyShaderModule(vkDevice, vkPipelineShaderStageCreateInfo_txtr[i].module, vkAllocator); + vkDestroyShaderModule(vkDevice, vkPipelineShaderStageCreateInfo_glyph[i].module, vkAllocator); } - AM_Release(textureFragShaderAssetHandle); + // reverse order + AM_Release(fragGlyphAssetHandle); + AM_Release(vertGlyphAssetHandle); AM_Release(vertShaderAssetHandle); + AM_Release(textureFragShaderAssetHandle); } // debug texture @@ -2575,7 +2704,7 @@ void RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) { vkCmdSetViewport(commandBuffer, 0, 1, &viewport); vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - // TODO 2d overlay grbinds + // 2d overlay grbinds FontTypeIndex count; FontType *fts = FontType_GetFonts(count); for (FontTypeIndex i = FontTypeIndex{0}; i < count; ++i) @@ -2584,7 +2713,6 @@ void RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) { vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipelines.named.glyph); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pkePipelines.pipe_layouts.named.glyph, 0, 1, &ft->vkDescriptorSets[imageIndex], 0, {}); - vkCmdBindVertexBuffers(commandBuffer, 0, 1, &UniformBuffers[imageIndex], offsets); vkCmdBindIndexBuffer(commandBuffer, ft->bindings.indexBD.buffer, ft->bindings.indexBD.offsets[0], VK_INDEX_TYPE_UINT16); vkCmdBindVertexBuffers(commandBuffer, ft->bindings.vertexBD.firstBinding, ft->bindings.vertexBD.bindingCount, &ft->bindings.vertexBD.buffer, ft->bindings.vertexBD.offsets); @@ -2836,18 +2964,22 @@ void DestroyWindow() { vkDestroyImage(vkDevice, pkeDebugHitbox.vkImage, vkAllocator); vkFreeMemory(vkDevice, pkeDebugHitbox.textureMemory, vkAllocator); - for (long i = 0; i < 3; ++i) { - if (pkePipelines.pipelines.arr[i] != VK_NULL_HANDLE) - vkDestroyPipeline(vkDevice, pkePipelines.pipelines.arr[i], vkAllocator); - } - for (long i = 0; i < 2; ++i) { - if (pkePipelines.pipelines.arr[i] != VK_NULL_HANDLE) - vkDestroyPipelineLayout(vkDevice, pkePipelines.pipe_layouts.arr[i], vkAllocator); - } - for (long i = 0; i < 2; ++i) { - if (pkePipelines.pipelines.arr[i] != VK_NULL_HANDLE) - vkDestroyDescriptorSetLayout(vkDevice, pkePipelines.descr_layouts.arr[i], vkAllocator); - } + if (pkePipelines.pipelines.named.texture != VK_NULL_HANDLE) + vkDestroyPipeline(vkDevice, pkePipelines.pipelines.named.texture, vkAllocator); + if (pkePipelines.pipelines.named.texture_wireframe != VK_NULL_HANDLE) + vkDestroyPipeline(vkDevice, pkePipelines.pipelines.named.texture_wireframe, vkAllocator); + if (pkePipelines.pipelines.named.glyph != VK_NULL_HANDLE) + vkDestroyPipeline(vkDevice, pkePipelines.pipelines.named.glyph, vkAllocator); + + if (pkePipelines.pipe_layouts.named.texture != VK_NULL_HANDLE) + vkDestroyPipelineLayout(vkDevice, pkePipelines.pipe_layouts.named.texture, vkAllocator); + if (pkePipelines.pipe_layouts.named.glyph != VK_NULL_HANDLE) + vkDestroyPipelineLayout(vkDevice, pkePipelines.pipe_layouts.named.glyph, vkAllocator); + + if (pkePipelines.descr_layouts.named.texture != VK_NULL_HANDLE) + vkDestroyDescriptorSetLayout(vkDevice, pkePipelines.descr_layouts.named.texture, vkAllocator); + if (pkePipelines.descr_layouts.named.glyph != VK_NULL_HANDLE) + vkDestroyDescriptorSetLayout(vkDevice, pkePipelines.descr_layouts.named.glyph, vkAllocator); for (long i = 0; i < swapchainLength; ++i) { vkDestroyBuffer(vkDevice, UniformBuffers[i], vkAllocator); diff --git a/src/window.hpp b/src/window.hpp index 5cb346f..f511d80 100644 --- a/src/window.hpp +++ b/src/window.hpp @@ -60,23 +60,20 @@ struct DebugHitbox { VkDescriptorSet *vkDescriptorSets = nullptr; }; extern DebugHitbox pkeDebugHitbox; -struct ImplementedPipelines { - union { - VkDescriptorSetLayout arr[2] = { VK_NULL_HANDLE, VK_NULL_HANDLE }; - struct ImplementedPipelineLayoutsByName { +struct ImplementedPKVK { + struct ImplementedDescrSetLayouts { + struct ImplementedDescrSetLayoutsByName { VkDescriptorSetLayout texture; VkDescriptorSetLayout glyph; } named; } descr_layouts; - union { - VkPipelineLayout arr[2] = { VK_NULL_HANDLE, VK_NULL_HANDLE }; + struct ImplementedPipelineLayouts { struct ImplementedPipelineLayoutsByName { VkPipelineLayout texture; VkPipelineLayout glyph; } named; } pipe_layouts; - union { - VkPipeline arr[3] = { VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE }; + struct ImplementedPipelines { struct ImplementedPipelinesByName { VkPipeline texture; VkPipeline texture_wireframe; @@ -84,7 +81,7 @@ struct ImplementedPipelines { } named; } pipelines; }; -extern ImplementedPipelines pkePipelines; +extern ImplementedPKVK pkePipelines; void CreateWindow(PKEWindowProperties wp); void DestroyWindow(); @@ -94,6 +91,11 @@ void Render(); unsigned int FindMemoryTypeIndex(uint32_t typeFilter, VkMemoryPropertyFlags memPropertyFlags); void CalculateCombinedMemReqs(uint64_t memReqsCount, VkMemoryRequirements *memReqs, VkMemoryRequirements &combinedMemReqs); +enum PKVK_TmpBufferFlags : uint8_t { + PKVK_TmpBufferFlags_NONE = 0, + PKVK_TmpBufferFlags_MAP_MEMORY = 1, + PKVK_TmpBufferFlags_ALL = 0xFF, +}; struct PKVK_TmpBufferDetails { VkQueue queue = VK_NULL_HANDLE; VkCommandBuffer cmdBuffer = VK_NULL_HANDLE; @@ -101,7 +103,7 @@ struct PKVK_TmpBufferDetails { VkDeviceMemory deviceMemory = VK_NULL_HANDLE; void *deviceData = nullptr; }; -void PKVK_BeginBuffer(unsigned int family_index, VkDeviceSize requestedMemorySize, PKVK_TmpBufferDetails &tmpBufferDetails); -void PKVK_EndBuffer(PKVK_TmpBufferDetails &tmpBufferDetails); +void PKVK_BeginBuffer(unsigned int family_index, VkDeviceSize requestedMemorySize, PKVK_TmpBufferDetails &tmpBufferDetails, PKVK_TmpBufferFlags flags = PKVK_TmpBufferFlags_ALL); +void PKVK_EndBuffer(PKVK_TmpBufferDetails &tmpBufferDetails, PKVK_TmpBufferFlags flags = PKVK_TmpBufferFlags_ALL); #endif /* PKE_WINDOW_HPP */ |
