cleaned build script, further work on different types of asset loading (needs rework)

This commit is contained in:
Matthew 2025-05-24 21:40:29 +10:00
parent b642955c8d
commit 31d4066acf
17 changed files with 388 additions and 198 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
build/
old_build/
external/dxvk
assets/shaders

View File

@ -120,9 +120,7 @@ if ($Global:vulkan)
if ($Global:pack)
{
Pop-Location
Invoke-Expression ".\build\$($packer_out_name)"
Push-Location build
Invoke-Expression ".\$($packer_out_name)"
}
if (-not (Test-Path -Path ".\$($vma_out_name)" -PathType "Leaf"))

View File

@ -16,15 +16,12 @@ if [ -v test ]; then test_build=1; echo "[test build]"; fi
# source files
source_files="../src/entry_linux.c"
packer_source_files="../src/packer.c"
# includes
include_flags="-I../src/ -I../external/ -L. -I../external/dxvk/include/ -L../external/dxvk/lib/"
packer_include_flags="-I../src/ -I../external/"
# executable name
out_name="Gears"
packer_out_name="Packer"
# vma flags
vma_source_files="../external/vma/vma.cpp"
@ -32,6 +29,12 @@ vma_compile_flags="-std=c++20 -D_USE_MATH_DEFINES -I../external/vma -c -Wno-ever
vma_out="-o"
vma_obj="vma.o"
# packer
packer_source_files="../src/packer.c"
packer_include_flags="-I../src/ -I../external/"
packer_out_name="Packer"
packer_flags="-DBUILD_PACKER"
# glslc
glsl_compile="glslc"
glsl_flags="--target-spv=spv1.6 -std=460"
@ -41,7 +44,7 @@ glsl_stage_tesc="-fshader-stage=tesc"
glsl_stage_tese="-fshader-stage=tese"
glsl_stage_geom="-fshader-stage=geom"
glsl_stage_comp="-fshader-stage=comp"
glsl_out="-o./shaders/glsl/"
glsl_out="-o../assets/shaders/"
# clang
clang_common="${include_flags} ${render_flag} -DCOMPILER_CLANG -std=c23 -fuse-ld=mold -Xclang -flto-visibility-public-std -Wno-unknown-warning-option -fdiagnostics-absolute-paths -Wall -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wno-for-loop-analysis -DVMA_STATIC_VULKAN_FUNCTIONS=0 -ferror-limit=60"
@ -83,12 +86,10 @@ mkdir -p build
cd build
if [ ! -v packer ]; then
# SPIR-V
mkdir -p ../assets/shaders
if [ -v vulkan ]; then
mkdir -p ./shaders/glsl
for file in ../src/shaders/glsl/*.glsl; do
for file in ../src/shaders/glsl/*.glsl; do
base_name=$(basename -- "$file" .glsl)
case "$base_name" in
@ -102,25 +103,23 @@ if [ -v vulkan ]; then
esac
$glsl_compile $glsl_flags $glsl_stage $file "${glsl_out}${base_name}.spv"
done
fi
done
# VMA
if ! [ -f libvma.a ]; then
$cpp_compiler $vma_compile_flags $vma_source_files $vma_out $vma_obj
ar rcs libvma.a vma.o
rm vma.o
fi
elif [ -v packer ] || ! [ -f Packer ]; then
$compile $packer_source_files $compile_link $link_os_gfx $packer_include_flags $out $packer_out_name
# Packer
if [ -v packer ] || ! [ -f Packer ]; then
$compile $packer_source_files $compile_link $link_os_gfx $packer_flags $packer_include_flags $out $packer_out_name
fi
if [ -v pack ]; then
cd ..
./build/Packer
cd build
if [ -v pack ] || ! [ -f assets.sgp ]; then
./Packer
fi
if ! [ -v packer ]; then
$compile $source_files $compile_link $link_os_gfx $out $out_name
fi
$compile $source_files $compile_link $link_os_gfx $out $out_name

View File

@ -25,10 +25,14 @@ const u32 M3D_LABEL = CreateMagicValue('L', 'B', 'L', 'S');
// ::Assets::Globals::Start::
u8 ASSET_PACK[] =
{
#embed "../assets.sgp"
};
#ifndef BUILD_PACKER
u8 ASSET_PACK[] =
{
#embed "../build/assets.sgp"
};
#else
u8 ASSET_PACK[] = {};
#endif
static FileHeader File_Header = {0};
@ -139,21 +143,41 @@ static Asset apLoadModel(ModelAsset asset_id)
{
AssetFile *asset_info = Model_Assets + asset_id;
asset.bytes = FLMemAlloc(asset_info->len);
MemCpy(asset.bytes, &ASSET_PACK[asset_info->data_offset], asset_info->len);
asset.len = asset_info->len;
u8 *bytes = FLMemAlloc(asset_info->len);
MemCpy(bytes, &ASSET_PACK[asset_info->data_offset], asset_info->len);
asset.model = apParseModel(bytes);
FLMemFree(bytes);
Model_Asset_Lookup[asset_id] = asset;
}
return asset;
}
static TextureAssetMeta apGetTextureMeta(TextureAsset asset_id)
static TexMeta apGetTextureMeta(TextureAsset asset_id)
{
AssetFile *asset_file = Texture_Assets + asset_id;
return asset_file->texture_meta;
}
static ModelMeta apGetModelMeta(ModelAsset asset_id)
{
/*
AssetFile *asset_file = Model_Assets + asset_id;
return asset_file->model_meta;
*/
ModelMeta meta = {0};
Asset asset = Model_Asset_Lookup[asset_id];
if (asset.model != NULL)
{
meta.i_count = asset.model->i_count;
}
return meta;
}
static void apUnloadTexture(TextureAsset asset_id)
{
Asset *asset = Texture_Asset_Lookup + asset_id;
@ -236,3 +260,4 @@ static m3dModel *apParseModel(rawptr data)
}
// ::Assets::Models::Functions::End::

View File

@ -70,22 +70,25 @@ typedef enum ModelAssetTag_e : u32
MODEL_ASSET_TAG_MAX,
} ModelAssetTag;
typedef struct TextureAssetMeta
typedef struct TexMeta
{
u32 w;
u32 h;
u32 ch;
} TextureAssetMeta;
} TexMeta;
typedef struct ModelAssetMeta
typedef struct ModelMeta
{
u32 vert_count;
u32 idx_count;
} ModelAssetMeta;
u32 i_count;
} ModelMeta;
typedef struct Asset
{
union
{
u8 *bytes;
m3dModel *model;
};
u64 len;
} Asset;
@ -101,8 +104,8 @@ typedef struct AssetFile
u64 len;
union
{
TextureAssetMeta texture_meta;
ModelAssetMeta model_meta;
TexMeta texture_meta;
ModelMeta model_meta;
};
} AssetFile;
@ -127,7 +130,8 @@ static void apInit();
static Asset apLoadTexture(TextureAsset asset_id);
static Asset apLoadShader(ShaderAsset asset_id);
static Asset apLoadModel(ModelAsset asset_id);
static TextureAssetMeta apGetTextureMeta(TextureAsset asset_id);
static TexMeta apGetTextureMeta(TextureAsset asset_id);
static ModelMeta apGetModelMeta(ModelAsset asset_id);
static void apUnloadTexture(TextureAsset asset_id);
static void apUnloadShader(ShaderAsset asset_id);
static void apUnloadModel(ModelAsset asset_id);

View File

@ -24,6 +24,7 @@
#include "stb/stb_image.h"
#include "xxhash/xxhash.h"
#include "fastlz/fastlz.h"
#include "m3d/m3d.h"
#include "renderer.h"
#include "game.h"

View File

@ -63,37 +63,16 @@ static void gRunCycle(gGameCtx *ctx, pGameInput *inputs, u32 i_count)
vTextureCleanUp();
/*
if (gButton(ctx, "Show 2", 150.0f, 150.0f, 200.0f, 200.0f))
{
gWindow(ctx, "Window 2", 500.0f, 500.0f, 600.0f, 600.0f);
}
if (gButton(ctx, "Show 1", 50.0f, 50.0f, 100.0f, 100.0f))
{
gWindow(ctx, "Window 1", 200.0f, 200.0f, 400.0f, 400.0f);
}
if (gButton(ctx, "Show 3", 150.0f, 300.0f, 200.0f, 350.0f))
{
gWindow(ctx, "Window 3", 250.0f, 500.0f, 400.0f, 650.0f);
}
*/
u64 index = vFrameIndex();
rDescHandle texture;
if (index == 0)
texture = rTextureLoad(HAMSMOKER);
else
texture = rTextureLoad(HOG);
rTextureUnload(texture);
rDescHandle yoder = rMeshLoad(MODEL_YODA);
ctx->pc.mesh_index = yoder.desc_index;
ModelMeta model_meta = apGetModelMeta(MODEL_YODA);
rViewportSize(&ctx->pc.res);
ctx->pc.time = (f32)pCPUTimerRead();
gWindow(ctx, "texture", 100.0f, 100.0f, 300.0f, 300.0f, texture);
rawptr vert_buffer = rBufferGUIVertMapping();
rawptr idx_buffer = rBufferGUIIdxMapping();
@ -102,14 +81,17 @@ static void gRunCycle(gGameCtx *ctx, pGameInput *inputs, u32 i_count)
vBufferQueueWait();
rPipelineBind(rPIPELINE_GUI, rPT_GRAPHICS);
rPipelineBind(rPIPELINE_PBR, rPT_GRAPHICS);
rPushConstantsSet(&ctx->pc);
rBufferBindGUIVertex();
rBufferBindGUIIndex();
//rBufferBindGUIVertex();
//rBufferBindGUIIndex();
rDrawIndexed(6, ctx->gui.instance_count);
rBufferBindMesh(&ctx->pc, yoder);
rDrawIndexed(model_meta.i_count, 1);
rFrameFinish();

View File

@ -102,60 +102,20 @@ i32 WriteHeader(pFile file, FileHeader *header)
void MoveToShaderDir(c8 **return_dir)
{
if (pDirIsVisible("build"))
{
Assert(pDirNavigate("build/shaders/glsl") == 0, "Unable to change to shader directory");
*return_dir = "../../..";
}
else if (pDirIsVisible("shaders"))
{
Assert(pDirNavigate("shaders/glsl") == 0 , "Unable to change to shader directory");
*return_dir = "../..";
}
else
Assert(false, "Unable to find shader directory");
Assert(pDirNavigate("../assets/shaders") == 0, "Unable to change to shader directory");
*return_dir = "../../build";
}
void MoveToTextureDir(c8 **return_dir)
{
if (pDirIsVisible("textures"))
{
Assert(pDirNavigate("./textures") == 0, "Unable to change to textures directory");
*return_dir = "..";
}
else if (pDirIsVisible("assets"))
{
Assert(pDirNavigate("./assets/textures") == 0, "Unable to change to assets directory");
*return_dir = "../..";
}
else if (pDirIsVisible("shaders"))
{
Assert(pDirNavigate("../assets/textures") == 0, "Unable to change to assets directory");
*return_dir = "../build";
}
else
Assert(false, "Unable to find assets directory");
*return_dir = "../../build";
}
void MoveToModelDir(c8 **return_dir)
{
if (pDirIsVisible("models"))
{
Assert(pDirNavigate("./models") == 0, "Unable to change to models directory");
*return_dir = "..";
}
else if (pDirIsVisible("assets"))
{
Assert(pDirNavigate("./assets/models") == 0, "Unable to change to assets directory");
*return_dir = "../..";
}
else if (pDirIsVisible("shaders"))
{
Assert(pDirNavigate("../assets/models") == 0, "Unable to change to assets directory");
*return_dir = "../build";
}
else
Assert(false, "Unable to find assets directory");
*return_dir = "../../build";
}
void InitHeader(FileHeader *header)
@ -450,12 +410,17 @@ int main(int argc, c8 **argv)
}
#endif
if (pDirIsVisible("build"))
{
Assert(pDirNavigate("./build") == 0, "Unable to change to build directory");
}
SetArrayLookups();
void *mem = pMemAllocZeroed(GB(1));
Arena *arena = ArenaInitDebug(mem, GB(1), __LINE__);
pFile file = pFileOpen("assets.sgp", pFS_WRITE | pFS_TRUNC);
pFile file = pFileOpen("assets.sgp", pFS_WRITE | pFS_TRUNC | pFS_CREATE);
Assert(file > 0, "File is null");
FileHeader header = {0};

View File

@ -123,6 +123,7 @@ typedef enum e_pFSAccess
pFS_WRITE = 0x02,
pFS_TRUNC = 0x04,
pFS_APPEND = 0x08,
pFS_CREATE = 0x10,
} pFSAccess;
b32 pDirNavigate(c8 *dir);

View File

@ -243,11 +243,16 @@ static pFile pFileOpen(c8 *file_name, pFSAccess acc)
flags = O_WRONLY;
if (BitEq(acc, pFS_TRUNC))
{
flags |= O_TRUNC;
}
else if (BitEq(acc, pFS_APPEND))
flags |= O_APPEND;
return open(file_name, flags);
if (BitEq(acc, pFS_CREATE))
flags |= O_CREAT;
return open(file_name, flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
}
static void pFileClose(pFile file)

View File

@ -44,6 +44,7 @@ typedef enum RenderBufferType_e
rRBT_STORAGE = 0x0008,
rRBT_HOST = 0x0010,
rRBT_STAGING = 0x0020,
rRBT_ADDR = 0x0040,
rRBT_HOST_VERTEX = rRBT_HOST | rRBT_VERTEX,
rRBT_HOST_INDEX = rRBT_HOST | rRBT_INDEX,
rRBT_HOST_UNIFORM = rRBT_HOST | rRBT_UNIFORM,
@ -110,13 +111,16 @@ void rDestroy();
static b32 rBufferMap();
static rDescHandle rTextureLoad(TextureAsset asset_id);
static rDescHandle rMeshLoad(ModelAsset asset_id);
static void rTextureUnload(rDescHandle handle);
static void rMeshUnload(rDescHandle handle);
static void rBufferBindVertex(rRenderBuffer *buffer);
static void rBufferBindIndex(rRenderBuffer *buffer);
static rawptr rBufferGUIVertMapping();
static rawptr rBufferGUIIdxMapping();
static void rBufferBindGUIVertex();
static void rBufferBindGUIIndex();
static void rBufferBindMesh(rPushConst *pc, rDescHandle handle);
// ::Renderer::Uniforms::Header::
// ::Renderer::PushConstants::Header::

View File

@ -75,7 +75,7 @@ static inline VkSemaphore vFrameSwapSem()
return v_Renderer.frame_handles[vFrameIndex()].sc_sem;
}
static inline vBufferAllocPtrArray *vFrameBuffers()
static inline vBufferPtrArray *vFrameBuffers()
{
return v_Renderer.buffers.frame_buffers + vFrameIndex();
}
@ -337,14 +337,14 @@ static void vSwapchainResize()
// ::Vulkan::Images::Functions::Start::
static vImageView *vImageViewCreate(TextureAssetMeta meta)
static vImageView *vImageViewCreate(TexMeta meta)
{
vImageView *view = FLMemAlloc(sizeof(vImageView));
Assert(vImageViewInit(view, meta.w, meta.h, meta.ch), "vImageViewCreate failure: vImage");
return view;
}
static vTransfer *vTextureTransferInit(Arena *arena, u32 asset_id, VkImage image, u8 *bytes, TextureAssetMeta *meta)
static vTransfer *vTextureTransferInit(Arena *arena, u32 asset_id, VkImage image, rawptr bytes, TexMeta *meta)
{
vTransfer *transfer = MakeArray(arena, vTransfer, 1);
@ -491,7 +491,14 @@ static void vDescPushImageAndHandle(rDescHandle handle, vImageView *view)
vImagePush(handle.asset_id, view);
}
static u32 vDescPushImage(vImageView *view)
static void vDescPushModelAndHandle(rDescHandle handle, vModelBuffers *buffer)
{
vDescHandlePush(vDT_MESH, handle);
vModelPush(handle.asset_id, buffer);
}
// TODO: batch descriptor writes
static u32 vDescPushImageDesc(vImageView *view)
{
u32 index = vDescIndexPop(vDT_SAMPLED_IMAGE);
@ -515,6 +522,31 @@ static u32 vDescPushImage(vImageView *view)
return index;
}
static u32 vDescPushMeshDesc(vMeshBuffer *buffer)
{
u32 index = vDescIndexPop(vDT_MESH);
VkDescriptorBufferInfo buffer_info = {
.buffer = buffer->uniform.buffer,
.offset = 0,
.range = VK_WHOLE_SIZE,
};
VkWriteDescriptorSet desc_write = {
.sType = STYPE(WRITE_DESCRIPTOR_SET),
.dstSet = v_Renderer.handles.desc_sets[vDT_MESH],
.dstBinding = 0,
.descriptorCount = 1,
.dstArrayElement = index,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.pBufferInfo = &buffer_info,
};
vkUpdateDescriptorSets(v_Renderer.handles.device, 1, &desc_write, 0, NULL);
return index;
}
static void vDescIndexPush(vDescType type, u32 index)
{
vDescBindings *bindings = v_Renderer.desc_bindings + type;
@ -586,8 +618,33 @@ static void vDescHandleDelete(vDescType type, u32 asset_id)
// ::Vulkan::Buffers::Functions::Start::
static vTransfer *vMeshTransferInit(Arena *arena, u32 asset_id, vMeshBuffer *mesh, rawptr bytes, u64 size)
{
vTransfer *transfer = MakeArray(arena, vTransfer, 1);
static VkResult vBufferCreate(vBufferAlloc* buf, rRenderBufferType type, u64 size)
transfer->type = vTT_MESH;
transfer->data = bytes;
transfer->size = size;
transfer->mesh = mesh;
transfer->asset_id = asset_id;
return transfer;
}
static vTransfer *vBufferTransferInit(Arena *arena, u32 asset_id, vBuffer *index, rawptr bytes, u64 size)
{
vTransfer *transfer = MakeArray(arena, vTransfer, 1);
transfer->type = vTT_BUFFER;
transfer->data = bytes;
transfer->asset_id = asset_id;
transfer->size = size;
transfer->buffer = index->buffer;
return transfer;
}
static VkResult vBufferCreate(vBuffer* buf, rRenderBufferType type, u64 size)
{
Assert(type != rRBT_NONE, "vBufferCreate: rRenderBufferType must not be rRBT_NONE");
@ -628,6 +685,12 @@ static VkResult vBufferCreate(vBufferAlloc* buf, rRenderBufferType type, u64 siz
buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
}
if (BitEq(type, rRBT_ADDR))
{
buffer_info.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
}
if ((type & rRBT_HOST) == rRBT_HOST || type == rRBT_STAGING)
{
alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
@ -663,7 +726,30 @@ static rawptr vMapBuffer(VmaAllocation alloc)
return ptr;
}
// ::Vulkan::Buffers::Functions::Start::
static void vModelPush(ModelAsset asset_id, vModelBuffers *buffer)
{
HashTablePushU64Rawptr(&v_Renderer.buffers.buffers, asset_id, buffer);
}
static vModelBuffers *vModelPop(ModelAsset asset_id)
{
return (vModelBuffers *)HashTableDeleteU64Rawptr(&v_Renderer.buffers.buffers, asset_id);
}
static vModelBuffers *vModelSearch(ModelAsset asset_id)
{
vModelBuffers *buffers = NULL;
KeyValuePair *pair = HashTableSearchU64(&v_Renderer.buffers.buffers, asset_id);
if (pair != NULL)
{
buffers = (vModelBuffers *)pair->value_rawptr;
}
return buffers;
}
// ::Vulkan::Buffers::Functions::End::
@ -885,6 +971,7 @@ static b32 vDeviceCheckFeatureSupport(VkPhysicalDevice device)
result &= (b32)features_12.descriptorBindingPartiallyBound;
result &= (b32)features_12.runtimeDescriptorArray;
result &= (b32)features_12.shaderSampledImageArrayNonUniformIndexing;
result &= (b32)features_12.shaderUniformBufferArrayNonUniformIndexing;
result &= (b32)features_13.synchronization2;
result &= (b32)features_13.dynamicRendering;
@ -1106,6 +1193,7 @@ static b32 vDeviceFunctionsInit() {
INIT_DEV_FN(vkCmdClearColorImage);
INIT_DEV_FN(vkCreateSampler);
INIT_DEV_FN(vkDestroySampler);
INIT_DEV_FN(vkGetBufferDeviceAddress);
return true;
}
@ -1714,7 +1802,7 @@ static b32 vBuffersInit()
for (u32 i = 0; i < FRAME_OVERLAP; i++)
{
InitArrayType(buf->frame_buffers[i], arena, vBufferAlloc *, 128);
InitArrayType(buf->frame_buffers[i], arena, vBuffer *, 128);
InitArrayType(buf->frame_images[i], arena, vImageView *, 128);
buf->tex_destroy_queue.data[i] = MakeArray(arena, b8, TEXTURE_ASSET_MAX);
@ -1784,6 +1872,7 @@ static void vTransferUpload(vTransfer **transfers, u32 count)
u64 transfer_size = 0;
VkDeviceSize offset = 0;
b32 imm_started = false;
b32 mesh_uniform_uploaded = false;
u32 i = 0;
for (;;)
{
@ -1820,6 +1909,34 @@ static void vTransferUpload(vTransfer **transfers, u32 count)
imm_started = true;
}
if (!mesh_uniform_uploaded && transfers[i]->type == vTT_MESH)
{
VkBufferDeviceAddressInfo addr_info = {
.sType = STYPE(BUFFER_DEVICE_ADDRESS_INFO),
.buffer = transfers[i]->mesh->mesh.buffer,
};
vMesh mesh = {
.vertices = vkGetBufferDeviceAddress(device, &addr_info),
};
VkBufferCopy copy = {
.srcOffset = offset,
.dstOffset = cast(VkDeviceSize, 0),
.size = sizeof(vMesh),
};
MemCpy(ptr, &mesh, sizeof(vMesh));
ptr = PtrAdd(ptr, sizeof(vMesh));
ptr_pos += sizeof(vMesh);
offset += sizeof(vMesh);
vkCmdCopyBuffer(buffer, transfer->alloc.buffer, transfers[i]->mesh->uniform.buffer, 1, &copy);
mesh_uniform_uploaded = true;
}
if (transfers[i]->type != vTT_NONE)
{
u64 remaining = Diff(TRANSFER_BUFFER_CAP, ptr_pos);
@ -1827,25 +1944,34 @@ static void vTransferUpload(vTransfer **transfers, u32 count)
if (transfer_size > remaining)
transfer_size = remaining;
MemCpy(ptr, transfers[i]->data, transfer_size);
MemCpy(ptr, data_ptr, transfer_size);
ptr = PtrAdd(ptr, transfer_size);
PtrAddAdjustLen(data_ptr, data_len, transfer_size);
ptr_pos += transfer_size;
}
// TODO:
/* == Transfers ==
* - offsets for target buffer
* - batch copy commands where possible
*/
if (transfers[i]->type == vTT_IMAGE)
{
MemZero(&transfers[i]->image_copy, sizeof(VkBufferImageCopy));
transfers[i]->image_copy.bufferRowLength = transfers[i]->w;
transfers[i]->image_copy.bufferImageHeight = transfers[i]->h;
transfers[i]->image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
transfers[i]->image_copy.imageSubresource.layerCount = 1;
transfers[i]->image_copy.imageExtent.width = transfers[i]->w;
transfers[i]->image_copy.imageExtent.height = transfers[i]->h;
transfers[i]->image_copy.imageExtent.depth = 1;
transfers[i]->image_copy.bufferOffset = offset;
VkBufferImageCopy copy = {
.bufferRowLength = transfers[i]->w,
.bufferImageHeight = transfers[i]->h,
.imageSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.layerCount = 1,
},
.imageExtent = {
.width = transfers[i]->w,
.height = transfers[i]->h,
.depth = 1,
},
.bufferOffset = offset,
};
vImageTransitionLayout(buffer,
transfers[i]->image,
@ -1857,7 +1983,7 @@ static void vTransferUpload(vTransfer **transfers, u32 count)
transfers[i]->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
&transfers[i]->image_copy);
&copy);
vImageTransitionLayout(buffer,
transfers[i]->image,
@ -1866,14 +1992,23 @@ static void vTransferUpload(vTransfer **transfers, u32 count)
offset += (VkDeviceSize)transfer_size;
}
else if (transfers[i]->type == vTT_BUFFER)
else if (transfers[i]->type == vTT_BUFFER || transfers[i]->type == vTT_MESH)
{
transfers[i]->buffer_copy.srcOffset = offset;
transfers[i]->buffer_copy.dstOffset = cast(VkDeviceSize, 0);
transfers[i]->buffer_copy.size = transfer_size;
VkBuffer target_buf;
if (transfers[i]->type == vTT_BUFFER)
target_buf = transfers[i]->buffer;
else if (transfers[i]->type == vTT_MESH)
target_buf = transfers[i]->mesh->mesh.buffer;
// TODO: batch buffer types into one vulkan command
vkCmdCopyBuffer(buffer, transfer->alloc.buffer, transfers[i]->buffer, 1, &transfers[i]->buffer_copy);
VkBufferCopy copy = {
.srcOffset = offset,
.dstOffset = 0,
.size = transfer_size,
};
Printfln("transfer size %llu", transfer_size);
vkCmdCopyBuffer(buffer, transfer->alloc.buffer, target_buf, 1, &copy);
offset += cast(VkDeviceSize, transfer_size);
}
@ -1884,6 +2019,7 @@ static void vTransferUpload(vTransfer **transfers, u32 count)
data_len = 0;
transfer_size = 0;
i += 1;
mesh_uniform_uploaded = false;
}
}

View File

@ -160,6 +160,7 @@ VK_DECLARE(vkDeviceWaitIdle);
VK_DECLARE(vkCmdClearColorImage);
VK_DECLARE(vkCreateSampler);
VK_DECLARE(vkDestroySampler);
VK_DECLARE(vkGetBufferDeviceAddress);
#include "vma/vk_mem_alloc.h"
@ -177,6 +178,7 @@ typedef enum DescType_e
vDT_SHARED,
vDT_SAMPLED_IMAGE, // DO NOT MOVE FROM POSITION 1 !!
vDT_MATERIAL,
vDT_MESH,
vDT_MAX,
} vDescType;
@ -230,6 +232,11 @@ PtrArrayType(vImageView);
ArrayType(vImageView);
PtrArrayType(b8);
typedef struct vMesh
{
VkDeviceAddress vertices;
} vMesh;
typedef struct vSampler
{
vImage image;
@ -237,14 +244,19 @@ typedef struct vSampler
VkSampler sampler;
} vSampler;
typedef struct vBufferAlloc
typedef struct vBuffer
{
VkBuffer buffer;
VmaAllocation alloc;
} vBufferAlloc;
} vBuffer;
PtrArrayType(vBufferAlloc);
ArrayType(vBufferAlloc);
PtrArrayType(vBuffer);
ArrayType(vBuffer);
typedef struct vMeshBuffer
{
vBuffer mesh, uniform;
} vMeshBuffer;
typedef struct vSwapchainState
{
@ -339,7 +351,7 @@ typedef struct vRImages
typedef struct vMappedBuffer
{
vBufferAlloc alloc;
vBuffer alloc;
rawptr ptr;
u64 cap;
} vMappedBuffer;
@ -347,7 +359,7 @@ typedef struct vMappedBuffer
typedef struct vRBuffers
{
HashTable buffers;
vBufferAllocPtrArray frame_buffers[FRAME_OVERLAP];
vBufferPtrArray frame_buffers[FRAME_OVERLAP];
HashTable images;
vImageViewPtrArray frame_images[FRAME_OVERLAP];
@ -358,10 +370,17 @@ typedef struct vRBuffers
vMappedBuffer gui_idx;
} vRBuffers;
typedef struct vModelBuffers
{
vMeshBuffer *mesh;
vBuffer *index;
} vModelBuffers;
typedef enum vTransferType : u32
{
vTT_NONE,
vTT_BUFFER,
vTT_MESH,
vTT_IMAGE,
} vTransferType;
@ -382,14 +401,10 @@ typedef struct vTransfer
};
union
{
vMeshBuffer *mesh;
VkBuffer buffer;
VkImage image;
};
union
{
VkBufferCopy buffer_copy;
VkBufferImageCopy image_copy;
};
} vTransfer;
typedef struct vUploadQueue
@ -444,6 +459,7 @@ typedef struct rPushConst
{
Vec2 res;
f32 time;
u32 mesh_index;
} rPushConst;
typedef struct rGlobalUniforms
@ -503,7 +519,7 @@ static inline u32 vFrameIndex();
static inline VkImage vFrameSwapImage();
static inline b8 *vFrameTexDestroyQueue();
static inline b8 *vFrameNextTexDestroyQueue();
static inline vBufferAllocPtrArray *vFrameBuffers();
static inline vBufferPtrArray *vFrameBuffers();
static inline void vImageTransition(VkCommandBuffer cmd, vImage *img, VkImageLayout new);
static inline void vImageTransitionLayout(VkCommandBuffer cmd, VkImage img, VkImageLayout curr, VkImageLayout new);
static inline void vImageCopyToImage(VkCommandBuffer cmd, VkImage src, VkImage dst, VkExtent2D src_ext, VkExtent2D dst_ext);
@ -535,8 +551,8 @@ static void vSwapchainResize();
// ::Vulkan::Images::Functions::Header::
static vTransfer *vTextureTransferInit(Arena *arena, u32 asset_id, VkImage image, u8 *bytes, TextureAssetMeta *meta);
static vImageView *vImageViewCreate(TextureAssetMeta meta);
static vTransfer *vTextureTransferInit(Arena *arena, u32 asset_id, VkImage image, rawptr bytes, TexMeta *meta);
static vImageView *vImageViewCreate(TexMeta meta);
static b32 vImageViewInit(vImageView *view, u32 width, u32 height, u32 channels);
static void vTextureCleanUp();
static void vImagePush(TextureAsset asset_id, vImageView *view);
@ -546,18 +562,25 @@ static vImageView *vImageSearch(TextureAsset asset_id);
// ::Vulkan::Descriptors::Functions::Header::
static void vDescPushImageAndHandle(rDescHandle handle, vImageView *view);
static void vDescPushModelAndHandle(rDescHandle handle, vModelBuffers *buffer);
static void vDescIndexPush(vDescType type, u32 index);
static u32 vDescIndexPop(vDescType type);
static rDescHandle vDescHandleSearch(vDescType type, u32 asset_id);
static void vDescHandlePush(vDescType type, rDescHandle handle);
static rDescHandle vDescHandlePop(vDescType type, u32 asset_id);
static void vDescHandleDelete(vDescType type, u32 asset_id);
static u32 vDescPushImage(vImageView *view);
static u32 vDescPushImageDesc(vImageView *view);
static u32 vDescPushMeshDesc(vMeshBuffer *buffer);
// ::Vulkan::Buffers::Functions::Header::
static VkResult vBufferCreate(vBufferAlloc* buf, rRenderBufferType type, u64 size);
static vTransfer *vMeshTransferInit(Arena *arena, u32 asset_id, vMeshBuffer *mesh, rawptr bytes, u64 size);
static vTransfer *vBufferTransferInit(Arena *arena, u32 asset_id, vBuffer *index, rawptr bytes, u64 size);
static VkResult vBufferCreate(vBuffer* buf, rRenderBufferType type, u64 size);
static rawptr vMapBuffer(VmaAllocation alloc);
static void vModelPush(ModelAsset asset_id, vModelBuffers *buffer);
static vModelBuffers *vModelPop(ModelAsset asset_id);
static vModelBuffers *vModelSearch(ModelAsset asset_id);
// ::Vulkan::CleanUp::Functions::Header::

View File

@ -38,7 +38,7 @@ void rDestroy()
{
VkDevice device = v_Renderer.handles.device;
VkInstance instance = v_Renderer.handles.inst;
vBufferAllocPtrArray *frame_buffers = v_Renderer.buffers.frame_buffers;
vBufferPtrArray *frame_buffers = v_Renderer.buffers.frame_buffers;
vImmHandles imm = v_Renderer.imm;
VmaAllocator vma_alloc = v_Renderer.handles.vma_alloc;
VkSwapchainKHR swapchain = v_Renderer.handles.swapchain;
@ -128,17 +128,18 @@ static rDescHandle rTextureLoad(TextureAsset asset_id)
vImageView *view = FLMemAlloc(sizeof(vImageView));
Asset asset = apLoadTexture(asset_id);
TextureAssetMeta meta = apGetTextureMeta(asset_id);
TexMeta meta = apGetTextureMeta(asset_id);
// TODO: handle errors instead of failing
Assert(vImageViewInit(view, meta.w, meta.h, meta.ch), "rTextureLoad failure: vImageViewInit failed");
handle.asset_id = asset_id;
handle.desc_index = vDescPushImage(view);
handle.desc_index = vDescPushImageDesc(view);
vTransfer *transfer = vTextureTransferInit(vFrameArena(), asset_id, view->image.image, asset.bytes, &meta);
TicketMutLock(&v_Renderer.upload.mut);
vTransfer *transfer = vTextureTransferInit(vFrameArena(), asset_id, view->image.image, asset.bytes, &meta);
u32 job_idx = JobQueueAdd(&v_Renderer.upload.job_queue, 1);
v_Renderer.upload.transfers[job_idx] = transfer;
vDescPushImageAndHandle(handle, view);
@ -151,6 +152,47 @@ static rDescHandle rTextureLoad(TextureAsset asset_id)
return handle;
}
static rDescHandle rMeshLoad(ModelAsset asset_id)
{
rDescHandle handle = vDescHandleSearch(vDT_MESH, asset_id);
if (handle.asset_id == UINT32_MAX)
{
vMeshBuffer *buffer = FLMemAlloc(sizeof(vMeshBuffer));
vBuffer *index_buffer = FLMemAlloc(sizeof(vBuffer));
vModelBuffers *model_buffer = FLMemAlloc(sizeof(vModelBuffers));
model_buffer->mesh = buffer;
model_buffer->index = index_buffer;
Asset asset = apLoadModel(asset_id);
// TODO: handle errors
Assert(vBufferCreate(&buffer->mesh, rRBT_STORAGE | rRBT_ADDR, sizeof(rPBRVertex) * asset.model->v_count) == VK_SUCCESS, "rMeshLoad failure: vBufferCreate didn't return VK_SUCCESS");
Assert(vBufferCreate(&buffer->uniform, rRBT_UNIFORM, sizeof(vMesh)) == VK_SUCCESS, "rMeshLoad failure: vBufferCreate didn't return VK_SUCCESS");
Assert(vBufferCreate(index_buffer, rRBT_INDEX, sizeof(u32) * asset.model->i_count) == VK_SUCCESS, "rMeshLoad failure: vBufferCreate didn't return VK_SUCCESS");
handle.asset_id = asset_id;
handle.desc_index = vDescPushMeshDesc(buffer);
vTransfer *transfer = vMeshTransferInit(vFrameArena(), asset_id, buffer, asset.model->vertices, asset.model->v_count * sizeof(rPBRVertex));
vTransfer *index_transfer = vBufferTransferInit(vFrameArena(), asset_id, index_buffer, asset.model->indices, asset.model->i_count * sizeof(u32));
TicketMutLock(&v_Renderer.upload.mut);
u32 job_idx = JobQueueAdd(&v_Renderer.upload.job_queue, 2);
v_Renderer.upload.transfers[job_idx] = transfer;
v_Renderer.upload.transfers[job_idx + 1] = index_transfer;
vDescPushModelAndHandle(handle, model_buffer);
TicketMutUnlock(&v_Renderer.upload.mut);
vLoaderWake();
}
return handle;
}
static void rTextureUnload(rDescHandle current_handle)
{
rDescHandle handle = vDescHandleSearch(vDT_SAMPLED_IMAGE, current_handle.asset_id);
@ -218,6 +260,16 @@ static void rBufferBindGUIIndex()
vkCmdBindIndexBuffer(cmd, buffer, 0, VK_INDEX_TYPE_UINT32);
}
static void rBufferBindMesh(rPushConst *pc, rDescHandle handle)
{
vModelBuffers *buffers = vModelSearch(handle.asset_id);
if (buffers != NULL)
{
Printfln("binding index buffer");
vkCmdBindIndexBuffer(vFrameCmdBuf(), buffers->index->buffer, 0, VK_INDEX_TYPE_UINT32);
}
}
// ::Vulkan::Renderer::Buffers::Functions::End::

View File

@ -6,13 +6,11 @@
#include "structures.glsl"
layout (location = 0) in vec4 in_pos;
layout (location = 1) in vec4 in_col;
layout (location = 0) out vec4 out_col;
void main()
{
out_col = in_col;
gl_Position = in_pos;
Vertex v = Meshes[nonuniformEXT(PC.mesh_index)].buf.vertices[gl_VertexIndex];
gl_Position = v.pos;
out_col = v.col;
}

View File

@ -3,9 +3,8 @@
// ==========================================
struct Vertex {
float uv_x;
float uv_y;
float x, y, z;
vec4 pos;
vec4 col;
};
struct GUIVertex {
@ -14,6 +13,10 @@ struct GUIVertex {
vec4 col;
};
layout (buffer_reference, std430) readonly buffer VertexBuffer {
Vertex vertices[];
};
layout (set = 0, binding = 0) uniform GlobalUniform {
vec2 res;
} Globals;
@ -36,15 +39,12 @@ layout (set = 2, binding = 0) uniform PBRMaterials {
float ao;
} Materials[];
layout (std430, buffer_reference) readonly buffer VertexBuffer {
Vertex vertices[];
};
layout (std430, buffer_reference) readonly buffer GUIVertexBuffer {
GUIVertex vertices[];
};
layout (set = 3, binding = 0) uniform ModelMeshes {
VertexBuffer buf;
} Meshes[];
layout (push_constant) uniform Constants {
vec2 res;
float time;
uint mesh_index;
} PC;

View File

@ -82,6 +82,7 @@ static VkPhysicalDeviceVulkan12Features vk_12_features = {
.descriptorBindingStorageBufferUpdateAfterBind = VK_TRUE,
.descriptorBindingPartiallyBound = VK_TRUE,
.shaderSampledImageArrayNonUniformIndexing = VK_TRUE,
.shaderUniformBufferArrayNonUniformIndexing = VK_TRUE,
.runtimeDescriptorArray = VK_TRUE,
};
@ -258,6 +259,7 @@ static VkDescriptorSetLayoutCreateInfo shared_layout_create_info = {
static VkDescriptorType desc_type_map[vDT_MAX] = {
[vDT_SAMPLED_IMAGE] = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
[vDT_MATERIAL] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
[vDT_MESH] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
};
static VkDescriptorBindingFlags bindless_desc_binding_flags = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT;
@ -460,17 +462,10 @@ VkVertexInputBindingDescription pbr_input_bind_desc = {
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
};
VkVertexInputAttributeDescription pbr_input_descriptions[] = {
{ .binding = 0, .location = 0, .format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = 0 },
{ .binding = 1, .location = 1, .format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = offsetof(rPBRVertex, col) },
};
VkPipelineVertexInputStateCreateInfo pbr_vertex_input_info = {
.sType = STYPE(PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO),
.vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = &pbr_input_bind_desc,
.vertexAttributeDescriptionCount = Len(pbr_input_descriptions),
.pVertexAttributeDescriptions = pbr_input_descriptions,
};
VkPipelineInputAssemblyStateCreateInfo pbr_assembly_info = {