소스 검색

Update kong to 67806999a5ce3c11d8daeee2eec368b1fc32fdbe

luboslenco 3 달 전
부모
커밋
7c0d64789d

+ 29 - 10
base/sources/libs/kong/analyzer.c

@@ -15,7 +15,7 @@ static raytracing_pipelines all_raytracing_pipelines;
 // a pipeline group is a collection of pipelines that share shaders
 static raytracing_pipeline_groups all_raytracing_pipeline_groups;
 
-static void find_referenced_global_for_var(variable v, global_array *globals, bool write) {
+static void find_referenced_global_for_var(variable v, global_array *globals, bool read, bool write) {
 	for (global_id j = 0; get_global(j) != NULL && get_global(j)->type != NO_TYPE; ++j) {
 		global *g = get_global(j);
 
@@ -25,6 +25,10 @@ static void find_referenced_global_for_var(variable v, global_array *globals, bo
 				if (globals->globals[k] == j) {
 					found = true;
 
+					if (read) {
+						globals->readable[k] = true;
+					}
+
 					if (write) {
 						globals->writable[k] = true;
 					}
@@ -34,6 +38,7 @@ static void find_referenced_global_for_var(variable v, global_array *globals, bo
 			}
 			if (!found) {
 				globals->globals[globals->size]  = j;
+				globals->readable[globals->size] = read;
 				globals->writable[globals->size] = write;
 				globals->size += 1;
 			}
@@ -74,12 +79,12 @@ void find_referenced_globals(function *f, global_array *globals) {
 			case OPCODE_GREATER_EQUAL:
 			case OPCODE_LESS:
 			case OPCODE_LESS_EQUAL: {
-				find_referenced_global_for_var(o->op_binary.left, globals, false);
-				find_referenced_global_for_var(o->op_binary.right, globals, false);
+				find_referenced_global_for_var(o->op_binary.left, globals, false, false);
+				find_referenced_global_for_var(o->op_binary.right, globals, false, false);
 				break;
 			}
 			case OPCODE_LOAD_ACCESS_LIST: {
-				find_referenced_global_for_var(o->op_load_access_list.from, globals, false);
+				find_referenced_global_for_var(o->op_load_access_list.from, globals, true, false);
 				break;
 			}
 			case OPCODE_STORE_ACCESS_LIST:
@@ -87,12 +92,12 @@ void find_referenced_globals(function *f, global_array *globals) {
 			case OPCODE_ADD_AND_STORE_ACCESS_LIST:
 			case OPCODE_DIVIDE_AND_STORE_ACCESS_LIST:
 			case OPCODE_MULTIPLY_AND_STORE_ACCESS_LIST: {
-				find_referenced_global_for_var(o->op_store_access_list.to, globals, true);
+				find_referenced_global_for_var(o->op_store_access_list.to, globals, false, true);
 				break;
 			}
 			case OPCODE_CALL: {
 				for (uint8_t i = 0; i < o->op_call.parameters_size; ++i) {
-					find_referenced_global_for_var(o->op_call.parameters[i], globals, false);
+					find_referenced_global_for_var(o->op_call.parameters[i], globals, false, false);
 				}
 				break;
 			}
@@ -172,8 +177,6 @@ void find_used_builtins(function *f) {
 		opcode *o = (opcode *)&data[index];
 		switch (o->type) {
 		case OPCODE_CALL: {
-			char *func_name = get_name(o->op_call.func);
-
 			name_id func = o->op_call.func;
 
 			if (func == add_name("dispatch_thread_id")) {
@@ -267,6 +270,8 @@ void find_used_capabilities(function *f) {
 			type_id  from_type = from.type.type;
 
 			if (is_texture(from_type)) {
+				f->used_capabilities.image_read = true;
+
 				if (get_type(from_type)->array_size > 0) {
 					last_base_texture_from = from;
 					last_base_texture_to   = o->op_load_access_list.to;
@@ -306,6 +311,7 @@ void find_used_capabilities(function *f) {
 				if (called->name == func_name) {
 					find_used_capabilities(f);
 
+					f->used_capabilities.image_read |= called->used_capabilities.image_read;
 					f->used_capabilities.image_write |= called->used_capabilities.image_write;
 
 					break;
@@ -489,6 +495,14 @@ static void find_all_render_pipelines(void) {
 	}
 }
 
+static bool same_shader(function *a, function *b) {
+	if (a == NULL && b == NULL) {
+		return false;
+	}
+
+	return a == b;
+}
+
 static void find_render_pipeline_groups(void) {
 	static_array_init(all_render_pipeline_groups);
 
@@ -516,8 +530,10 @@ static void find_render_pipeline_groups(void) {
 
 			for (size_t index_in_bucket = 0; index_in_bucket < group.size; ++index_in_bucket) {
 				render_pipeline *pipeline_in_group = &all_render_pipelines.values[group.values[index_in_bucket]];
-				if (pipeline->vertex_shader == pipeline_in_group->vertex_shader || pipeline->amplification_shader == pipeline_in_group->amplification_shader ||
-				    pipeline->mesh_shader == pipeline_in_group->mesh_shader || pipeline->fragment_shader == pipeline_in_group->fragment_shader) {
+				if (same_shader(pipeline->vertex_shader, pipeline_in_group->vertex_shader) ||
+				    same_shader(pipeline->amplification_shader, pipeline_in_group->amplification_shader) ||
+				    same_shader(pipeline->mesh_shader, pipeline_in_group->mesh_shader) ||
+				    same_shader(pipeline->fragment_shader, pipeline_in_group->fragment_shader)) {
 					found = true;
 					break;
 				}
@@ -688,6 +704,9 @@ static void update_globals_in_descriptor_set_group(descriptor_set_group *group,
 
 			for (size_t global_index2 = 0; global_index2 < globals->size; ++global_index2) {
 				if (globals->globals[global_index2] == g) {
+					if (globals->readable[global_index2]) {
+						set->globals.readable[global_index] = true;
+					}
 					if (globals->writable[global_index2]) {
 						set->globals.writable[global_index] = true;
 					}

+ 85 - 28
base/sources/libs/kong/backends/metal.c

@@ -53,7 +53,7 @@ static type_id vertex_inputs[256];
 ////
 // static size_t  vertex_inputs_size = 0;
 size_t  vertex_inputs_size = 0;
-///
+////
 static type_id fragment_inputs[256];
 ////
 // static size_t  fragment_inputs_size = 0;
@@ -103,6 +103,55 @@ static void type_name(type_id id, char *output_name) {
 
 static void write_types(char *metal, size_t *offset) {
 	for (type_id i = 0; get_type(i) != NULL; ++i) {
+		type *t = get_type(i);
+		if (!t->built_in && has_attribute(&t->attributes, add_name("pipe"))) {
+			name_id vertex_shader_name = NO_NAME;
+
+			for (size_t j = 0; j < t->members.size; ++j) {
+				if (t->members.m[j].name == add_name("vertex")) {
+					vertex_shader_name = t->members.m[j].value.identifier;
+				}
+			}
+
+			for (function_id i = 0; get_function(i) != NULL; ++i) {
+				function *f = get_function(i);
+				if (f->name == vertex_shader_name) {
+					uint64_t parameter_ids[256] = {0};
+					for (uint8_t parameter_index = 0; parameter_index < f->parameters_size; ++parameter_index) {
+						for (size_t i = 0; i < f->block->block.vars.size; ++i) {
+							if (f->parameter_names[parameter_index] == f->block->block.vars.v[i].name) {
+								parameter_ids[parameter_index] = f->block->block.vars.v[i].variable_id;
+								break;
+							}
+						}
+					}
+
+					*offset += sprintf(&metal[*offset], "struct _kong_%s_attributes {\n", get_name(f->name));
+
+					uint32_t a = 0;
+
+					for (uint8_t parameter_index = 0; parameter_index < f->parameters_size; ++parameter_index) {
+						type *t = get_type(f->parameter_types[parameter_index].type);
+
+						for (size_t j = 0; j < t->members.size; ++j) {
+							*offset += sprintf(&metal[*offset], "\t%s _%" PRIu64 "_%s [[attribute(%u)]];\n", type_string(t->members.m[j].type.type),
+							                   parameter_ids[parameter_index], get_name(t->members.m[j].name), a);
+
+							a += 1;
+						}
+					}
+
+					*offset += sprintf(&metal[*offset], "};\n\n");
+				}
+			}
+		}
+	}
+
+	for (type_id i = 0; get_type(i) != NULL; ++i) {
+		if (is_vertex_input(i)) {
+			continue;
+		}
+
 		type *t = get_type(i);
 
 		if (!t->built_in && !has_attribute(&t->attributes, add_name("pipe"))) {
@@ -110,13 +159,7 @@ static void write_types(char *metal, size_t *offset) {
 			type_name(i, name);
 			*offset += sprintf(&metal[*offset], "struct %s {\n", name);
 
-			if (is_vertex_input(i)) {
-				for (size_t j = 0; j < t->members.size; ++j) {
-					*offset +=
-					    sprintf(&metal[*offset], "\t%s %s [[attribute(%zu)]];\n", type_string(t->members.m[j].type.type), get_name(t->members.m[j].name), j);
-				}
-			}
-			else if (is_fragment_input(i)) {
+			if (is_fragment_input(i)) {
 				for (size_t j = 0; j < t->members.size; ++j) {
 					if (j == 0) {
 						*offset += sprintf(&metal[*offset], "\t%s %s [[position]];\n", type_string(t->members.m[j].type.type), get_name(t->members.m[j].name));
@@ -142,12 +185,12 @@ static int global_register_indices[512];
 static function_id vertex_functions[256];
 ////
 // static size_t      vertex_functions_size = 0;
-size_t      vertex_functions_size = 0;
+size_t              vertex_functions_size = 0;
 ////
 static function_id fragment_functions[256];
 ////
 // static size_t      fragment_functions_size = 0;
-size_t      fragment_functions_size = 0;
+size_t             fragment_functions_size = 0;
 ////
 static function_id compute_functions[256];
 static size_t      compute_functions_size = 0;
@@ -322,15 +365,13 @@ static void write_functions(char *code, size_t *offset) {
 		char buffers[1024];
 		memset(buffers, 0, sizeof(buffers));
 
-		if (is_vertex_function(i) || is_fragment_function(i) || is_compute_function(i)) {
-			global_array globals = {0};
-			find_referenced_globals(f, &globals);
+		size_t buffer_index = f->parameters_size;
 
+		if (is_vertex_function(i) || is_fragment_function(i) || is_compute_function(i)) {
 			size_t buffers_offset = 0;
 
 			descriptor_set_group *set_group = get_descriptor_set_group(f->descriptor_set_group_index);
 
-			size_t buffer_index          = 1;
 			size_t argument_buffer_index = 0;
 
 			for (size_t set_index = 0; set_index < set_group->size; ++set_index) {
@@ -371,12 +412,10 @@ static void write_functions(char *code, size_t *offset) {
 		}
 
 		if (is_vertex_function(i)) {
-			*offset += sprintf(&code[*offset], "vertex %s %s(%s _%" PRIu64 " [[stage_in]]", type_string(f->return_type.type), get_name(f->name),
-			                   type_string(f->parameter_types[0].type), parameter_ids[0]);
-			for (uint8_t parameter_index = 1; parameter_index < f->parameters_size; ++parameter_index) {
-				*offset += sprintf(&code[*offset], ", %s _%" PRIu64, type_string(f->parameter_types[0].type), parameter_ids[0]);
-			}
-			*offset += sprintf(&code[*offset], "%s, uint _kong_vertex_id [[vertex_id]]) {\n", buffers);
+			*offset += sprintf(&code[*offset], "vertex %s %s(_kong_%s_attributes _kong_stage_in [[stage_in]]", type_string(f->return_type.type),
+			                   get_name(f->name), get_name(f->name));
+
+			*offset += sprintf(&code[*offset], "%s, uint _kong_vertex_id [[vertex_id]], uint _kong_instance_id [[instance_id]]) {\n", buffers);
 		}
 		else if (is_fragment_function(i)) {
 			if (get_type(f->return_type.type)->array_size > 0) {
@@ -445,14 +484,17 @@ static void write_functions(char *code, size_t *offset) {
 				bool root_constant = var_name(o->op_load_access_list.from, from_name);
 
 				indent(code, offset, indentation);
-				*offset += sprintf(&code[*offset], "%s _%" PRIu64 " = %s", type_string(o->op_load_access_list.to.type.type), o->op_load_access_list.to.index,
-				                   from_name);
+				*offset += sprintf(&code[*offset], "%s _%" PRIu64 " = ", type_string(o->op_load_access_list.to.type.type), o->op_load_access_list.to.index);
 
-				type *s = get_type(o->op_load_access_list.from.type.type);
+				type_id s = o->op_load_access_list.from.type.type;
 
 				for (size_t i = 0; i < o->op_load_access_list.access_list_size; ++i) {
 					switch (o->op_load_access_list.access_list[i].kind) {
 					case ACCESS_ELEMENT:
+						if (i == 0) {
+							*offset += sprintf(&code[*offset], "%s", from_name);
+						}
+
 						if (is_texture(o->op_load_access_list.from.type.type) && i == 0) {
 							*offset += sprintf(&code[*offset], ".read(_%" PRIu64 ")", o->op_load_access_list.access_list[i].access_element.index.index);
 						}
@@ -461,14 +503,28 @@ static void write_functions(char *code, size_t *offset) {
 						}
 						break;
 					case ACCESS_MEMBER:
-						if (i == 0 && g != NULL) {
+						if (i == 0 && g != NULL && !root_constant) {
+							*offset += sprintf(&code[*offset], "%s", from_name);
+
 							*offset += sprintf(&code[*offset], "->%s", get_name(o->op_load_access_list.access_list[i].access_member.name));
 						}
+						else if (i == 0 && is_vertex_input(s)) {
+							*offset +=
+							    sprintf(&code[*offset], "_kong_stage_in.%s_%s", from_name, get_name(o->op_load_access_list.access_list[i].access_member.name));
+						}
 						else {
+							if (i == 0) {
+								*offset += sprintf(&code[*offset], "%s", from_name);
+							}
+
 							*offset += sprintf(&code[*offset], ".%s", get_name(o->op_load_access_list.access_list[i].access_member.name));
 						}
 						break;
 					case ACCESS_SWIZZLE: {
+						if (i == 0) {
+							*offset += sprintf(&code[*offset], "%s", from_name);
+						}
+
 						char swizzle[4];
 
 						for (uint32_t swizzle_index = 0; swizzle_index < o->op_load_access_list.access_list[i].access_swizzle.swizzle.size; ++swizzle_index) {
@@ -481,7 +537,7 @@ static void write_functions(char *code, size_t *offset) {
 					}
 					}
 
-					s = get_type(o->op_load_access_list.access_list[i].type);
+					s = o->op_load_access_list.access_list[i].type;
 				}
 
 				*offset += sprintf(&code[*offset], ";\n");
@@ -870,9 +926,10 @@ char *metal_export(char *directory) {
 					vertex_functions[vertex_functions_size] = i;
 					vertex_functions_size += 1;
 
-					assert(f->parameters_size > 0);
-					vertex_inputs[vertex_inputs_size] = f->parameter_types[0].type;
-					vertex_inputs_size += 1;
+					for (uint8_t parameter_index = 0; parameter_index < f->parameters_size; ++parameter_index) {
+						vertex_inputs[vertex_inputs_size] = f->parameter_types[parameter_index].type;
+						vertex_inputs_size += 1;
+					}
 				}
 				else if (f->name == fragment_shader_name) {
 					fragment_functions[fragment_functions_size] = i;

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 321 - 145
base/sources/libs/kong/backends/spirv.c


+ 25 - 5
base/sources/libs/kong/backends/wgsl.c

@@ -147,6 +147,7 @@ static void write_code(char *wgsl, char *directory, const char *filename) {
 
 static type_id vertex_inputs[256];
 static size_t  vertex_inputs_size = 0;
+static size_t  vertex_location_offsets[256];
 static type_id fragment_inputs[256];
 static size_t  fragment_inputs_size = 0;
 
@@ -159,6 +160,15 @@ static bool is_vertex_input(type_id t) {
 	return false;
 }
 
+static size_t find_vertex_location_offset(type_id t) {
+	for (size_t i = 0; i < vertex_inputs_size; ++i) {
+		if (t == vertex_inputs[i]) {
+			return vertex_location_offsets[i];
+		}
+	}
+	return 0;
+}
+
 static bool is_fragment_input(type_id t) {
 	for (size_t i = 0; i < fragment_inputs_size; ++i) {
 		if (t == fragment_inputs[i]) {
@@ -197,8 +207,12 @@ static void write_types(char *wgsl, size_t *offset) {
 			}
 
 			if (is_vertex_input(i)) {
+				size_t location = find_vertex_location_offset(i);
+
 				for (size_t j = 0; j < t->members.size; ++j) {
-					*offset += sprintf(&wgsl[*offset], "\t@location(%zu) %s: %s,\n", j, get_name(t->members.m[j].name), type_string(t->members.m[j].type.type));
+					*offset +=
+					    sprintf(&wgsl[*offset], "\t@location(%zu) %s: %s,\n", location, get_name(t->members.m[j].name), type_string(t->members.m[j].type.type));
+					++location;
 				}
 			}
 			else if (is_fragment_input(i)) {
@@ -804,7 +818,7 @@ static void write_functions(char *code, size_t *offset) {
 					check(o->op_call.parameters_size == 4, context, "sample_lod requires four arguments");
 					indent(code, offset, indentation);
 					*offset +=
-					    sprintf(&code[*offset], "var _%s: %s = textureSample(%s, %s, %s, %s);\n", get_var(o->op_call.var, f).str,
+					    sprintf(&code[*offset], "var %s: %s = textureSampleLevel(%s, %s, %s, %s);\n", get_var(o->op_call.var, f).str,
 					            type_string(o->op_call.var.type.type), get_var(o->op_call.parameters[0], f).str, get_var(o->op_call.parameters[1], f).str,
 					            get_var(o->op_call.parameters[2], f).str, get_var(o->op_call.parameters[3], f).str);
 				}
@@ -936,9 +950,15 @@ void wgsl_export(char *directory) {
 					vertex_functions[vertex_functions_size] = i;
 					vertex_functions_size += 1;
 
-					assert(f->parameters_size > 0);
-					vertex_inputs[vertex_inputs_size] = f->parameter_types[0].type;
-					vertex_inputs_size += 1;
+					size_t vertex_location_offset = 0;
+
+					for (uint32_t parameter_index = 0; parameter_index < f->parameters_size; ++parameter_index) {
+						vertex_inputs[vertex_inputs_size]           = f->parameter_types[parameter_index].type;
+						vertex_location_offsets[vertex_inputs_size] = vertex_location_offset;
+
+						vertex_inputs_size += 1;
+						vertex_location_offset += get_type(f->parameter_types[parameter_index].type)->members.size;
+					}
 				}
 				else if (f->name == fragment_shader_name) {
 					fragment_functions[fragment_functions_size] = i;

+ 1 - 1
base/sources/libs/kong/compiler.c

@@ -15,7 +15,7 @@ typedef struct allocated_global {
 static allocated_global allocated_globals[1024];
 ////
 // static size_t           allocated_globals_size = 0;
-size_t           allocated_globals_size = 0;
+size_t                  allocated_globals_size = 0;
 ////
 
 allocated_global find_allocated_global(name_id name) {

+ 1 - 0
base/sources/libs/kong/functions.h

@@ -20,6 +20,7 @@ typedef struct builtins {
 
 typedef struct capabilities {
 	bool capabilities_analyzed;
+	bool image_read;
 	bool image_write;
 } capabilities;
 

+ 1 - 1
base/sources/libs/kong/globals.c

@@ -7,7 +7,7 @@
 static global    globals[1024];
 ////
 // static global_id globals_size = 0;
-global_id globals_size = 0;
+global_id        globals_size = 0;
 ////
 
 void globals_init(void) {

+ 1 - 0
base/sources/libs/kong/globals.h

@@ -52,6 +52,7 @@ typedef struct global {
 
 typedef struct global_array {
 	global_id globals[256];
+	bool      readable[256];
 	bool      writable[256];
 	size_t    size;
 } global_array;

+ 280 - 95
base/sources/libs/kong/integrations/kore3.c

@@ -396,7 +396,7 @@ static void write_root_signature(FILE *output, descriptor_set *all_descriptor_se
 		}
 	}
 
-	fprintf(output, "\tD3D12_ROOT_PARAMETER params[%i] = {};\n", table_count);
+	fprintf(output, "\tD3D12_ROOT_PARAMETER params[%i] = {0};\n", table_count);
 
 	uint32_t table_index = 0;
 
@@ -432,7 +432,7 @@ static void write_root_signature(FILE *output, descriptor_set *all_descriptor_se
 				}
 			}
 
-			fprintf(output, "\n\tD3D12_DESCRIPTOR_RANGE ranges%i[%zu] = {};\n", table_index, count);
+			fprintf(output, "\n\tD3D12_DESCRIPTOR_RANGE ranges%i[%zu] = {0};\n", table_index, count);
 
 			size_t range_index = 0;
 			for (size_t global_index = 0; global_index < set->globals.size; ++global_index) {
@@ -500,7 +500,7 @@ static void write_root_signature(FILE *output, descriptor_set *all_descriptor_se
 				}
 			}
 
-			fprintf(output, "\n\tD3D12_DESCRIPTOR_RANGE ranges%i[%zu] = {};\n", table_index, count);
+			fprintf(output, "\n\tD3D12_DESCRIPTOR_RANGE ranges%i[%zu] = {0};\n", table_index, count);
 
 			size_t range_index = 0;
 			for (size_t global_index = 0; global_index < set->globals.size; ++global_index) {
@@ -523,15 +523,18 @@ static void write_root_signature(FILE *output, descriptor_set *all_descriptor_se
 		}
 	}
 
-	fprintf(output, "\n\tD3D12_ROOT_SIGNATURE_DESC desc = {};\n");
+	fprintf(output, "\n\tD3D12_ROOT_SIGNATURE_DESC desc = {0};\n");
 	fprintf(output, "\tdesc.NumParameters = %i;\n", table_count);
 	fprintf(output, "\tdesc.pParameters = params;\n");
 
 	fprintf(output, "\n\tID3D12RootSignature* root_signature;\n");
 	fprintf(output, "\tID3DBlob *blob;\n");
-	fprintf(output, "\tD3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1_0, &blob, nullptr);\n");
-	fprintf(output, "\tdevice->d3d12.device->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&root_signature));\n");
-	fprintf(output, "\tblob->Release();\n");
+	fprintf(output, "\tD3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1_0, &blob, NULL);\n");
+	fprintf(
+	    output,
+	    "\tdevice->d3d12.device->lpVtbl->CreateRootSignature(device->d3d12.device, 0, blob->lpVtbl->GetBufferPointer(blob), blob->lpVtbl->GetBufferSize(blob), "
+	    "&IID_ID3D12RootSignature, &root_signature);\n");
+	fprintf(output, "\tblob->lpVtbl->Release(blob);\n");
 
 	fprintf(output, "\n\treturn root_signature;\n");
 }
@@ -643,9 +646,10 @@ void kore3_export(char *directory, api_kind api) {
 		}
 	}
 
-	type_id vertex_inputs[256]      = {0};
-	size_t  vertex_input_slots[256] = {0};
-	size_t  vertex_inputs_size      = 0;
+	type_id vertex_inputs[256]              = {0};
+	size_t  vertex_input_slots[256]         = {0};
+	bool    vertex_inputs_per_instance[256] = {0};
+	size_t  vertex_inputs_size              = 0;
 
 	for (type_id i = 0; get_type(i) != NULL; ++i) {
 		type *t = get_type(i);
@@ -676,8 +680,9 @@ void kore3_export(char *directory, api_kind api) {
 						check(f->parameters_size > 0, context, "Vertex function requires at least one parameter");
 
 						for (size_t input_index = 0; input_index < f->parameters_size; ++input_index) {
-							vertex_inputs[vertex_inputs_size]      = f->parameter_types[input_index].type;
-							vertex_input_slots[vertex_inputs_size] = input_index;
+							vertex_inputs[vertex_inputs_size]              = f->parameter_types[input_index].type;
+							vertex_input_slots[vertex_inputs_size]         = input_index;
+							vertex_inputs_per_instance[vertex_inputs_size] = f->parameter_attributes[input_index] == add_name("per_instance");
 							vertex_inputs_size += 1;
 						}
 
@@ -847,6 +852,9 @@ void kore3_export(char *directory, api_kind api) {
 					}
 					else {
 						fprintf(output, "\tkore_gpu_texture_view %s;\n", get_name(g->name));
+						if (api == API_METAL) {
+							fprintf(output, "\tvoid *%s_view;\n", get_name(g->name));
+						}
 					}
 				}
 				else if (is_sampler(g->type)) {
@@ -1085,7 +1093,19 @@ void kore3_export(char *directory, api_kind api) {
 		if (api != API_WEBGPU) {
 			for (size_t set_index = 0; set_index < sets_count; ++set_index) {
 				descriptor_set *set = sets[set_index];
-				fprintf(output, "static uint32_t %s_table_index = UINT32_MAX;\n\n", get_name(set->name));
+				if (api == API_METAL) {
+					fprintf(output, "static uint32_t %s_vertex_table_index = UINT32_MAX;\n\n", get_name(set->name));
+					fprintf(output, "static uint32_t %s_fragment_table_index = UINT32_MAX;\n\n", get_name(set->name));
+					fprintf(output, "static uint32_t %s_compute_table_index = UINT32_MAX;\n\n", get_name(set->name));
+				}
+				else if (api == API_VULKAN) {
+					if (set->name != add_name("root_constants")) {
+						fprintf(output, "static uint32_t %s_table_index = UINT32_MAX;\n\n", get_name(set->name));
+					}
+				}
+				else {
+					fprintf(output, "static uint32_t %s_table_index = UINT32_MAX;\n\n", get_name(set->name));
+				}
 			}
 		}
 
@@ -1102,51 +1122,51 @@ void kore3_export(char *directory, api_kind api) {
 
 				global_array globals = {0};
 
-				if (api == API_OPENGL) {
-					for (global_id i = 0; get_global(i) != NULL; ++i) {
-						global *g = get_global(i);
-						if (g->type == sampler_type_id) {
-						}
-						else if (is_texture(g->type)) {
-						}
-						else if (g->type == float_id) {
-						}
-						else if (!get_type(g->type)->built_in) {
-							fprintf(output, "static uint32_t _%" PRIu64 "_uniform_block_index;\n", g->var_index);
-						}
+				for (global_id i = 0; get_global(i) != NULL; ++i) {
+					global *g = get_global(i);
+					if (g->type == sampler_type_id) {
+					}
+					else if (is_texture(g->type)) {
+					}
+					else if (g->type == float_id) {
+					}
+					else if (!get_type(g->type)->built_in) {
+						fprintf(output, "static uint32_t _%" PRIu64 "_uniform_block_index;\n", g->var_index);
 					}
+				}
 
-					for (size_t j = 0; j < t->members.size; ++j) {
-						if (t->members.m[j].name == add_name("vertex")) {
-							vertex_shader_name = t->members.m[j].value.identifier;
-						}
-						if (t->members.m[j].name == add_name("fragment")) {
-							fragment_shader_name = t->members.m[j].value.identifier;
-						}
+				for (size_t j = 0; j < t->members.size; ++j) {
+					if (t->members.m[j].name == add_name("vertex")) {
+						vertex_shader_name = t->members.m[j].value.identifier;
+					}
+					if (t->members.m[j].name == add_name("fragment")) {
+						fragment_shader_name = t->members.m[j].value.identifier;
 					}
+				}
 
-					assert(vertex_shader_name != NO_NAME);
-					assert(fragment_shader_name != NO_NAME);
+				assert(vertex_shader_name != NO_NAME);
+				assert(fragment_shader_name != NO_NAME);
 
-					for (function_id i = 0; get_function(i) != NULL; ++i) {
-						function *f = get_function(i);
+				for (function_id i = 0; get_function(i) != NULL; ++i) {
+					function *f = get_function(i);
 
-						if (f->name == vertex_shader_name) {
-							vertex_function = f;
-						}
+					if (f->name == vertex_shader_name) {
+						vertex_function = f;
+					}
 
-						if (f->name == fragment_shader_name) {
-							fragment_function = f;
-						}
+					if (f->name == fragment_shader_name) {
+						fragment_function = f;
+					}
 
-						if (vertex_function != NULL && fragment_function != NULL) {
-							break;
-						}
+					if (vertex_function != NULL && fragment_function != NULL) {
+						break;
 					}
+				}
 
-					assert(vertex_function != NULL);
-					assert(fragment_function != NULL);
+				assert(vertex_function != NULL);
+				assert(fragment_function != NULL);
 
+				if (api == API_OPENGL) {
 					find_referenced_globals(vertex_function, &globals);
 					find_referenced_globals(fragment_function, &globals);
 
@@ -1185,8 +1205,27 @@ void kore3_export(char *directory, api_kind api) {
 
 				if (api != API_WEBGPU) {
 					descriptor_set_group *group = find_descriptor_set_group_for_pipe_type(t);
-					for (size_t group_index = 0; group_index < group->size; ++group_index) {
-						fprintf(output, "\t%s_table_index = %zu;\n", get_name(group->values[group_index]->name), group_index);
+
+					if (api == API_VULKAN) {
+						size_t index = 0;
+						for (size_t group_index = 0; group_index < group->size; ++group_index) {
+							if (group->values[group_index]->name != add_name("root_constants")) {
+								fprintf(output, "\t%s_table_index = %zu;\n", get_name(group->values[group_index]->name), index);
+								index += 1;
+							}
+						}
+					}
+					else {
+						for (size_t group_index = 0; group_index < group->size; ++group_index) {
+							if (api == API_METAL) {
+								fprintf(output, "\t%s_vertex_table_index = %zu;\n", get_name(group->values[group_index]->name),
+								        group_index + vertex_function->parameters_size);
+								fprintf(output, "\t%s_fragment_table_index = %zu;\n", get_name(group->values[group_index]->name), group_index + 1);
+							}
+							else {
+								fprintf(output, "\t%s_table_index = %zu;\n", get_name(group->values[group_index]->name), group_index);
+							}
+						}
 					}
 				}
 
@@ -1203,7 +1242,12 @@ void kore3_export(char *directory, api_kind api) {
 
 				descriptor_set_group *group = find_descriptor_set_group_for_pipe_type(t);
 				for (size_t group_index = 0; group_index < group->size; ++group_index) {
-					fprintf(output, "\t%s_table_index = %zu;\n", get_name(group->values[group_index]->name), group_index);
+					if (api == API_METAL) {
+						fprintf(output, "\t%s_compute_table_index = %zu;\n", get_name(group->values[group_index]->name), group_index);
+					}
+					else {
+						fprintf(output, "\t%s_table_index = %zu;\n", get_name(group->values[group_index]->name), group_index);
+					}
 				}
 
 				fprintf(output, "}\n\n");
@@ -1392,8 +1436,19 @@ void kore3_export(char *directory, api_kind api) {
 
 				fprintf(output, "void kong_set_root_constants_%s(kore_gpu_command_list *list, %s *constants) {\n", get_name(root_constants_global->name),
 				        root_constants_type_name);
-				fprintf(output, "\tkore_%s_command_list_set_root_constants(list, %s_table_index, constants, %i);\n", api_short, get_name(set->name),
-				        struct_size(root_constants_global->type));
+				if (api == API_METAL) {
+					fprintf(output,
+					        "\tkore_%s_command_list_set_root_constants(list, %s_vertex_table_index, %s_fragment_table_index, %s_compute_table_index, "
+					        "constants, %i);\n",
+					        api_short, get_name(set->name), get_name(set->name), get_name(set->name), struct_size(root_constants_global->type));
+				}
+				else if (api == API_VULKAN) {
+					fprintf(output, "\tkore_%s_command_list_set_root_constants(list, constants, %i);\n", api_short, struct_size(root_constants_global->type));
+				}
+				else {
+					fprintf(output, "\tkore_%s_command_list_set_root_constants(list, %s_table_index, constants, %i);\n", api_short, get_name(set->name),
+					        struct_size(root_constants_global->type));
+				}
 				fprintf(output, "}\n\n");
 
 				continue;
@@ -1610,7 +1665,31 @@ void kore3_export(char *directory, api_kind api) {
 					}
 					else if (is_texture(g->type)) {
 						fprintf(output, "\t\tid<MTLTexture> texture = (__bridge id<MTLTexture>)parameters->%s.texture->metal.texture;\n", get_name(g->name));
-						fprintf(output, "\t\t[argument_encoder setTexture: texture atIndex: %zu];\n", index);
+
+						if (g->type == tex2d_type_id) {
+							fprintf(output,
+							        "\t\tid<MTLTexture> view = [texture newTextureViewWithPixelFormat:texture.pixelFormat textureType:MTLTextureType2D "
+							        "levels:NSMakeRange(parameters->%s.base_mip_level, parameters->%s.mip_level_count) "
+							        "slices:NSMakeRange(parameters->%s.base_array_layer, parameters->%s.array_layer_count)];\n",
+							        get_name(g->name), get_name(g->name), get_name(g->name), get_name(g->name));
+						}
+						else if (g->type == tex2darray_type_id) {
+							fprintf(output,
+							        "\t\tid<MTLTexture> view = [texture newTextureViewWithPixelFormat:texture.pixelFormat textureType:MTLTextureType2DArray "
+							        "levels:NSMakeRange(parameters->%s.base_mip_level, parameters->%s.mip_level_count) "
+							        "slices:NSMakeRange(parameters->%s.base_array_layer, parameters->%s.array_layer_count)];\n",
+							        get_name(g->name), get_name(g->name), get_name(g->name), get_name(g->name));
+						}
+						else if (g->type == texcube_type_id) {
+							fprintf(output,
+							        "\t\tid<MTLTexture> view = [texture newTextureViewWithPixelFormat:texture.pixelFormat textureType:MTLTextureTypeCube "
+							        "levels:NSMakeRange(parameters->%s.base_mip_level, parameters->%s.mip_level_count) "
+							        "slices:NSMakeRange(parameters->%s.base_array_layer, parameters->%s.array_layer_count)];\n",
+							        get_name(g->name), get_name(g->name), get_name(g->name), get_name(g->name));
+						}
+
+						fprintf(output, "\t\t[argument_encoder setTexture: view atIndex: %zu];\n", index);
+						fprintf(output, "\t\tset->%s_view = (__bridge_retained void*)view;\n", get_name(g->name));
 						index += 1;
 					}
 					else if (is_sampler(g->type)) {
@@ -1670,6 +1749,7 @@ void kore3_export(char *directory, api_kind api) {
 
 				for (size_t global_index = 0; global_index < set->globals.size; ++global_index) {
 					global *g            = get_global(set->globals.globals[global_index]);
+					bool    readable     = set->globals.readable[global_index];
 					bool    writable     = set->globals.writable[global_index];
 					type_id base_type_id = get_type(g->type)->base != NO_TYPE ? get_type(g->type)->base : g->type;
 
@@ -1708,7 +1788,7 @@ void kore3_export(char *directory, api_kind api) {
 							fprintf(output, "\tset->%s_count = parameters->%s_count;\n", get_name(g->name), get_name(g->name));
 						}
 						else {
-							if (writable) {
+							if (readable | writable) {
 								fprintf(output, "\tkore_vulkan_descriptor_set_set_storage_image_descriptor(device, &set->set, &parameters->%s, %zu);\n",
 								        get_name(g->name), other_index);
 							}
@@ -1739,7 +1819,7 @@ void kore3_export(char *directory, api_kind api) {
 							debug_context context = {0};
 							error(context, "Cube maps can not be writable");
 						}
-						fprintf(output, "\tkore_%s_descriptor_set_set_texture_cube_view_srv(device, &set->set, &parameters->%s, %zu);\n", api_short,
+						fprintf(output, "\tkore_vulkan_descriptor_set_set_sampled_cube_image_descriptor(device, &set->set, &parameters->%s, %zu);\n",
 						        get_name(g->name), other_index);
 
 						fprintf(output, "\tset->%s = parameters->%s;\n", get_name(g->name), get_name(g->name));
@@ -1775,6 +1855,9 @@ void kore3_export(char *directory, api_kind api) {
 						if (g->type == tex2darray_type_id) {
 							fprintf(output, "\t\t.dimension = WGPUTextureViewDimension_2DArray,\n");
 						}
+						else if (g->type == texcube_type_id) {
+							fprintf(output, "\t\t.dimension = WGPUTextureViewDimension_Cube,\n");
+						}
 						else {
 							fprintf(output, "\t\t.dimension = WGPUTextureViewDimension_2D,\n");
 						}
@@ -1936,10 +2019,10 @@ void kore3_export(char *directory, api_kind api) {
 						}
 						else {
 							if (writable) {
-								fprintf(output, "\tkore_%s_descriptor_set_prepare_texture(list, &set->%s, true);\n", api_short, get_name(g->name));
+								fprintf(output, "\tkore_%s_descriptor_set_prepare_texture(list, set->%s_view, true);\n", api_short, get_name(g->name));
 							}
 							else {
-								fprintf(output, "\tkore_%s_descriptor_set_prepare_texture(list, &set->%s, false);\n", api_short, get_name(g->name));
+								fprintf(output, "\tkore_%s_descriptor_set_prepare_texture(list, set->%s_view, false);\n", api_short, get_name(g->name));
 							}
 						}
 					}
@@ -2103,7 +2186,10 @@ void kore3_export(char *directory, api_kind api) {
 					fprintf(output, ");\n");
 				}
 				else if (api == API_METAL) {
-					fprintf(output, "\n\tkore_metal_command_list_set_descriptor_set(list, &set->set");
+					fprintf(output,
+					        "\n\tkore_metal_command_list_set_descriptor_set(list, %s_vertex_table_index, %s_fragment_table_index, %s_compute_table_index, "
+					        "&set->set",
+					        get_name(set->name), get_name(set->name), get_name(set->name));
 					if (dynamic_count > 0) {
 						fprintf(output, ", dynamic_buffers, dynamic_offsets, dynamic_sizes, %u", dynamic_count);
 					}
@@ -2194,8 +2280,24 @@ void kore3_export(char *directory, api_kind api) {
 
 				if (api != API_WEBGPU) {
 					descriptor_set_group *group = find_descriptor_set_group_for_function(f);
-					for (size_t group_index = 0; group_index < group->size; ++group_index) {
-						fprintf(output, "\t%s_table_index = %zu;\n", get_name(group->values[group_index]->name), group_index);
+					if (api == API_VULKAN) {
+						size_t index = 0;
+						for (size_t group_index = 0; group_index < group->size; ++group_index) {
+							if (group->values[group_index]->name != add_name("root_constants")) {
+								fprintf(output, "\t%s_table_index = %zu;\n", get_name(group->values[group_index]->name), index);
+								++index;
+							}
+						}
+					}
+					else {
+						for (size_t group_index = 0; group_index < group->size; ++group_index) {
+							if (api == API_METAL) {
+								fprintf(output, "\t%s_compute_table_index = %zu;\n", get_name(group->values[group_index]->name), group_index);
+							}
+							else {
+								fprintf(output, "\t%s_table_index = %zu;\n", get_name(group->values[group_index]->name), group_index);
+							}
+						}
 					}
 				}
 
@@ -2345,19 +2447,6 @@ void kore3_export(char *directory, api_kind api) {
 					// }
 				}
 
-				fprintf(output, "\t%s_parameters.fragment.targets[0].blend.color.src_factor = %s;\n", get_name(t->name),
-				        convert_blend_mode(blend_source, api_caps));
-				fprintf(output, "\t%s_parameters.fragment.targets[0].blend.color.dst_factor = %s;\n", get_name(t->name),
-				        convert_blend_mode(blend_destination, api_caps));
-				fprintf(output, "\t%s_parameters.fragment.targets[0].blend.color.operation = %s;\n", get_name(t->name),
-				        convert_blend_op(blend_operation, api_caps));
-				fprintf(output, "\t%s_parameters.fragment.targets[0].blend.alpha.src_factor = %s;\n", get_name(t->name),
-				        convert_blend_mode(alpha_blend_source, api_caps));
-				fprintf(output, "\t%s_parameters.fragment.targets[0].blend.alpha.dst_factor = %s;\n", get_name(t->name),
-				        convert_blend_mode(alpha_blend_destination, api_caps));
-				fprintf(output, "\t%s_parameters.fragment.targets[0].blend.alpha.operation = %s;\n\n", get_name(t->name),
-				        convert_blend_op(alpha_blend_operation, api_caps));
-
 				{
 					debug_context context = {0};
 					check(vertex_shader_name != NO_NAME || mesh_shader_name != NO_NAME, context, "No vertex or mesh shader name found");
@@ -2536,13 +2625,17 @@ void kore3_export(char *directory, api_kind api) {
 					fprintf(output, "\n");
 				}
 				else {
-					fprintf(output, "\t%s_parameters.fragment.targets_count = 1;\n", get_name(t->name));
-
 					member *format = find_member(t, "format");
 					if (format == NULL) {
 						format = find_member(t, "format0");
 					}
-					if (format != NULL) {
+
+					if (format == NULL) {
+						fprintf(output, "\t%s_parameters.fragment.targets_count = 0;\n", get_name(t->name));
+					}
+					else {
+						fprintf(output, "\t%s_parameters.fragment.targets_count = 1;\n", get_name(t->name));
+
 						debug_context context = {0};
 						check(format->value.kind == TOKEN_IDENTIFIER, context, "format expects an identifier");
 
@@ -2554,12 +2647,37 @@ void kore3_export(char *directory, api_kind api) {
 							fprintf(output, "\t%s_parameters.fragment.targets[0].format = %s;\n", get_name(t->name),
 							        convert_texture_format(g->value.value.ints[0]));
 						}
+
+						fprintf(output, "\t%s_parameters.fragment.targets[0].write_mask = 0xf;\n\n", get_name(t->name));
 					}
-					else {
-						fprintf(output, "\t%s_parameters.fragment.targets[0].format = KORE_GPU_TEXTURE_FORMAT_RGBA8_UNORM;\n", get_name(t->name));
+				}
+
+				uint32_t target_count = get_type(fragment_function->return_type.type)->array_size;
+
+				if (target_count == 0) {
+					member *format = find_member(t, "format");
+					if (format == NULL) {
+						format = find_member(t, "format0");
 					}
 
-					fprintf(output, "\t%s_parameters.fragment.targets[0].write_mask = 0xf;\n\n", get_name(t->name));
+					if (format != NULL) {
+						target_count = 1;
+					}
+				}
+
+				for (uint32_t target_index = 0; target_index < target_count; ++target_index) {
+					fprintf(output, "\t%s_parameters.fragment.targets[%u].blend.color.src_factor = %s;\n", get_name(t->name), target_index,
+					        convert_blend_mode(blend_source, api_caps));
+					fprintf(output, "\t%s_parameters.fragment.targets[%u].blend.color.dst_factor = %s;\n", get_name(t->name), target_index,
+					        convert_blend_mode(blend_destination, api_caps));
+					fprintf(output, "\t%s_parameters.fragment.targets[%u].blend.color.operation = %s;\n", get_name(t->name), target_index,
+					        convert_blend_op(blend_operation, api_caps));
+					fprintf(output, "\t%s_parameters.fragment.targets[%u].blend.alpha.src_factor = %s;\n", get_name(t->name), target_index,
+					        convert_blend_mode(alpha_blend_source, api_caps));
+					fprintf(output, "\t%s_parameters.fragment.targets[%u].blend.alpha.dst_factor = %s;\n", get_name(t->name), target_index,
+					        convert_blend_mode(alpha_blend_destination, api_caps));
+					fprintf(output, "\t%s_parameters.fragment.targets[%u].blend.alpha.operation = %s;\n\n", get_name(t->name), target_index,
+					        convert_blend_op(alpha_blend_operation, api_caps));
 				}
 
 				if (api == API_VULKAN) {
@@ -2568,19 +2686,38 @@ void kore3_export(char *directory, api_kind api) {
 					fprintf(output, "\t{\n");
 
 					if (group->size == 0) {
-						fprintf(output, "\t\tkore_%s_render_pipeline_init(&device->%s, &%s, &%s_parameters, NULL, 0);\n", api_short, api_short,
+						fprintf(output, "\t\tkore_%s_render_pipeline_init(&device->%s, &%s, &%s_parameters, NULL, 0, 0);\n", api_short, api_short,
 						        get_name(t->name), get_name(t->name));
 					}
 					else {
-
-						fprintf(output, "\t\tVkDescriptorSetLayout layouts[%zu];\n", group->size);
+						size_t root_constants_size = 0;
+						size_t group_size          = group->size;
 
 						for (size_t layout_index = 0; layout_index < group->size; ++layout_index) {
-							fprintf(output, "\t\tlayouts[%zu] = %s_set_layout;\n", layout_index, get_name(group->values[layout_index]->name));
+							if (group->values[layout_index]->name == add_name("root_constants")) {
+								--group_size;
+							}
+						}
+
+						fprintf(output, "\t\tVkDescriptorSetLayout layouts[%zu];\n", group_size);
+
+						size_t layout_index = 0;
+						for (size_t i = 0; i < group->size; ++i) {
+							if (group->values[i]->name == add_name("root_constants")) {
+								for (size_t global_index = 0; global_index < group->values[i]->globals.size; ++global_index) {
+									global *g = get_global(group->values[i]->globals.globals[global_index]);
+									root_constants_size += struct_size(g->type);
+								}
+
+								continue;
+							}
+
+							fprintf(output, "\t\tlayouts[%zu] = %s_set_layout;\n", layout_index, get_name(group->values[i]->name));
+							++layout_index;
 						}
 
-						fprintf(output, "\t\tkore_%s_render_pipeline_init(&device->%s, &%s, &%s_parameters, layouts, %zu);\n", api_short, api_short,
-						        get_name(t->name), get_name(t->name), group->size);
+						fprintf(output, "\t\tkore_%s_render_pipeline_init(&device->%s, &%s, &%s_parameters, layouts, %zu, %zu);\n", api_short, api_short,
+						        get_name(t->name), get_name(t->name), group_size, root_constants_size);
 					}
 
 					fprintf(output, "\t}\n");
@@ -2667,19 +2804,38 @@ void kore3_export(char *directory, api_kind api) {
 					fprintf(output, "\t{\n");
 
 					if (group->size == 0) {
-						fprintf(output, "\t\tkore_%s_compute_pipeline_init(&device->%s, &%s, &%s_parameters, NULL, 0);\n", api_short, api_short,
+						fprintf(output, "\t\tkore_%s_compute_pipeline_init(&device->%s, &%s, &%s_parameters, NULL, 0, 0);\n", api_short, api_short,
 						        get_name(f->name), get_name(f->name));
 					}
 					else {
-
-						fprintf(output, "\t\tVkDescriptorSetLayout layouts[%zu];\n", group->size);
+						size_t root_constants_size = 0;
+						size_t group_size          = group->size;
 
 						for (size_t layout_index = 0; layout_index < group->size; ++layout_index) {
-							fprintf(output, "\t\tlayouts[%zu] = %s_set_layout;\n", layout_index, get_name(group->values[layout_index]->name));
+							if (group->values[layout_index]->name == add_name("root_constants")) {
+								--group_size;
+							}
+						}
+
+						fprintf(output, "\t\tVkDescriptorSetLayout layouts[%zu];\n", group_size);
+
+						size_t layout_index = 0;
+						for (size_t i = 0; i < group->size; ++i) {
+							if (group->values[i]->name == add_name("root_constants")) {
+								for (size_t global_index = 0; global_index < group->values[i]->globals.size; ++global_index) {
+									global *g = get_global(group->values[i]->globals.globals[global_index]);
+									root_constants_size += struct_size(g->type);
+								}
+
+								continue;
+							}
+
+							fprintf(output, "\t\tlayouts[%zu] = %s_set_layout;\n", layout_index, get_name(group->values[i]->name));
+							++layout_index;
 						}
 
-						fprintf(output, "\t\tkore_%s_compute_pipeline_init(&device->%s, &%s, &%s_parameters, layouts, %zu);\n", api_short, api_short,
-						        get_name(f->name), get_name(f->name), group->size);
+						fprintf(output, "\t\tkore_%s_compute_pipeline_init(&device->%s, &%s, &%s_parameters, layouts, %zu, %zu);\n", api_short, api_short,
+						        get_name(f->name), get_name(f->name), group_size, root_constants_size);
 					}
 
 					fprintf(output, "\t}\n");
@@ -2784,7 +2940,7 @@ void kore3_export(char *directory, api_kind api) {
 
 	if (api == API_DIRECT3D12) {
 		char filename[512];
-		sprintf(filename, "%s/%s", directory, "kong_ray_root_signatures.cpp");
+		sprintf(filename, "%s/%s", directory, "kong_ray_root_signatures.c");
 
 		FILE *output = fopen(filename, "wb");
 
@@ -2794,7 +2950,7 @@ void kore3_export(char *directory, api_kind api) {
 		for (type_id i = 0; get_type(i) != NULL; ++i) {
 			type *t = get_type(i);
 			if (!t->built_in && has_attribute(&t->attributes, add_name("raypipe"))) {
-				fprintf(output, "extern \"C\" ID3D12RootSignature *kong_create_%s_root_signature(kore_gpu_device *device) {\n", get_name(t->name));
+				fprintf(output, "ID3D12RootSignature *kong_create_%s_root_signature(kore_gpu_device *device) {\n", get_name(t->name));
 				write_root_signature(output, sets, sets_count);
 				fprintf(output, "}\n");
 			}
@@ -2831,12 +2987,13 @@ void kore3_export(char *directory, api_kind api) {
 
 			for (size_t global_index = 0; global_index < set->globals.size; ++global_index) {
 				global *g        = get_global(set->globals.globals[global_index]);
+				bool    readable = set->globals.readable[global_index];
 				bool    writable = set->globals.writable[global_index];
 
 				if (g->type == tex2d_type_id) {
 					fprintf(output, "\t\t\t{\n");
 					fprintf(output, "\t\t\t\t.binding = %zu,\n", global_index);
-					if (writable) {
+					if (readable | writable) {
 						fprintf(output, "\t\t\t\t.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,\n");
 					}
 					else {
@@ -2850,7 +3007,7 @@ void kore3_export(char *directory, api_kind api) {
 				else if (g->type == tex2darray_type_id) {
 					fprintf(output, "\t\t\t{\n");
 					fprintf(output, "\t\t\t\t.binding = %zu,\n", global_index);
-					if (writable) {
+					if (readable | writable) {
 						fprintf(output, "\t\t\t\t.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,\n");
 					}
 					else {
@@ -2862,6 +3019,18 @@ void kore3_export(char *directory, api_kind api) {
 					fprintf(output, "\t\t\t},\n");
 				}
 				else if (g->type == texcube_type_id) {
+					fprintf(output, "\t\t\t{\n");
+					fprintf(output, "\t\t\t\t.binding = %zu,\n", global_index);
+					if (readable | writable) {
+						fprintf(output, "\t\t\t\t.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,\n");
+					}
+					else {
+						fprintf(output, "\t\t\t\t.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,\n");
+					}
+					fprintf(output, "\t\t\t\t.descriptorCount = 1,\n");
+					fprintf(output, "\t\t\t\t.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT,\n");
+					fprintf(output, "\t\t\t\t.pImmutableSamplers = NULL,\n");
+					fprintf(output, "\t\t\t},\n");
 				}
 				else if (is_sampler(g->type)) {
 					fprintf(output, "\t\t\t{\n");
@@ -2989,6 +3158,22 @@ void kore3_export(char *directory, api_kind api) {
 					fprintf(output, "\t\t\t},\n");
 				}
 				else if (g->type == texcube_type_id) {
+					fprintf(output, "\t\t\t{\n");
+					fprintf(output, "\t\t\t\t.binding = %zu,\n", global_index);
+					if (writable) {
+						fprintf(output, "\t\t\t\t.storageTexture = {.viewDimension = WGPUTextureViewDimension_Cube, .format = WGPUTextureFormat_RGBA32Float, "
+						                ".access = WGPUStorageTextureAccess_WriteOnly},\n");
+					}
+					else {
+						fprintf(output, "\t\t\t\t.texture = {.sampleType = WGPUTextureSampleType_Float, .viewDimension = WGPUTextureViewDimension_Cube},\n");
+					}
+					if (writable) {
+						fprintf(output, "\t\t\t\t.visibility = WGPUShaderStage_Fragment | WGPUShaderStage_Compute,\n");
+					}
+					else {
+						fprintf(output, "\t\t\t\t.visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment | WGPUShaderStage_Compute,\n");
+					}
+					fprintf(output, "\t\t\t},\n");
 				}
 				else if (is_sampler(g->type)) {
 					fprintf(output, "\t\t\t{\n");

+ 3 - 0
base/sources/libs/kong/kong.c

@@ -69,6 +69,7 @@ typedef enum integration_kind { INTEGRATION_KORE3 } integration_kind;
 
 ////
 /*
+////
 int main(int argc, char **argv) {
 	arg_mode mode = MODE_MODECHECK;
 
@@ -344,5 +345,7 @@ int main(int argc, char **argv) {
 
 	return 0;
 }
+
+////
 */
 ////

+ 1 - 1
base/sources/libs/kong/names.c

@@ -10,7 +10,7 @@ static char   *names       = NULL;
 static size_t  names_size  = 1024 * 1024;
 ////
 // static name_id names_index = 1;
-name_id names_index = 1;
+name_id        names_index = 1;
 ////
 
 static struct {

+ 1 - 1
base/sources/libs/kong/sets.c

@@ -5,7 +5,7 @@
 static descriptor_set sets[MAX_SETS];
 ////
 // static size_t         sets_count = 0;
-size_t         sets_count = 0;
+size_t                sets_count = 0;
 ////
 
 descriptor_set *create_set(name_id name) {

+ 1 - 1
base/sources/libs/kong/types.c

@@ -10,7 +10,7 @@ static type   *types           = NULL;
 static type_id types_size      = 1024;
 ////
 // static type_id next_type_index = 0;
-type_id next_type_index = 0;
+type_id        next_type_index = 0;
 ////
 
 type_id void_id;

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.