From 337a03090868b20f5ccd3540332cbba7c8139113 Mon Sep 17 00:00:00 2001 From: Atharva Nimbalkar Date: Wed, 14 Jul 2021 03:41:32 +0530 Subject: [PATCH] vkd3d-shader/glsl: Implement VKD3DSIH_MOV. --- libs/vkd3d-shader/glsl.c | 174 +++++++++++++++++++++++++++++++++++---- 1 file changed, 157 insertions(+), 17 deletions(-) diff --git a/libs/vkd3d-shader/glsl.c b/libs/vkd3d-shader/glsl.c index a9aafa20..c8d62ce5 100644 --- a/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d-shader/glsl.c @@ -18,10 +18,23 @@ #include "vkd3d_shader_private.h" +struct glsl_src +{ + struct vkd3d_string_buffer *str; +}; + +struct glsl_dst +{ + const struct vkd3d_shader_dst_param *vsir; + struct vkd3d_string_buffer *register_name; + struct vkd3d_string_buffer *mask; +}; + struct vkd3d_glsl_generator { struct vsir_program *program; - struct vkd3d_string_buffer buffer; + struct vkd3d_string_buffer_cache string_buffers; + struct vkd3d_string_buffer *buffer; struct vkd3d_shader_location location; struct vkd3d_shader_message_context *message_context; unsigned int indent; @@ -45,18 +58,140 @@ static void shader_glsl_print_indent(struct vkd3d_string_buffer *buffer, unsigne vkd3d_string_buffer_printf(buffer, "%*s", 4 * indent, ""); } +static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer, + struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_register *reg) +{ + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled register type %#x.", reg->type); + vkd3d_string_buffer_printf(buffer, "", reg->type); +} + +static void shader_glsl_print_swizzle(struct vkd3d_string_buffer *buffer, uint32_t swizzle, uint32_t mask) +{ + const char swizzle_chars[] = "xyzw"; + unsigned int i; + + vkd3d_string_buffer_printf(buffer, "."); + for (i = 0; i < VKD3D_VEC4_SIZE; ++i) + { + if (mask & (VKD3DSP_WRITEMASK_0 << i)) + vkd3d_string_buffer_printf(buffer, "%c", swizzle_chars[vsir_swizzle_get_component(swizzle, i)]); + } +} + +static void shader_glsl_print_write_mask(struct vkd3d_string_buffer *buffer, uint32_t write_mask) +{ + vkd3d_string_buffer_printf(buffer, "."); + if (write_mask & VKD3DSP_WRITEMASK_0) + vkd3d_string_buffer_printf(buffer, "x"); + if (write_mask & VKD3DSP_WRITEMASK_1) + vkd3d_string_buffer_printf(buffer, "y"); + if (write_mask & VKD3DSP_WRITEMASK_2) + vkd3d_string_buffer_printf(buffer, "z"); + if (write_mask & VKD3DSP_WRITEMASK_3) + vkd3d_string_buffer_printf(buffer, "w"); +} + +static void glsl_src_cleanup(struct glsl_src *src, struct vkd3d_string_buffer_cache *cache) +{ + vkd3d_string_buffer_release(cache, src->str); +} + +static void glsl_src_init(struct glsl_src *glsl_src, struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_src_param *vsir_src, uint32_t mask) +{ + const struct vkd3d_shader_register *reg = &vsir_src->reg; + + glsl_src->str = vkd3d_string_buffer_get(&gen->string_buffers); + + if (reg->non_uniform) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled 'non-uniform' modifer."); + if (vsir_src->modifiers) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled source modifier(s) %#x.", vsir_src->modifiers); + + shader_glsl_print_register_name(glsl_src->str, gen, reg); + if (reg->dimension == VSIR_DIMENSION_VEC4) + shader_glsl_print_swizzle(glsl_src->str, vsir_src->swizzle, mask); +} + +static void glsl_dst_cleanup(struct glsl_dst *dst, struct vkd3d_string_buffer_cache *cache) +{ + vkd3d_string_buffer_release(cache, dst->mask); + vkd3d_string_buffer_release(cache, dst->register_name); +} + +static uint32_t glsl_dst_init(struct glsl_dst *glsl_dst, struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_dst_param *vsir_dst) +{ + uint32_t write_mask = vsir_dst->write_mask; + + if (ins->flags & VKD3DSI_PRECISE_XYZW) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled 'precise' modifer."); + if (vsir_dst->reg.non_uniform) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled 'non-uniform' modifer."); + + glsl_dst->vsir = vsir_dst; + glsl_dst->register_name = vkd3d_string_buffer_get(&gen->string_buffers); + glsl_dst->mask = vkd3d_string_buffer_get(&gen->string_buffers); + + shader_glsl_print_register_name(glsl_dst->register_name, gen, &vsir_dst->reg); + shader_glsl_print_write_mask(glsl_dst->mask, write_mask); + + return write_mask; +} + +static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( + struct vkd3d_glsl_generator *gen, struct glsl_dst *dst, const char *format, ...) +{ + va_list args; + + if (dst->vsir->shift) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled destination shift %#x.", dst->vsir->shift); + if (dst->vsir->modifiers) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled destination modifier(s) %#x.", dst->vsir->modifiers); + + shader_glsl_print_indent(gen->buffer, gen->indent); + vkd3d_string_buffer_printf(gen->buffer, "%s%s = ", dst->register_name->buffer, dst->mask->buffer); + + va_start(args, format); + vkd3d_string_buffer_vprintf(gen->buffer, format, args); + va_end(args); + + vkd3d_string_buffer_printf(gen->buffer, ";\n"); +} + static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) { - shader_glsl_print_indent(&gen->buffer, gen->indent); - vkd3d_string_buffer_printf(&gen->buffer, "/* */\n", ins->opcode); + shader_glsl_print_indent(gen->buffer, gen->indent); + vkd3d_string_buffer_printf(gen->buffer, "/* */\n", ins->opcode); vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, "Internal compiler error: Unhandled instruction %#x.", ins->opcode); } -static void shader_glsl_ret(struct vkd3d_glsl_generator *generator, - const struct vkd3d_shader_instruction *ins) +static void shader_glsl_mov(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) { - const struct vkd3d_shader_version *version = &generator->program->shader_version; + struct glsl_src src; + struct glsl_dst dst; + uint32_t mask; + + mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); + glsl_src_init(&src, gen, &ins->src[0], mask); + + shader_glsl_print_assignment(gen, &dst, "%s", src.str->buffer); + + glsl_src_cleanup(&src, &gen->string_buffers); + glsl_dst_cleanup(&dst, &gen->string_buffers); +} + +static void shader_glsl_ret(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) +{ + const struct vkd3d_shader_version *version = &gen->program->shader_version; /* * TODO: Implement in_subroutine @@ -64,28 +199,31 @@ static void shader_glsl_ret(struct vkd3d_glsl_generator *generator, */ if (version->major >= 4) { - shader_glsl_print_indent(&generator->buffer, generator->indent); - vkd3d_string_buffer_printf(&generator->buffer, "return;\n"); + shader_glsl_print_indent(gen->buffer, gen->indent); + vkd3d_string_buffer_printf(gen->buffer, "return;\n"); } } -static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator, - const struct vkd3d_shader_instruction *instruction) +static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_instruction *ins) { - generator->location = instruction->location; + gen->location = ins->location; - switch (instruction->opcode) + switch (ins->opcode) { case VKD3DSIH_DCL_INPUT: case VKD3DSIH_DCL_OUTPUT: case VKD3DSIH_DCL_OUTPUT_SIV: case VKD3DSIH_NOP: break; + case VKD3DSIH_MOV: + shader_glsl_mov(gen, ins); + break; case VKD3DSIH_RET: - shader_glsl_ret(generator, instruction); + shader_glsl_ret(gen, ins); break; default: - shader_glsl_unhandled(generator, instruction); + shader_glsl_unhandled(gen, ins); break; } } @@ -93,7 +231,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator static int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *gen, struct vkd3d_shader_code *out) { const struct vkd3d_shader_instruction_array *instructions = &gen->program->instructions; - struct vkd3d_string_buffer *buffer = &gen->buffer; + struct vkd3d_string_buffer *buffer = gen->buffer; unsigned int i; void *code; @@ -132,7 +270,8 @@ static int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *gen, struc static void vkd3d_glsl_generator_cleanup(struct vkd3d_glsl_generator *gen) { - vkd3d_string_buffer_cleanup(&gen->buffer); + vkd3d_string_buffer_release(&gen->string_buffers, gen->buffer); + vkd3d_string_buffer_cache_cleanup(&gen->string_buffers); } static void vkd3d_glsl_generator_init(struct vkd3d_glsl_generator *gen, @@ -140,7 +279,8 @@ static void vkd3d_glsl_generator_init(struct vkd3d_glsl_generator *gen, { memset(gen, 0, sizeof(*gen)); gen->program = program; - vkd3d_string_buffer_init(&gen->buffer); + vkd3d_string_buffer_cache_init(&gen->string_buffers); + gen->buffer = vkd3d_string_buffer_get(&gen->string_buffers); gen->message_context = message_context; }