diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | Makefile | 31 | ||||
| -rw-r--r-- | asset.cpp | 101 | ||||
| -rw-r--r-- | asset.hpp | 41 | ||||
| -rw-r--r-- | c2.cpp | 21 | ||||
| -rw-r--r-- | packer.c | 82 | ||||
| -rw-r--r-- | qstd/Makefile | 7 | ||||
| -rw-r--r-- | qstd/pack.c | 165 | ||||
| -rw-r--r-- | qstd/pack.h | 40 | ||||
| -rw-r--r-- | vid_enums.h | 26 | ||||
| -rw-r--r-- | video.cpp | 179 | ||||
| -rw-r--r-- | video.hpp | 18 | 
12 files changed, 615 insertions, 98 deletions
| @@ -7,3 +7,5 @@ tags  /qstd/libqstd.a  /sc/sc  /c2 +/pack +/packer @@ -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 @@ -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 @@ -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;  } + @@ -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 |