summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile31
-rw-r--r--asset.cpp101
-rw-r--r--asset.hpp41
-rw-r--r--c2.cpp21
-rw-r--r--packer.c82
-rw-r--r--qstd/Makefile7
-rw-r--r--qstd/pack.c165
-rw-r--r--qstd/pack.h40
-rw-r--r--vid_enums.h26
-rw-r--r--video.cpp179
-rw-r--r--video.hpp18
12 files changed, 615 insertions, 98 deletions
diff --git a/.gitignore b/.gitignore
index 337b226..1468a38 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,5 @@ tags
/qstd/libqstd.a
/sc/sc
/c2
+/pack
+/packer
diff --git a/Makefile b/Makefile
index 9508cd4..1d01b16 100644
--- a/Makefile
+++ b/Makefile
@@ -2,12 +2,13 @@
target = c2
data_dir = data
-shaders = data/triangle.csh
-tools = qstd cfg sc
-objects = app.o c2.o video.o pipeline.o
+shaders = $(data_dir)/triangle.csh
+packed_files = $(shaders)
+tools = qstd cfg sc packer
+objects = app.o c2.o video.o pipeline.o asset.o
includes = -Iqstd
defines = -Dplat_x86 -Dplat_posix -Dplat_x11 -Dallocation_default_alignment=8
-cflags = $(includes) $(defines) $(DEBUG_COMPILE_FLAG)
+cflags = -MMD -MF $(basename $@).d $(includes) $(defines) $(DEBUG_COMPILE_FLAG)
libs = -lX11 -lm
lflags = $(libs) $(DEBUG_LINK_FLAG)
@@ -23,19 +24,28 @@ cfg: qstd
sc: qstd cfg
$(MAKE) -C sc
+packer: packer.c | qstd
+ $(CC) $(cflags) packer.c $(lflags) -Lqstd -lqstd -o packer
+
+pack: $(packed_files) packer
+ ./packer pack $(data_dir) $(packed_files)
+
data/triangle.csh: intermediate/triangle.glsl | $(data_dir) sc
- ./sc/sc intermediate/triangle.glsl data/triangle.csh
+ ./sc/sc intermediate/triangle.glsl $(data_dir)/triangle.csh
-app.o: app.cpp app.hpp qstd/memory.h qstd/plat.h
+app.o:
$(CXX) -c $(cflags) app.cpp -o app.o
-video.o: video.cpp video.hpp app.hpp qstd/memory.h qstd/plat.h qstd/str.h sc/sh_enums.h
+video.o:
$(CXX) -c $(cflags) video.cpp -o video.o
-pipeline.o: pipeline.cpp video.hpp qstd/memory.h qstd/plat.h
+pipeline.o:
$(CXX) -c $(cflags) pipeline.cpp -o pipeline.o
-c2.o: c2.cpp app.hpp video.hpp qstd/memory.h qstd/plat.h
+asset.o:
+ $(CXX) -c $(cflags) asset.cpp -o asset.o
+
+c2.o:
$(CXX) -c $(cflags) c2.cpp -o c2.o
$(target): $(objects) qstd/libqstd.a
@@ -54,3 +64,6 @@ clean:
make -C qstd clean
make -C cfg clean
make -C sc clean
+
+-include $(objects:%.o=%.d)
+-include packer.d
diff --git a/asset.cpp b/asset.cpp
new file mode 100644
index 0000000..09260e0
--- /dev/null
+++ b/asset.cpp
@@ -0,0 +1,101 @@
+#include "asset.hpp"
+
+extern "C" {
+#include "memory.h"
+#include "pack.h"
+#include "plat.h"
+#include "str.h"
+}
+
+#define max_asset_types 32
+
+struct RLoader {
+ char magic[4];
+ Asset_Loader* loader;
+};
+
+struct Manager {
+ RLoader loaders[max_asset_types];
+
+ Manager() {
+ int i;
+ for (i = 0; i < max_asset_types; i++) {
+ loaders[i].loader = 0;
+ }
+ }
+
+ RLoader* find_loader(const char* magic) {
+ uint32_t hash = hash_string(magic);
+ int bucket = (int)(hash % max_asset_types);
+ int i;
+ for (i = 0; i < max_asset_types; i++) {
+ RLoader& e = loaders[bucket];
+ if (!e.loader || (
+ e.magic[0] == magic[0] &&
+ e.magic[1] == magic[1] &&
+ e.magic[2] == magic[2] &&
+ e.magic[3] == magic[3]
+ )) return &e;
+ bucket = (bucket + 1) % max_asset_types;
+ }
+ return 0;
+ }
+
+ Asset_Loader& get_loader(const char* magic) {
+ RLoader* r = find_loader(magic);
+ assert(r != 0 && r->loader != 0);
+ return *r->loader;
+ }
+
+ void set_loader(const char* magic, Asset_Loader* l) {
+ RLoader* r = find_loader(magic);
+ assert(r != 0 && r->loader == 0);
+ r->magic[0] = magic[0];
+ r->magic[1] = magic[1];
+ r->magic[2] = magic[2];
+ r->magic[3] = magic[3];
+ r->loader = l;
+ }
+} manager;
+
+void register_asset_loader(
+ const char* magic,
+ Asset_Loader* loader
+) {
+ manager.set_loader(magic, loader);
+}
+
+void Asset_Arena::init(Arena* arena, const char* pack_name) {
+ p = pack_open(pack_name, arena);
+ a = arena;
+ assets = 0;
+}
+
+void Asset_Arena::destroy() {
+ Asset* a;
+ for (a = assets; a; a = a->next) {
+ a->unload(a->loader);
+ }
+ pack_close(p);
+}
+
+void Asset_Arena::claim(Asset* a) {
+ if (assets) {
+ a->next = assets;
+ assets = a;
+ } else assets = a;
+}
+
+Asset* Asset_Arena::load(const char* name) {
+ char magic[4];
+ Pack_File* f = pack_open_file(p, name);
+ if (!f) return 0;
+ pack_read(f, magic, 4);
+ pack_seek(f, 0, seek_rel_start);
+ Asset_Loader& loader = manager.get_loader(magic);
+ Asset* asset = loader.load(a, f);
+ asset->loader = &loader;
+ pack_close_file(f);
+ claim(asset);
+ return asset;
+}
diff --git a/asset.hpp b/asset.hpp
new file mode 100644
index 0000000..27ac990
--- /dev/null
+++ b/asset.hpp
@@ -0,0 +1,41 @@
+#ifndef asset_hpp
+#define asset_hpp
+
+struct Arena;
+struct Asset_Loader;
+struct Pack_File;
+struct Pack;
+
+struct Asset {
+ Asset* next;
+ Asset_Loader* loader;
+ virtual bool load(
+ Asset_Loader* loader,
+ Arena* a,
+ Pack_File* f
+ ) = 0;
+ virtual void unload(Asset_Loader* loader) = 0;
+};
+
+struct Asset_Loader {
+ virtual Asset* load(Arena* a, Pack_File* f) = 0;
+};
+
+struct Asset_Arena {
+ Pack* p;
+ Arena* a;
+ Asset* assets;
+
+ void init(Arena* arena, const char* pack_name);
+ void destroy();
+
+ Asset* load(const char* name);
+ void claim(Asset* a);
+};
+
+void register_asset_loader(
+ const char* magic,
+ Asset_Loader* loader
+);
+
+#endif
diff --git a/c2.cpp b/c2.cpp
index 92cff0b..9510c6a 100644
--- a/c2.cpp
+++ b/c2.cpp
@@ -7,6 +7,7 @@ extern "C" {
#include <string.h>
#define video_arena_size (1024 * 1024 * 16)
+#define asset_arena_size (1024 * 1024 * 4)
#define per_frame_memory_size (1024 * 1024)
static float verts[] = {
@@ -24,8 +25,10 @@ struct C2 : public App {
int main() {
Arena video_arena;
+ Arena asset_arena;
+ Asset_Arena assets;
Device* dev;
- Shader_Id shader;
+ Shader* shader;
Buffer_Id vbo;
C2* app = App::create<C2>("c2");
void* per_frame;
@@ -35,9 +38,15 @@ int main() {
arena_alloc(app->arena, video_arena_size),
video_arena_size
);
+ init_arena(
+ &asset_arena,
+ arena_alloc(app->arena, asset_arena_size),
+ asset_arena_size
+ );
+ assets.init(&asset_arena, "pack");
dev = Device::create(&video_arena, app);
app->dev = dev;
- shader = dev->load_shader("data/triangle.csh");
+ shader = (Shader*)assets.load("triangle.csh");
per_frame = heap_alloc(
dev->heap,
per_frame_memory_size
@@ -68,14 +77,14 @@ int main() {
Render_Pass& pass = pb.build_rp();
pb.begin();
- pb.shader(shader);
- pb.vertex_format(dev->get_shader(shader).vf);
+ pb.shader(shader->id);
+ pb.vertex_format(shader->vf);
Pipeline& pip = pb.build();
Vertex_Buffer_Binding binding[] = {{
.id = vbo,
.offset = 0,
- .target = dev->get_shader(shader).binding_index("verts")
+ .target = shader->binding_index("verts")
}, {}};
Draw draw{};
@@ -90,8 +99,8 @@ int main() {
dev->present();
app->end();
}
+ assets.destroy();
dev->destroy_buffer(vbo);
- dev->destroy_shader(shader);
dev->destroy();
app->destroy();
}
diff --git a/packer.c b/packer.c
new file mode 100644
index 0000000..ca1cb4a
--- /dev/null
+++ b/packer.c
@@ -0,0 +1,82 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "memory.h"
+#include "pack.h"
+#include "plat.h"
+
+char magic[4] = { 'P', 'A', 'C', 'K' };
+#define buffer_size 1024
+
+int main(int argc, const char** argv) {
+ FILE* outfile;
+ const char* workingdir, * dsep = "";
+ char buffer[buffer_size];
+ int file_count = argc - 3, i;
+ uint32_t coff, table_size;
+ Pack_Entry* table;
+ Pack* pack;
+ if (file_count <= 0) return 0;
+ if (argc < 3) {
+ print_err("Usage: %s <outfile> <dir> infile...\n");
+ return 3;
+ }
+ outfile = fopen(argv[1], "wb");
+ if (!outfile) {
+ print_err("Failed to open %s\n", argv[1]);
+ return 6;
+ }
+ workingdir = argv[2];
+ if (workingdir[strlen(workingdir) - 1] != '/')
+ dsep = "/";
+ table_size = sizeof *table * file_count;
+ pack = malloc(get_pack_size(file_count));
+ if (!pack) {
+ print_err("Out of memory.\n");
+ return 1;
+ }
+ table = get_pack_table(pack);
+ for (i = 0; i < file_count; i++) {
+ table[i].name[0] = 0;
+ }
+ pack->filename = 0;
+ pack->file_count = file_count;
+ for (i = 0; i < file_count; i++) {
+ Pack_Entry* e;
+ e = pack_find_entry(pack, argv[i + 3]);
+ if (!e || e->name[0]) {
+ print_err("Hash table error.\n");
+ return 5;
+ }
+ strcpy(e->name, argv[i + 3] + strlen(workingdir) + strlen(dsep));
+ }
+ fwrite(magic, 1, 4, outfile);
+ fwrite(&pack->file_count, 1, 4, outfile);
+ fwrite(table, 1, table_size, outfile);
+ coff = ftell(outfile);
+ for (i = 0; i < file_count; i++) {
+ FILE* infile;
+ Pack_Entry* e = &table[i];
+ uint32_t j;
+ infile = fopen(argv[i + 3], "rb");
+ if (!infile) {
+ print_err("Failed to open %s.\n", argv[i + 3]);
+ return 6;
+ }
+ fseek(infile, 0, SEEK_END);
+ e->size = ftell(infile);
+ e->offset = coff;
+ rewind(infile);
+ fseek(outfile, e->offset, SEEK_SET);
+ for (j = 0; j < e->size; j += buffer_size) {
+ int read = fread(buffer, 1, buffer_size, infile);
+ fwrite(buffer, 1, read, outfile);
+ }
+ coff += e->size;
+ }
+ fseek(outfile, 8, SEEK_SET);
+ fwrite(table, 1, table_size, outfile);
+ fclose(outfile);
+ return 0;
+}
diff --git a/qstd/Makefile b/qstd/Makefile
index 3c4b6a8..c4b088b 100644
--- a/qstd/Makefile
+++ b/qstd/Makefile
@@ -5,7 +5,7 @@ defines = -Dplat_x86 -Dplat_posix -Dallocation_default_alignment=8
cflags = -std=c90 -pedantic -Wall -Wextra $(DEBUG_COMPILE_FLAG) $(includes) $(defines)
lflags = $(DEBUG_LINK_FLAG)
-objects = plat.o memory.o str.o
+objects = plat.o memory.o str.o pack.o
.PHONY: all clean
@@ -17,9 +17,12 @@ memory.o: memory.c memory.h plat.h
plat.o: plat.c plat.h
$(CC) -c $(cflags) plat.c -o plat.o
-str.o: str.c str.h
+str.o: str.c str.h memory.h
$(CC) -c $(cflags) str.c -o str.o
+pack.o: pack.c pack.h str.h plat.h memory.h
+ $(CC) -c $(cflags) pack.c -o pack.o
+
$(target): $(objects)
$(AR) -rcs $(target) $(objects)
diff --git a/qstd/pack.c b/qstd/pack.c
new file mode 100644
index 0000000..e9ca0c3
--- /dev/null
+++ b/qstd/pack.c
@@ -0,0 +1,165 @@
+#include "memory.h"
+#include "pack.h"
+#include "plat.h"
+#include "str.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#define pack_max_files 4
+
+typedef struct Pack_File {
+ FILE* handle;
+ Pack_Entry* entry;
+ int offset;
+} Pack_File;
+
+Pack_Entry* get_pack_table(Pack* p) {
+ return (Pack_Entry*)(
+ (char*)&p[1] + pack_max_files * sizeof(Pack_File)
+ );
+}
+
+int get_pack_size(int entry_count) {
+ return sizeof(Pack) +
+ pack_max_files * sizeof(Pack_File) +
+ entry_count * sizeof(Pack_Entry);
+}
+
+Pack_Entry* pack_find_entry(Pack* p, const char* name) {
+ Pack_Entry* tab = get_pack_table(p);
+ uint32_t hash = hash_string(name);
+ int idx = (int)(hash % p->file_count), i;
+ int e = (int)p->file_count;
+ for (i = 0; i < e; i++) {
+ Pack_Entry* e = &tab[idx];
+ if (!e->name[0] || string_equal(name, e->name))
+ return e;
+ idx = (int)((idx + 1) % p->file_count);
+ }
+ return 0;
+}
+
+static void insert_entry(Pack* p, const Pack_Entry* e) {
+ Pack_Entry* d = pack_find_entry(p, e->name);
+ assert(d != 0);
+ if (d->name[0])
+ print_war("Duplicate entry in %s: %s\n", p->filename, e->name);
+ *d = *e;
+}
+
+static void read_table(Pack* p, FILE* f) {
+ uint32_t i, e = p->file_count;
+ Pack_Entry* tab = get_pack_table(p);
+ for (i = 0; i < e; i++)
+ tab[i].name[0] = 0;
+ for (i = 0; i < e; i++) {
+ Pack_Entry e;
+ fread(&e, sizeof e, 1, f);
+ insert_entry(p, &e);
+ }
+}
+
+static void init_files(Pack* p) {
+ int i;
+ Pack_File* files = (Pack_File*)&p[1];
+ for (i = 0; i < pack_max_files; i++) {
+ files[i].handle = 0;
+ }
+}
+
+Pack* pack_open(const char* filename, Arena* a) {
+ Pack* p;
+ char magic[4];
+ uint32_t entry_count;
+ FILE* f = fopen(filename, "rb");
+ if (!f) return 0;
+ fread(magic, 1, 4, f);
+ if (
+ magic[0] != 'P' ||
+ magic[1] != 'A' ||
+ magic[2] != 'C' ||
+ magic[3] != 'K'
+ ) {
+ fclose(f);
+ return 0;
+ }
+ fread(&entry_count, 4, 1, f);
+ p = arena_alloc(a, get_pack_size(entry_count));
+ p->filename = dup_string(a, filename);
+ p->file_count = entry_count;
+ init_files(p);
+ read_table(p, f);
+ fclose(f);
+ return p;
+}
+
+void pack_close(Pack* p) {
+ (void)p;
+}
+
+Pack_Entry* pack_get_entry(Pack* p, const char* name) {
+ Pack_Entry* e = pack_find_entry(p, name);
+ if (!e || e->name[0] == 0) return 0;
+ return e;
+}
+
+static Pack_File* init_handle(
+ Pack* p,
+ Pack_File* h,
+ const char* name
+) {
+ FILE* f;
+ Pack_Entry* e = pack_find_entry(p, name);
+ if (!e || !e->name[0]) return 0;
+ f = fopen(p->filename, "rb");
+ if (!f) return 0;
+ h->offset = 0;
+ h->handle = f;
+ h->entry = e;
+ return h;
+}
+
+Pack_File* pack_open_file(Pack* p, const char* name) {
+ int i;
+ Pack_File* files = (Pack_File*)&p[1];
+ for (i = 0; i < pack_max_files; i++) {
+ Pack_File* file = &files[i];
+ if (!file->handle)
+ return init_handle(p, file, name);
+ }
+ return 0;
+}
+
+void pack_close_file(Pack_File* f) {
+ fclose(f->handle);
+}
+
+int pack_read(Pack_File* f, void* buf, int size) {
+ int diff = (f->offset + size) - f->entry->size;
+ int read;
+ if (diff > 0) size -= diff;
+ fseek(f->handle, f->entry->offset + f->offset, SEEK_SET);
+ read = fread(buf, 1, size, f->handle);
+ f->offset += read;
+ return read;
+}
+
+void pack_seek(Pack_File* f, int offset, Seek_Rel rel) {
+ switch (rel) {
+ case seek_rel_cur:
+ f->offset += offset;
+ break;
+ case seek_rel_start:
+ f->offset = offset;
+ break;
+ case seek_rel_end:
+ f->offset = f->entry->size - offset;
+ break;
+ }
+}
+
+int pack_tell(Pack_File* f) {
+ return f->offset;
+}
diff --git a/qstd/pack.h b/qstd/pack.h
new file mode 100644
index 0000000..447cd5b
--- /dev/null
+++ b/qstd/pack.h
@@ -0,0 +1,40 @@
+#ifndef pack_h
+#define pack_h
+
+#include <stdint.h>
+
+struct Arena;
+struct Pack_File;
+
+typedef struct {
+ char name[56];
+ uint32_t offset;
+ uint32_t size;
+} Pack_Entry;
+
+typedef struct Pack {
+ char* filename;
+ uint32_t file_count;
+} Pack;
+
+Pack_Entry* pack_find_entry(Pack* p, const char* name);
+Pack_Entry* get_pack_table(Pack* p);
+int get_pack_size(int entry_count);
+
+Pack* pack_open(const char* filename, struct Arena* a);
+void pack_close(Pack* p);
+Pack_Entry* pack_get_entry(Pack* p, const char* name);
+
+typedef enum {
+ seek_rel_cur,
+ seek_rel_start,
+ seek_rel_end
+} Seek_Rel;
+
+struct Pack_File* pack_open_file(Pack* p, const char* name);
+void pack_close_file(struct Pack_File* h);
+int pack_read(struct Pack_File* f, void* buf, int size);
+void pack_seek(struct Pack_File* f, int offset, Seek_Rel rel);
+int pack_tell(struct Pack_File* f);
+
+#endif
diff --git a/vid_enums.h b/vid_enums.h
new file mode 100644
index 0000000..fca4f06
--- /dev/null
+++ b/vid_enums.h
@@ -0,0 +1,26 @@
+#ifndef vid_enums_h
+#define vid_enums_h
+
+#define texture_format_xmacro() \
+ x(r8i) \
+ x(r16f) \
+ x(r32f) \
+ x(rg8i) \
+ x(rg16f) \
+ x(rg32f) \
+ x(rgb8i) \
+ x(rgb16f) \
+ x(rgb32f) \
+ x(rgba8i) \
+ x(rgba16f) \
+ x(rgba32f) \
+ x(bc1)
+
+typedef enum {
+#define x(n) texture_format_ ## n,
+ texture_format_xmacro()
+#undef x
+ texture_format_count
+} Texture_Format;
+
+#endif
diff --git a/video.cpp b/video.cpp
index 9e2ca05..1670a61 100644
--- a/video.cpp
+++ b/video.cpp
@@ -11,9 +11,10 @@
extern "C" {
#include "memory.h"
+#include "pack.h"
#include "plat.h"
-#include "str.h"
#include "sc/sh_enums.h"
+#include "str.h"
}
#include <algorithm>
@@ -337,7 +338,7 @@ struct Shader_Vk : public Shader {
int attr_count;
int binding_count;
- bool init(Device_Vk* dev, FILE* f);
+ bool init(Device_Vk* dev, Pack_File* f);
void destroy(Device_Vk* dev);
int find_binding(const char* name);
@@ -349,7 +350,7 @@ struct Shader_Vk : public Shader {
char entrypoints[shader_type_count][24];
Vertex_Format vfd;
- bool init(Device_Vk* dev, FILE* f);
+ bool init(Device_Vk* dev, Pack_File* f);
bool init_module(
Device_Vk* dev,
int stage,
@@ -596,6 +597,12 @@ struct std::hash<Render_Pass> {
}
};
+struct Shader_Loader : public Asset_Loader {
+ Device_Vk* dev;
+ void init(Device_Vk* d);
+ Asset* load(Arena* a, Pack_File* f) override;
+};
+
struct Device_Vk : public Device {
VkAllocationCallbacks ac;
VkInstance inst;
@@ -611,6 +618,7 @@ struct Device_Vk : public Device {
Swapchain swapchain;
Context_Vk contexts[max_contexts];
Context_Vk* current_ctx;
+ Shader_Loader shader_loader;
#ifdef DEBUG
VkDebugUtilsMessengerEXT msg;
#endif
@@ -971,6 +979,8 @@ void Device_Vk::init_internal() {
shader_count = 1;
rpo_cache.init();
pso_cache.init();
+ shader_loader.init(this);
+ register_asset_loader("CSH2", &shader_loader);
find_exts(exts, ext_count);
init_ac();
create_inst(exts, ext_count);
@@ -1983,52 +1993,6 @@ void Vertex_Format_Vk::destroy(Device_Vk* dev) {
heap_free(dev->heap, bindings);
}
-/* todo proper asset manager which will load this stuff */
-bool Shader_Vk::init(Device_Vk* dev, FILE* f) {
- char magic[4];
- int binding_count, target_count, i;
- fread(magic, 4, 1, f);
- if (
- magic[0] != 'C' ||
- magic[1] != 'S' ||
- magic[2] != 'H' ||
- magic[3] != '2'
- ) return false;
- fread(&type, 4, 1, f);
- fread(&binding_count, 4, 1, f);
- fread(&target_count, 4, 1, f);
- vfd.binding_count = binding_count;
- assert(binding_count);
- if (!vfd.init(dev, f))
- return false;
- vf = dev->create_vf(*this);
- fseek(
- f,
- 32 * target_count,
- SEEK_CUR
- );
- for (i = 0; i < shader_type_count; i++) {
- int o, s;
- fread(&o, 4, 1, f);
- fread(&s, 4, 1, f);
- if (o) {
- bool r;
- int before = ftell(f);
- char* buf = (char*)heap_alloc(dev->heap, s);
- fseek(f, o, SEEK_SET);
- fread(buf, 1, s, f);
- r = init_module(dev, i, buf, s);
- heap_free(dev->heap, buf);
- fseek(f, before, SEEK_SET);
- if (!r) return false;
- } else {
- modules[i] = VK_NULL_HANDLE;
- }
- fread(entrypoints[i], 1, 24, f);
- }
- return true;
-}
-
bool Shader_Vk::init_module(
Device_Vk* dev,
int stage,
@@ -2076,27 +2040,27 @@ int Shader_Vk::Vertex_Format::find_attribute(const char* name) {
bool Shader_Vk::Vertex_Format::init(
Device_Vk* dev,
- FILE* f
+ Pack_File* f
) {
int i, attr_index = 0;
- int start = ftell(f);
+ int start = pack_tell(f);
attr_count = 0;
for (i = 0; i < binding_count; i++) {
char name[24];
int count, j;
SBinding_Rate rate;
- fread(name, 1, sizeof name, f);
- fread(&rate, 4, 1, f);
- fread(&count, 4, 1, f);
+ pack_read(f, name, sizeof name);
+ pack_read(f, &rate, 4);
+ pack_read(f, &count, 4);
for (j = 0; j < count; j++) {
char aname[28];
SVariable_Type type;
- fread(aname, 1, sizeof aname, f);
- fread(&type, 4, 1, f);
+ pack_read(f, aname, sizeof aname);
+ pack_read(f, &type, 4);
attr_count++;
}
}
- fseek(f, start, SEEK_SET);
+ pack_seek(f, start, seek_rel_start);
bindings = (Binding*)heap_alloc(
dev->heap,
binding_count * sizeof *bindings
@@ -2114,9 +2078,9 @@ bool Shader_Vk::Vertex_Format::init(
char name[24];
int count, j;
SBinding_Rate rate;
- fread(name, 1, sizeof name, f);
- fread(&rate, 4, 1, f);
- fread(&count, 4, 1, f);
+ pack_read(f, name, sizeof name);
+ pack_read(f, &rate, 4);
+ pack_read(f, &count, 4);
binding = &bindings[find_binding(name)];
strcpy(binding->name, name);
binding->rate = rate;
@@ -2131,8 +2095,8 @@ bool Shader_Vk::Vertex_Format::init(
Attribute* attr;
char aname[28];
SVariable_Type type;
- fread(aname, 1, sizeof aname, f);
- fread(&type, 4, 1, f);
+ pack_read(f, aname, sizeof aname);
+ pack_read(f, &type, 4);
bucket = find_attribute(aname);
binding->attributes[j] = bucket;
attr = &attributes[bucket];
@@ -2276,27 +2240,86 @@ Shader& Device::get_shader(Shader_Id id) {
return ((Device_Vk*)this)->shaders[id];
}
-Shader_Id Device::load_shader(const char* fname) {
- FILE* f = fopen(fname, "rb");
+bool Shader::load(
+ Asset_Loader* loader,
+ Arena* a,
+ Pack_File* f
+) {
+ Device_Vk* dev = ((Shader_Loader*)loader)->dev;
+ Shader_Vk& sh = *(Shader_Vk*)this;
+ return sh.init(dev, f);
+}
+
+void Shader::unload(Asset_Loader* loader_) {
+ Shader_Loader* loader = (Shader_Loader*)loader_;
+ Device_Vk* dev = loader->dev;
+ Shader_Vk& sh = *(Shader_Vk*)this;
+ sh.destroy(dev);
+ dev->shaders.remove(id);
+}
+
+void Shader_Loader::init(Device_Vk* d) {
+ dev = d;
+}
+
+Asset* Shader_Loader::load(
+ Arena* a,
+ Pack_File* f
+) {
Shader_Vk* s;
- Device_Vk* dev = (Device_Vk*)this;
Shader_Id id;
- bool r;
- if (!f) return Shader_Id(0);
id = dev->alloc_shader();
- s = (Shader_Vk*)&get_shader(id);
- r = s->init(dev, f);
- fclose(f);
- if (!r) {
- heap_free(heap, s);
+ s = (Shader_Vk*)&dev->get_shader(id);
+ s->id = id;
+ if (!s->load(this, a, f)) {
+ dev->shaders.remove(id);
return 0;
}
- return id;
+ return s;
}
-void Device::destroy_shader(Shader_Id id) {
- Device_Vk* dev = (Device_Vk*)this;
- Shader_Vk& buf = *(Shader_Vk*)&get_shader(id);
- buf.destroy(dev);
- dev->shaders.remove(id);
+bool Shader_Vk::init(Device_Vk* dev, Pack_File* f) {
+ char magic[4];
+ int binding_count, target_count, i;
+ pack_read(f, magic, 4);
+ if (
+ magic[0] != 'C' ||
+ magic[1] != 'S' ||
+ magic[2] != 'H' ||
+ magic[3] != '2'
+ ) return false;
+ pack_read(f, &type, 4);
+ pack_read(f, &binding_count, 4);
+ pack_read(f, &target_count, 4);
+ vfd.binding_count = binding_count;
+ assert(binding_count);
+ if (!vfd.init(dev, f))
+ return false;
+ vf = dev->create_vf(*this);
+ pack_seek(
+ f,
+ 32 * target_count,
+ seek_rel_cur
+ );
+ for (i = 0; i < shader_type_count; i++) {
+ int o, s;
+ pack_read(f, &o, 4);
+ pack_read(f, &s, 4);
+ if (o) {
+ bool r;
+ int before = pack_tell(f);
+ char* buf = (char*)heap_alloc(dev->heap, s);
+ pack_seek(f, o, seek_rel_start);
+ pack_read(f, buf, s);
+ r = init_module(dev, i, buf, s);
+ heap_free(dev->heap, buf);
+ pack_seek(f, before, seek_rel_start);
+ if (!r) return false;
+ } else {
+ modules[i] = VK_NULL_HANDLE;
+ }
+ pack_read(f, entrypoints[i], 24);
+ }
+ return true;
}
+
diff --git a/video.hpp b/video.hpp
index b59fd5c..786d013 100644
--- a/video.hpp
+++ b/video.hpp
@@ -4,6 +4,12 @@
#include <stddef.h>
#include <stdint.h>
+extern "C" {
+#include "vid_enums.h"
+}
+
+#include "asset.hpp"
+
struct App;
struct Arena;
struct Heap;
@@ -139,9 +145,7 @@ struct Device {
Buffer& get_buffer(Buffer_Id id);
void destroy_buffer(Buffer_Id id);
- Shader_Id load_shader(const char* fname);
Shader& get_shader(Shader_Id id);
- void destroy_shader(Shader_Id id);
};
struct Context {
@@ -162,7 +166,8 @@ struct Context {
void submit(Device& d, const Render_Pass& rp);
};
-struct Shader {
+struct Shader : public Asset {
+ Shader_Id id;
Vertex_Format_Id vf;
void destroy(Device* dev);
@@ -170,6 +175,13 @@ struct Shader {
int binding_index(const char* name);
int attribute_index(const char* name);
int target_index(const char* name);
+
+ bool load(
+ Asset_Loader* loader,
+ Arena* a,
+ Pack_File* f
+ ) override;
+ void unload(Asset_Loader* loader) override;
};
#endif