Signed-off-by: Atharva Nimbalkar atharvakn@gmail.com --- libs/vkd3d-shader/glsl.c | 234 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+)
diff --git a/libs/vkd3d-shader/glsl.c b/libs/vkd3d-shader/glsl.c index d34b5e8..75b7bbc 100644 --- a/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d-shader/glsl.c @@ -18,15 +18,60 @@
#include "vkd3d_shader_private.h"
+struct glsl_src_param +{ + struct vkd3d_string_buffer *param_str; +}; + +struct glsl_dst_param +{ + struct vkd3d_string_buffer *reg_name; + struct vkd3d_string_buffer *mask_str; +}; + +static const char * const shift_glsl_tab[] = +{ + "", /* 0 (none) */ + "2.0 * ", /* 1 (x2) */ + "4.0 * ", /* 2 (x4) */ + "8.0 * ", /* 3 (x8) */ + "16.0 * ", /* 4 (x16) */ + "32.0 * ", /* 5 (x32) */ + "", /* 6 (x64) */ + "", /* 7 (x128) */ + "", /* 8 (d256) */ + "", /* 9 (d128) */ + "", /* 10 (d64) */ + "", /* 11 (d32) */ + "0.0625 * ", /* 12 (d16) */ + "0.125 * ", /* 13 (d8) */ + "0.25 * ", /* 14 (d4) */ + "0.5 * " /* 15 (d2) */ +}; + struct vkd3d_glsl_generator { struct vkd3d_shader_version version; struct vkd3d_string_buffer buffer; struct vkd3d_shader_location location; + struct vkd3d_string_buffer_cache string_buffers; struct vkd3d_shader_message_context *message_context; bool failed; };
+static void glsl_dst_param_cleanup(struct glsl_dst_param *dst, + struct vkd3d_string_buffer_cache *buffers) +{ + vkd3d_string_buffer_release(buffers, dst->mask_str); + vkd3d_string_buffer_release(buffers, dst->reg_name); +} + +static void glsl_src_param_cleanup(struct glsl_src_param *src, + struct vkd3d_string_buffer_cache *buffers) +{ + vkd3d_string_buffer_release(buffers, src->param_str); +} + 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) @@ -41,6 +86,8 @@ struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shad generator->location.source_name = compile_info->source_name; generator->location.line = 2; /* Line 1 is the version token. */ generator->message_context = message_context; + vkd3d_string_buffer_cache_init(&generator->string_buffers); + return generator; }
@@ -72,6 +119,189 @@ static void shader_glsl_ret(struct vkd3d_glsl_generator *generator, } }
+static bool shader_is_scalar(const struct vkd3d_shader_register *reg) +{ + switch (reg->type) + { + case VKD3DSPR_RASTOUT: + /* oFog & oPts */ + if (reg->idx[0].offset) + return true; + /* oPos */ + return false; + + case VKD3DSPR_CONSTBOOL: /* b# */ + case VKD3DSPR_DEPTHOUT: /* oDepth */ + case VKD3DSPR_DEPTHOUTGE: + case VKD3DSPR_DEPTHOUTLE: + case VKD3DSPR_LOOP: /* aL */ + case VKD3DSPR_OUTPOINTID: + case VKD3DSPR_PREDICATE: /* p0 */ + case VKD3DSPR_PRIMID: /* primID */ + case VKD3DSPR_COVERAGE: /* vCoverage */ + case VKD3DSPR_SAMPLEMASK: /* oMask */ + return true; + + case VKD3DSPR_MISCTYPE: + switch (reg->idx[0].offset) + { + case 0: /* vPos */ + return false; + case 1: /* vFace */ + return true; + default: + return false; + } + + case VKD3DSPR_IMMCONST: + return reg->immconst_type == VKD3D_IMMCONST_SCALAR; + + default: + return false; + } +} + +static void shader_glsl_print_write_mask(uint32_t write_mask, struct vkd3d_string_buffer *str) +{ + vkd3d_string_buffer_printf(str, "."); + if (write_mask & VKD3DSP_WRITEMASK_0) vkd3d_string_buffer_printf(str, "x"); + if (write_mask & VKD3DSP_WRITEMASK_1) vkd3d_string_buffer_printf(str, "y"); + if (write_mask & VKD3DSP_WRITEMASK_2) vkd3d_string_buffer_printf(str, "z"); + if (write_mask & VKD3DSP_WRITEMASK_3) vkd3d_string_buffer_printf(str, "w"); +} + +/* Get the GLSL write mask for the destination register */ +static uint32_t shader_glsl_get_write_mask(const struct vkd3d_shader_dst_param *param, + struct vkd3d_string_buffer *write_mask) +{ + uint32_t mask = param->write_mask; + + if (shader_is_scalar(¶m->reg)) + { + return VKD3DSP_WRITEMASK_0; + } + + shader_glsl_print_write_mask(mask, write_mask); + return mask; +} + +static void glsl_src_param_init_ext(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_src_param *vkd3d_src, uint32_t mask, struct glsl_src_param *glsl_src, + enum vkd3d_data_type data_type); + +/* Writes the GLSL variable name that corresponds to the register that the + * DX opcode parameter is trying to access */ +static void shader_glsl_get_register_name(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_register *reg, enum vkd3d_data_type data_type, + struct vkd3d_string_buffer *register_name, bool *is_swizzled) +{ + /* TODO: Add implementation + * Sets an error state as of now + */ + if(is_swizzled) + *is_swizzled = false; + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled register type %#x.", reg->type); +} + +/* From a given parameter token, generate the corresponding GLSL string. + * Also, return the actual register name and swizzle in case the + * caller needs this information as well. */ +static void glsl_src_param_init_ext(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_src_param *vkd3d_src, uint32_t mask, struct glsl_src_param *glsl_src, + enum vkd3d_data_type data_type) +{ + /* + * TODO: Add implementation + * Sets an error state as of now. + */ + + glsl_src->param_str = vkd3d_string_buffer_get(&gen->string_buffers); + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled parameter token."); +} + +static void glsl_src_param_init(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_src_param *vkd3d_src, uint32_t mask, + struct glsl_src_param *glsl_src) +{ + glsl_src_param_init_ext(gen, vkd3d_src, mask, glsl_src, vkd3d_src->reg.data_type); +} + +/* From a given parameter token, generate the corresponding GLSL string. + * Also, return the actual register name and swizzle in case the + * caller needs this information as well. */ +static uint32_t glsl_dst_param_init(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_dst_param *vkd3d_dst, struct glsl_dst_param *glsl_dst) +{ + glsl_dst->mask_str = vkd3d_string_buffer_get(&gen->string_buffers); + glsl_dst->reg_name = vkd3d_string_buffer_get(&gen->string_buffers); + shader_glsl_get_register_name(gen, &vkd3d_dst->reg, vkd3d_dst->reg.data_type, glsl_dst->reg_name, NULL); + return shader_glsl_get_write_mask(vkd3d_dst, glsl_dst->mask_str); +} + +/* Append the destination part of the instruction to the buffer, return the effective write mask */ +static void shader_glsl_append_dst(struct vkd3d_glsl_generator *gen, + struct vkd3d_string_buffer *buffer, + const struct vkd3d_shader_instruction *ins, + struct glsl_dst_param *dst_param) +{ + if (ins->flags & VKD3DSI_PRECISE_XYZW) + vkd3d_string_buffer_printf(dst_param->reg_name, "tmp_precise[%u]", 0); + + switch (ins->dst[0].reg.data_type) + { + case VKD3D_DATA_FLOAT: + vkd3d_string_buffer_printf(buffer, "%s%s = %s(", + dst_param->reg_name->buffer, dst_param->mask_str->buffer, shift_glsl_tab[ins->dst[0].shift]); + break; + default: + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Unhandled data type %#x.", ins->dst[0].reg.data_type); + vkd3d_string_buffer_printf(buffer, "%s%s = %s(", + dst_param->reg_name->buffer, dst_param->mask_str->buffer, shift_glsl_tab[ins->dst[0].shift]); + break; + } +} + +static void VKD3D_PRINTF_FUNC(4, 5) shader_glsl_print_assignment(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_instruction *ins, + struct glsl_dst_param *dst_param, + const char *fmt, ...) +{ + va_list args; + + shader_glsl_append_dst(gen, &gen->buffer, ins, dst_param); + va_start(args, fmt); + vkd3d_string_buffer_vprintf(&gen->buffer, fmt, args); + va_end(args); +} + +static void shader_glsl_cast(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_instruction *ins, + const char *vector_constructor, const char *scalar_constructor) +{ + struct glsl_src_param src_param; + struct glsl_dst_param dst_param; + + unsigned int write_mask = glsl_dst_param_init(gen, &ins->dst[0], &dst_param); + uint32_t mask_size = vkd3d_write_mask_component_count(write_mask); + glsl_src_param_init(gen, &ins->src[0], write_mask, &src_param); + if (mask_size > 1) + shader_glsl_print_assignment(gen, ins, &dst_param, "%s%u(%s));\n", vector_constructor, mask_size, src_param.param_str->buffer); + else + shader_glsl_print_assignment(gen, ins, &dst_param, "%s(%s));\n", scalar_constructor, src_param.param_str->buffer); + + glsl_src_param_cleanup(&src_param, &gen->string_buffers); + glsl_dst_param_cleanup(&dst_param, &gen->string_buffers); +} + +static void shader_glsl_to_float(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_instruction *ins) +{ + shader_glsl_cast(gen, ins, "vec", "float"); +} + static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator, const struct vkd3d_shader_instruction *instruction) { @@ -80,6 +310,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator case VKD3DSIH_DCL_INPUT: case VKD3DSIH_DCL_OUTPUT_SIV: break; + case VKD3DSIH_ITOF: + shader_glsl_to_float(generator, instruction); + break; case VKD3DSIH_RET: shader_glsl_ret(generator, instruction); break; @@ -138,5 +371,6 @@ int vkd3d_glsl_generator_generate(void *parser_data, const uint32_t *parser_ptr, void vkd3d_glsl_generator_destroy(struct vkd3d_glsl_generator *generator) { vkd3d_string_buffer_cleanup(&generator->buffer); + vkd3d_string_buffer_cache_cleanup(&generator->string_buffers); vkd3d_free(generator); }