Main goal of slang_ir is to provide access to the internal intermediate representation of slang. This will help creating custom shader languages compilers with leveraging the backends available in slang, automatic differentiation (great for ml) and slang's optimization capabilities.
API design of this library is heavily inspired by libgccjit.
Library targets to mid-level instructions (not high-level that slang specific like Result type), but with exceptions for automatic differentiation support.
// source code location
type slang_ir_locationyou can always pass NULL to any API entrypoint accepting one.
slang_ir_location_create(slang_ir_builder* builder, const char* filename, int line, int column)type slang_ir_type
type slang_ir_vector_type
type slang_ir_array_type
type slang_ir_matrix_type// get base type
slang_ir_type *slang_ir_type_get(slang_ir_builder* builder, enum slang_ir_types type_)
enum
slang_ir_types
{
SLANG_IR_TYPE_VOID,
SLANG_IR_TYPE_BOOL,
SLANG_IR_TYPE_INT8,
SLANG_IR_TYPE_INT16,
SLANG_IR_TYPE_INT,
SLANG_IR_TYPE_INT64,
SLANG_IR_TYPE_UINT8,
SLANG_IR_TYPE_UINT16,
SLANG_IR_TYPE_UINT,
SLANG_IR_TYPE_UINT64,
SLANG_IR_TYPE_HALF,
SLANG_IR_TYPE_FLOAT,
SLANG_IR_TYPE_DOUBLE,
};
// get int type with specified size
slang_ir_type *slang_ir_type_get_int(slang_ir_builder* b, int num_bytes, int is_signed)Vec = {
struct_name = "VectorType",
operands = { { "elementType", "IRType" }, { "elementCount" } },
hoistable = true,
},// get vec type
slang_ir_vector_type *slang_ir_type_get_vector(slang_ir_type *type, size_t num_elements)
size_t slang_ir_vector_type_get_num_elements (slang_ir_vector_type *vector_type);
gcc_jit_type *slang_ir_vector_type_get_element_type (slang_ir_vector_type *vector_type);
// sizeof
size_t slang_ir_type_get_size(slang_ir_type *type)ArrayTypeBase = {
hoistable = true,
{
Array = {
struct_name = "ArrayType",
operands = {
{ "elementType", "IRType" },
{ "elementCount" },
{ "stride", optional = true },
},
},
},
{
UnsizedArray = {
struct_name = "UnsizedArrayType",
operands = { { "elementType", "IRType" }, { "stride", optional = true } },
},
},
},slang_ir_array_type *slang_ir_type_get_array(slang_ir_type *type, int64_t num_elements, int stride);
slang_ir_array_type *slang_ir_type_get_unsized_array(slang_ir_type *type, int stride);Mat = {
struct_name = "MatrixType",
operands = { { "elementType", "IRType" }, { "rowCount" }, { "columnCount" }, { "layout" } },
hoistable = true,
},enum
slang_ir_matrix_layouts
{
SLANG_IR_MATRIX_LAYOUT_UNKNOWN = 0,
SLANG_IR_MATRIX_LAYOUT_ROW_MAJOR = 1,
SLANG_IR_MATRIX_LAYOUT_COLUMN_MAJOR = 2,
};
slang_ir_matrix_type slang_ir_type_get_matrix(slang_ir_type *type, int64_t num_rows, int64_t num_cols, enum slang_ir_matrix_layouts layout)Unlike libgccjit, we need to create function type and then function, it better map to modern programming languages. First param is return type / return param
slang_ir_function_param_create(slang_ir_builder* builder, slang_ir_location* loc, lang_ir_type* type, const char* name)
slang_ir_type_get_func(int num_params, gcc_jit_param **params)
slang_ir_function slang_ir_function_create(slang_ir_builder* builder, slang_ir_type* function_type, const char *name)
slang_ir_rvalue *slang_ir_function_call(slang_ir_builder* builder, slang_ir_location* loc, slang_ir_function* func, int num_args, slang_ir_rvalue **args)
slang_ir_lvalue *slang_ir_function_discard(slang_ir_rvalue *fn_expr) // need for lvalue function call, if rvalue is not function: NULL
enum
slang_ir_entry_point_annotations
{
SLANG_IR_ENTRY_POINT_ANNOTATION_STAGE_VERTEX = 0,
SLANG_IR_ENTRY_POINT_ANNOTATION_STAGE_FRAGMENT = 1,
SLANG_IR_ENTRY_POINT_ANNOTATION_STAGE_COMPUTE = 2,
// will be place for tesselation stage etc.
}
void slang_ir_func_add_entry_point_annotation(slang_ir_builder* builder, slang_ir_function* func, enum slang_ir_entry_point_annotations annotation)void slang_ir_func_add_numthreads_annotation(slang_ir_builder* builder, slang_ir_function* func, int x, int y, int z)API currently support annotations only for normal differentiation, without custom differentiation support in user code. For it, these 3 annotations is enough
enum
slang_ir_differentiation_annotations
{
SLANG_IR_DIFFERENTIATION_ANNOTATION_ZERO = 0,
SLANG_IR_DIFFERENTIATION_ANNOTATION_TYPE = 1,
SLANG_IR_DIFFERENTIATION_ANNOTATION_ADD = 2,
}
slang_ir_function slang_ir_differentiate(slang_ir_builder* builder, slang_ir_function* func)
void slang_ir_add_differentiation_annotation(slang_ir_builder* builder, slang_ir_function* func, enum slang_ir_differentiation_annotations annotation)type slang_ir_rvalueenum
slang_ir_unary_op
{
SLANG_IR_UNARY_OP_ARITH_NEGATE, // -x
SLANG_IR_UNARY_OP_BITWISE_NEGATE, // ~x
SLANG_IR_UNARY_OP_LOGICAL_NEGATE, // !x
}
slang_ir_rvalue *gcc_jit_context_create_unary_op(slang_ir_builder* builder, slang_ir_location *loc, enum slang_ir_unary_op op, slang_ir_type *result_type, slang_ir_rvalue *x)enum
slang_ir_binary_op
{
SLANG_IR_BINARY_OP_ARITH_ADD, // x + y
SLANG_IR_BINARY_OP_ARITH_SUB, // x - y
SLANG_IR_BINARY_OP_ARITH_MUL, // x * y
SLANG_IR_BINARY_OP_ARITH_DIV, // x / y
SLANG_IR_BINARY_OP_ARITH_MOD, // x % y
SLANG_IR_BINARY_OP_BITWISE_AND, // x & y
SLANG_IR_BINARY_OP_BITWISE_XOR, // x ^ y
SLANG_IR_BINARY_OP_BITWISE_OR, // x | y
SLANG_IR_BINARY_OP_LOGICAL_AND, // x && y
SLANG_IR_BINARY_OP_LOGICAL_OR, // x || y
SLANG_IR_BINARY_OP_SHL, // x << y
SLANG_IR_BINARY_OP_SHR, // x >> y
}
slang_ir_rvalue *gcc_jit_context_create_binary_op(slang_ir_builder* builder, slang_ir_location *loc, enum slang_ir_binary_op op, slang_ir_type *result_type, slang_ir_rvalue *a, slang_ir_rvalue *b)enum
slang_ir_comparison
{
SLANG_IR_COMPARISON_EQ, // x == y
SLANG_IR_COMPARISON_NE, // x != y
SLANG_IR_COMPARISON_LT, // x < y
SLANG_IR_COMPARISON_LE, // x <= y
SLANG_IR_COMPARISON_GT, // x > y
SLANG_IR_COMPARISON_GE, // x >= y
}
slang_ir_rvalue *gcc_jit_context_create_comparison(slang_ir_builder* builder, slang_ir_location *loc, enum slang_ir_comparison op, slang_ir_rvalue *a, slang_ir_rvalue *b)TODO
char *slang_ir_builder_emit_spirv(slang_ir_builder* builder, slang_ir_function* entry_point)