This commit is contained in:
2025-10-01 20:25:28 +02:00

129
README.md
View File

@@ -1,7 +1,10 @@
# Shader Compiler
# Ink
A compiler for a custom, platform-agnostic shader language that compiles to platform specific shader languages (currently only HLSL).
Ink is not a standalone executable, but rather a library you use to compile your shaders. It has metaprogramming capabilities in the sense that all stages are exposed and data is editable at will.
In the future we will support a better API for adding code and possibly macros if we deem it necessary.
## Features
A simple passthrough shader (`passthrough.shd`) can look as follows
@@ -41,40 +44,55 @@ Camera_Data :: struct {
projection : float4x4;
view : float4x4;
}
```
And there is a special struct called `properties`, which is used for custom data you want to pass in.
#### ** Note: Properties will likely be deprecated, since the language now supports `@` hints to easily mark buffers and values with metadata.**
```hlsl
properties {
projection : float4x4;
view : float4x4;
}
```
which will be exposed in the compiled result. `properties` can be renamed to a custom/shorter name like
```
p :: properties {
...
```
You can also define constant buffers
```
camera :: constant_buffer {
camera :: Constant_Buffer {
projection : float4x4;
view : float4x4;
}
```
You can mark these with `@` hints to mark specific mappings for your engine
```
camera :: Constant_Buffer @camera {
projection : float4x4;
view : float4x4;
}
```
Structured buffers - simply called `Buffer` - are now also supported
```
buffer :: Buffer {
color : float4;
model : float4x4;
}
vertex main :: (position : float3 @position, instance_id : int) -> float4 @outposition {
return mul(position, buffer[instance_id].model);
}
pixel main :: (instance_id : int) {
return buffer[instance_id].color;
}
```
You will get a `Buffer` instance returned in the compiled result which has all the fields in the buffer exposed. See more below.
## Jai Usage Example
To compile a shader and use the result, you can do the following in jai
```jai
// In the future, you can pass environment defines to the compiler.
ctx : Compiler_Context;
compile_file(*compiler, "shader.shd", allocator);
add_define(*ctx, "SKINNING"); // Pass environment defines here, you can also use the `#add_define` in your shaders for debugging.
compile_file(*compiler, "shader.ink", allocator);
if ctx.had_error {
log_error("%\n", report_messages(ctx.messages),, temp);
@@ -84,49 +102,14 @@ if ctx.had_error {
// The ctx now contains all the needed information like the source text, entry points, constant buffers etc.
```
When parsing a shader you get the following struct as a result
### Output data
When parsing a shader you pass a `Compiler_Context` struct which in turn will contain all the output data in the end. See `module.jai` for more info.
An example of output data are buffers (constant, structured)
```
Compiler_Context :: struct {
file : Input_File;
environment : Environment;
tokens : [..]Token;;
root : *AST_Node;
nodes : [..]AST_Node;
codegen_result_text : string;
constant_buffers : Static_Array(Type_Variable_Handle, 16);
scope_stack : Scope_Stack;
type_variables : [..]Type_Variable;
property_name : string;
vertex_entry_point : struct {
node : *AST_Node;
name : string;
input : [..]Field;
}
pixel_entry_point : struct {
node : *AST_Node;
name : string;
return_value : Field;
}
properties : Properties;
max_constant_buffers :: 16;
cbuffers : Static_Array(Constant_Buffer, max_constant_buffers);
had_error : bool;
messages : [..]Compiler_Message;
}
Constant_Buffer :: struct {
Buffer :: struct {
name : string;
fields : Static_Array(Property_Field, 16);
@@ -137,11 +120,6 @@ Constant_Buffer :: struct {
buffer_index : u32;
}
Properties :: struct {
fields : [..]Property_Field;
buffer_index : u32;
}
```
A field is just a simple struct with a name and type (and hints such as semantics or custom hints in the future)
@@ -170,7 +148,7 @@ Field_Kind :: enum {
Function;
Struct;
Array; // Not yet supported
Array;
}
Field_Type :: struct {
@@ -180,23 +158,14 @@ Field_Type :: struct {
children : [..]Field;
}
Hint_Kind :: enum {
None;
Position;
Target;
Custom;
}
```
## Notable missing features
- While
- Arrays
- Multiple render targets
- Custom buffers/structured buffers
- Interpolation specifiers
- Proper variant handling with environment defines
- Importing files such as shared utils etc. with something other than textual `#load`
- Importing files such as shared utils etc. with something other than textual `#load`
- Other output languages
- compute shaders
- mesh/amplification shaders