Skip to content

Commit

Permalink
Create some special C code for WebGPU
Browse files Browse the repository at this point in the history
  • Loading branch information
RobDangerous committed Oct 5, 2023
1 parent 58c466a commit 720a716
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 52 deletions.
3 changes: 3 additions & 0 deletions Sources/api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

typedef enum api_kind { API_UNKNOWN, API_DIRECT3D9, API_DIRECT3D11, API_DIRECT3D12, API_OPENGL, API_METAL, API_WEBGPU, API_VULKAN } api_kind;
20 changes: 11 additions & 9 deletions Sources/backends/hlsl.c
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ static void write_functions(char *hlsl, size_t *offset, shader_stage stage, func
}
}

static void hlsl_export_vertex(char *directory, Direct3D d3d, function *main) {
static void hlsl_export_vertex(char *directory, api_kind d3d, function *main) {
char *hlsl = (char *)calloc(1024 * 1024, 1);
size_t offset = 0;

Expand All @@ -495,14 +495,15 @@ static void hlsl_export_vertex(char *directory, Direct3D d3d, function *main) {
size_t output_size;
int result = 1;
switch (d3d) {
case DIRECT3D_9:
case API_DIRECT3D9:
result = compile_hlsl_to_d3d9(hlsl, &output, &output_size, SHADER_STAGE_VERTEX, false);
break;
case DIRECT3D_11:
case API_DIRECT3D11:
case API_DIRECT3D12:
result = compile_hlsl_to_d3d11(hlsl, &output, &output_size, SHADER_STAGE_VERTEX, false);
break;
default:
error(context, "Unknown Direct3D version");
error(context, "Unsupported API for HLSL");
}
check(result == 0, context, "HLSL compilation failed");

Expand All @@ -517,7 +518,7 @@ static void hlsl_export_vertex(char *directory, Direct3D d3d, function *main) {
write_bytecode(hlsl, directory, filename, var_name, output, output_size);
}

static void hlsl_export_fragment(char *directory, Direct3D d3d, function *main) {
static void hlsl_export_fragment(char *directory, api_kind d3d, function *main) {
char *hlsl = (char *)calloc(1024 * 1024, 1);
size_t offset = 0;

Expand All @@ -536,14 +537,15 @@ static void hlsl_export_fragment(char *directory, Direct3D d3d, function *main)
size_t output_size;
int result = 1;
switch (d3d) {
case DIRECT3D_9:
case API_DIRECT3D9:
result = compile_hlsl_to_d3d9(hlsl, &output, &output_size, SHADER_STAGE_FRAGMENT, false);
break;
case DIRECT3D_11:
case API_DIRECT3D11:
case API_DIRECT3D12:
result = compile_hlsl_to_d3d11(hlsl, &output, &output_size, SHADER_STAGE_FRAGMENT, false);
break;
default:
error(context, "Unknown Direct3D version");
error(context, "Unsupported API for HLSL");
}
check(result == 0, context, "HLSL compilation failed");

Expand All @@ -558,7 +560,7 @@ static void hlsl_export_fragment(char *directory, Direct3D d3d, function *main)
write_bytecode(hlsl, directory, filename, var_name, output, output_size);
}

void hlsl_export(char *directory, Direct3D d3d) {
void hlsl_export(char *directory, api_kind d3d) {
int cbuffer_index = 0;
int texture_index = 0;
int sampler_index = 0;
Expand Down
6 changes: 3 additions & 3 deletions Sources/backends/hlsl.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

#include <stdint.h>
#include "../api.h"

typedef enum Direct3D { DIRECT3D_9, DIRECT3D_11 } Direct3D;
#include <stdint.h>

void hlsl_export(char *directory, Direct3D d3d);
void hlsl_export(char *directory, api_kind d3d);
49 changes: 45 additions & 4 deletions Sources/backends/wgsl.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,52 @@ static char *function_string(name_id func) {

static void write_code(char *wgsl, char *directory, const char *filename) {
char full_filename[512];
sprintf(full_filename, "%s/%s.c", directory, filename);

FILE *file = fopen(full_filename, "wb");
fprintf(file, "%s", wgsl);
fclose(file);
{
sprintf(full_filename, "%s/%s.h", directory, filename);
FILE *file = fopen(full_filename, "wb");
fprintf(file, "#include <stddef.h>\n\n");
fprintf(file, "extern const char *wgsl;\n");
fprintf(file, "extern size_t wgsl_size;\n");
fclose(file);
}

{
sprintf(full_filename, "%s/%s.c", directory, filename);
FILE *file = fopen(full_filename, "wb");

fprintf(file, "#include \"%s.h\"\n\n", filename);

fprintf(file, "const char *wgsl = \"");

size_t length = strlen(wgsl);

for (size_t i = 0; i < length; ++i) {
if (wgsl[i] == '\n') {
fprintf(file, "\\n");
}
else if (wgsl[i] == '\r') {
fprintf(file, "\\r");
}
else if (wgsl[i] == '\t') {
fprintf(file, "\\t");
}
else if (wgsl[i] == '"') {
fprintf(file, "\\\"");
}
else {
fprintf(file, "%c", wgsl[i]);
}
}

fprintf(file, "\";\n\n");

fprintf(file, "size_t wgsl_size = %" PRIu64 ";\n\n", length);

fprintf(file, "/*\n%s*/\n", wgsl);

fclose(file);
}
}

static void find_referenced_functions(function *f, function **functions, size_t *functions_size) {
Expand Down
64 changes: 45 additions & 19 deletions Sources/integrations/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ static const char *structure_type(type_id type) {

static int global_register_indices[512];

void c_export(char *directory) {
void c_export(char *directory, api_kind api) {
int cbuffer_index = 0;
int texture_index = 0;
int sampler_index = 0;
Expand Down Expand Up @@ -192,18 +192,23 @@ void c_export(char *directory) {

fprintf(output, "#include \"kong.h\"\n\n");

for (type_id i = 0; get_type(i) != NULL; ++i) {
type *t = get_type(i);
if (!t->built_in && t->attribute == add_name("pipe")) {
for (size_t j = 0; j < t->members.size; ++j) {
debug_context context = {0};
if (t->members.m[j].name == add_name("vertex")) {
check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "vertex expects an identifier");
fprintf(output, "#include \"kong_%s.h\"\n", get_name(t->members.m[j].value.identifier));
}
else if (t->members.m[j].name == add_name("fragment")) {
check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "fragment expects an identifier");
fprintf(output, "#include \"kong_%s.h\"\n", get_name(t->members.m[j].value.identifier));
if (api == API_WEBGPU) {
fprintf(output, "#include \"wgsl.h\"\n");
}
else {
for (type_id i = 0; get_type(i) != NULL; ++i) {
type *t = get_type(i);
if (!t->built_in && t->attribute == add_name("pipe")) {
for (size_t j = 0; j < t->members.size; ++j) {
debug_context context = {0};
if (t->members.m[j].name == add_name("vertex")) {
check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "vertex expects an identifier");
fprintf(output, "#include \"kong_%s.h\"\n", get_name(t->members.m[j].value.identifier));
}
else if (t->members.m[j].name == add_name("fragment")) {
check(t->members.m[j].value.kind == TOKEN_IDENTIFIER, context, "fragment expects an identifier");
fprintf(output, "#include \"kong_%s.h\"\n", get_name(t->members.m[j].value.identifier));
}
}
}
}
Expand Down Expand Up @@ -293,7 +298,16 @@ void c_export(char *directory) {
}
}

if (api == API_WEBGPU) {
fprintf(output, "\nvoid kinc_g5_internal_webgpu_create_shader_module(const void *source, size_t length);\n");
}

fprintf(output, "\nvoid kong_init(void) {\n");

if (api == API_WEBGPU) {
fprintf(output, "\tkinc_g5_internal_webgpu_create_shader_module(wgsl, wgsl_size);\n\n");
}

for (type_id i = 0; get_type(i) != NULL; ++i) {
type *t = get_type(i);
if (!t->built_in && t->attribute == add_name("pipe")) {
Expand All @@ -303,16 +317,28 @@ void c_export(char *directory) {

for (size_t j = 0; j < t->members.size; ++j) {
if (t->members.m[j].name == add_name("vertex")) {
fprintf(output, "\tkinc_g4_shader_init(&%s, %s_code, %s_code_size, KINC_G4_SHADER_TYPE_VERTEX);\n",
get_name(t->members.m[j].value.identifier), get_name(t->members.m[j].value.identifier),
get_name(t->members.m[j].value.identifier));
if (api == API_WEBGPU) {
fprintf(output, "\tkinc_g4_shader_init(&%s, \"%s\", 0, KINC_G4_SHADER_TYPE_VERTEX);\n", get_name(t->members.m[j].value.identifier),
get_name(t->members.m[j].value.identifier));
}
else {
fprintf(output, "\tkinc_g4_shader_init(&%s, %s_code, %s_code_size, KINC_G4_SHADER_TYPE_VERTEX);\n",
get_name(t->members.m[j].value.identifier), get_name(t->members.m[j].value.identifier),
get_name(t->members.m[j].value.identifier));
}
fprintf(output, "\t%s.vertex_shader = &%s;\n\n", get_name(t->name), get_name(t->members.m[j].value.identifier));
vertex_shader_name = t->members.m[j].value.identifier;
}
else if (t->members.m[j].name == add_name("fragment")) {
fprintf(output, "\tkinc_g4_shader_init(&%s, %s_code, %s_code_size, KINC_G4_SHADER_TYPE_FRAGMENT);\n",
get_name(t->members.m[j].value.identifier), get_name(t->members.m[j].value.identifier),
get_name(t->members.m[j].value.identifier));
if (api == API_WEBGPU) {
fprintf(output, "\tkinc_g4_shader_init(&%s, \"%s\", 0, KINC_G4_SHADER_TYPE_FRAGMENT);\n",
get_name(t->members.m[j].value.identifier), get_name(t->members.m[j].value.identifier));
}
else {
fprintf(output, "\tkinc_g4_shader_init(&%s, %s_code, %s_code_size, KINC_G4_SHADER_TYPE_FRAGMENT);\n",
get_name(t->members.m[j].value.identifier), get_name(t->members.m[j].value.identifier),
get_name(t->members.m[j].value.identifier));
}
fprintf(output, "\t%s.fragment_shader = &%s;\n\n", get_name(t->name), get_name(t->members.m[j].value.identifier));
}
else if (t->members.m[j].name == add_name("depth_write")) {
Expand Down
4 changes: 3 additions & 1 deletion Sources/integrations/c.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "../api.h"

#include <stdint.h>

void c_export(char *directory);
void c_export(char *directory, api_kind api);
61 changes: 45 additions & 16 deletions Sources/kong.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ int main(int argc, char **argv) {
char *inputs[256] = {0};
size_t inputs_size = 0;
char *platform = NULL;
char *api = NULL;
api_kind api = API_UNKNOWN;
char *output = NULL;

for (int i = 1; i < argc; ++i) {
Expand Down Expand Up @@ -465,7 +465,31 @@ int main(int argc, char **argv) {
break;
}
case MODE_API: {
api = argv[i];
if (strcmp(argv[i], "direct3d9") == 0) {
api = API_DIRECT3D9;
}
else if (strcmp(argv[i], "direct3d11") == 0) {
api = API_DIRECT3D11;
}
else if (strcmp(argv[i], "direct3d12") == 0) {
api = API_DIRECT3D12;
}
else if (strcmp(argv[i], "opengl") == 0) {
api = API_OPENGL;
}
else if (strcmp(argv[i], "metal") == 0) {
api = API_METAL;
}
else if (strcmp(argv[i], "webgpu") == 0) {
api = API_WEBGPU;
}
else if (strcmp(argv[i], "vulkan") == 0) {
api = API_VULKAN;
}
else {
debug_context context = {0};
error(context, "Unknown API %s", argv[i]);
}
mode = MODE_MODECHECK;
break;
}
Expand All @@ -477,7 +501,7 @@ int main(int argc, char **argv) {
check(inputs_size > 0, context, "no input parameters found");
check(output != NULL, context, "output parameter not found");
check(platform != NULL, context, "platform parameter not found");
check(api != NULL, context, "api parameter not found");
check(api != API_UNKNOWN, context, "api parameter not found");

names_init();
types_init();
Expand Down Expand Up @@ -522,27 +546,32 @@ int main(int argc, char **argv) {
convert_function_block(&get_function(i)->code, get_function(i)->block);
}

if (strcmp(api, "direct3d9") == 0) {
hlsl_export(output, DIRECT3D_9);
}
else if (strcmp(api, "direct3d11") == 0 || strcmp(api, "direct3d12") == 0) {
hlsl_export(output, DIRECT3D_11);
}
else if (strcmp(api, "opengl") == 0) {
switch (api) {
case API_DIRECT3D9:
case API_DIRECT3D11:
case API_DIRECT3D12:
hlsl_export(output, api);
break;
case API_OPENGL:
glsl_export(output);
}
else if (strcmp(api, "metal") == 0) {
break;
case API_METAL:
metal_export(output);
}
else if (strcmp(api, "webgpu") == 0) {
break;
case API_WEBGPU:
wgsl_export(output);
break;
case API_VULKAN: {
debug_context context = {0};
error(context, "SPIRV not yet supported");
}
else {
default: {
debug_context context = {0};
error(context, "Unknown API");
}
}

c_export(output);
c_export(output, api);

return 0;
}

0 comments on commit 720a716

Please sign in to comment.