Signed-off-by: Atharva Nimbalkar atharvakn@gmail.com --- Makefile.am | 1 + libs/vkd3d-shader/glsl.c | 118 +++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_main.c | 17 +++- libs/vkd3d-shader/vkd3d_shader_private.h | 9 ++ 4 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 libs/vkd3d-shader/glsl.c
diff --git a/Makefile.am b/Makefile.am index 9624485..18ba0fa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -169,6 +169,7 @@ libvkd3d_shader_la_SOURCES = \ include/vkd3d_shader.h \ libs/vkd3d-shader/checksum.c \ libs/vkd3d-shader/dxbc.c \ + libs/vkd3d-shader/glsl.c \ libs/vkd3d-shader/hlsl.c \ libs/vkd3d-shader/hlsl.h \ libs/vkd3d-shader/hlsl_codegen.c \ diff --git a/libs/vkd3d-shader/glsl.c b/libs/vkd3d-shader/glsl.c new file mode 100644 index 0000000..5b4b62b --- /dev/null +++ b/libs/vkd3d-shader/glsl.c @@ -0,0 +1,118 @@ +/* + * Copyright 2021 Atharva Nimbalkar + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "vkd3d_shader_private.h" + +struct vkd3d_glsl_generator +{ + struct vkd3d_string_buffer buffer; + struct vkd3d_shader_location location; + struct vkd3d_shader_message_context *message_context; + bool failed; +}; + +struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_message_context *message_context) +{ + struct vkd3d_glsl_generator *generator; + + if (!(generator = vkd3d_malloc(sizeof(*generator)))) + return NULL; + + memset(generator, 0, sizeof(*generator)); + generator->location.source_name = compile_info->source_name; + generator->location.line = 2; /* Line 1 is the version token. */ + generator->message_context = message_context; + return generator; +} + +static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error( + struct vkd3d_glsl_generator *generator, + enum vkd3d_shader_error error, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vkd3d_shader_verror(generator->message_context, &generator->location, error, fmt, args); + va_end(args); + generator->failed = true; + return; +} + +static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator, + const struct vkd3d_shader_instruction *instruction) +{ + switch (instruction->handler_idx) + { + default: + vkd3d_glsl_compiler_error(generator, + VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Unhandled instruction %#x", instruction->handler_idx); + break; + } + + ++generator->location.line; + return; +} + +int vkd3d_glsl_generator_generate(void *parser_data, const uint32_t *parser_ptr, + struct vkd3d_glsl_generator *generator, + struct vkd3d_shader_code *out) +{ + void *code; + struct vkd3d_shader_instruction ins; + + vkd3d_string_buffer_printf(&generator->buffer, "#version 440\n\n"); + vkd3d_string_buffer_printf(&generator->buffer, "void main()\n{\n"); + + while (!shader_sm4_is_end(parser_data, &parser_ptr)) + { + shader_sm4_read_instruction(parser_data, &parser_ptr, &ins); + + if (ins.handler_idx == VKD3DSIH_INVALID) + { + vkd3d_glsl_compiler_error(generator, + VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Encountered unrecognized or invalid instruction."); + break; + } + + vkd3d_glsl_handle_instruction(generator, &ins); + } + + if (generator->failed) + return VKD3D_ERROR; + + vkd3d_string_buffer_printf(&generator->buffer, "}\n"); + + if ((code = vkd3d_malloc(generator->buffer.buffer_size))) + { + memcpy(code, generator->buffer.buffer, generator->buffer.content_size); + out->size = generator->buffer.content_size; + out->code = code; + } + else return VKD3D_ERROR_OUT_OF_MEMORY; + + return VKD3D_OK; +} + +void vkd3d_glsl_generator_destroy(struct vkd3d_glsl_generator *generator) +{ + vkd3d_string_buffer_cleanup(&generator->buffer); + vkd3d_free(generator); +} diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index a9b5d0a..d2182e1 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1034,11 +1034,22 @@ static int compile_dxbc_tpf(const struct vkd3d_shader_compile_info *compile_info
if (compile_info->target_type == VKD3D_SHADER_TARGET_GLSL) { - vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Internal compiler error: Unhandled instruction."); + struct vkd3d_glsl_generator *glsl_generator; + + if (!(glsl_generator = vkd3d_glsl_generator_create(compile_info, message_context))) + { + ERR("Failed to create GLSL generator.\n"); + vkd3d_shader_parser_destroy(&parser); + vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info); + return VKD3D_ERROR; + } + + ret = vkd3d_glsl_generator_generate(parser.data, parser.ptr, glsl_generator, out); + + vkd3d_glsl_generator_destroy(glsl_generator); vkd3d_shader_parser_destroy(&parser); vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info); - return VKD3D_ERROR; + return ret; }
if (!(spirv_compiler = vkd3d_dxbc_compiler_create(&parser.shader_version, diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index b490b9c..3863797 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -984,6 +984,15 @@ void free_shader_desc(struct vkd3d_shader_desc *desc); int shader_parse_input_signature(const void *dxbc, size_t dxbc_length, struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_signature *signature);
+struct vkd3d_glsl_generator; + +struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_message_context *message_context); +int vkd3d_glsl_generator_generate(void *parser_data, const uint32_t *parser_ptr, + struct vkd3d_glsl_generator *generator, + struct vkd3d_shader_code *out); +void vkd3d_glsl_generator_destroy(struct vkd3d_glsl_generator *generator); + struct vkd3d_dxbc_compiler;
struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version,
Signed-off-by: Atharva Nimbalkar atharvakn@gmail.com --- libs/vkd3d-shader/glsl.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/libs/vkd3d-shader/glsl.c b/libs/vkd3d-shader/glsl.c index 5b4b62b..466493e 100644 --- a/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d-shader/glsl.c @@ -59,6 +59,8 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator { switch (instruction->handler_idx) { + case VKD3DSIH_DCL_INPUT: + break; default: vkd3d_glsl_compiler_error(generator, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Atharva Nimbalkar atharvakn@gmail.com --- libs/vkd3d-shader/glsl.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/libs/vkd3d-shader/glsl.c b/libs/vkd3d-shader/glsl.c index 466493e..ac132e8 100644 --- a/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d-shader/glsl.c @@ -60,6 +60,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator switch (instruction->handler_idx) { case VKD3DSIH_DCL_INPUT: + case VKD3DSIH_DCL_OUTPUT_SIV: break; default: vkd3d_glsl_compiler_error(generator,
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Atharva Nimbalkar atharvakn@gmail.com --- libs/vkd3d-shader/glsl.c | 23 ++++++++++++++++++++++- libs/vkd3d-shader/vkd3d_shader_main.c | 2 +- libs/vkd3d-shader/vkd3d_shader_private.h | 3 ++- 3 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/glsl.c b/libs/vkd3d-shader/glsl.c index ac132e8..d339fbd 100644 --- a/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d-shader/glsl.c @@ -20,13 +20,15 @@
struct vkd3d_glsl_generator { + struct vkd3d_shader_version version; struct vkd3d_string_buffer buffer; struct vkd3d_shader_location location; struct vkd3d_shader_message_context *message_context; bool failed; };
-struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shader_compile_info *compile_info, +struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shader_version *version, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context) { struct vkd3d_glsl_generator *generator; @@ -35,6 +37,7 @@ struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shad return NULL;
memset(generator, 0, sizeof(*generator)); + generator->version = *version; generator->location.source_name = compile_info->source_name; generator->location.line = 2; /* Line 1 is the version token. */ generator->message_context = message_context; @@ -54,6 +57,21 @@ static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error( return; }
+static void shader_glsl_ret(struct vkd3d_glsl_generator *generator, + const struct vkd3d_shader_instruction *ins) +{ + const struct vkd3d_shader_version *version = &generator->version; + + /* + * TODO: Implement in_subroutine + * TODO: shader_glsl_generate_shader_epilogue(generator); + */ + if (version->major >= 4) + { + vkd3d_string_buffer_printf(&generator->buffer, "return;\n"); + } +} + static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator, const struct vkd3d_shader_instruction *instruction) { @@ -62,6 +80,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator case VKD3DSIH_DCL_INPUT: case VKD3DSIH_DCL_OUTPUT_SIV: break; + case VKD3DSIH_RET: + shader_glsl_ret(generator, instruction); + break; default: vkd3d_glsl_compiler_error(generator, VKD3D_SHADER_ERROR_GLSL_INTERNAL, diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index d2182e1..16994d2 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1036,7 +1036,7 @@ static int compile_dxbc_tpf(const struct vkd3d_shader_compile_info *compile_info { struct vkd3d_glsl_generator *glsl_generator;
- if (!(glsl_generator = vkd3d_glsl_generator_create(compile_info, message_context))) + if (!(glsl_generator = vkd3d_glsl_generator_create(&parser.shader_version, compile_info, message_context))) { ERR("Failed to create GLSL generator.\n"); vkd3d_shader_parser_destroy(&parser); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 3863797..9efa598 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -986,7 +986,8 @@ int shader_parse_input_signature(const void *dxbc, size_t dxbc_length,
struct vkd3d_glsl_generator;
-struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shader_compile_info *compile_info, +struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shader_version *version, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context); int vkd3d_glsl_generator_generate(void *parser_data, const uint32_t *parser_ptr, struct vkd3d_glsl_generator *generator,
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Atharva Nimbalkar atharvakn@gmail.com --- libs/vkd3d-shader/glsl.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/libs/vkd3d-shader/glsl.c b/libs/vkd3d-shader/glsl.c index d339fbd..38d18cc 100644 --- a/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d-shader/glsl.c @@ -78,6 +78,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator switch (instruction->handler_idx) { case VKD3DSIH_DCL_INPUT: + case VKD3DSIH_DCL_OUTPUT: case VKD3DSIH_DCL_OUTPUT_SIV: break; case VKD3DSIH_RET:
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com