[PATCH vkd3d 6/8] vkd3d-shader/glsl: Implement VKD3DSIH_ITOF.

Atharva Nimbalkar atharvakn at gmail.com
Tue Aug 17 23:19:19 CDT 2021


Signed-off-by: Atharva Nimbalkar <atharvakn at 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(&param->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);
 }
-- 
2.32.0




More information about the wine-devel mailing list