|
@@ -191,12 +191,15 @@ typedef enum spirv_opcode {
|
|
|
SPIRV_OPCODE_COMPOSITE_EXTRACT = 81,
|
|
|
SPIRV_OPCODE_SAMPLED_IMAGE = 86,
|
|
|
SPIRV_OPCODE_IMAGE_SAMPLE_IMPLICIT_LOD = 87,
|
|
|
+ SPIRV_OPCODE_IMAGE_SAMPLE_EXPLICIT_LOD = 88,
|
|
|
SPIRV_OPCODE_IMAGE_WRITE = 99,
|
|
|
SPIRV_OPCODE_CONVERT_F_TO_U = 109,
|
|
|
SPIRV_OPCODE_CONVERT_F_TO_S = 110,
|
|
|
SPIRV_OPCODE_CONVERT_S_TO_F = 111,
|
|
|
SPIRV_OPCODE_CONVERT_U_TO_F = 112,
|
|
|
SPIRV_OPCODE_BITCAST = 124,
|
|
|
+ SPIRV_OPCODE_S_NEGATE = 126,
|
|
|
+ SPIRV_OPCODE_F_NEGATE = 127,
|
|
|
SPIRV_OPCODE_I_ADD = 128,
|
|
|
SPIRV_OPCODE_F_ADD = 129,
|
|
|
SPIRV_OPCODE_I_SUB = 130,
|
|
@@ -206,12 +209,24 @@ typedef enum spirv_opcode {
|
|
|
SPIRV_OPCODE_VECTOR_TIMES_MATRIX = 144,
|
|
|
SPIRV_OPCODE_MATRIX_TIMES_VECTOR = 145,
|
|
|
SPIRV_OPCODE_MATRIX_TIMES_MATRIX = 146,
|
|
|
+ SPIRV_OPCODE_F_MOD = 161,
|
|
|
+ SPIRV_OPCODE_LOGICAL_OR = 166,
|
|
|
+ SPIRV_OPCODE_LOGICAL_AND = 167,
|
|
|
+ SPIRV_OPCODE_LOGICAL_NOT = 168,
|
|
|
+ SPIRV_OPCODE_I_EQUAL = 170,
|
|
|
+ SPIRV_OPCODE_I_NOT_EQUAL = 171,
|
|
|
+ SPIRV_OPCODE_F_ORD_EQUAL = 180,
|
|
|
+ SPIRV_OPCODE_F_ORD_NOT_EQUAL = 182,
|
|
|
SPIRV_OPCODE_F_ORD_LESS_THAN = 184,
|
|
|
+ SPIRV_OPCODE_F_ORD_GREATER_THAN = 186,
|
|
|
+ SPIRV_OPCODE_F_ORD_LESS_THAN_EQUAL = 188,
|
|
|
+ SPIRV_OPCODE_F_ORD_GREATER_THAN_EQUAL = 190,
|
|
|
SPIRV_OPCODE_LOOP_MERGE = 246,
|
|
|
SPIRV_OPCODE_SELECTION_MERGE = 247,
|
|
|
SPIRV_OPCODE_LABEL = 248,
|
|
|
SPIRV_OPCODE_BRANCH = 249,
|
|
|
SPIRV_OPCODE_BRANCH_CONDITIONAL = 250,
|
|
|
+ SPIRV_OPCODE_KILL = 252,
|
|
|
SPIRV_OPCODE_RETURN = 253,
|
|
|
} spirv_opcode;
|
|
|
|
|
@@ -290,6 +305,7 @@ typedef enum decoration {
|
|
|
|
|
|
typedef enum builtin {
|
|
|
BUILTIN_POSITION = 0,
|
|
|
+ BUILTIN_VERTEX_ID = 5,
|
|
|
BUILTIN_WORKGROUP_SIZE = 25,
|
|
|
BUILTIN_WORKGROUP_ID = 26,
|
|
|
BUILTIN_LOCAL_INVOCATION_ID = 27,
|
|
@@ -596,6 +612,7 @@ static spirv_id dispatch_thread_id_variable;
|
|
|
static spirv_id group_thread_id_variable;
|
|
|
static spirv_id group_id_variable;
|
|
|
static spirv_id work_group_size_variable;
|
|
|
+static spirv_id vertex_id_variable;
|
|
|
|
|
|
typedef struct complex_type {
|
|
|
type_id type;
|
|
@@ -902,6 +919,10 @@ static void write_op_return(instructions_buffer *instructions) {
|
|
|
write_simple_instruction(instructions, SPIRV_OPCODE_RETURN);
|
|
|
}
|
|
|
|
|
|
+static void write_op_discard(instructions_buffer *instructions) {
|
|
|
+ write_simple_instruction(instructions, SPIRV_OPCODE_KILL);
|
|
|
+}
|
|
|
+
|
|
|
static void write_op_function_end(instructions_buffer *instructions) {
|
|
|
write_simple_instruction(instructions, SPIRV_OPCODE_FUNCTION_END);
|
|
|
}
|
|
@@ -1031,6 +1052,36 @@ static spirv_id write_op_f_ord_less_than(instructions_buffer *instructions, spir
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+static spirv_id write_op_f_ord_less_than_equal(instructions_buffer *instructions, spirv_id type, spirv_id operand1, spirv_id operand2) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ uint32_t operands[] = {type.id, result.id, operand1.id, operand2.id};
|
|
|
+
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_F_ORD_LESS_THAN_EQUAL, operands);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static spirv_id write_op_f_ord_greater_than(instructions_buffer *instructions, spirv_id type, spirv_id operand1, spirv_id operand2) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ uint32_t operands[] = {type.id, result.id, operand1.id, operand2.id};
|
|
|
+
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_F_ORD_GREATER_THAN, operands);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static spirv_id write_op_f_ord_greater_than_equal(instructions_buffer *instructions, spirv_id type, spirv_id operand1, spirv_id operand2) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ uint32_t operands[] = {type.id, result.id, operand1.id, operand2.id};
|
|
|
+
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_F_ORD_GREATER_THAN_EQUAL, operands);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
static spirv_id write_op_i_add(instructions_buffer *instructions, spirv_id type, spirv_id operand1, spirv_id operand2) {
|
|
|
spirv_id result = allocate_index();
|
|
|
|
|
@@ -1091,6 +1142,16 @@ static spirv_id write_op_f_div(instructions_buffer *instructions, spirv_id type,
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+static spirv_id write_op_f_mod(instructions_buffer *instructions, spirv_id type, spirv_id operand1, spirv_id operand2) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ uint32_t operands[] = {type.id, result.id, operand1.id, operand2.id};
|
|
|
+
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_F_MOD, operands);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
static spirv_id write_op_matrix_times_vector(instructions_buffer *instructions, spirv_id type, spirv_id operand1, spirv_id operand2) {
|
|
|
spirv_id result = allocate_index();
|
|
|
|
|
@@ -1201,6 +1262,17 @@ static spirv_id write_op_image_sample_implicit_lod(instructions_buffer *instruct
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+static spirv_id write_op_image_sample_explicit_lod(instructions_buffer *instructions, spirv_id result_type, spirv_id sampled_image, spirv_id coordinate, spirv_id lod) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ int lod_operands = 0x2;
|
|
|
+ uint32_t operands[] = {result_type.id, result.id, sampled_image.id, coordinate.id, lod_operands, lod.id};
|
|
|
+
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_IMAGE_SAMPLE_EXPLICIT_LOD, operands);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
static spirv_id write_op_ext_inst(instructions_buffer *instructions, spirv_id result_type, spirv_id set, uint32_t instruction, spirv_id operand) {
|
|
|
spirv_id result = allocate_index();
|
|
|
|
|
@@ -1238,6 +1310,90 @@ static void write_op_variable_preallocated(instructions_buffer *instructions, sp
|
|
|
// return result;
|
|
|
// }
|
|
|
|
|
|
+static spirv_id write_op_f_ord_equal(instructions_buffer *instructions, spirv_id type, spirv_id operand1, spirv_id operand2) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ uint32_t operands[] = {type.id, result.id, operand1.id, operand2.id};
|
|
|
+
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_F_ORD_EQUAL, operands);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static spirv_id write_op_i_equal(instructions_buffer *instructions, spirv_id type, spirv_id operand1, spirv_id operand2) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ uint32_t operands[] = {type.id, result.id, operand1.id, operand2.id};
|
|
|
+
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_I_EQUAL, operands);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static spirv_id write_op_f_ord_not_equal(instructions_buffer *instructions, spirv_id type, spirv_id operand1, spirv_id operand2) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ uint32_t operands[] = {type.id, result.id, operand1.id, operand2.id};
|
|
|
+
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_F_ORD_NOT_EQUAL, operands);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static spirv_id write_op_i_not_equal(instructions_buffer *instructions, spirv_id type, spirv_id operand1, spirv_id operand2) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ uint32_t operands[] = {type.id, result.id, operand1.id, operand2.id};
|
|
|
+
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_I_NOT_EQUAL, operands);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static spirv_id write_op_f_negate(instructions_buffer *instructions, spirv_id type, spirv_id operand) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ uint32_t operands[] = {type.id, result.id, operand.id};
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_F_NEGATE, operands);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static spirv_id write_op_s_negate(instructions_buffer *instructions, spirv_id type, spirv_id operand) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ uint32_t operands[] = {type.id, result.id, operand.id};
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_S_NEGATE, operands);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static spirv_id write_op_logical_and(instructions_buffer *instructions, spirv_id type, spirv_id operand1, spirv_id operand2) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ uint32_t operands[] = {type.id, result.id, operand1.id, operand2.id};
|
|
|
+
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_LOGICAL_AND, operands);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static spirv_id write_op_logical_or(instructions_buffer *instructions, spirv_id type, spirv_id operand1, spirv_id operand2) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ uint32_t operands[] = {type.id, result.id, operand1.id, operand2.id};
|
|
|
+
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_LOGICAL_OR, operands);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static spirv_id write_op_not(instructions_buffer *instructions, spirv_id type, spirv_id operand) {
|
|
|
+ spirv_id result = allocate_index();
|
|
|
+
|
|
|
+ uint32_t operands[] = {type.id, result.id, operand.id};
|
|
|
+ write_instruction(instructions, WORD_COUNT(operands), SPIRV_OPCODE_LOGICAL_NOT, operands);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
static struct {
|
|
|
uint64_t key;
|
|
|
spirv_id value;
|
|
@@ -1507,7 +1663,29 @@ static void write_function(instructions_buffer *instructions, function *f, spirv
|
|
|
hmput(index_map, o->op_call.var.index, id);
|
|
|
}
|
|
|
else if (func == add_name("sample_lod")) {
|
|
|
- assert(false);
|
|
|
+ variable image_var = o->op_call.parameters[0];
|
|
|
+
|
|
|
+ spirv_id image_type;
|
|
|
+ spirv_id sampled_image_type;
|
|
|
+
|
|
|
+ if (image_var.type.type == tex2d_type_id) {
|
|
|
+ image_type = spirv_image_type;
|
|
|
+ sampled_image_type = spirv_sampled_image_type;
|
|
|
+ }
|
|
|
+ else if (image_var.type.type == tex2darray_type_id) {
|
|
|
+ image_type = spirv_image2darray_type;
|
|
|
+ sampled_image_type = spirv_sampled_image2darray_type;
|
|
|
+ }
|
|
|
+
|
|
|
+ spirv_id image = write_op_load(instructions, image_type, convert_kong_index_to_spirv_id(image_var.index));
|
|
|
+
|
|
|
+ spirv_id sampler = write_op_load(instructions, spirv_sampler_type, convert_kong_index_to_spirv_id(o->op_call.parameters[1].index));
|
|
|
+
|
|
|
+ spirv_id sampled_image = write_op_sampled_image(instructions, sampled_image_type, image, sampler);
|
|
|
+ spirv_id id = write_op_image_sample_explicit_lod(instructions, spirv_float4_type, sampled_image,
|
|
|
+ convert_kong_index_to_spirv_id(o->op_call.parameters[2].index),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_call.parameters[3].index));
|
|
|
+ hmput(index_map, o->op_call.var.index, id);
|
|
|
}
|
|
|
else if (func == add_name("float")) {
|
|
|
if (o->op_call.parameters[0].type.type == int_id) {
|
|
@@ -1642,6 +1820,10 @@ static void write_function(instructions_buffer *instructions, function *f, spirv
|
|
|
spirv_id id = write_op_load(instructions, convert_type_to_spirv_id(uint3_id), group_id_variable);
|
|
|
hmput(index_map, o->op_call.var.index, id);
|
|
|
}
|
|
|
+ else if (func == add_name("vertex_id")) {
|
|
|
+ spirv_id id = write_op_load(instructions, convert_type_to_spirv_id(uint_id), vertex_id_variable);
|
|
|
+ hmput(index_map, o->op_call.var.index, id);
|
|
|
+ }
|
|
|
else if (func == add_name("length")) {
|
|
|
spirv_id id = write_op_ext_inst(instructions, spirv_float_type, glsl_import, SPIRV_GLSL_STD_LENGTH,
|
|
|
convert_kong_index_to_spirv_id(o->op_call.parameters[0].index));
|
|
@@ -1662,7 +1844,11 @@ static void write_function(instructions_buffer *instructions, function *f, spirv
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
- case OPCODE_STORE_ACCESS_LIST: {
|
|
|
+ case OPCODE_STORE_ACCESS_LIST:
|
|
|
+ case OPCODE_ADD_AND_STORE_ACCESS_LIST:
|
|
|
+ case OPCODE_SUB_AND_STORE_ACCESS_LIST:
|
|
|
+ case OPCODE_MULTIPLY_AND_STORE_ACCESS_LIST:
|
|
|
+ case OPCODE_DIVIDE_AND_STORE_ACCESS_LIST: {
|
|
|
spirv_id indices[256];
|
|
|
int plain_indices[256];
|
|
|
access_kind access_kinds[256];
|
|
@@ -1754,14 +1940,141 @@ static void write_function(instructions_buffer *instructions, function *f, spirv
|
|
|
|
|
|
spirv_id pointer =
|
|
|
write_op_access_chain(instructions, access_type, convert_kong_index_to_spirv_id(o->op_store_access_list.to.index), indices, indices_size);
|
|
|
- write_op_store(instructions, pointer, convert_kong_index_to_spirv_id(o->op_store_access_list.from.index));
|
|
|
+
|
|
|
+ spirv_id stored;
|
|
|
+
|
|
|
+ if (o->type == OPCODE_STORE_ACCESS_LIST) {
|
|
|
+ stored = convert_kong_index_to_spirv_id(o->op_store_access_list.from.index);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ spirv_id loaded_pointer = write_op_load(instructions, convert_type_to_spirv_id(access_kong_type), pointer);
|
|
|
+ spirv_id from = convert_kong_index_to_spirv_id(o->op_store_access_list.from.index);
|
|
|
+
|
|
|
+ if (o->type == OPCODE_ADD_AND_STORE_ACCESS_LIST) {
|
|
|
+ if (vector_base_type(access_kong_type) == float_id) {
|
|
|
+ stored = write_op_f_add(instructions, convert_type_to_spirv_id(access_kong_type), loaded_pointer, from);
|
|
|
+ }
|
|
|
+ else if (vector_base_type(access_kong_type) == int_id || vector_base_type(access_kong_type) == uint_id) {
|
|
|
+ stored = write_op_i_add(instructions, convert_type_to_spirv_id(access_kong_type), loaded_pointer, from);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (o->type == OPCODE_SUB_AND_STORE_ACCESS_LIST) {
|
|
|
+ if (vector_base_type(access_kong_type) == float_id) {
|
|
|
+ stored = write_op_f_sub(instructions, convert_type_to_spirv_id(access_kong_type), loaded_pointer, from);
|
|
|
+ }
|
|
|
+ else if (vector_base_type(access_kong_type) == int_id || vector_base_type(access_kong_type) == uint_id) {
|
|
|
+ stored = write_op_i_sub(instructions, convert_type_to_spirv_id(access_kong_type), loaded_pointer, from);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (o->type == OPCODE_MULTIPLY_AND_STORE_ACCESS_LIST) {
|
|
|
+ stored = write_op_f_mul(instructions, convert_type_to_spirv_id(access_kong_type), loaded_pointer, from);
|
|
|
+ }
|
|
|
+ else if (o->type == OPCODE_DIVIDE_AND_STORE_ACCESS_LIST) {
|
|
|
+ stored = write_op_f_div(instructions, convert_type_to_spirv_id(access_kong_type), loaded_pointer, from);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ write_op_store(instructions, pointer, stored);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OPCODE_AND: {
|
|
|
+ spirv_id result = write_op_logical_and(instructions, spirv_bool_type, convert_kong_index_to_spirv_id(o->op_binary.left.index),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_binary.right.index));
|
|
|
+ hmput(index_map, o->op_binary.result.index, result);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OPCODE_OR: {
|
|
|
+ spirv_id result = write_op_logical_or(instructions, spirv_bool_type, convert_kong_index_to_spirv_id(o->op_binary.left.index),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_binary.right.index));
|
|
|
+ hmput(index_map, o->op_binary.result.index, result);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OPCODE_NOT: {
|
|
|
+ spirv_id operand;
|
|
|
+ if (o->op_not.from.kind != VARIABLE_INTERNAL) {
|
|
|
+ operand = write_op_load(instructions, convert_type_to_spirv_id(o->op_not.from.type.type),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_not.from.index));
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ operand = convert_kong_index_to_spirv_id(o->op_not.from.index);
|
|
|
+ }
|
|
|
+
|
|
|
+ spirv_id result = write_op_not(instructions, spirv_bool_type, operand);
|
|
|
+ hmput(index_map, o->op_not.to.index, result);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OPCODE_NEGATE: {
|
|
|
+ spirv_id from;
|
|
|
+ if (o->op_negate.from.kind != VARIABLE_INTERNAL) {
|
|
|
+ from = write_op_load(instructions, convert_type_to_spirv_id(o->op_negate.from.type.type),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_negate.from.index));
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ from = convert_kong_index_to_spirv_id(o->op_negate.from.index);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vector_base_type(o->op_binary.result.type.type) == float_id) {
|
|
|
+ spirv_id result = write_op_f_negate(instructions, convert_type_to_spirv_id(o->op_negate.to.type.type), from);
|
|
|
+ hmput(index_map, o->op_negate.to.index, result);
|
|
|
+ }
|
|
|
+ else if (vector_base_type(o->op_binary.result.type.type) == int_id || vector_base_type(o->op_binary.result.type.type) == uint_id) {
|
|
|
+ spirv_id result = write_op_s_negate(instructions, convert_type_to_spirv_id(o->op_negate.to.type.type), from);
|
|
|
+ hmput(index_map, o->op_negate.to.index, result);
|
|
|
}
|
|
|
+
|
|
|
break;
|
|
|
}
|
|
|
case OPCODE_STORE_VARIABLE: {
|
|
|
write_op_store(instructions, convert_kong_index_to_spirv_id(o->op_store_var.to.index), convert_kong_index_to_spirv_id(o->op_store_var.from.index));
|
|
|
break;
|
|
|
}
|
|
|
+ case OPCODE_ADD_AND_STORE_VARIABLE:
|
|
|
+ case OPCODE_SUB_AND_STORE_VARIABLE:
|
|
|
+ case OPCODE_MULTIPLY_AND_STORE_VARIABLE:
|
|
|
+ case OPCODE_DIVIDE_AND_STORE_VARIABLE: {
|
|
|
+ spirv_id to = convert_kong_index_to_spirv_id(o->op_store_var.to.index);
|
|
|
+ spirv_id from = convert_kong_index_to_spirv_id(o->op_store_var.from.index);
|
|
|
+ spirv_id to_loaded = write_op_load(instructions, convert_type_to_spirv_id(o->op_store_var.to.type.type), to);
|
|
|
+ spirv_id from_loaded = write_op_load(instructions, convert_type_to_spirv_id(o->op_store_var.from.type.type), from);
|
|
|
+ spirv_id result;
|
|
|
+
|
|
|
+ switch (o->type) {
|
|
|
+ case OPCODE_ADD_AND_STORE_VARIABLE: {
|
|
|
+ if (vector_base_type(o->op_store_var.to.type.type) == float_id) {
|
|
|
+ result = write_op_f_add(instructions, convert_type_to_spirv_id(o->op_store_var.to.type.type), to_loaded, from_loaded);
|
|
|
+ }
|
|
|
+ else if (vector_base_type(o->op_store_var.to.type.type) == int_id || vector_base_type(o->op_store_var.to.type.type) == uint_id) {
|
|
|
+ result = write_op_i_add(instructions, convert_type_to_spirv_id(o->op_store_var.to.type.type), to_loaded, from_loaded);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OPCODE_SUB_AND_STORE_VARIABLE: {
|
|
|
+ if (vector_base_type(o->op_store_var.to.type.type) == float_id) {
|
|
|
+ result = write_op_f_sub(instructions, convert_type_to_spirv_id(o->op_store_var.to.type.type), to_loaded, from_loaded);
|
|
|
+ }
|
|
|
+ else if (vector_base_type(o->op_store_var.to.type.type) == int_id || vector_base_type(o->op_store_var.to.type.type) == uint_id) {
|
|
|
+ result = write_op_i_sub(instructions, convert_type_to_spirv_id(o->op_store_var.to.type.type), to_loaded, from_loaded);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OPCODE_MULTIPLY_AND_STORE_VARIABLE: {
|
|
|
+ result = write_op_f_mul(instructions, convert_type_to_spirv_id(o->op_store_var.to.type.type), to_loaded, from_loaded);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OPCODE_DIVIDE_AND_STORE_VARIABLE: {
|
|
|
+ result = write_op_f_div(instructions, convert_type_to_spirv_id(o->op_store_var.to.type.type), to_loaded, from_loaded);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ assert(false);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ write_op_store(instructions, to, result);
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
case OPCODE_RETURN: {
|
|
|
if (stage == SHADER_STAGE_VERTEX && main) {
|
|
|
type *output_type = get_type(output);
|
|
@@ -1830,12 +2143,34 @@ static void write_function(instructions_buffer *instructions, function *f, spirv
|
|
|
ends_with_return = true;
|
|
|
break;
|
|
|
}
|
|
|
+ case OPCODE_DISCARD: {
|
|
|
+ write_op_discard(instructions);
|
|
|
+ break;
|
|
|
+ }
|
|
|
case OPCODE_LESS: {
|
|
|
spirv_id result = write_op_f_ord_less_than(instructions, spirv_bool_type, convert_kong_index_to_spirv_id(o->op_binary.left.index),
|
|
|
convert_kong_index_to_spirv_id(o->op_binary.right.index));
|
|
|
hmput(index_map, o->op_binary.result.index, result);
|
|
|
break;
|
|
|
}
|
|
|
+ case OPCODE_LESS_EQUAL: {
|
|
|
+ spirv_id result = write_op_f_ord_less_than_equal(instructions, spirv_bool_type, convert_kong_index_to_spirv_id(o->op_binary.left.index),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_binary.right.index));
|
|
|
+ hmput(index_map, o->op_binary.result.index, result);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OPCODE_GREATER: {
|
|
|
+ spirv_id result = write_op_f_ord_greater_than(instructions, spirv_bool_type, convert_kong_index_to_spirv_id(o->op_binary.left.index),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_binary.right.index));
|
|
|
+ hmput(index_map, o->op_binary.result.index, result);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OPCODE_GREATER_EQUAL: {
|
|
|
+ spirv_id result = write_op_f_ord_greater_than_equal(instructions, spirv_bool_type, convert_kong_index_to_spirv_id(o->op_binary.left.index),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_binary.right.index));
|
|
|
+ hmput(index_map, o->op_binary.result.index, result);
|
|
|
+ break;
|
|
|
+ }
|
|
|
case OPCODE_ADD: {
|
|
|
spirv_id left;
|
|
|
if (o->op_binary.left.kind != VARIABLE_INTERNAL) {
|
|
@@ -1968,44 +2303,133 @@ static void write_function(instructions_buffer *instructions, function *f, spirv
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
- case OPCODE_IF: {
|
|
|
- write_op_selection_merge(instructions, convert_kong_index_to_spirv_id(o->op_if.end_id), SELECTION_CONTROL_NONE);
|
|
|
-
|
|
|
- write_op_branch_conditional(instructions, convert_kong_index_to_spirv_id(o->op_if.condition.index),
|
|
|
- convert_kong_index_to_spirv_id(o->op_if.start_id), convert_kong_index_to_spirv_id(o->op_if.end_id));
|
|
|
+ case OPCODE_MOD: {
|
|
|
+ spirv_id left;
|
|
|
+ if (o->op_binary.left.kind != VARIABLE_INTERNAL) {
|
|
|
+ left =
|
|
|
+ write_op_load(instructions, convert_type_to_spirv_id(o->op_binary.left.type.type), convert_kong_index_to_spirv_id(o->op_binary.left.index));
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ left = convert_kong_index_to_spirv_id(o->op_binary.left.index);
|
|
|
+ }
|
|
|
|
|
|
- break;
|
|
|
- }
|
|
|
- case OPCODE_WHILE_START: {
|
|
|
- spirv_id while_start_label = convert_kong_index_to_spirv_id(o->op_while_start.start_id);
|
|
|
- spirv_id while_continue_label = convert_kong_index_to_spirv_id(o->op_while_start.continue_id);
|
|
|
- spirv_id while_end_label = convert_kong_index_to_spirv_id(o->op_while_start.end_id);
|
|
|
+ spirv_id right;
|
|
|
+ if (o->op_binary.right.kind != VARIABLE_INTERNAL) {
|
|
|
+ right = write_op_load(instructions, convert_type_to_spirv_id(o->op_binary.right.type.type),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_binary.right.index));
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ right = convert_kong_index_to_spirv_id(o->op_binary.right.index);
|
|
|
+ }
|
|
|
|
|
|
- write_op_branch(instructions, while_start_label);
|
|
|
- write_op_label_preallocated(instructions, while_start_label);
|
|
|
+ spirv_id result = write_op_f_mod(instructions, convert_type_to_spirv_id(o->op_binary.result.type.type), left, right);
|
|
|
|
|
|
- write_op_loop_merge(instructions, while_end_label, while_continue_label, LOOP_CONTROL_NONE);
|
|
|
+ hmput(index_map, o->op_binary.result.index, result);
|
|
|
|
|
|
- spirv_id loop_start_id = allocate_index();
|
|
|
- write_op_branch(instructions, loop_start_id);
|
|
|
- write_op_label_preallocated(instructions, loop_start_id);
|
|
|
break;
|
|
|
}
|
|
|
- case OPCODE_WHILE_CONDITION: {
|
|
|
- spirv_id while_end_label = convert_kong_index_to_spirv_id(o->op_while.end_id);
|
|
|
+ case OPCODE_EQUALS: {
|
|
|
+ spirv_id left;
|
|
|
+ if (o->op_binary.left.kind != VARIABLE_INTERNAL) {
|
|
|
+ left = write_op_load(instructions, convert_type_to_spirv_id(o->op_binary.left.type.type),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_binary.left.index));
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ left = convert_kong_index_to_spirv_id(o->op_binary.left.index);
|
|
|
+ }
|
|
|
|
|
|
- spirv_id pass = allocate_index();
|
|
|
+ spirv_id right;
|
|
|
+ if (o->op_binary.right.kind != VARIABLE_INTERNAL) {
|
|
|
+ right = write_op_load(instructions, convert_type_to_spirv_id(o->op_binary.right.type.type),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_binary.right.index));
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ right = convert_kong_index_to_spirv_id(o->op_binary.right.index);
|
|
|
+ }
|
|
|
|
|
|
- write_op_branch_conditional(instructions, convert_kong_index_to_spirv_id(o->op_while.condition.index), pass, while_end_label);
|
|
|
+ type_id result_type = o->op_binary.result.type.type;
|
|
|
+
|
|
|
+ if (result_type == float_id) {
|
|
|
+ spirv_id result = write_op_f_ord_equal(instructions, convert_type_to_spirv_id(result_type), left, right);
|
|
|
+ hmput(index_map, o->op_binary.result.index, result);
|
|
|
+ }
|
|
|
+ else if (result_type == int_id) {
|
|
|
+ spirv_id result = write_op_i_equal(instructions, convert_type_to_spirv_id(result_type), left, right);
|
|
|
+ hmput(index_map, o->op_binary.result.index, result);
|
|
|
+ }
|
|
|
|
|
|
- write_op_label_preallocated(instructions, pass);
|
|
|
break;
|
|
|
}
|
|
|
- case OPCODE_WHILE_END: {
|
|
|
- spirv_id while_start_label = convert_kong_index_to_spirv_id(o->op_while_end.start_id);
|
|
|
- spirv_id while_continue_label = convert_kong_index_to_spirv_id(o->op_while_end.continue_id);
|
|
|
- spirv_id while_end_label = convert_kong_index_to_spirv_id(o->op_while_end.end_id);
|
|
|
-
|
|
|
+ case OPCODE_NOT_EQUALS: {
|
|
|
+ spirv_id left;
|
|
|
+ if (o->op_binary.left.kind != VARIABLE_INTERNAL) {
|
|
|
+ left = write_op_load(instructions, convert_type_to_spirv_id(o->op_binary.left.type.type),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_binary.left.index));
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ left = convert_kong_index_to_spirv_id(o->op_binary.left.index);
|
|
|
+ }
|
|
|
+
|
|
|
+ spirv_id right;
|
|
|
+ if (o->op_binary.right.kind != VARIABLE_INTERNAL) {
|
|
|
+ right = write_op_load(instructions, convert_type_to_spirv_id(o->op_binary.right.type.type),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_binary.right.index));
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ right = convert_kong_index_to_spirv_id(o->op_binary.right.index);
|
|
|
+ }
|
|
|
+
|
|
|
+ type_id result_type = o->op_binary.result.type.type;
|
|
|
+
|
|
|
+ if (result_type == float_id) {
|
|
|
+ spirv_id result = write_op_f_ord_not_equal(instructions, convert_type_to_spirv_id(result_type), left, right);
|
|
|
+ hmput(index_map, o->op_binary.result.index, result);
|
|
|
+ }
|
|
|
+ else if (result_type == int_id) {
|
|
|
+ spirv_id result = write_op_i_not_equal(instructions, convert_type_to_spirv_id(result_type), left, right);
|
|
|
+ hmput(index_map, o->op_binary.result.index, result);
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OPCODE_IF: {
|
|
|
+ write_op_selection_merge(instructions, convert_kong_index_to_spirv_id(o->op_if.end_id), SELECTION_CONTROL_NONE);
|
|
|
+
|
|
|
+ write_op_branch_conditional(instructions, convert_kong_index_to_spirv_id(o->op_if.condition.index),
|
|
|
+ convert_kong_index_to_spirv_id(o->op_if.start_id), convert_kong_index_to_spirv_id(o->op_if.end_id));
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OPCODE_WHILE_START: {
|
|
|
+ spirv_id while_start_label = convert_kong_index_to_spirv_id(o->op_while_start.start_id);
|
|
|
+ spirv_id while_continue_label = convert_kong_index_to_spirv_id(o->op_while_start.continue_id);
|
|
|
+ spirv_id while_end_label = convert_kong_index_to_spirv_id(o->op_while_start.end_id);
|
|
|
+
|
|
|
+ write_op_branch(instructions, while_start_label);
|
|
|
+ write_op_label_preallocated(instructions, while_start_label);
|
|
|
+
|
|
|
+ write_op_loop_merge(instructions, while_end_label, while_continue_label, LOOP_CONTROL_NONE);
|
|
|
+
|
|
|
+ spirv_id loop_start_id = allocate_index();
|
|
|
+ write_op_branch(instructions, loop_start_id);
|
|
|
+ write_op_label_preallocated(instructions, loop_start_id);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OPCODE_WHILE_CONDITION: {
|
|
|
+ spirv_id while_end_label = convert_kong_index_to_spirv_id(o->op_while.end_id);
|
|
|
+
|
|
|
+ spirv_id pass = allocate_index();
|
|
|
+
|
|
|
+ write_op_branch_conditional(instructions, convert_kong_index_to_spirv_id(o->op_while.condition.index), pass, while_end_label);
|
|
|
+
|
|
|
+ write_op_label_preallocated(instructions, pass);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case OPCODE_WHILE_END: {
|
|
|
+ spirv_id while_start_label = convert_kong_index_to_spirv_id(o->op_while_end.start_id);
|
|
|
+ spirv_id while_continue_label = convert_kong_index_to_spirv_id(o->op_while_end.continue_id);
|
|
|
+ spirv_id while_end_label = convert_kong_index_to_spirv_id(o->op_while_end.end_id);
|
|
|
+
|
|
|
write_op_branch(instructions, while_continue_label);
|
|
|
write_op_label_preallocated(instructions, while_continue_label);
|
|
|
|
|
@@ -2020,7 +2444,7 @@ static void write_function(instructions_buffer *instructions, function *f, spirv
|
|
|
}
|
|
|
default: {
|
|
|
debug_context context = {0};
|
|
|
- error(context, "Opcode not implemented for SPIR-V");
|
|
|
+ error(context, "Opcode %d not implemented for SPIR-V", o->type);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
@@ -2325,6 +2749,12 @@ static void write_globals(instructions_buffer *decorations, instructions_buffer
|
|
|
write_op_decorate_value(decorations, group_id_variable, DECORATION_BUILTIN, BUILTIN_WORKGROUP_ID);
|
|
|
}
|
|
|
|
|
|
+ if (main->used_builtins.vertex_id) {
|
|
|
+ write_op_variable_preallocated(global_vars_block, convert_pointer_type_to_spirv_id(uint_id, STORAGE_CLASS_INPUT), vertex_id_variable,
|
|
|
+ STORAGE_CLASS_INPUT);
|
|
|
+ write_op_decorate_value(decorations, vertex_id_variable, DECORATION_BUILTIN, BUILTIN_VERTEX_ID);
|
|
|
+ }
|
|
|
+
|
|
|
if (stage == SHADER_STAGE_COMPUTE) {
|
|
|
write_op_decorate_value(decorations, work_group_size_variable, DECORATION_BUILTIN, BUILTIN_WORKGROUP_SIZE);
|
|
|
}
|
|
@@ -2445,6 +2875,12 @@ static void spirv_export_vertex(char *directory, function *main, bool debug) {
|
|
|
interfaces_count += 1;
|
|
|
}
|
|
|
|
|
|
+ if (main->used_builtins.vertex_id) {
|
|
|
+ vertex_id_variable = allocate_index();
|
|
|
+ interfaces[interfaces_count] = vertex_id_variable;
|
|
|
+ interfaces_count += 1;
|
|
|
+ }
|
|
|
+
|
|
|
write_op_entry_point(&decorations, EXECUTION_MODEL_VERTEX, entry_point, "main", interfaces, (uint16_t)interfaces_count);
|
|
|
|
|
|
write_vertex_input_decorations(&decorations, input_vars, (uint32_t)input_vars_count);
|
|
@@ -2854,6 +3290,389 @@ void spirv_export(char *directory, bool debug) {
|
|
|
}
|
|
|
|
|
|
////
|
|
|
-void spirv_export2(char **vs, char **fs, bool debug) {
|
|
|
+
|
|
|
+static char *write_bytecode2(int *size_out, instructions_buffer *header, instructions_buffer *decorations,
|
|
|
+ instructions_buffer *base_types, instructions_buffer *constants, instructions_buffer *aggregate_types,
|
|
|
+ instructions_buffer *global_vars, instructions_buffer *instructions, bool debug) {
|
|
|
+ uint8_t *output_header = (uint8_t *)header->instructions;
|
|
|
+ size_t output_header_size = header->offset * 4;
|
|
|
+
|
|
|
+ uint8_t *output_decorations = (uint8_t *)decorations->instructions;
|
|
|
+ size_t output_decorations_size = decorations->offset * 4;
|
|
|
+
|
|
|
+ uint8_t *output_base_types = (uint8_t *)base_types->instructions;
|
|
|
+ size_t output_base_types_size = base_types->offset * 4;
|
|
|
+
|
|
|
+ uint8_t *output_constants = (uint8_t *)constants->instructions;
|
|
|
+ size_t output_constants_size = constants->offset * 4;
|
|
|
+
|
|
|
+ uint8_t *output_aggregate_types = (uint8_t *)aggregate_types->instructions;
|
|
|
+ size_t output_aggregate_types_size = aggregate_types->offset * 4;
|
|
|
+
|
|
|
+ uint8_t *output_global_vars = (uint8_t *)global_vars->instructions;
|
|
|
+ size_t output_global_vars_size = global_vars->offset * 4;
|
|
|
+
|
|
|
+ uint8_t *output_instructions = (uint8_t *)instructions->instructions;
|
|
|
+ size_t output_instructions_size = instructions->offset * 4;
|
|
|
+
|
|
|
+
|
|
|
+ {
|
|
|
+ char *buffer = malloc(1024 * 128);
|
|
|
+ int pos = 0;
|
|
|
+ memcpy(buffer + pos, output_header, output_header_size);
|
|
|
+ pos += output_header_size;
|
|
|
+ memcpy(buffer + pos, output_decorations, output_decorations_size);
|
|
|
+ pos += output_decorations_size;
|
|
|
+ memcpy(buffer + pos, output_base_types, output_base_types_size);
|
|
|
+ pos += output_base_types_size;
|
|
|
+ memcpy(buffer + pos, output_constants, output_constants_size);
|
|
|
+ pos += output_constants_size;
|
|
|
+ memcpy(buffer + pos, output_aggregate_types, output_aggregate_types_size);
|
|
|
+ pos += output_aggregate_types_size;
|
|
|
+ memcpy(buffer + pos, output_global_vars, output_global_vars_size);
|
|
|
+ pos += output_global_vars_size;
|
|
|
+ memcpy(buffer + pos, output_instructions, output_instructions_size);
|
|
|
+ pos += output_instructions_size;
|
|
|
+
|
|
|
+ *size_out =
|
|
|
+ output_header_size + output_decorations_size + output_base_types_size + output_constants_size + output_aggregate_types_size +
|
|
|
+ output_global_vars_size + output_instructions_size;
|
|
|
+
|
|
|
+ return buffer;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static char *spirv_export_vertex2(function *main, bool debug, int *size_out) {
|
|
|
+ next_index = 1;
|
|
|
+ init_maps();
|
|
|
+
|
|
|
+ find_used_builtins(main);
|
|
|
+ find_used_capabilities(main);
|
|
|
+
|
|
|
+ instructions_buffer header = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ instructions_buffer decorations = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ instructions_buffer base_types = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ instructions_buffer constants = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ instructions_buffer aggregate_types = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ instructions_buffer global_vars = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ instructions_buffer instructions = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ assert(main->parameters_size > 0);
|
|
|
+ type_id vertex_input = main->parameter_types[0].type;
|
|
|
+ type_id vertex_output = main->return_type.type;
|
|
|
+
|
|
|
+ debug_context context = {0};
|
|
|
+ check(vertex_input != NO_TYPE, context, "vertex input missing");
|
|
|
+ check(vertex_output != NO_TYPE, context, "vertex output missing");
|
|
|
+
|
|
|
+ write_capabilities(&decorations, &main->used_capabilities);
|
|
|
+ glsl_import = write_op_ext_inst_import(&decorations, "GLSL.std.450");
|
|
|
+ write_op_memory_model(&decorations, ADDRESSING_MODEL_LOGICAL, MEMORY_MODEL_GLSL450);
|
|
|
+
|
|
|
+ type *input = get_type(vertex_input);
|
|
|
+ type *output = get_type(vertex_output);
|
|
|
+
|
|
|
+ spirv_id entry_point = allocate_index();
|
|
|
+
|
|
|
+ input_vars_count = input->members.size;
|
|
|
+ for (size_t input_var_index = 0; input_var_index < input_vars_count; ++input_var_index) {
|
|
|
+ input_vars[input_var_index] = allocate_index();
|
|
|
+ }
|
|
|
+
|
|
|
+ output_vars_count = output->members.size;
|
|
|
+ for (size_t output_var_index = 0; output_var_index < output_vars_count; ++output_var_index) {
|
|
|
+ output_vars[output_var_index] = allocate_index();
|
|
|
+ }
|
|
|
+ per_vertex_var = output_vars[0];
|
|
|
+
|
|
|
+ spirv_id interfaces[256];
|
|
|
+ size_t interfaces_count = 0;
|
|
|
+
|
|
|
+ for (size_t input_var_index = 0; input_var_index < input_vars_count; ++input_var_index) {
|
|
|
+ interfaces[interfaces_count] = input_vars[input_var_index];
|
|
|
+ interfaces_count += 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (size_t output_var_index = 0; output_var_index < output_vars_count; ++output_var_index) {
|
|
|
+ interfaces[interfaces_count] = output_vars[output_var_index];
|
|
|
+ interfaces_count += 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (main->used_builtins.vertex_id) {
|
|
|
+ vertex_id_variable = allocate_index();
|
|
|
+ interfaces[interfaces_count] = vertex_id_variable;
|
|
|
+ interfaces_count += 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ write_op_entry_point(&decorations, EXECUTION_MODEL_VERTEX, entry_point, "main", interfaces, (uint16_t)interfaces_count);
|
|
|
+
|
|
|
+ write_vertex_input_decorations(&decorations, input_vars, (uint32_t)input_vars_count);
|
|
|
+
|
|
|
+ write_base_types(&base_types);
|
|
|
+
|
|
|
+ write_globals(&decorations, &aggregate_types, &global_vars, main, SHADER_STAGE_VERTEX);
|
|
|
+
|
|
|
+ for (size_t i = 0; i < input_vars_count; ++i) {
|
|
|
+ member m = input->members.m[i];
|
|
|
+ input_types[i] = m.type.type;
|
|
|
+
|
|
|
+ if (m.type.type == float2_id) {
|
|
|
+ write_op_variable_preallocated(&instructions, convert_pointer_type_to_spirv_id(float2_id, STORAGE_CLASS_INPUT), input_vars[i], STORAGE_CLASS_INPUT);
|
|
|
+ }
|
|
|
+ else if (m.type.type == float3_id) {
|
|
|
+ write_op_variable_preallocated(&instructions, convert_pointer_type_to_spirv_id(float3_id, STORAGE_CLASS_INPUT), input_vars[i], STORAGE_CLASS_INPUT);
|
|
|
+ }
|
|
|
+ else if (m.type.type == float4_id) {
|
|
|
+ write_op_variable_preallocated(&instructions, convert_pointer_type_to_spirv_id(float4_id, STORAGE_CLASS_INPUT), input_vars[i], STORAGE_CLASS_INPUT);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ debug_context context = {0};
|
|
|
+ error(context, "Type unsupported for input in SPIR-V");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ spirv_id types[] = {spirv_float4_type};
|
|
|
+ spirv_id output_struct = write_type_struct(&aggregate_types, types, 1);
|
|
|
+ write_vertex_output_decorations(&decorations, output_struct, output_vars, (uint32_t)output_vars_count);
|
|
|
+
|
|
|
+ output_struct_pointer_type = write_type_pointer(&aggregate_types, STORAGE_CLASS_OUTPUT, output_struct);
|
|
|
+ write_op_variable_preallocated(&instructions, output_struct_pointer_type, per_vertex_var, STORAGE_CLASS_OUTPUT);
|
|
|
+
|
|
|
+ // special handling for the first one (position) via per_vertex_var
|
|
|
+ for (size_t i = 1; i < output_vars_count; ++i) {
|
|
|
+ member m = output->members.m[i];
|
|
|
+ output_types[i] = m.type.type;
|
|
|
+
|
|
|
+ if (m.type.type == float2_id) {
|
|
|
+ write_op_variable_preallocated(&instructions, convert_pointer_type_to_spirv_id(float2_id, STORAGE_CLASS_OUTPUT), output_vars[i],
|
|
|
+ STORAGE_CLASS_OUTPUT);
|
|
|
+ }
|
|
|
+ else if (m.type.type == float3_id) {
|
|
|
+ write_op_variable_preallocated(&instructions, convert_pointer_type_to_spirv_id(float3_id, STORAGE_CLASS_OUTPUT), output_vars[i],
|
|
|
+ STORAGE_CLASS_OUTPUT);
|
|
|
+ }
|
|
|
+ else if (m.type.type == float4_id) {
|
|
|
+ write_op_variable_preallocated(&instructions, convert_pointer_type_to_spirv_id(float4_id, STORAGE_CLASS_OUTPUT), output_vars[i],
|
|
|
+ STORAGE_CLASS_OUTPUT);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ debug_context context = {0};
|
|
|
+ error(context, "Type unsupported for input in SPIR-V");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ write_functions(&instructions, main, entry_point, SHADER_STAGE_VERTEX, vertex_input, vertex_output);
|
|
|
+
|
|
|
+ write_types(&aggregate_types, main);
|
|
|
+
|
|
|
+ // header
|
|
|
+ write_magic_number(&header);
|
|
|
+ write_version_number(&header);
|
|
|
+ write_generator_magic_number(&header);
|
|
|
+ write_bound(&header);
|
|
|
+ write_instruction_schema(&header);
|
|
|
+
|
|
|
+ write_constants(&constants);
|
|
|
+
|
|
|
+ return write_bytecode2(size_out, &header, &decorations, &base_types, &constants, &aggregate_types, &global_vars, &instructions, debug);
|
|
|
}
|
|
|
+
|
|
|
+static char *spirv_export_fragment2(function *main, bool debug, int *size_out) {
|
|
|
+ next_index = 1;
|
|
|
+ init_maps();
|
|
|
+
|
|
|
+ find_used_builtins(main);
|
|
|
+ find_used_capabilities(main);
|
|
|
+
|
|
|
+ instructions_buffer header = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ instructions_buffer decorations = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ instructions_buffer base_types = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ instructions_buffer constants = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ instructions_buffer aggregate_types = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ instructions_buffer global_vars = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ instructions_buffer instructions = {
|
|
|
+ .instructions = (uint32_t *)calloc(1024 * 1024, 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ assert(main->parameters_size > 0);
|
|
|
+ type_id pixel_input = main->parameter_types[0].type;
|
|
|
+ type_id pixel_output = main->return_type.type;
|
|
|
+
|
|
|
+ debug_context context = {0};
|
|
|
+ check(pixel_input != NO_TYPE, context, "fragment input missing");
|
|
|
+ check(pixel_output != NO_TYPE, context, "fragment output missing");
|
|
|
+
|
|
|
+ write_capabilities(&decorations, &main->used_capabilities);
|
|
|
+ glsl_import = write_op_ext_inst_import(&decorations, "GLSL.std.450");
|
|
|
+ write_op_memory_model(&decorations, ADDRESSING_MODEL_LOGICAL, MEMORY_MODEL_GLSL450);
|
|
|
+
|
|
|
+ type *input = get_type(pixel_input);
|
|
|
+ type *output = get_type(pixel_output);
|
|
|
+
|
|
|
+ spirv_id entry_point = allocate_index();
|
|
|
+
|
|
|
+ input_vars_count = input->members.size - 1; // jump over pos input
|
|
|
+ for (size_t input_var_index = 0; input_var_index < input_vars_count; ++input_var_index) {
|
|
|
+ input_vars[input_var_index] = allocate_index();
|
|
|
+ }
|
|
|
+
|
|
|
+ assert(output->built_in); // has to be a float4 or a float4[]
|
|
|
+
|
|
|
+ if (output->array_size > 0) {
|
|
|
+ output_vars_count = output->array_size;
|
|
|
+ for (size_t output_var_index = 0; output_var_index < output->array_size; ++output_var_index) {
|
|
|
+ output_vars[output_var_index] = allocate_index();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ output_vars_count = 1;
|
|
|
+ output_vars[0] = allocate_index();
|
|
|
+ }
|
|
|
+
|
|
|
+ spirv_id interfaces[256];
|
|
|
+ size_t interfaces_count = 0;
|
|
|
+
|
|
|
+ for (size_t input_var_index = 0; input_var_index < input_vars_count; ++input_var_index) {
|
|
|
+ interfaces[interfaces_count] = input_vars[input_var_index];
|
|
|
+ interfaces_count += 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (size_t output_var_index = 0; output_var_index < output_vars_count; ++output_var_index) {
|
|
|
+ interfaces[interfaces_count] = output_vars[output_var_index];
|
|
|
+ interfaces_count += 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ write_op_entry_point(&decorations, EXECUTION_MODEL_FRAGMENT, entry_point, "main", interfaces, (uint16_t)interfaces_count);
|
|
|
+
|
|
|
+ write_op_execution_mode(&decorations, entry_point, EXECUTION_MODE_ORIGIN_UPPER_LEFT);
|
|
|
+
|
|
|
+ write_fragment_input_decorations(&decorations, input_vars, (uint32_t)input_vars_count);
|
|
|
+
|
|
|
+ write_base_types(&base_types);
|
|
|
+
|
|
|
+ write_globals(&decorations, &aggregate_types, &global_vars, main, SHADER_STAGE_FRAGMENT);
|
|
|
+
|
|
|
+ for (size_t i = 0; i < input_vars_count; ++i) {
|
|
|
+ member m = input->members.m[i + 1]; // jump over pos input
|
|
|
+ input_types[i] = m.type.type;
|
|
|
+
|
|
|
+ if (m.type.type == float2_id) {
|
|
|
+ write_op_variable_preallocated(&instructions, convert_pointer_type_to_spirv_id(float2_id, STORAGE_CLASS_INPUT), input_vars[i], STORAGE_CLASS_INPUT);
|
|
|
+ }
|
|
|
+ else if (m.type.type == float3_id) {
|
|
|
+ write_op_variable_preallocated(&instructions, convert_pointer_type_to_spirv_id(float3_id, STORAGE_CLASS_INPUT), input_vars[i], STORAGE_CLASS_INPUT);
|
|
|
+ }
|
|
|
+ else if (m.type.type == float4_id) {
|
|
|
+ write_op_variable_preallocated(&instructions, convert_pointer_type_to_spirv_id(float4_id, STORAGE_CLASS_INPUT), input_vars[i], STORAGE_CLASS_INPUT);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ debug_context context = {0};
|
|
|
+ error(context, "Type unsupported for input in SPIR-V");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ write_fragment_output_decorations(&decorations, output_vars, (uint32_t)output_vars_count);
|
|
|
+
|
|
|
+ for (size_t i = 0; i < output_vars_count; ++i) {
|
|
|
+ write_op_variable_preallocated(&instructions, convert_pointer_type_to_spirv_id(float4_id, STORAGE_CLASS_OUTPUT), output_vars[i], STORAGE_CLASS_OUTPUT);
|
|
|
+ }
|
|
|
+
|
|
|
+ write_functions(&instructions, main, entry_point, SHADER_STAGE_FRAGMENT, pixel_input, NO_TYPE);
|
|
|
+
|
|
|
+ write_types(&aggregate_types, main);
|
|
|
+
|
|
|
+ // header
|
|
|
+ write_magic_number(&header);
|
|
|
+ write_version_number(&header);
|
|
|
+ write_generator_magic_number(&header);
|
|
|
+ write_bound(&header);
|
|
|
+ write_instruction_schema(&header);
|
|
|
+
|
|
|
+ write_constants(&constants);
|
|
|
+
|
|
|
+ return write_bytecode2(size_out, &header, &decorations, &base_types, &constants, &aggregate_types, &global_vars, &instructions, debug);
|
|
|
+}
|
|
|
+
|
|
|
+void spirv_export2(char **vs, char **fs, int *vs_size, int *fs_size, bool debug) {
|
|
|
+ function *vertex_shaders[256];
|
|
|
+ size_t vertex_shaders_size = 0;
|
|
|
+
|
|
|
+ function *fragment_shaders[256];
|
|
|
+ size_t fragment_shaders_size = 0;
|
|
|
+
|
|
|
+ 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;
|
|
|
+ name_id fragment_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;
|
|
|
+ }
|
|
|
+ else if (t->members.m[j].name == add_name("fragment")) {
|
|
|
+ fragment_shader_name = t->members.m[j].value.identifier;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ debug_context context = {0};
|
|
|
+ check(vertex_shader_name != NO_NAME, context, "vertex shader missing");
|
|
|
+ check(fragment_shader_name != NO_NAME, context, "fragment shader missing");
|
|
|
+
|
|
|
+ for (function_id i = 0; get_function(i) != NULL; ++i) {
|
|
|
+ function *f = get_function(i);
|
|
|
+ if (f->name == vertex_shader_name) {
|
|
|
+ vertex_shaders[vertex_shaders_size] = f;
|
|
|
+ vertex_shaders_size += 1;
|
|
|
+ }
|
|
|
+ else if (f->name == fragment_shader_name) {
|
|
|
+ fragment_shaders[fragment_shaders_size] = f;
|
|
|
+ fragment_shaders_size += 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ *vs = spirv_export_vertex2(vertex_shaders[0], debug, vs_size);
|
|
|
+ *fs = spirv_export_fragment2(fragment_shaders[0], debug, fs_size);
|
|
|
+}
|
|
|
+
|
|
|
////
|