Skip to content

Commit

Permalink
Write more SPIR-V
Browse files Browse the repository at this point in the history
  • Loading branch information
RobDangerous committed Oct 9, 2023
1 parent dd85725 commit 0d84145
Showing 1 changed file with 115 additions and 11 deletions.
126 changes: 115 additions & 11 deletions Sources/backends/spirv.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "../functions.h"
#include "../shader_stage.h"

#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -73,7 +74,18 @@ static void write_bytecode(char *directory, const char *filename, const char *na
}
}

typedef enum spirv_opcode { OPCODE_EXT_INST_IMPORT = 11, OPCODE_MEMORY_MODEL = 14, OPCODE_ENTRY_POINT = 15, OPCODE_CAPABILITY = 17 } spirv_opcode;
typedef enum spirv_opcode {
OPCODE_EXT_INST_IMPORT = 11,
OPCODE_MEMORY_MODEL = 14,
OPCODE_ENTRY_POINT = 15,
OPCODE_CAPABILITY = 17,
OPCODE_TYPE_VOID = 19,
OPCODE_TYPE_INT = 21,
OPCODE_TYPE_FLOAT = 22,
OPCODE_TYPE_VECTOR = 23,
OPCODE_TYPE_FUNCTION = 33,
OPCODE_CONSTANT = 43
} spirv_opcode;

typedef enum addressing_model { ADDRESSING_MODEL_LOGICAL = 0 } addressing_model;

Expand All @@ -83,6 +95,8 @@ typedef enum capability { CAPABILITY_SHADER = 1 } capability;

typedef enum execution_model { EXECUTION_MODEL_VERTEX = 0, EXECUTION_MODEL_FRAGMENT = 4 } execution_model;

static uint32_t operands_buffer[4096];

static void write_instruction(uint32_t *instructions, size_t *offset, uint16_t word_count, spirv_opcode o, uint32_t *operands) {
instructions[(*offset)++] = (word_count << 16) | (uint16_t)o;
for (uint16_t i = 0; i < word_count - 1; ++i) {
Expand All @@ -107,12 +121,11 @@ static uint32_t write_op_ext_inst_import(uint32_t *instructions, size_t *offset,
uint32_t result = next_index;
++next_index;

uint32_t operands[256] = {0};
operands[0] = result;
operands_buffer[0] = result;

uint32_t name_length = write_string(&operands[1], name);
uint32_t name_length = write_string(&operands_buffer[1], name);

write_instruction(instructions, offset, 2 + name_length, OPCODE_EXT_INST_IMPORT, operands);
write_instruction(instructions, offset, 2 + name_length, OPCODE_EXT_INST_IMPORT, operands_buffer);

return result;
}
Expand All @@ -124,23 +137,112 @@ static void write_op_memory_model(uint32_t *instructions, size_t *offset, uint32

static void write_op_entry_point(uint32_t *instructions, size_t *offset, execution_model em, uint32_t entry_point, const char *name, uint32_t *interfaces,
uint16_t interfaces_size) {
uint32_t operands[256] = {0};
operands[0] = (uint32_t)em;
operands[1] = entry_point;
operands_buffer[0] = (uint32_t)em;
operands_buffer[1] = entry_point;

uint32_t name_length = write_string(&operands[2], name);
uint32_t name_length = write_string(&operands_buffer[2], name);

for (uint16_t i = 0; i < interfaces_size; ++i) {
operands[2 + name_length + i] = interfaces[i];
operands_buffer[2 + name_length + i] = interfaces[i];
}

write_instruction(instructions, offset, 3 + name_length + interfaces_size, OPCODE_ENTRY_POINT, operands);
write_instruction(instructions, offset, 3 + name_length + interfaces_size, OPCODE_ENTRY_POINT, operands_buffer);
}

static void write_capabilities(uint32_t *instructions, size_t *offset) {
write_capability(instructions, offset, CAPABILITY_SHADER);
}

static uint32_t write_type_void(uint32_t *instructions, size_t *offset) {
uint32_t void_type = next_index;
++next_index;
write_instruction(instructions, offset, 2, OPCODE_TYPE_VOID, &void_type);
return void_type;
}

#define WORD_COUNT(operands) (1 + sizeof(operands) / 4)

static uint32_t write_type_function(uint32_t *instructions, size_t *offset, uint32_t return_type, uint32_t *parameter_types, uint16_t parameter_types_size) {
uint32_t function_type = next_index;
++next_index;

operands_buffer[0] = function_type;
operands_buffer[1] = return_type;
for (uint16_t i = 0; i < parameter_types_size; ++i) {
operands_buffer[i + 2] = parameter_types[0];
}
write_instruction(instructions, offset, 3 + parameter_types_size, OPCODE_TYPE_FUNCTION, operands_buffer);
return function_type;
}

static uint32_t write_type_float(uint32_t *instructions, size_t *offset, uint32_t width) {
uint32_t float_type = next_index;
++next_index;

uint32_t operands[2];
operands[0] = float_type;
operands[1] = width;
write_instruction(instructions, offset, WORD_COUNT(operands), OPCODE_TYPE_FLOAT, operands);
return float_type;
}

static uint32_t write_type_vector(uint32_t *instructions, size_t *offset, uint32_t component_type, uint32_t component_count) {
uint32_t vector_type = next_index;
++next_index;

uint32_t operands[3];
operands[0] = vector_type;
operands[1] = component_type;
operands[2] = component_count;
write_instruction(instructions, offset, WORD_COUNT(operands), OPCODE_TYPE_VECTOR, operands);
return vector_type;
}

static uint32_t write_type_int(uint32_t *instructions, size_t *offset, uint32_t width, bool signedness) {
uint32_t int_type = next_index;
++next_index;

uint32_t operands[3];
operands[0] = int_type;
operands[1] = width;
operands[2] = signedness ? 1 : 0;
write_instruction(instructions, offset, WORD_COUNT(operands), OPCODE_TYPE_INT, operands);
return int_type;
}

static uint32_t spirv_float_type;

static void write_types(uint32_t *instructions, size_t *offset) {
uint32_t void_type = write_type_void(instructions, offset);

uint32_t void_function_type = write_type_function(instructions, offset, void_type, NULL, 0);

spirv_float_type = write_type_float(instructions, offset, 32);

uint32_t float4_type = write_type_vector(instructions, offset, spirv_float_type, 4);

uint32_t uint_type = write_type_int(instructions, offset, 32, false);

uint32_t int_type = write_type_int(instructions, offset, 32, true);
}

static uint32_t write_constant(uint32_t *instructions, size_t *offset, uint32_t type, uint32_t value) {
uint32_t value_id = next_index;
++next_index;

uint32_t operands[3];
operands[0] = type;
operands[1] = value_id;
operands[2] = value;
write_instruction(instructions, offset, WORD_COUNT(operands), OPCODE_CONSTANT, operands);
return value_id;
}

static uint32_t write_constant_float(uint32_t *instructions, size_t *offset, float value) {
uint32_t uint32_value = *(uint32_t *)&value;
return write_constant(instructions, offset, spirv_float_type, uint32_value);
}

static void spirv_export_vertex(char *directory, function *main) {
uint32_t *instructions = (uint32_t *)calloc(1024 * 1024, 1);
size_t offset = 0;
Expand All @@ -159,6 +261,8 @@ static void spirv_export_vertex(char *directory, function *main) {
uint32_t interfaces[] = {3, 4};
write_op_entry_point(instructions, &offset, EXECUTION_MODEL_VERTEX, entry_point, "main", interfaces, sizeof(interfaces) / 4);

write_types(instructions, &offset);

char *name = get_name(main->name);

char filename[512];
Expand Down

0 comments on commit 0d84145

Please sign in to comment.