[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(¶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);
}
--
2.32.0
More information about the wine-devel
mailing list