Based on vkd3d-proton patches. From: Joshua Ashton joshua@froggi.es
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/dxbc.c | 15 +++-- libs/vkd3d-shader/spirv.c | 75 +++++++++++++++++++----- libs/vkd3d-shader/trace.c | 43 +++++++++++++- libs/vkd3d-shader/vkd3d_shader_private.h | 4 ++ 4 files changed, 116 insertions(+), 21 deletions(-)
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index cd90354a..782aed13 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -329,6 +329,7 @@ enum vkd3d_sm4_register_type VKD3D_SM4_RT_OUTPUT = 0x02, VKD3D_SM4_RT_INDEXABLE_TEMP = 0x03, VKD3D_SM4_RT_IMMCONST = 0x04, + VKD3D_SM4_RT_IMMCONST64 = 0x05, VKD3D_SM4_RT_SAMPLER = 0x06, VKD3D_SM4_RT_RESOURCE = 0x07, VKD3D_SM4_RT_CONSTBUFFER = 0x08, @@ -1244,7 +1245,7 @@ static const enum vkd3d_shader_register_type register_type_table[] = /* VKD3D_SM4_RT_OUTPUT */ VKD3DSPR_OUTPUT, /* VKD3D_SM4_RT_INDEXABLE_TEMP */ VKD3DSPR_IDXTEMP, /* VKD3D_SM4_RT_IMMCONST */ VKD3DSPR_IMMCONST, - /* UNKNOWN */ ~0u, + /* VKD3D_SM4_RT_IMMCONST64 */ VKD3DSPR_IMMCONST64, /* VKD3D_SM4_RT_SAMPLER */ VKD3DSPR_SAMPLER, /* VKD3D_SM4_RT_RESOURCE */ VKD3DSPR_RESOURCE, /* VKD3D_SM4_RT_CONSTBUFFER */ VKD3DSPR_CONSTBUFFER, @@ -1618,21 +1619,23 @@ static bool shader_sm4_read_param(struct vkd3d_sm4_data *priv, const DWORD **ptr return false; }
- if (register_type == VKD3D_SM4_RT_IMMCONST) + if (register_type == VKD3D_SM4_RT_IMMCONST || register_type == VKD3D_SM4_RT_IMMCONST64) { enum vkd3d_sm4_dimension dimension = (token & VKD3D_SM4_DIMENSION_MASK) >> VKD3D_SM4_DIMENSION_SHIFT; + unsigned int dword_count;
switch (dimension) { case VKD3D_SM4_DIMENSION_SCALAR: param->immconst_type = VKD3D_IMMCONST_SCALAR; - if (end - *ptr < 1) + dword_count = 1 + (register_type == VKD3D_SM4_RT_IMMCONST64); + if (end - *ptr < dword_count) { WARN("Invalid ptr %p, end %p.\n", *ptr, end); return false; } - memcpy(param->u.immconst_uint, *ptr, 1 * sizeof(DWORD)); - *ptr += 1; + memcpy(param->u.immconst_uint, *ptr, dword_count * sizeof(DWORD)); + *ptr += dword_count; break;
case VKD3D_SM4_DIMENSION_VEC4: @@ -1707,7 +1710,7 @@ static bool shader_sm4_read_src_param(struct vkd3d_sm4_data *priv, const DWORD * return false; }
- if (src_param->reg.type == VKD3DSPR_IMMCONST) + if (src_param->reg.type == VKD3DSPR_IMMCONST || src_param->reg.type == VKD3DSPR_IMMCONST64) { src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE; } diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index ca523cb5..bdbd688d 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1118,19 +1118,18 @@ static uint32_t vkd3d_spirv_get_op_type_pointer(struct vkd3d_spirv_builder *buil vkd3d_spirv_build_op_type_pointer); }
-/* Types larger than 32-bits are not supported. */ static uint32_t vkd3d_spirv_build_op_constant(struct vkd3d_spirv_builder *builder, - uint32_t result_type, uint32_t value) + uint32_t result_type, const uint32_t *values, unsigned int value_count) { - return vkd3d_spirv_build_op_tr1(builder, &builder->global_stream, - SpvOpConstant, result_type, value); + return vkd3d_spirv_build_op_trv(builder, &builder->global_stream, + SpvOpConstant, result_type, values, value_count); }
static uint32_t vkd3d_spirv_get_op_constant(struct vkd3d_spirv_builder *builder, - uint32_t result_type, uint32_t value) + uint32_t result_type, const uint32_t *values, unsigned int value_count) { - return vkd3d_spirv_build_once2(builder, SpvOpConstant, result_type, value, - vkd3d_spirv_build_op_constant); + return vkd3d_spirv_build_once1v(builder, SpvOpConstant, result_type, values, + value_count, vkd3d_spirv_build_op_constant); }
static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_builder *builder, @@ -2608,18 +2607,35 @@ static void vkd3d_dxbc_compiler_put_symbol(struct vkd3d_dxbc_compiler *compiler, } }
+static unsigned int vkd3d_spirv_get_component_value_count(enum vkd3d_shader_component_type component_type) +{ + switch (component_type) + { + case VKD3D_SHADER_COMPONENT_UINT: + case VKD3D_SHADER_COMPONENT_INT: + case VKD3D_SHADER_COMPONENT_FLOAT: + return 1; + case VKD3D_SHADER_COMPONENT_DOUBLE: + return 2; + default: + ERR("Invalid shader component type %u.\n", component_type); + return 1; + } +} + static uint32_t vkd3d_dxbc_compiler_get_constant(struct vkd3d_dxbc_compiler *compiler, enum vkd3d_shader_component_type component_type, unsigned int component_count, const uint32_t *values) { uint32_t type_id, scalar_type_id, component_ids[VKD3D_VEC4_SIZE]; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - unsigned int i; + unsigned int i, value_count;
assert(0 < component_count && component_count <= VKD3D_VEC4_SIZE); type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
switch (component_type) { + case VKD3D_SHADER_COMPONENT_DOUBLE: case VKD3D_SHADER_COMPONENT_UINT: case VKD3D_SHADER_COMPONENT_INT: case VKD3D_SHADER_COMPONENT_FLOAT: @@ -2629,15 +2645,17 @@ static uint32_t vkd3d_dxbc_compiler_get_constant(struct vkd3d_dxbc_compiler *com return vkd3d_spirv_build_op_undef(builder, &builder->global_stream, type_id); }
+ value_count = vkd3d_spirv_get_component_value_count(component_type); + if (component_count == 1) { - return vkd3d_spirv_get_op_constant(builder, type_id, *values); + return vkd3d_spirv_get_op_constant(builder, type_id, values, value_count); } else { scalar_type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); for (i = 0; i < component_count; ++i) - component_ids[i] = vkd3d_spirv_get_op_constant(builder, scalar_type_id, values[i]); + component_ids[i] = vkd3d_spirv_get_op_constant(builder, scalar_type_id, &values[i * value_count], value_count); return vkd3d_spirv_get_op_constant_composite(builder, type_id, component_ids, component_count); } } @@ -3011,7 +3029,7 @@ static bool vkd3d_dxbc_compiler_get_register_info(const struct vkd3d_dxbc_compil struct vkd3d_symbol reg_symbol, *symbol; struct rb_entry *entry;
- assert(reg->type != VKD3DSPR_IMMCONST); + assert(reg->type != VKD3DSPR_IMMCONST && reg->type != VKD3DSPR_IMMCONST64);
if (reg->type == VKD3DSPR_TEMP) { @@ -3255,6 +3273,33 @@ static uint32_t vkd3d_dxbc_compiler_emit_load_constant(struct vkd3d_dxbc_compile vkd3d_component_type_from_data_type(reg->data_type), component_count, values); }
+static uint32_t vkd3d_dxbc_compiler_emit_load_constant64(struct vkd3d_dxbc_compiler *compiler, + const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask) +{ + unsigned int component_count = vkd3d_write_mask_component_count_typed(write_mask, VKD3D_DATA_DOUBLE); + uint64_t values[2] = {0}; + unsigned int i, j; + + assert(reg->type == VKD3DSPR_IMMCONST64); + + if (reg->immconst_type == VKD3D_IMMCONST_SCALAR) + { + for (i = 0; i < component_count; ++i) + values[i] = reg->u.immconst_uint64[0]; + } + else + { + for (i = 0, j = 0; i < VKD3D_DVEC2_SIZE; ++i) + { + if (write_mask & (VKD3DSP_WRITEMASK_0 << (i * 2))) + values[j++] = reg->u.immconst_uint64[vkd3d_swizzle_get_component(swizzle, i * 2) / 2u]; + } + } + + return vkd3d_dxbc_compiler_get_constant(compiler, + vkd3d_component_type_from_data_type(reg->data_type), component_count, (const uint32_t*)values); +} + static uint32_t vkd3d_dxbc_compiler_emit_load_scalar(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask, const struct vkd3d_shader_register_info *reg_info) @@ -3265,7 +3310,7 @@ static uint32_t vkd3d_dxbc_compiler_emit_load_scalar(struct vkd3d_dxbc_compiler enum vkd3d_shader_component_type component_type; unsigned int skipped_component_mask;
- assert(reg->type != VKD3DSPR_IMMCONST); + assert(reg->type != VKD3DSPR_IMMCONST && reg->type != VKD3DSPR_IMMCONST64); assert(vkd3d_write_mask_component_count(write_mask) == 1);
component_idx = vkd3d_write_mask_get_component_idx(write_mask); @@ -3314,6 +3359,8 @@ static uint32_t vkd3d_dxbc_compiler_emit_load_reg(struct vkd3d_dxbc_compiler *co
if (reg->type == VKD3DSPR_IMMCONST) return vkd3d_dxbc_compiler_emit_load_constant(compiler, reg, swizzle, write_mask); + else if (reg->type == VKD3DSPR_IMMCONST64) + return vkd3d_dxbc_compiler_emit_load_constant64(compiler, reg, swizzle, write_mask);
component_count = vkd3d_write_mask_component_count(write_mask); component_type = vkd3d_component_type_from_data_type(reg->data_type); @@ -3526,7 +3573,7 @@ static void vkd3d_dxbc_compiler_emit_store_reg(struct vkd3d_dxbc_compiler *compi struct vkd3d_shader_register_info reg_info; uint32_t type_id;
- assert(reg->type != VKD3DSPR_IMMCONST); + assert(reg->type != VKD3DSPR_IMMCONST && reg->type != VKD3DSPR_IMMCONST64);
if (!vkd3d_dxbc_compiler_get_register_info(compiler, reg, ®_info)) return; @@ -6637,7 +6684,7 @@ static void vkd3d_dxbc_compiler_emit_mov(struct vkd3d_dxbc_compiler *compiler, uint32_t components[VKD3D_VEC4_SIZE]; unsigned int i, component_count;
- if (src->reg.type == VKD3DSPR_IMMCONST || dst->modifiers || src->modifiers) + if (src->reg.type == VKD3DSPR_IMMCONST || src->reg.type == VKD3DSPR_IMMCONST64 || dst->modifiers || src->modifiers) goto general_implementation;
vkd3d_dxbc_compiler_get_register_info(compiler, &dst->reg, &dst_reg_info); diff --git a/libs/vkd3d-shader/trace.c b/libs/vkd3d-shader/trace.c index 4e355118..859c428c 100644 --- a/libs/vkd3d-shader/trace.c +++ b/libs/vkd3d-shader/trace.c @@ -869,6 +869,10 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const shader_addline(buffer, "l"); break;
+ case VKD3DSPR_IMMCONST64: + shader_addline(buffer, "d"); + break; + case VKD3DSPR_CONSTBUFFER: shader_addline(buffer, "cb"); break; @@ -1038,6 +1042,42 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const } shader_addline(buffer, ")"); } + else if (reg->type == VKD3DSPR_IMMCONST64) + { + shader_addline(buffer, "("); + switch (reg->immconst_type) + { + case VKD3D_IMMCONST_SCALAR: + switch (reg->data_type) + { + case VKD3D_DATA_DOUBLE: + shader_addline(buffer, "%f", reg->u.immconst_double[0]); + break; + default: + shader_addline(buffer, "<unhandled data type %#x>", reg->data_type); + break; + } + break; + + case VKD3D_IMMCONST_VEC4: + switch (reg->data_type) + { + case VKD3D_DATA_DOUBLE: + shader_addline(buffer, "%f, %f", + reg->u.immconst_double[0], reg->u.immconst_double[1]); + break; + default: + shader_addline(buffer, "<unhandled data type %#x>", reg->data_type); + break; + } + break; + + default: + shader_addline(buffer, "<unhandled immconst_type %#x>", reg->immconst_type); + break; + } + shader_addline(buffer, ")"); + } else if (reg->type != VKD3DSPR_RASTOUT && reg->type != VKD3DSPR_MISCTYPE && reg->type != VKD3DSPR_NULL) @@ -1148,7 +1188,8 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, default: shader_addline(buffer, "_unknown_modifier(%#x)", src_modifier); }
- if (param->reg.type != VKD3DSPR_IMMCONST && param->reg.type != VKD3DSPR_SAMPLER) + if (param->reg.type != VKD3DSPR_IMMCONST && param->reg.type != VKD3DSPR_IMMCONST64 + && param->reg.type != VKD3DSPR_SAMPLER) { static const char swizzle_chars[] = "xyzw"; DWORD swizzle_x = (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(0)) & VKD3D_SHADER_SWIZZLE_MASK; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 03bc2e1b..f56ca183 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -58,6 +58,7 @@ #include <string.h>
#define VKD3D_VEC4_SIZE 4 +#define VKD3D_DVEC2_SIZE 2
enum vkd3d_shader_error { @@ -381,6 +382,7 @@ enum vkd3d_shader_register_type VKD3DSPR_LABEL = 18, VKD3DSPR_PREDICATE = 19, VKD3DSPR_IMMCONST, + VKD3DSPR_IMMCONST64, VKD3DSPR_CONSTBUFFER, VKD3DSPR_IMMCONSTBUFFER, VKD3DSPR_PRIMID, @@ -611,6 +613,8 @@ struct vkd3d_shader_register { DWORD immconst_uint[VKD3D_VEC4_SIZE]; float immconst_float[VKD3D_VEC4_SIZE]; + uint64_t immconst_uint64[VKD3D_DVEC2_SIZE]; + double immconst_double[VKD3D_DVEC2_SIZE]; unsigned fp_body_idx; } u; };