diff --git a/.gitignore b/.gitignore index 5a58160..de46c10 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .gdb_history *.spv *.o -main \ No newline at end of file +main +*.pack \ No newline at end of file diff --git a/Makefile b/Makefile index 46ed02f..8bdfd35 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ CC=$(PREFIX)gcc CXX=$(PREFIX)g++ OBJCOPY=$(PREFIX)objcopy +AS=$(PREFIX)as OBJARCH = elf64-x86-64 @@ -30,44 +31,24 @@ endif OBJS = \ src/main.o \ - src/volk/volk.o - -BINS = \ - index.idx.o \ - position_normal_texture.vtx.o \ - sprite.data.o - -SHADERS = \ - shader/triangle.vs.spv.o \ - shader/triangle.ps.spv.o + src/volk/volk.o \ + src/file.o \ + src/pack.o LIBS = \ ../SDL3-dist/lib64/libSDL3.a all: main -define BUILD_BINARY_O - $(OBJCOPY) -I binary -O $(OBJARCH) $< $@ -endef - -%.vtx.o: %.vtx - $(BUILD_BINARY_O) - -%.idx.o: %.idx - $(BUILD_BINARY_O) - -%.spv.o: %.spv - $(BUILD_BINARY_O) - -%.data.o: %.data - $(BUILD_BINARY_O) - %.o: %.c $(CC) $(ARCH) $(CSTD) $(CFLAGS) $(FLAGS) $(OPT) $(DEBUG) -c $< -o $@ %.o: %.cpp $(CXX) $(ARCH) $(CXXSTD) $(CFLAGS) $(FLAGS) $(OPT) $(DEBUG) -c $< -o $@ +%.o: %.s + $(AS) $< -o $@ + main: $(OBJS) $(LIBS) $(BINS) $(SHADERS) $(CC) $(ARCH) $(LDFLAGS) $(FLAGS) $(OPT) $(DEBUG) $^ -o $@ @@ -77,6 +58,13 @@ main: $(OBJS) $(LIBS) $(BINS) $(SHADERS) %.ps.spv: %.hlsl ../dxc/bin/dxc -spirv -T ps_6_1 -E PSMain -fspv-target-env=vulkan1.3 $< -Fo $@ +tool/pack_file: tool/pack_file.cpp + make -C tool pack_file + +PACK_FILENAMES = $(shell cat filenames.txt) +files.pack: tool/pack_file $(PACK_FILENAMES) filenames.txt + ./tool/pack_file $@ $(PACK_FILENAMES) + .SUFFIXES: .INTERMEDIATE: .SECONDARY: diff --git a/filenames.txt b/filenames.txt new file mode 100644 index 0000000..75a1c2d --- /dev/null +++ b/filenames.txt @@ -0,0 +1,5 @@ +shader/triangle.vs.spv +shader/triangle.ps.spv +index.idx +position_normal_texture.vtx +sprite.data diff --git a/include/file.h b/include/file.h new file mode 100644 index 0000000..e9fda03 --- /dev/null +++ b/include/file.h @@ -0,0 +1,5 @@ +#pragma once + +namespace file { + void const * open(const char * r_filename, uint32_t * out_size); +} diff --git a/include/pack.h b/include/pack.h new file mode 100644 index 0000000..9c96fb6 --- /dev/null +++ b/include/pack.h @@ -0,0 +1,19 @@ +#include + +namespace pack { + struct file_entry { + char filename[128]; + uint32_t offset; + uint32_t size; + }; + + struct header { + uint32_t magic; + uint32_t header_size; + uint32_t entry_count; + file_entry entry[0]; + }; + static_assert((sizeof (header)) == 12); + + const uint32_t magic_value = 0x037c2dc0; +} diff --git a/src/file.cpp b/src/file.cpp new file mode 100644 index 0000000..2f14cbb --- /dev/null +++ b/src/file.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include + +#include "pack.h" +#include "file.h" + +extern "C" { + extern uint8_t const _files_pack_start[]; + extern uint8_t const _files_pack_end[]; +}; + +namespace file { + + void const * open(const char * r_filename, uint32_t * out_size) + { + fprintf(stderr, "(pack) filename: %s\n", r_filename); + + pack::header const * header = (pack::header const *)&_files_pack_start[0]; + if (header->magic != pack::magic_value) { + fprintf(stderr, "invalid header magic: %08x expected magic value: %08x\n", header->magic, pack::magic_value); + exit(EXIT_FAILURE); + } + ptrdiff_t data = (ptrdiff_t)&_files_pack_start[header->header_size]; + + for (unsigned int i = 0; i < header->entry_count; i++) { + if (strcmp(header->entry[i].filename, r_filename) == 0) { + *out_size = header->entry[i].size; + return (void const *)(data + header->entry[i].offset); + } + } + + fprintf(stderr, "filename not found in pack file %s\n", r_filename); + exit(EXIT_FAILURE); + } + +} diff --git a/src/main.cpp b/src/main.cpp index fa5fb78..fa624e3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,34 +8,7 @@ #include "directxmath/directxmath.h" #include "new.h" - -extern "C" { - extern uint8_t const _binary_position_normal_texture_vtx_start[]; - extern void * const _binary_position_normal_texture_vtx_size; - extern uint8_t const _binary_index_idx_start[]; - extern void * const _binary_index_idx_size; - - extern uint8_t const _binary_shader_triangle_vs_spv_start[]; - extern void * const _binary_shader_triangle_vs_spv_size; - extern uint8_t const _binary_shader_triangle_ps_spv_start[]; - extern void * const _binary_shader_triangle_ps_spv_size; - - extern uint8_t const _binary_sprite_data_start[]; - extern void * const _binary_sprite_data_size; -} - -#define vtx_start _binary_position_normal_texture_vtx_start -#define vtx_size (size_t)(&_binary_position_normal_texture_vtx_size) -#define idx_start _binary_index_idx_start -#define idx_size (size_t)(&_binary_index_idx_size) - -#define vs_start _binary_shader_triangle_vs_spv_start -#define vs_size (size_t)(&_binary_shader_triangle_vs_spv_size) -#define ps_start _binary_shader_triangle_ps_spv_start -#define ps_size (size_t)(&_binary_shader_triangle_ps_spv_size) - -#define sprite_start _binary_sprite_data_start -#define sprite_size (size_t)(&_binary_sprite_data_size) +#include "file.h" #define SDL_CHECK(f) \ { \ @@ -512,8 +485,13 @@ int main() // mesh ////////////////////////////////////////////////////////////////////// - VkDeviceSize vtxBufferSize{ vtx_size }; - VkDeviceSize idxBufferSize{ idx_size }; + uint32_t vertexSize; + void const * vertexStart = file::open("position_normal_texture.vtx", &vertexSize); + uint32_t indexSize; + void const * indexStart = file::open("index.idx", &indexSize); + + VkDeviceSize vtxBufferSize{ vertexSize }; + VkDeviceSize idxBufferSize{ indexSize }; VkBufferCreateInfo vertexIndexBufferCreateInfo{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .size = vtxBufferSize + idxBufferSize, @@ -538,8 +516,8 @@ int main() void * vertexIndexMappedData; VK_CHECK(vkMapMemory(device, vertexIndexBufferMemory, 0, vertexIndexBufferCreateInfo.size, 0, &vertexIndexMappedData)); - memcpy((void *)(((ptrdiff_t)vertexIndexMappedData) + 0), vtx_start, vtx_size); - memcpy((void *)(((ptrdiff_t)vertexIndexMappedData) + vtx_size), idx_start, idx_size); + memcpy((void *)(((ptrdiff_t)vertexIndexMappedData) + 0), vertexStart, vertexSize); + memcpy((void *)(((ptrdiff_t)vertexIndexMappedData) + vertexSize), indexStart, indexSize); vkUnmapMemory(device, vertexIndexBufferMemory); ////////////////////////////////////////////////////////////////////// @@ -673,10 +651,13 @@ int main() // texture transfer: source buffer + uint32_t spriteSize; + void const * spriteStart = file::open("sprite.data", &spriteSize); + VkBuffer textureSourceBuffer{}; VkBufferCreateInfo textureSourceBufferCreateInfo{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = sprite_size, + .size = spriteSize, .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT }; VK_CHECK(vkCreateBuffer(device, &textureSourceBufferCreateInfo, nullptr, &textureSourceBuffer)); @@ -697,7 +678,7 @@ int main() void * textureSourceMappedData; VK_CHECK(vkMapMemory(device, textureSourceBufferMemory, 0, textureSourceBufferCreateInfo.size, 0, &textureSourceMappedData)); - memcpy((void *)(((ptrdiff_t)textureSourceMappedData) + 0), sprite_start, sprite_size); + memcpy((void *)(((ptrdiff_t)textureSourceMappedData) + 0), spriteStart, spriteSize); vkUnmapMemory(device, textureSourceBufferMemory); VkFenceCreateInfo textureFenceCreateInfo{ @@ -872,18 +853,23 @@ int main() // shaders ////////////////////////////////////////////////////////////////////// + uint32_t triangleVSSize; + void const * triangleVSStart = file::open("shader/triangle.vs.spv", &triangleVSSize); + uint32_t trianglePSSize; + void const * trianglePSStart = file::open("shader/triangle.ps.spv", &trianglePSSize); + VkShaderModuleCreateInfo vertexShaderModuleCreateInfo{ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .codeSize = vs_size, - .pCode = (uint32_t *)vs_start + .codeSize = triangleVSSize, + .pCode = (uint32_t *)triangleVSStart }; VkShaderModule vertexShaderModule{}; VK_CHECK(vkCreateShaderModule(device, &vertexShaderModuleCreateInfo, nullptr, &vertexShaderModule)); VkShaderModuleCreateInfo pixelShaderModuleCreateInfo{ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .codeSize = ps_size, - .pCode = (uint32_t *)ps_start + .codeSize = trianglePSSize, + .pCode = (uint32_t *)trianglePSStart }; VkShaderModule pixelShaderModule{}; VK_CHECK(vkCreateShaderModule(device, &pixelShaderModuleCreateInfo, nullptr, &pixelShaderModule)); diff --git a/src/pack.s b/src/pack.s new file mode 100644 index 0000000..ef3403f --- /dev/null +++ b/src/pack.s @@ -0,0 +1,5 @@ + .global _files_pack_start + .global _files_pack_end +_files_pack_start: + .incbin "files.pack" +_files_pack_end: diff --git a/tool/Makefile b/tool/Makefile new file mode 100644 index 0000000..54f1ec5 --- /dev/null +++ b/tool/Makefile @@ -0,0 +1,5 @@ +OPT = -O2 +CFLAGS = -I../include + +pack_file: pack_file.cpp + g++ -o $@ $(OPT) $(CFLAGS) $^ diff --git a/tool/pack_file.cpp b/tool/pack_file.cpp new file mode 100644 index 0000000..ecab6ea --- /dev/null +++ b/tool/pack_file.cpp @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include + +#include "pack.h" + +static uint8_t copy_buffer[1024 * 1024]; +static int const copy_buffer_size = (sizeof (copy_buffer)); + +void copy_file(FILE * output, FILE * input, size_t size) +{ + size_t written = 0; + + while (true) { + size_t read_size = fread(copy_buffer, 1, copy_buffer_size, input); + if (read_size == 0) + break; + + size_t write_size = fwrite(copy_buffer, 1, read_size, output); + assert(write_size == read_size); + + written += write_size; + + if (read_size < copy_buffer_size) + break; + } + + assert(written == size); +} + +FILE * file_size(const char * filename, uint32_t * out_size) +{ + FILE * f = fopen(filename, "rb"); + if (f == nullptr) { + fprintf(stderr, "fopen(%s): %s\n", filename, strerror(errno)); + return nullptr; + } + + int fseek_end_ret = fseek(f, 0, SEEK_END); + if (fseek_end_ret < 0) { + fprintf(stderr, "fseek(%s, SEEK_END): %s\n", filename, strerror(errno)); + return nullptr; + } + + long size = ftell(f); + if (size < 0) { + fprintf(stderr, "ftell(%s): %s\n", filename, strerror(errno)); + return nullptr; + } + + int fseek_set_ret = fseek(f, 0, SEEK_SET); + if (fseek_set_ret < 0) { + fprintf(stderr, "fseek(%s, SEEK_SET): %s\n", filename, strerror(errno)); + return nullptr; + } + + *out_size = size; + + return f; +} + +int main(int argc, char const * argv[]) +{ + assert(argc >= 3); + + int files_count = argc - 2; + char const * output_filename = argv[1]; + char const * const * filenames = &argv[2]; + FILE * files[files_count]; + + int header_size = (sizeof (pack::header)) + (sizeof (pack::file_entry)) * files_count; + pack::header * header = (pack::header *)malloc(header_size); + memset(header, 0, header_size); + + header->magic = pack::magic_value; + header->header_size = header_size; + header->entry_count = files_count; + int offset = 0; + + for (int i = 0; i < files_count; i++) { + char const * filename = filenames[i]; + uint32_t size; + FILE * file = file_size(filename, &size); + assert(file != nullptr); + files[i] = file; + int filename_length = strlen(filename); + assert(filename_length <= 127); + memcpy(header->entry[i].filename, filename, filename_length); + header->entry[i].offset = offset; + header->entry[i].size = size; + offset += size; + } + + FILE * fout = fopen(output_filename, "wb"); + if (fout == nullptr) { + fprintf(stderr, "fopen(%s): %s\n", output_filename, strerror(errno)); + return EXIT_FAILURE; + } + + fwrite((void *)header, 1, header_size, fout); + + for (int i = 0; i < files_count; i++) { + copy_file(fout, files[i], header->entry[i].size); + int fclose_ret = fclose(files[i]); + assert(fclose_ret == 0); + } + + int fclose_ret = fclose(fout); + assert(fclose_ret == 0); +}