Signed-off-by: Atharva Nimbalkar atharvakn@gmail.com --- libs/vkd3d-shader/glsl.c | 186 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 180 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d-shader/glsl.c b/libs/vkd3d-shader/glsl.c index 75b7bbc..32458f0 100644 --- a/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d-shader/glsl.c @@ -161,6 +161,30 @@ static bool shader_is_scalar(const struct vkd3d_shader_register *reg) } }
+static void shader_glsl_print_swizzle(uint32_t swizzle, bool fixup, uint32_t mask, + struct vkd3d_string_buffer *str) +{ + /* For registers of type VKD3DDECLTYPE_D3DCOLOR, data is stored as "bgra", + * but addressed as "rgba". To fix this we need to swap the register's x + * and z components. */ + const char *swizzle_chars = fixup ? "zyxw" : "xyzw"; + unsigned int i; + + vkd3d_string_buffer_printf(str, "."); + for (i = 0; i < 4; ++i) + { + if (mask & (VKD3DSP_WRITEMASK_0 << i)) + vkd3d_string_buffer_printf(str, "%c", swizzle_chars[vkd3d_swizzle_get_component(swizzle, i)]); + } +} + +static void shader_glsl_get_swizzle(const struct vkd3d_shader_src_param *param, + bool fixup, uint32_t mask, struct vkd3d_string_buffer *swizzle_str) +{ + if (!shader_is_scalar(¶m->reg)) + shader_glsl_print_swizzle(param->swizzle, fixup, mask, swizzle_str); +} + static void shader_glsl_print_write_mask(uint32_t write_mask, struct vkd3d_string_buffer *str) { vkd3d_string_buffer_printf(str, "."); @@ -204,6 +228,120 @@ static void shader_glsl_get_register_name(struct vkd3d_glsl_generator *gen, "Internal compiler error: Unhandled register type %#x.", reg->type); }
+static void shader_glsl_sprintf_cast(struct vkd3d_glsl_generator *gen, + struct vkd3d_string_buffer *dst_param, const char *src_param, + enum vkd3d_data_type dst_data_type, enum vkd3d_data_type src_data_type, unsigned int size) +{ + if (dst_data_type == VKD3D_DATA_UNORM || dst_data_type == VKD3D_DATA_SNORM) + dst_data_type = VKD3D_DATA_FLOAT; + if (src_data_type == VKD3D_DATA_UNORM || src_data_type == VKD3D_DATA_SNORM) + src_data_type = VKD3D_DATA_FLOAT; + + if (dst_data_type == src_data_type) + { + vkd3d_string_buffer_printf(dst_param, "%s", src_param); + return; + } + + if (src_data_type == VKD3D_DATA_FLOAT) + { + switch (dst_data_type) + { + case VKD3D_DATA_INT: + vkd3d_string_buffer_printf(dst_param, "floatBitsToInt(%s)", src_param); + return; + case VKD3D_DATA_RESOURCE: + case VKD3D_DATA_SAMPLER: + case VKD3D_DATA_UINT: + vkd3d_string_buffer_printf(dst_param, "floatBitsToUint(%s)", src_param); + return; + default: + break; + } + } + + if (src_data_type == VKD3D_DATA_UINT && dst_data_type == VKD3D_DATA_FLOAT) + { + vkd3d_string_buffer_printf(dst_param, "uintBitsToFloat(%s)", src_param); + return; + } + + if (src_data_type == VKD3D_DATA_INT) + { + switch (dst_data_type) + { + case VKD3D_DATA_FLOAT: + vkd3d_string_buffer_printf(dst_param, "intBitsToFloat(%s)", src_param); + return; + case VKD3D_DATA_UINT: + if (size == 1) + vkd3d_string_buffer_printf(dst_param, "uint(%s)", src_param); + else + vkd3d_string_buffer_printf(dst_param, "uvec%u(%s)", size, src_param); + return; + default: + break; + } + } + + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Unhandled cast from %#x to %#x.\n", src_data_type, dst_data_type); + vkd3d_string_buffer_printf(dst_param, "%s", src_param); +} + +/* Generate a GLSL parameter that does the input modifier computation and return the input register/mask to use */ +static void shader_glsl_gen_modifier(struct vkd3d_glsl_generator *gen, + enum vkd3d_shader_src_modifier src_modifier, + const char *in_reg, const struct vkd3d_string_buffer *in_regswizzle, + struct vkd3d_string_buffer *out_str) +{ + switch (src_modifier) + { + case VKD3DSPSM_DZ: /* Need to handle this in the instructions itself (texld & texcrd). */ + case VKD3DSPSM_DW: + case VKD3DSPSM_NONE: + vkd3d_string_buffer_printf(out_str, "%s%s", in_reg, in_regswizzle->buffer); + break; + case VKD3DSPSM_NEG: + vkd3d_string_buffer_printf(out_str, "-%s%s", in_reg, in_regswizzle->buffer); + break; + case VKD3DSPSM_NOT: + vkd3d_string_buffer_printf(out_str, "!%s%s", in_reg, in_regswizzle->buffer); + break; + case VKD3DSPSM_BIAS: + vkd3d_string_buffer_printf(out_str, "(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle->buffer, in_regswizzle->buffer); + break; + case VKD3DSPSM_BIASNEG: + vkd3d_string_buffer_printf(out_str, "-(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle->buffer, in_regswizzle->buffer); + break; + case VKD3DSPSM_SIGN: + vkd3d_string_buffer_printf(out_str, "(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle->buffer); + break; + case VKD3DSPSM_SIGNNEG: + vkd3d_string_buffer_printf(out_str, "-(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle->buffer); + break; + case VKD3DSPSM_COMP: + vkd3d_string_buffer_printf(out_str, "(1.0 - %s%s)", in_reg, in_regswizzle->buffer); + break; + case VKD3DSPSM_X2: + vkd3d_string_buffer_printf(out_str, "(2.0 * %s%s)", in_reg, in_regswizzle->buffer); + break; + case VKD3DSPSM_X2NEG: + vkd3d_string_buffer_printf(out_str, "-(2.0 * %s%s)", in_reg, in_regswizzle->buffer); + break; + case VKD3DSPSM_ABS: + vkd3d_string_buffer_printf(out_str, "abs(%s%s)", in_reg, in_regswizzle->buffer); + break; + case VKD3DSPSM_ABSNEG: + vkd3d_string_buffer_printf(out_str, "-abs(%s%s)", in_reg, in_regswizzle->buffer); + break; + default: + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Unhandled modifier %#x\n", src_modifier); + vkd3d_string_buffer_printf(out_str, "%s%s", in_reg, in_regswizzle->buffer); + } +} + /* 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. */ @@ -211,14 +349,50 @@ 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. - */ + struct vkd3d_string_buffer *param_str = vkd3d_string_buffer_get(&gen->string_buffers); + struct vkd3d_string_buffer *reg_name = vkd3d_string_buffer_get(&gen->string_buffers); + struct vkd3d_string_buffer *swizzle_str = vkd3d_string_buffer_get(&gen->string_buffers); + enum vkd3d_data_type param_data_type; + bool is_color = false; + unsigned int size;
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."); + shader_glsl_get_register_name(gen, &vkd3d_src->reg, data_type, reg_name, &is_color); + shader_glsl_get_swizzle(vkd3d_src, false, mask, swizzle_str); + + switch (vkd3d_src->reg.type) + { + case VKD3DSPR_IMMCONST: + param_data_type = data_type; + size = vkd3d_src->reg.immconst_type == VKD3D_IMMCONST_SCALAR ? 1 : 4; + break; + case VKD3DSPR_FORKINSTID: + case VKD3DSPR_GSINSTID: + case VKD3DSPR_JOININSTID: + case VKD3DSPR_LOCALTHREADINDEX: + case VKD3DSPR_OUTPOINTID: + case VKD3DSPR_PRIMID: + param_data_type = VKD3D_DATA_INT; + size = 1; + break; + case VKD3DSPR_LOCALTHREADID: + case VKD3DSPR_THREADGROUPID: + case VKD3DSPR_THREADID: + param_data_type = VKD3D_DATA_INT; + size = 3; + break; + default: + param_data_type = VKD3D_DATA_FLOAT; + size = 4; + break; + } + + shader_glsl_sprintf_cast(gen, param_str, reg_name->buffer, data_type, param_data_type, size); + shader_glsl_gen_modifier(gen, vkd3d_src->modifiers, param_str->buffer, swizzle_str, glsl_src->param_str); + + vkd3d_string_buffer_release(&gen->string_buffers, swizzle_str); + vkd3d_string_buffer_release(&gen->string_buffers, reg_name); + vkd3d_string_buffer_release(&gen->string_buffers, param_str); }
static void glsl_src_param_init(struct vkd3d_glsl_generator *gen,