summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-02-04 19:17:59 -0500
committerJonathan Bradley <jcb@pikum.xyz>2025-02-04 19:17:59 -0500
commit61e179f9580c985cb5ca80ea732fc7572d31c489 (patch)
tree122ff15c6d94ce5aebff4ff6f1fc6d13317abe16
parenta3fb454f9935960dc2d367455f891d8fedfb9016 (diff)
pke: chkpt: text rendering, no errors but blank
-rw-r--r--assets/shaders/glyph.vert2
-rw-r--r--editor/editor.cpp163
-rw-r--r--src/font.cpp430
-rw-r--r--src/font.hpp7
-rw-r--r--src/game.cpp6
-rw-r--r--src/window.cpp366
-rw-r--r--src/window.hpp24
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 */