wine-staging/patches/vkd3d-latest/0005-Updated-vkd3d-to-ae27fded1a039fda84b526cd9bd7b64aeb5.patch

1978 lines
83 KiB
Diff
Raw Normal View History

2024-10-02 19:53:56 -07:00
From 10e8e5d62381bc132ac64fd9a5a7f1e39b3c843b Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Thu, 3 Oct 2024 10:05:51 +1000
Subject: [PATCH] Updated vkd3d to ae27fded1a039fda84b526cd9bd7b64aeb5573b5.
---
libs/vkd3d/include/vkd3d_shader.h | 78 ++++-
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 37 ++-
libs/vkd3d/libs/vkd3d-shader/fx.c | 172 ++++++++---
libs/vkd3d/libs/vkd3d-shader/glsl.c | 75 ++++-
libs/vkd3d/libs/vkd3d-shader/hlsl.c | 106 ++++++-
libs/vkd3d/libs/vkd3d-shader/hlsl.h | 24 +-
libs/vkd3d/libs/vkd3d-shader/hlsl.y | 146 +++++----
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 32 +-
libs/vkd3d/libs/vkd3d-shader/ir.c | 281 +++++++++++++++++-
libs/vkd3d/libs/vkd3d-shader/spirv.c | 131 +++++---
libs/vkd3d/libs/vkd3d-shader/tpf.c | 47 ++-
.../libs/vkd3d-shader/vkd3d_shader_private.h | 3 +
12 files changed, 945 insertions(+), 187 deletions(-)
diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h
index 115bb21b932..d08ee74a3a0 100644
--- a/libs/vkd3d/include/vkd3d_shader.h
+++ b/libs/vkd3d/include/vkd3d_shader.h
@@ -480,8 +480,8 @@ enum vkd3d_shader_parameter_type
/** The parameter value is embedded directly in the shader. */
VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT,
/**
- * The parameter value is provided to the shader via a specialization
- * constant. This value is only supported for the SPIR-V target type.
+ * The parameter value is provided to the shader via specialization
+ * constants. This value is only supported for the SPIR-V target type.
*/
VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT,
/**
@@ -506,6 +506,13 @@ enum vkd3d_shader_parameter_data_type
VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32,
/** The parameter is provided as a 32-bit float. \since 1.13 */
VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32,
+ /**
+ * The parameter is provided as a 4-dimensional vector of 32-bit floats.
+ * This parameter must be used with struct vkd3d_shader_parameter1;
+ * it cannot be used with struct vkd3d_shader_parameter.
+ * \since 1.14
+ */
+ VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_DATA_TYPE),
};
@@ -589,6 +596,58 @@ enum vkd3d_shader_parameter_name
* \since 1.13
*/
VKD3D_SHADER_PARAMETER_NAME_FLAT_INTERPOLATION,
+ /**
+ * A mask of enabled clip planes.
+ *
+ * When this parameter is provided to a vertex shader, for each nonzero bit
+ * of this mask, a user clip distance will be generated from vertex position
+ * in clip space, and the clip plane defined by the indexed vector, taken
+ * from the VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_# parameter.
+ *
+ * Regardless of the specific clip planes which are enabled, the clip
+ * distances which are output are a contiguous array starting from clip
+ * distance 0. This affects the interface of OpenGL. For example, if only
+ * clip planes 1 and 3 are enabled (and so the value of the mask is 0xa),
+ * the user should enable only GL_CLIP_DISTANCE0 and GL_CLIP_DISTANCE1.
+ *
+ * The default value is zero, i.e. do not enable any clip planes.
+ *
+ * The data type for this parameter must be
+ * VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32.
+ *
+ * Only VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT is supported in this
+ * version of vkd3d-shader.
+ *
+ * If the source shader writes clip distances and this parameter is nonzero,
+ * compilation fails.
+ *
+ * \since 1.14
+ */
+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK,
+ /**
+ * Clip plane values.
+ * See VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK for documentation of
+ * clip planes.
+ *
+ * These enum values are contiguous and arithmetic may safely be performed
+ * on them. That is, VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_[n] is
+ * VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0 plus n.
+ *
+ * The data type for each parameter must be
+ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4.
+ *
+ * The default value for each plane is a (0, 0, 0, 0) vector.
+ *
+ * \since 1.14
+ */
+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0,
+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_1,
+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_2,
+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_3,
+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_4,
+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_5,
+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_6,
+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_7,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME),
};
@@ -636,6 +695,13 @@ struct vkd3d_shader_parameter_immediate_constant1
* VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32.
*/
float f32;
+ /**
+ * A pointer to the value if the parameter's data type is
+ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4.
+ *
+ * \since 1.14
+ */
+ float f32_vec4[4];
void *_pointer_pad;
uint32_t _pad[4];
} u;
@@ -647,7 +713,13 @@ struct vkd3d_shader_parameter_immediate_constant1
*/
struct vkd3d_shader_parameter_specialization_constant
{
- /** The ID of the specialization constant. */
+ /**
+ * The ID of the specialization constant.
+ * If the type comprises more than one constant, such as
+ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4, then a contiguous
+ * array of specialization constants should be used, one for each component,
+ * and this ID should point to the first component.
+ */
uint32_t id;
};
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
index 763d52e1b62..267cf410cbe 100644
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
@@ -457,17 +457,36 @@ static uint32_t swizzle_from_sm1(uint32_t swizzle)
shader_sm1_get_swizzle_component(swizzle, 3));
}
+/* D3DBC doesn't have the concept of index count. All registers implicitly have
+ * exactly one index. However for some register types the index doesn't make
+ * sense, so we remove it. */
+static unsigned int idx_count_from_reg_type(enum vkd3d_shader_register_type reg_type)
+{
+ switch (reg_type)
+ {
+ case VKD3DSPR_DEPTHOUT:
+ return 0;
+
+ default:
+ return 1;
+ }
+}
+
static void shader_sm1_parse_src_param(uint32_t param, struct vkd3d_shader_src_param *rel_addr,
struct vkd3d_shader_src_param *src)
{
enum vkd3d_shader_register_type reg_type = ((param & VKD3D_SM1_REGISTER_TYPE_MASK) >> VKD3D_SM1_REGISTER_TYPE_SHIFT)
| ((param & VKD3D_SM1_REGISTER_TYPE_MASK2) >> VKD3D_SM1_REGISTER_TYPE_SHIFT2);
+ unsigned int idx_count = idx_count_from_reg_type(reg_type);
- vsir_register_init(&src->reg, reg_type, VKD3D_DATA_FLOAT, 1);
+ vsir_register_init(&src->reg, reg_type, VKD3D_DATA_FLOAT, idx_count);
src->reg.precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT;
src->reg.non_uniform = false;
- src->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK;
- src->reg.idx[0].rel_addr = rel_addr;
+ if (idx_count == 1)
+ {
+ src->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK;
+ src->reg.idx[0].rel_addr = rel_addr;
+ }
if (src->reg.type == VKD3DSPR_SAMPLER)
src->reg.dimension = VSIR_DIMENSION_NONE;
else if (src->reg.type == VKD3DSPR_DEPTHOUT)
@@ -483,12 +502,16 @@ static void shader_sm1_parse_dst_param(uint32_t param, struct vkd3d_shader_src_p
{
enum vkd3d_shader_register_type reg_type = ((param & VKD3D_SM1_REGISTER_TYPE_MASK) >> VKD3D_SM1_REGISTER_TYPE_SHIFT)
| ((param & VKD3D_SM1_REGISTER_TYPE_MASK2) >> VKD3D_SM1_REGISTER_TYPE_SHIFT2);
+ unsigned int idx_count = idx_count_from_reg_type(reg_type);
- vsir_register_init(&dst->reg, reg_type, VKD3D_DATA_FLOAT, 1);
+ vsir_register_init(&dst->reg, reg_type, VKD3D_DATA_FLOAT, idx_count);
dst->reg.precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT;
dst->reg.non_uniform = false;
- dst->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK;
- dst->reg.idx[0].rel_addr = rel_addr;
+ if (idx_count == 1)
+ {
+ dst->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK;
+ dst->reg.idx[0].rel_addr = rel_addr;
+ }
if (dst->reg.type == VKD3DSPR_SAMPLER)
dst->reg.dimension = VSIR_DIMENSION_NONE;
else if (dst->reg.type == VKD3DSPR_DEPTHOUT)
@@ -614,7 +637,7 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *
const struct vkd3d_shader_register *reg, bool is_dcl, unsigned int mask)
{
const struct vkd3d_shader_version *version = &sm1->p.program->shader_version;
- unsigned int register_index = reg->idx[0].offset;
+ unsigned int register_index = reg->idx_count > 0 ? reg->idx[0].offset : 0;
switch (reg->type)
{
diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c
index 84e827e7943..cc18857a010 100644
--- a/libs/vkd3d/libs/vkd3d-shader/fx.c
+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c
@@ -182,6 +182,7 @@ struct fx_write_context
struct vkd3d_bytecode_buffer unstructured;
struct vkd3d_bytecode_buffer structured;
+ struct vkd3d_bytecode_buffer objects;
struct rb_tree strings;
struct list types;
@@ -1072,19 +1073,63 @@ static uint32_t write_fx_2_default_value(struct hlsl_type *value_type, struct hl
return offset;
}
-static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct fx_write_context *fx)
+static uint32_t write_fx_2_object_initializer(const struct hlsl_ir_var *var, struct fx_write_context *fx)
{
- struct vkd3d_bytecode_buffer *buffer = &fx->unstructured;
- const struct hlsl_type *type = var->data_type;
- uint32_t offset, elements_count = 1;
+ const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type);
+ unsigned int i, elements_count = hlsl_get_multiarray_size(var->data_type);
+ struct vkd3d_bytecode_buffer *buffer = &fx->objects;
+ uint32_t offset = fx->unstructured.size, id, size;
struct hlsl_ctx *ctx = fx->ctx;
+ const void *data;
- if (type->class == HLSL_CLASS_ARRAY)
+ for (i = 0; i < elements_count; ++i)
{
- elements_count = hlsl_get_multiarray_size(type);
- type = hlsl_get_multiarray_element_type(type);
+ if (type->class == HLSL_CLASS_SAMPLER)
+ {
+ hlsl_fixme(ctx, &var->loc, "Writing fx_2_0 sampler objects initializers is not implemented.");
+ }
+ else
+ {
+ switch (type->class)
+ {
+ case HLSL_CLASS_STRING:
+ {
+ const char *string = var->default_values[i].string ? var->default_values[i].string : "";
+ size = strlen(string) + 1;
+ data = string;
+ break;
+ }
+ case HLSL_CLASS_TEXTURE:
+ size = 0;
+ break;
+ case HLSL_CLASS_PIXEL_SHADER:
+ case HLSL_CLASS_VERTEX_SHADER:
+ size = 0;
+ hlsl_fixme(ctx, &var->loc, "Writing fx_2_0 shader objects initializers is not implemented.");
+ break;
+ default:
+ vkd3d_unreachable();
+ }
+ id = fx->object_variable_count++;
+
+ put_u32(&fx->unstructured, id);
+
+ put_u32(buffer, id);
+ put_u32(buffer, size);
+ if (size)
+ bytecode_put_bytes(buffer, data, size);
+ }
}
+ return offset;
+}
+
+static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct fx_write_context *fx)
+{
+ const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type);
+ struct hlsl_ctx *ctx = fx->ctx;
+ uint32_t offset;
+
/* Note that struct fields must all be numeric;
* this was validated in check_invalid_object_fields(). */
switch (type->class)
@@ -1096,19 +1141,17 @@ static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct f
offset = write_fx_2_default_value(var->data_type, var->default_values, fx);
break;
- case HLSL_CLASS_TEXTURE:
- case HLSL_CLASS_PIXEL_SHADER:
case HLSL_CLASS_SAMPLER:
+ case HLSL_CLASS_TEXTURE:
case HLSL_CLASS_STRING:
+ case HLSL_CLASS_PIXEL_SHADER:
case HLSL_CLASS_VERTEX_SHADER:
- hlsl_fixme(ctx, &var->loc, "Write fx 2.0 object initializer.");
- /* fallthrough */
+ offset = write_fx_2_object_initializer(var, fx);
+ break;
default:
- /* Objects are given sequential ids. */
- offset = put_u32(buffer, fx->object_variable_count++);
- for (uint32_t i = 1; i < elements_count; ++i)
- put_u32(buffer, fx->object_variable_count++);
+ offset = 0;
+ hlsl_fixme(ctx, &var->loc, "Writing initializer not implemented for parameter class %#x.", type->class);
break;
}
@@ -1134,6 +1177,7 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type
return is_type_supported_fx_2(ctx, type->e.array.type, loc);
case HLSL_CLASS_TEXTURE:
+ case HLSL_CLASS_SAMPLER:
switch (type->sampler_dim)
{
case HLSL_SAMPLER_DIM_1D:
@@ -1147,9 +1191,10 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type
}
break;
- case HLSL_CLASS_PIXEL_SHADER:
- case HLSL_CLASS_SAMPLER:
case HLSL_CLASS_STRING:
+ return true;
+
+ case HLSL_CLASS_PIXEL_SHADER:
case HLSL_CLASS_VERTEX_SHADER:
hlsl_fixme(ctx, loc, "Write fx 2.0 parameter class %#x.", type->class);
return false;
@@ -1257,19 +1302,18 @@ static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
object_count = put_u32(structured, 0);
write_fx_2_parameters(&fx);
- set_u32(structured, parameter_count, fx.parameter_count);
- set_u32(structured, object_count, fx.object_variable_count);
-
write_techniques(ctx->globals, &fx);
- set_u32(structured, technique_count, fx.technique_count);
- set_u32(structured, shader_count, fx.shader_count);
-
- put_u32(structured, 0); /* String count */
+ put_u32(structured, fx.object_variable_count - 1);
put_u32(structured, 0); /* Resource count */
- /* TODO: strings */
+ bytecode_put_bytes(structured, fx.objects.data, fx.objects.size);
/* TODO: resources */
+ set_u32(structured, parameter_count, fx.parameter_count);
+ set_u32(structured, object_count, fx.object_variable_count);
+ set_u32(structured, technique_count, fx.technique_count);
+ set_u32(structured, shader_count, fx.shader_count);
+
size = align(fx.unstructured.size, 4);
set_u32(&buffer, offset, size);
@@ -1278,6 +1322,7 @@ static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
vkd3d_free(fx.unstructured.data);
vkd3d_free(fx.structured.data);
+ vkd3d_free(fx.objects.data);
if (!fx.technique_count)
hlsl_error(ctx, &ctx->location, VKD3D_SHADER_ERROR_HLSL_MISSING_TECHNIQUE, "No techniques found.");
@@ -1516,11 +1561,14 @@ static uint32_t write_fx_4_state_numeric_value(struct hlsl_ir_constant *value, s
static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hlsl_state_block_entry *entry,
struct fx_write_context *fx)
{
- uint32_t value_offset = 0, assignment_type = 0, rhs_offset;
- uint32_t type_offset;
+ uint32_t value_offset = 0, assignment_type = 0, rhs_offset, type_offset, offset;
+ struct vkd3d_bytecode_buffer *unstructured = &fx->unstructured;
struct vkd3d_bytecode_buffer *buffer = &fx->structured;
- struct hlsl_ctx *ctx = fx->ctx;
struct hlsl_ir_node *value = entry->args->node;
+ struct hlsl_ctx *ctx = fx->ctx;
+ struct hlsl_ir_var *index_var;
+ struct hlsl_ir_constant *c;
+ struct hlsl_ir_load *load;
put_u32(buffer, entry->name_id);
put_u32(buffer, entry->lhs_index);
@@ -1531,7 +1579,7 @@ static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hl
{
case HLSL_IR_CONSTANT:
{
- struct hlsl_ir_constant *c = hlsl_ir_constant(value);
+ c = hlsl_ir_constant(value);
value_offset = write_fx_4_state_numeric_value(c, fx);
assignment_type = 1;
@@ -1539,15 +1587,71 @@ static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hl
}
case HLSL_IR_LOAD:
{
- struct hlsl_ir_load *l = hlsl_ir_load(value);
+ load = hlsl_ir_load(value);
- if (l->src.path_len)
+ if (load->src.path_len)
hlsl_fixme(ctx, &var->loc, "Indexed access in RHS values is not implemented.");
- value_offset = write_fx_4_string(l->src.var->name, fx);
+ value_offset = write_fx_4_string(load->src.var->name, fx);
assignment_type = 2;
break;
}
+ case HLSL_IR_INDEX:
+ {
+ struct hlsl_ir_index *index = hlsl_ir_index(value);
+ struct hlsl_ir_node *val = index->val.node;
+ struct hlsl_ir_node *idx = index->idx.node;
+ struct hlsl_type *type;
+
+ if (val->type != HLSL_IR_LOAD)
+ {
+ hlsl_fixme(ctx, &var->loc, "Unexpected indexed RHS value type.");
+ break;
+ }
+
+ load = hlsl_ir_load(val);
+ value_offset = write_fx_4_string(load->src.var->name, fx);
+ type = load->src.var->data_type;
+
+ switch (idx->type)
+ {
+ case HLSL_IR_CONSTANT:
+ {
+ c = hlsl_ir_constant(idx);
+ value_offset = put_u32(unstructured, value_offset);
+ put_u32(unstructured, c->value.u[0].u);
+ assignment_type = 3;
+
+ if (c->value.u[0].u >= type->e.array.elements_count)
+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS,
+ "Array index %u exceeds array size %u.", c->value.u[0].u, type->e.array.elements_count);
+ break;
+ }
+
+ case HLSL_IR_LOAD:
+ {
+ load = hlsl_ir_load(idx);
+ index_var = load->src.var;
+
+ /* Special case for uint index variables, for anything more complex use an expression. */
+ if (hlsl_types_are_equal(index_var->data_type, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT))
+ && !load->src.path_len)
+ {
+ offset = write_fx_4_string(index_var->name, fx);
+
+ value_offset = put_u32(unstructured, value_offset);
+ put_u32(unstructured, offset);
+ assignment_type = 4;
+ break;
+ }
+ }
+ /* fall through */
+
+ default:
+ hlsl_fixme(ctx, &var->loc, "Complex array index expressions in RHS values are not implemented.");
+ }
+ break;
+ }
default:
hlsl_fixme(ctx, &var->loc, "Unsupported assignment type for state %s.", entry->name);
}
@@ -2196,7 +2300,7 @@ static unsigned int decompose_fx_4_state_function_call(struct hlsl_ir_var *var,
const struct function_component *comp = &components[i];
unsigned int arg_index = (i + 1) % entry->args_count;
block->entries[entry_index + i] = clone_stateblock_entry(ctx, entry, comp->name,
- comp->lhs_has_index, comp->lhs_index, arg_index);
+ comp->lhs_has_index, comp->lhs_index, true, arg_index);
}
hlsl_free_state_block_entry(entry);
@@ -2242,7 +2346,7 @@ static unsigned int decompose_fx_4_state_block_expand_array(struct hlsl_ir_var *
for (i = 1; i < array_size; ++i)
{
block->entries[entry_index + i] = clone_stateblock_entry(ctx, entry,
- entry->name, true, i, 0);
+ entry->name, true, i, true, 0);
}
return array_size;
diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c
index 26fd4818970..e2bcca56f05 100644
--- a/libs/vkd3d/libs/vkd3d-shader/glsl.c
+++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c
@@ -365,18 +365,21 @@ static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment(
{
const struct vkd3d_shader_register *dst_reg = &dst->vsir->reg;
struct vkd3d_string_buffer *buffer = gen->buffer;
+ uint32_t modifiers = dst->vsir->modifiers;
bool close = true;
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)
+ if (modifiers & ~VKD3DSPDM_SATURATE)
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
- "Internal compiler error: Unhandled destination modifier(s) %#x.", dst->vsir->modifiers);
+ "Internal compiler error: Unhandled destination modifier(s) %#x.", modifiers);
shader_glsl_print_indent(buffer, gen->indent);
vkd3d_string_buffer_printf(buffer, "%s%s = ", dst->register_name->buffer, dst->mask->buffer);
+ if (modifiers & VKD3DSPDM_SATURATE)
+ vkd3d_string_buffer_printf(buffer, "clamp(");
switch (dst_reg->data_type)
{
@@ -399,7 +402,11 @@ static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment(
vkd3d_string_buffer_vprintf(buffer, format, args);
va_end(args);
- vkd3d_string_buffer_printf(buffer, "%s;\n", close ? ")" : "");
+ if (close)
+ vkd3d_string_buffer_printf(buffer, ")");
+ if (modifiers & VKD3DSPDM_SATURATE)
+ vkd3d_string_buffer_printf(buffer, ", 0.0, 1.0)");
+ vkd3d_string_buffer_printf(buffer, ";\n");
}
static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins)
@@ -455,16 +462,24 @@ static void shader_glsl_dot(struct vkd3d_glsl_generator *gen,
static void shader_glsl_intrinsic(struct vkd3d_glsl_generator *gen,
const struct vkd3d_shader_instruction *ins, const char *op)
{
+ struct vkd3d_string_buffer *args;
struct glsl_src src;
struct glsl_dst dst;
+ unsigned int i;
uint32_t mask;
mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]);
- glsl_src_init(&src, gen, &ins->src[0], mask);
+ args = vkd3d_string_buffer_get(&gen->string_buffers);
- shader_glsl_print_assignment(gen, &dst, "%s(%s)", op, src.str->buffer);
+ for (i = 0; i < ins->src_count; ++i)
+ {
+ glsl_src_init(&src, gen, &ins->src[i], mask);
+ vkd3d_string_buffer_printf(args, "%s%s", i ? ", " : "", src.str->buffer);
+ glsl_src_cleanup(&src, &gen->string_buffers);
+ }
+ shader_glsl_print_assignment(gen, &dst, "%s(%s)", op, args->buffer);
- glsl_src_cleanup(&src, &gen->string_buffers);
+ vkd3d_string_buffer_release(&gen->string_buffers, args);
glsl_dst_cleanup(&dst, &gen->string_buffers);
}
@@ -532,6 +547,13 @@ static void shader_glsl_if(struct vkd3d_glsl_generator *gen, const struct vkd3d_
++gen->indent;
}
+static void shader_glsl_else(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins)
+{
+ unsigned int i = 4 * (gen->indent - 1);
+
+ vkd3d_string_buffer_printf(gen->buffer, "%*s}\n%*selse\n%*s{\n", i, "", i, "", i, "");
+}
+
static void shader_glsl_endif(struct vkd3d_glsl_generator *gen)
{
--gen->indent;
@@ -539,6 +561,22 @@ static void shader_glsl_endif(struct vkd3d_glsl_generator *gen)
vkd3d_string_buffer_printf(gen->buffer, "}\n");
}
+static void shader_glsl_unary_op(struct vkd3d_glsl_generator *gen,
+ const struct vkd3d_shader_instruction *ins, const char *op)
+{
+ 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%s", op, src.str->buffer);
+
+ glsl_src_cleanup(&src, &gen->string_buffers);
+ glsl_dst_cleanup(&dst, &gen->string_buffers);
+}
+
static void shader_glsl_mov(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins)
{
struct glsl_src src;
@@ -757,6 +795,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen,
case VKD3DSIH_DP4:
shader_glsl_dot(gen, ins, VKD3DSP_WRITEMASK_ALL);
break;
+ case VKD3DSIH_ELSE:
+ shader_glsl_else(gen, ins);
+ break;
case VKD3DSIH_ENDIF:
shader_glsl_endif(gen);
break;
@@ -781,9 +822,25 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen,
case VKD3DSIH_IF:
shader_glsl_if(gen, ins);
break;
+ case VKD3DSIH_MAD:
+ shader_glsl_intrinsic(gen, ins, "fma");
+ break;
+ case VKD3DSIH_ISHL:
+ shader_glsl_binop(gen, ins, "<<");
+ break;
+ case VKD3DSIH_ISHR:
+ case VKD3DSIH_USHR:
+ shader_glsl_binop(gen, ins, ">>");
+ break;
case VKD3DSIH_LTO:
shader_glsl_relop(gen, ins, "<", "lessThan");
break;
+ case VKD3DSIH_MAX:
+ shader_glsl_intrinsic(gen, ins, "max");
+ break;
+ case VKD3DSIH_MIN:
+ shader_glsl_intrinsic(gen, ins, "min");
+ break;
case VKD3DSIH_INE:
case VKD3DSIH_NEU:
shader_glsl_relop(gen, ins, "!=", "notEqual");
@@ -804,6 +861,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen,
case VKD3DSIH_MUL:
shader_glsl_binop(gen, ins, "*");
break;
+ case VKD3DSIH_NOT:
+ shader_glsl_unary_op(gen, ins, "~");
+ break;
case VKD3DSIH_OR:
shader_glsl_binop(gen, ins, "|");
break;
@@ -822,6 +882,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen,
case VKD3DSIH_ROUND_Z:
shader_glsl_intrinsic(gen, ins, "trunc");
break;
+ case VKD3DSIH_RSQ:
+ shader_glsl_intrinsic(gen, ins, "inversesqrt");
+ break;
case VKD3DSIH_SQRT:
shader_glsl_intrinsic(gen, ins, "sqrt");
break;
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
index f4401bc5d89..ce3dd91f04f 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
@@ -1907,6 +1907,59 @@ struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, enum hlsl_compile_ty
return &compile->node;
}
+bool hlsl_state_block_add_entry(struct hlsl_state_block *state_block,
+ struct hlsl_state_block_entry *entry)
+{
+ if (!vkd3d_array_reserve((void **)&state_block->entries,
+ &state_block->capacity, state_block->count + 1,
+ sizeof(*state_block->entries)))
+ return false;
+
+ state_block->entries[state_block->count++] = entry;
+ return true;
+}
+
+struct hlsl_ir_node *hlsl_new_sampler_state(struct hlsl_ctx *ctx,
+ const struct hlsl_state_block *state_block, struct vkd3d_shader_location *loc)
+{
+ struct hlsl_ir_sampler_state *sampler_state;
+ struct hlsl_type *type = ctx->builtin_types.sampler[HLSL_SAMPLER_DIM_GENERIC];
+
+ if (!(sampler_state = hlsl_alloc(ctx, sizeof(*sampler_state))))
+ return NULL;
+
+ init_node(&sampler_state->node, HLSL_IR_SAMPLER_STATE, type, loc);
+
+ if (!(sampler_state->state_block = hlsl_alloc(ctx, sizeof(*sampler_state->state_block))))
+ {
+ vkd3d_free(sampler_state);
+ return NULL;
+ }
+
+ if (state_block)
+ {
+ for (unsigned int i = 0; i < state_block->count; ++i)
+ {
+ const struct hlsl_state_block_entry *src = state_block->entries[i];
+ struct hlsl_state_block_entry *entry;
+
+ if (!(entry = clone_stateblock_entry(ctx, src, src->name, src->lhs_has_index, src->lhs_index, false, 0)))
+ {
+ hlsl_free_instr(&sampler_state->node);
+ return NULL;
+ }
+
+ if (!hlsl_state_block_add_entry(sampler_state->state_block, entry))
+ {
+ hlsl_free_instr(&sampler_state->node);
+ return NULL;
+ }
+ }
+ }
+
+ return &sampler_state->node;
+}
+
struct hlsl_ir_node *hlsl_new_stateblock_constant(struct hlsl_ctx *ctx, const char *name,
struct vkd3d_shader_location *loc)
{
@@ -2295,6 +2348,13 @@ static struct hlsl_ir_node *clone_compile(struct hlsl_ctx *ctx,
return node;
}
+static struct hlsl_ir_node *clone_sampler_state(struct hlsl_ctx *ctx,
+ struct clone_instr_map *map, struct hlsl_ir_sampler_state *sampler_state)
+{
+ return hlsl_new_sampler_state(ctx, sampler_state->state_block,
+ &sampler_state->node.loc);
+}
+
static struct hlsl_ir_node *clone_stateblock_constant(struct hlsl_ctx *ctx,
struct clone_instr_map *map, struct hlsl_ir_stateblock_constant *constant)
{
@@ -2302,8 +2362,8 @@ static struct hlsl_ir_node *clone_stateblock_constant(struct hlsl_ctx *ctx,
}
struct hlsl_state_block_entry *clone_stateblock_entry(struct hlsl_ctx *ctx,
- struct hlsl_state_block_entry *src, const char *name, bool lhs_has_index,
- unsigned int lhs_index, unsigned int arg_index)
+ const struct hlsl_state_block_entry *src, const char *name, bool lhs_has_index,
+ unsigned int lhs_index, bool single_arg, unsigned int arg_index)
{
struct hlsl_state_block_entry *entry;
struct clone_instr_map map = { 0 };
@@ -2319,7 +2379,11 @@ struct hlsl_state_block_entry *clone_stateblock_entry(struct hlsl_ctx *ctx,
return NULL;
}
- entry->args_count = 1;
+ if (single_arg)
+ entry->args_count = 1;
+ else
+ entry->args_count = src->args_count;
+
if (!(entry->args = hlsl_alloc(ctx, sizeof(*entry->args) * entry->args_count)))
{
hlsl_free_state_block_entry(entry);
@@ -2332,7 +2396,16 @@ struct hlsl_state_block_entry *clone_stateblock_entry(struct hlsl_ctx *ctx,
hlsl_free_state_block_entry(entry);
return NULL;
}
- clone_src(&map, entry->args, &src->args[arg_index]);
+
+ if (single_arg)
+ {
+ clone_src(&map, entry->args, &src->args[arg_index]);
+ }
+ else
+ {
+ for (unsigned int i = 0; i < src->args_count; ++i)
+ clone_src(&map, &entry->args[i], &src->args[i]);
+ }
vkd3d_free(map.instrs);
return entry;
@@ -2440,6 +2513,9 @@ static struct hlsl_ir_node *clone_instr(struct hlsl_ctx *ctx,
case HLSL_IR_COMPILE:
return clone_compile(ctx, map, hlsl_ir_compile(instr));
+ case HLSL_IR_SAMPLER_STATE:
+ return clone_sampler_state(ctx, map, hlsl_ir_sampler_state(instr));
+
case HLSL_IR_STATEBLOCK_CONSTANT:
return clone_stateblock_constant(ctx, map, hlsl_ir_stateblock_constant(instr));
}
@@ -2860,6 +2936,7 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type)
[HLSL_IR_SWIZZLE ] = "HLSL_IR_SWIZZLE",
[HLSL_IR_COMPILE] = "HLSL_IR_COMPILE",
+ [HLSL_IR_SAMPLER_STATE] = "HLSL_IR_SAMPLER_STATE",
[HLSL_IR_STATEBLOCK_CONSTANT] = "HLSL_IR_STATEBLOCK_CONSTANT",
};
@@ -3337,6 +3414,12 @@ static void dump_ir_compile(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *bu
vkd3d_string_buffer_printf(buffer, ")");
}
+static void dump_ir_sampler_state(struct vkd3d_string_buffer *buffer,
+ const struct hlsl_ir_sampler_state *sampler_state)
+{
+ vkd3d_string_buffer_printf(buffer, "sampler_state {...}");
+}
+
static void dump_ir_stateblock_constant(struct vkd3d_string_buffer *buffer,
const struct hlsl_ir_stateblock_constant *constant)
{
@@ -3440,6 +3523,10 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer,
dump_ir_compile(ctx, buffer, hlsl_ir_compile(instr));
break;
+ case HLSL_IR_SAMPLER_STATE:
+ dump_ir_sampler_state(buffer, hlsl_ir_sampler_state(instr));
+ break;
+
case HLSL_IR_STATEBLOCK_CONSTANT:
dump_ir_stateblock_constant(buffer, hlsl_ir_stateblock_constant(instr));
break;
@@ -3665,6 +3752,13 @@ static void free_ir_compile(struct hlsl_ir_compile *compile)
vkd3d_free(compile);
}
+static void free_ir_sampler_state(struct hlsl_ir_sampler_state *sampler_state)
+{
+ if (sampler_state->state_block)
+ hlsl_free_state_block(sampler_state->state_block);
+ vkd3d_free(sampler_state);
+}
+
static void free_ir_stateblock_constant(struct hlsl_ir_stateblock_constant *constant)
{
vkd3d_free(constant->name);
@@ -3737,6 +3831,10 @@ void hlsl_free_instr(struct hlsl_ir_node *node)
free_ir_compile(hlsl_ir_compile(node));
break;
+ case HLSL_IR_SAMPLER_STATE:
+ free_ir_sampler_state(hlsl_ir_sampler_state(node));
+ break;
+
case HLSL_IR_STATEBLOCK_CONSTANT:
free_ir_stateblock_constant(hlsl_ir_stateblock_constant(node));
break;
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
index b8678962f67..4082b14fe04 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
@@ -326,6 +326,7 @@ enum hlsl_ir_node_type
HLSL_IR_SWITCH,
HLSL_IR_COMPILE,
+ HLSL_IR_SAMPLER_STATE,
HLSL_IR_STATEBLOCK_CONSTANT,
};
@@ -899,6 +900,14 @@ struct hlsl_ir_compile
unsigned int args_count;
};
+/* Represents a state block initialized with the "sampler_state" keyword. */
+struct hlsl_ir_sampler_state
+{
+ struct hlsl_ir_node node;
+
+ struct hlsl_state_block *state_block;
+};
+
/* Stateblock constants are undeclared values found on state blocks or technique passes descriptions,
* that do not concern regular pixel, vertex, or compute shaders, except for parsing. */
struct hlsl_ir_stateblock_constant
@@ -1212,6 +1221,12 @@ static inline struct hlsl_ir_compile *hlsl_ir_compile(const struct hlsl_ir_node
return CONTAINING_RECORD(node, struct hlsl_ir_compile, node);
}
+static inline struct hlsl_ir_sampler_state *hlsl_ir_sampler_state(const struct hlsl_ir_node *node)
+{
+ VKD3D_ASSERT(node->type == HLSL_IR_SAMPLER_STATE);
+ return CONTAINING_RECORD(node, struct hlsl_ir_sampler_state, node);
+};
+
static inline struct hlsl_ir_stateblock_constant *hlsl_ir_stateblock_constant(const struct hlsl_ir_node *node)
{
VKD3D_ASSERT(node->type == HLSL_IR_STATEBLOCK_CONSTANT);
@@ -1396,12 +1411,15 @@ bool hlsl_clone_block(struct hlsl_ctx *ctx, struct hlsl_block *dst_block, const
void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func);
void hlsl_dump_var_default_values(const struct hlsl_ir_var *var);
+bool hlsl_state_block_add_entry(struct hlsl_state_block *state_block,
+ struct hlsl_state_block_entry *entry);
bool hlsl_validate_state_block_entry(struct hlsl_ctx *ctx, struct hlsl_state_block_entry *entry,
const struct vkd3d_shader_location *loc);
struct hlsl_state_block_entry *clone_stateblock_entry(struct hlsl_ctx *ctx,
- struct hlsl_state_block_entry *src, const char *name, bool lhs_has_index,
- unsigned int lhs_index, unsigned int arg_index);
+ const struct hlsl_state_block_entry *src, const char *name, bool lhs_has_index,
+ unsigned int lhs_index, bool single_arg, unsigned int arg_index);
+void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body);
void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body);
int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func,
enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out);
@@ -1509,6 +1527,8 @@ struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name,
struct hlsl_struct_field *fields, size_t field_count);
struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int components,
struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc);
+struct hlsl_ir_node *hlsl_new_sampler_state(struct hlsl_ctx *ctx,
+ const struct hlsl_state_block *state_block, struct vkd3d_shader_location *loc);
struct hlsl_ir_node *hlsl_new_stateblock_constant(struct hlsl_ctx *ctx, const char *name,
struct vkd3d_shader_location *loc);
struct hlsl_ir_node *hlsl_new_string_constant(struct hlsl_ctx *ctx, const char *str,
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
index c39f2020ef7..b4d9f0988b0 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
@@ -437,6 +437,9 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct
if (hlsl_types_are_equal(src_type, dst_type))
return node;
+ if (node->type == HLSL_IR_SAMPLER_STATE && dst_type->class == HLSL_CLASS_SAMPLER)
+ return node;
+
if (!implicit_compatible_data_types(ctx, src_type, dst_type))
{
struct vkd3d_string_buffer *src_string, *dst_string;
@@ -613,6 +616,7 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx
case HLSL_IR_COMPILE:
case HLSL_IR_CONSTANT:
case HLSL_IR_EXPR:
+ case HLSL_IR_SAMPLER_STATE:
case HLSL_IR_STRING_CONSTANT:
case HLSL_IR_SWIZZLE:
case HLSL_IR_LOAD:
@@ -648,6 +652,7 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx
/* Wrap the node into a src to allow the reference to survive the multiple const passes. */
hlsl_src_from_node(&src, node);
+ hlsl_lower_index_loads(ctx, &expr);
hlsl_run_const_passes(ctx, &expr);
node = src.node;
hlsl_src_remove(&src);
@@ -2324,55 +2329,6 @@ static bool add_increment(struct hlsl_ctx *ctx, struct hlsl_block *block, bool d
return true;
}
-/* For some reason, for matrices, values from default value initializers end up in different
- * components than from regular initializers. Default value initializers fill the matrix in
- * vertical reading order (left-to-right top-to-bottom) instead of regular reading order
- * (top-to-bottom left-to-right), so they have to be adjusted.
- * An exception is that the order of matrix initializers for function parameters are row-major
- * (top-to-bottom left-to-right). */
-static unsigned int get_component_index_from_default_initializer_index(struct hlsl_ctx *ctx,
- struct hlsl_type *type, unsigned int index)
-{
- unsigned int element_comp_count, element, x, y, i;
- unsigned int base = 0;
-
- if (ctx->profile->major_version < 4)
- return index;
-
- if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT)
- return index;
-
- switch (type->class)
- {
- case HLSL_CLASS_MATRIX:
- x = index / type->dimy;
- y = index % type->dimy;
- return y * type->dimx + x;
-
- case HLSL_CLASS_ARRAY:
- element_comp_count = hlsl_type_component_count(type->e.array.type);
- element = index / element_comp_count;
- base = element * element_comp_count;
- return base + get_component_index_from_default_initializer_index(ctx, type->e.array.type, index - base);
-
- case HLSL_CLASS_STRUCT:
- for (i = 0; i < type->e.record.field_count; ++i)
- {
- struct hlsl_type *field_type = type->e.record.fields[i].type;
-
- element_comp_count = hlsl_type_component_count(field_type);
- if (index - base < element_comp_count)
- return base + get_component_index_from_default_initializer_index(ctx, field_type, index - base);
- base += element_comp_count;
- }
- break;
-
- default:
- return index;
- }
- vkd3d_unreachable();
-}
-
static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *instrs,
struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src,
bool is_default_values_initializer)
@@ -2397,11 +2353,10 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i
if (is_default_values_initializer)
{
struct hlsl_default_value default_value = {0};
- unsigned int dst_index;
if (hlsl_is_numeric_type(dst_comp_type))
{
- if (src->type == HLSL_IR_COMPILE)
+ if (src->type == HLSL_IR_COMPILE || src->type == HLSL_IR_SAMPLER_STATE)
{
/* Default values are discarded if they contain an object
* literal expression for a numeric component. */
@@ -2420,13 +2375,8 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i
return;
default_value = evaluate_static_expression(ctx, &block, dst_comp_type, &src->loc);
- if (dst->is_param)
- dst_index = *store_index;
- else
- dst_index = get_component_index_from_default_initializer_index(ctx, dst->data_type, *store_index);
-
if (dst->default_values)
- dst->default_values[dst_index] = default_value;
+ dst->default_values[*store_index] = default_value;
hlsl_block_cleanup(&block);
}
@@ -2434,12 +2384,41 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i
}
else
{
- if (!(conv = add_implicit_conversion(ctx, instrs, load, dst_comp_type, &src->loc)))
- return;
+ if (src->type == HLSL_IR_SAMPLER_STATE)
+ {
+ /* Sampler states end up in the variable's state_blocks instead of
+ * being used to initialize its value. */
+ struct hlsl_ir_sampler_state *sampler_state = hlsl_ir_sampler_state(src);
+
+ if (dst_comp_type->class != HLSL_CLASS_SAMPLER)
+ {
+ struct vkd3d_string_buffer *dst_string;
+
+ dst_string = hlsl_type_to_string(ctx, dst_comp_type);
+ if (dst_string)
+ hlsl_error(ctx, &src->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+ "Cannot assign sampler_state to %s.", dst_string->buffer);
+ hlsl_release_string_buffer(ctx, dst_string);
+ return;
+ }
- if (!hlsl_new_store_component(ctx, &block, &dst_deref, *store_index, conv))
- return;
- hlsl_block_add_block(instrs, &block);
+ if (!hlsl_array_reserve(ctx, (void **)&dst->state_blocks, &dst->state_block_capacity,
+ dst->state_block_count + 1, sizeof(*dst->state_blocks)))
+ return;
+
+ dst->state_blocks[dst->state_block_count] = sampler_state->state_block;
+ sampler_state->state_block = NULL;
+ ++dst->state_block_count;
+ }
+ else
+ {
+ if (!(conv = add_implicit_conversion(ctx, instrs, load, dst_comp_type, &src->loc)))
+ return;
+
+ if (!hlsl_new_store_component(ctx, &block, &dst_deref, *store_index, conv))
+ return;
+ hlsl_block_add_block(instrs, &block);
+ }
}
++*store_index;
@@ -2778,6 +2757,8 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var
is_default_values_initializer = (ctx->cur_buffer != ctx->globals_buffer)
|| (var->storage_modifiers & HLSL_STORAGE_UNIFORM)
|| ctx->cur_scope->annotations;
+ if (hlsl_get_multiarray_element_type(type)->class == HLSL_CLASS_SAMPLER)
+ is_default_values_initializer = false;
if (hlsl_type_is_shader(type))
is_default_values_initializer = false;
@@ -2836,6 +2817,9 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var
{
hlsl_block_add_block(initializers, v->initializer.instrs);
}
+
+ if (var->state_blocks)
+ TRACE("Variable %s has %u state blocks.\n", var->name, var->state_block_count);
}
else if (var->storage_modifiers & HLSL_STORAGE_STATIC)
{
@@ -6228,16 +6212,6 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim,
hlsl_release_string_buffer(ctx, string);
}
-static bool state_block_add_entry(struct hlsl_state_block *state_block, struct hlsl_state_block_entry *entry)
-{
- if (!vkd3d_array_reserve((void **)&state_block->entries, &state_block->capacity, state_block->count + 1,
- sizeof(*state_block->entries)))
- return false;
-
- state_block->entries[state_block->count++] = entry;
- return true;
-}
-
}
%locations
@@ -7850,6 +7824,11 @@ stateblock_lhs_identifier:
if (!($$ = hlsl_strdup(ctx, "pixelshader")))
YYABORT;
}
+ | KW_TEXTURE
+ {
+ if (!($$ = hlsl_strdup(ctx, "texture")))
+ YYABORT;
+ }
| KW_VERTEXSHADER
{
if (!($$ = hlsl_strdup(ctx, "vertexshader")))
@@ -7907,7 +7886,7 @@ state_block:
vkd3d_free($5.args);
$$ = $1;
- state_block_add_entry($$, entry);
+ hlsl_state_block_add_entry($$, entry);
}
| state_block any_identifier '(' func_arguments ')' ';'
{
@@ -7935,7 +7914,7 @@ state_block:
hlsl_validate_state_block_entry(ctx, entry, &@4);
$$ = $1;
- state_block_add_entry($$, entry);
+ hlsl_state_block_add_entry($$, entry);
}
state_block_list:
@@ -8668,6 +8647,25 @@ primary_expr:
}
vkd3d_free($1);
}
+ | KW_SAMPLER_STATE '{' state_block_start state_block '}'
+ {
+ struct hlsl_ir_node *sampler_state;
+ ctx->in_state_block = 0;
+
+ if (!ctx->in_state_block && ctx->cur_scope != ctx->globals)
+ hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_MISPLACED_SAMPLER_STATE,
+ "sampler_state must be in global scope or a state block.");
+
+ if (!(sampler_state = hlsl_new_sampler_state(ctx, $4, &@1)))
+ {
+ hlsl_free_state_block($4);
+ YYABORT;
+ }
+ hlsl_free_state_block($4);
+
+ if (!($$ = make_block(ctx, sampler_state)))
+ YYABORT;
+ }
| NEW_IDENTIFIER
{
if (ctx->in_state_block)
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
index feab6cf06c1..c5dd5e71e02 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
@@ -4062,6 +4062,7 @@ static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
case HLSL_IR_RESOURCE_LOAD:
case HLSL_IR_STRING_CONSTANT:
case HLSL_IR_SWIZZLE:
+ case HLSL_IR_SAMPLER_STATE:
if (list_empty(&instr->uses))
{
list_remove(&instr->entry);
@@ -4344,7 +4345,8 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop
case HLSL_IR_STRING_CONSTANT:
break;
case HLSL_IR_COMPILE:
- /* Compile calls are skipped as they are only relevent to effects. */
+ case HLSL_IR_SAMPLER_STATE:
+ /* These types are skipped as they are only relevant to effects. */
break;
}
}
@@ -5206,7 +5208,8 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx)
}
}
-static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, uint32_t space, uint32_t index)
+static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx,
+ uint32_t space, uint32_t index, bool allocated_only)
{
const struct hlsl_buffer *buffer;
@@ -5214,7 +5217,12 @@ static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, uint3
{
if (buffer->reservation.reg_type == 'b'
&& buffer->reservation.reg_space == space && buffer->reservation.reg_index == index)
+ {
+ if (allocated_only && !buffer->reg.allocated)
+ continue;
+
return buffer;
+ }
}
return NULL;
}
@@ -5397,8 +5405,8 @@ static void allocate_buffers(struct hlsl_ctx *ctx)
if (reservation->reg_type == 'b')
{
- const struct hlsl_buffer *reserved_buffer = get_reserved_buffer(ctx,
- reservation->reg_space, reservation->reg_index);
+ const struct hlsl_buffer *allocated_buffer = get_reserved_buffer(ctx,
+ reservation->reg_space, reservation->reg_index, true);
unsigned int max_index = get_max_cbuffer_reg_index(ctx);
if (buffer->reservation.reg_index > max_index)
@@ -5406,14 +5414,14 @@ static void allocate_buffers(struct hlsl_ctx *ctx)
"Buffer reservation cb%u exceeds target's maximum (cb%u).",
buffer->reservation.reg_index, max_index);
- if (reserved_buffer && reserved_buffer != buffer)
+ if (allocated_buffer && allocated_buffer != buffer)
{
hlsl_error(ctx, &buffer->loc, VKD3D_SHADER_ERROR_HLSL_OVERLAPPING_RESERVATIONS,
"Multiple buffers bound to space %u, index %u.",
reservation->reg_space, reservation->reg_index);
- hlsl_note(ctx, &reserved_buffer->loc, VKD3D_SHADER_LOG_ERROR,
+ hlsl_note(ctx, &allocated_buffer->loc, VKD3D_SHADER_LOG_ERROR,
"Buffer %s is already bound to space %u, index %u.",
- reserved_buffer->name, reservation->reg_space, reservation->reg_index);
+ allocated_buffer->name, reservation->reg_space, reservation->reg_index);
}
buffer->reg.space = reservation->reg_space;
@@ -5430,12 +5438,12 @@ static void allocate_buffers(struct hlsl_ctx *ctx)
else if (!reservation->reg_type)
{
unsigned int max_index = get_max_cbuffer_reg_index(ctx);
- while (get_reserved_buffer(ctx, 0, index))
+ while (get_reserved_buffer(ctx, 0, index, false))
++index;
if (index > max_index)
hlsl_error(ctx, &buffer->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION,
- "Too many buffers allocated, target's maximum is %u.", max_index);
+ "Too many buffers reserved, target's maximum is %u.", max_index);
buffer->reg.space = 0;
buffer->reg.index = index;
@@ -6178,12 +6186,16 @@ static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *bod
}
}
+void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body)
+{
+ lower_ir(ctx, lower_index_loads, body);
+}
+
void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body)
{
bool progress;
lower_ir(ctx, lower_matrix_swizzles, body);
- lower_ir(ctx, lower_index_loads, body);
lower_ir(ctx, lower_broadcasts, body);
while (hlsl_transform_ir(ctx, fold_redundant_casts, body, NULL));
diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c
index 88650a97068..2fe5472167f 100644
--- a/libs/vkd3d/libs/vkd3d-shader/ir.c
+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c
@@ -215,6 +215,14 @@ static void src_param_init_temp_float(struct vkd3d_shader_src_param *src, unsign
src->reg.idx[0].offset = idx;
}
+static void src_param_init_temp_float4(struct vkd3d_shader_src_param *src, unsigned int idx)
+{
+ vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1);
+ src->reg.dimension = VSIR_DIMENSION_VEC4;
+ src->swizzle = VKD3D_SHADER_NO_SWIZZLE;
+ src->reg.idx[0].offset = idx;
+}
+
static void src_param_init_temp_uint(struct vkd3d_shader_src_param *src, unsigned int idx)
{
vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1);
@@ -1864,13 +1872,13 @@ static bool use_flat_interpolation(const struct vsir_program *program,
if (parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT)
{
vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
- "Unsupported flat interpolation parameter type %#x.\n", parameter->type);
+ "Unsupported flat interpolation parameter type %#x.", parameter->type);
return false;
}
if (parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32)
{
vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE,
- "Invalid flat interpolation parameter data type %#x.\n", parameter->data_type);
+ "Invalid flat interpolation parameter data type %#x.", parameter->data_type);
return false;
}
@@ -5539,9 +5547,11 @@ static bool find_colour_signature_idx(const struct shader_signature *signature,
static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *program,
const struct vkd3d_shader_instruction *ret, enum vkd3d_shader_comparison_func compare_func,
- const struct vkd3d_shader_parameter1 *ref, uint32_t colour_signature_idx, uint32_t colour_temp, size_t *ret_pos)
+ const struct vkd3d_shader_parameter1 *ref, uint32_t colour_signature_idx,
+ uint32_t colour_temp, size_t *ret_pos, struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_instruction_array *instructions = &program->instructions;
+ static const struct vkd3d_shader_location no_loc;
size_t pos = ret - instructions->elements;
struct vkd3d_shader_instruction *ins;
@@ -5596,6 +5606,11 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr
VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF, VKD3D_DATA_UINT);
break;
+ case VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4:
+ vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER,
+ "Alpha test reference data type must be a single component.");
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+
default:
FIXME("Unhandled parameter data type %#x.\n", ref->data_type);
return VKD3D_ERROR_NOT_IMPLEMENTED;
@@ -5652,13 +5667,13 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro
if (func->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT)
{
vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
- "Unsupported alpha test function parameter type %#x.\n", func->type);
+ "Unsupported alpha test function parameter type %#x.", func->type);
return VKD3D_ERROR_NOT_IMPLEMENTED;
}
if (func->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32)
{
vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE,
- "Invalid alpha test function parameter data type %#x.\n", func->data_type);
+ "Invalid alpha test function parameter data type %#x.", func->data_type);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
compare_func = func->u.immediate_constant.u.u32;
@@ -5682,7 +5697,7 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro
if (ins->opcode == VKD3DSIH_RET)
{
if ((ret = insert_alpha_test_before_ret(program, ins, compare_func,
- ref, colour_signature_idx, colour_temp, &new_pos)) < 0)
+ ref, colour_signature_idx, colour_temp, &new_pos, message_context)) < 0)
return ret;
i = new_pos;
continue;
@@ -5709,6 +5724,202 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro
return VKD3D_OK;
}
+static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *program,
+ const struct vkd3d_shader_instruction *ret, uint32_t mask, uint32_t position_signature_idx,
+ uint32_t position_temp, uint32_t low_signature_idx, uint32_t high_signature_idx, size_t *ret_pos)
+{
+ struct vkd3d_shader_instruction_array *instructions = &program->instructions;
+ size_t pos = ret - instructions->elements;
+ struct vkd3d_shader_instruction *ins;
+ unsigned int output_idx = 0;
+
+ if (!shader_instruction_array_insert_at(&program->instructions, pos, vkd3d_popcount(mask) + 1))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+
+ ins = &program->instructions.elements[pos];
+
+ for (unsigned int i = 0; i < 8; ++i)
+ {
+ if (!(mask & (1u << i)))
+ continue;
+
+ vsir_instruction_init_with_params(program, ins, &ret->location, VKD3DSIH_DP4, 1, 2);
+ src_param_init_temp_float4(&ins->src[0], position_temp);
+ src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0 + i, VKD3D_DATA_FLOAT);
+ ins->src[1].swizzle = VKD3D_SHADER_NO_SWIZZLE;
+ ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4;
+
+ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1);
+ if (output_idx < 4)
+ ins->dst[0].reg.idx[0].offset = low_signature_idx;
+ else
+ ins->dst[0].reg.idx[0].offset = high_signature_idx;
+ ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4;
+ ins->dst[0].write_mask = (1u << (output_idx % 4));
+ ++output_idx;
+
+ ++ins;
+ }
+
+ vsir_instruction_init_with_params(program, ins, &ret->location, VKD3DSIH_MOV, 1, 1);
+ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1);
+ ins->dst[0].reg.idx[0].offset = position_signature_idx;
+ ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4;
+ ins->dst[0].write_mask = program->output_signature.elements[position_signature_idx].mask;
+ src_param_init_temp_float(&ins->src[0], position_temp);
+ ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4;
+ ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE;
+
+ *ret_pos = pos + vkd3d_popcount(mask) + 1;
+ return VKD3D_OK;
+}
+
+static bool find_position_signature_idx(const struct shader_signature *signature, uint32_t *idx)
+{
+ for (unsigned int i = 0; i < signature->element_count; ++i)
+ {
+ if (signature->elements[i].sysval_semantic == VKD3D_SHADER_SV_POSITION)
+ {
+ *idx = i;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *program,
+ struct vsir_transformation_context *ctx)
+{
+ struct shader_signature *signature = &program->output_signature;
+ unsigned int low_signature_idx = ~0u, high_signature_idx = ~0u;
+ const struct vkd3d_shader_parameter1 *mask_parameter = NULL;
+ struct signature_element *new_elements, *clip_element;
+ uint32_t position_signature_idx, position_temp, mask;
+ static const struct vkd3d_shader_location no_loc;
+ struct vkd3d_shader_instruction *ins;
+ unsigned int plane_count;
+ size_t new_pos;
+ int ret;
+
+ if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX)
+ return VKD3D_OK;
+
+ for (unsigned int i = 0; i < program->parameter_count; ++i)
+ {
+ const struct vkd3d_shader_parameter1 *parameter = &program->parameters[i];
+
+ if (parameter->name == VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK)
+ mask_parameter = parameter;
+ }
+
+ if (!mask_parameter)
+ return VKD3D_OK;
+
+ if (mask_parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT)
+ {
+ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
+ "Unsupported clip plane mask parameter type %#x.", mask_parameter->type);
+ return VKD3D_ERROR_NOT_IMPLEMENTED;
+ }
+ if (mask_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32)
+ {
+ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE,
+ "Invalid clip plane mask parameter data type %#x.", mask_parameter->data_type);
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ mask = mask_parameter->u.immediate_constant.u.u32;
+
+ if (!mask)
+ return VKD3D_OK;
+
+ for (unsigned int i = 0; i < signature->element_count; ++i)
+ {
+ if (signature->elements[i].sysval_semantic == VKD3D_SHADER_SV_CLIP_DISTANCE)
+ {
+ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER,
+ "Clip planes cannot be used if the shader writes clip distance.");
+ return VKD3D_ERROR_INVALID_ARGUMENT;
+ }
+ }
+
+ if (!find_position_signature_idx(signature, &position_signature_idx))
+ {
+ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC,
+ "Shader does not write position.");
+ return VKD3D_ERROR_INVALID_SHADER;
+ }
+
+ /* Append the clip plane signature indices. */
+
+ plane_count = vkd3d_popcount(mask);
+
+ if (!(new_elements = vkd3d_realloc(signature->elements,
+ (signature->element_count + 2) * sizeof(*signature->elements))))
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+ signature->elements = new_elements;
+
+ low_signature_idx = signature->element_count;
+ clip_element = &signature->elements[signature->element_count++];
+ memset(clip_element, 0, sizeof(*clip_element));
+ clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE;
+ clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT;
+ clip_element->register_count = 1;
+ clip_element->mask = vkd3d_write_mask_from_component_count(min(plane_count, 4));
+ clip_element->used_mask = clip_element->mask;
+ clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE;
+
+ if (plane_count > 4)
+ {
+ high_signature_idx = signature->element_count;
+ clip_element = &signature->elements[signature->element_count++];
+ memset(clip_element, 0, sizeof(*clip_element));
+ clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE;
+ clip_element->semantic_index = 1;
+ clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT;
+ clip_element->register_count = 1;
+ clip_element->mask = vkd3d_write_mask_from_component_count(plane_count - 4);
+ clip_element->used_mask = clip_element->mask;
+ clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE;
+ }
+
+ /* We're going to be reading from the output position, so we need to go
+ * through the whole shader and convert it to a temp. */
+
+ position_temp = program->temp_count++;
+
+ for (size_t i = 0; i < program->instructions.count; ++i)
+ {
+ ins = &program->instructions.elements[i];
+
+ if (vsir_instruction_is_dcl(ins))
+ continue;
+
+ if (ins->opcode == VKD3DSIH_RET)
+ {
+ if ((ret = insert_clip_planes_before_ret(program, ins, mask, position_signature_idx,
+ position_temp, low_signature_idx, high_signature_idx, &new_pos)) < 0)
+ return ret;
+ i = new_pos;
+ continue;
+ }
+
+ for (size_t j = 0; j < ins->dst_count; ++j)
+ {
+ struct vkd3d_shader_dst_param *dst = &ins->dst[j];
+
+ /* Note we run after I/O normalization. */
+ if (dst->reg.type == VKD3DSPR_OUTPUT && dst->reg.idx[0].offset == position_signature_idx)
+ {
+ dst->reg.type = VKD3DSPR_TEMP;
+ dst->reg.idx[0].offset = position_temp;
+ }
+ }
+ }
+
+ return VKD3D_OK;
+}
+
struct validation_context
{
struct vkd3d_shader_message_context *message_context;
@@ -6012,6 +6223,63 @@ static void vsir_validate_register(struct validation_context *ctx,
reg->dimension);
break;
+ case VKD3DSPR_DEPTHOUT:
+ if (reg->idx_count != 0)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT,
+ "Invalid index count %u for a DEPTHOUT register.",
+ reg->idx_count);
+ break;
+
+ case VKD3DSPR_DEPTHOUTGE:
+ if (reg->idx_count != 0)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT,
+ "Invalid index count %u for a DEPTHOUTGE register.",
+ reg->idx_count);
+ break;
+
+ case VKD3DSPR_DEPTHOUTLE:
+ if (reg->idx_count != 0)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT,
+ "Invalid index count %u for a DEPTHOUTLE register.",
+ reg->idx_count);
+ break;
+
+ case VKD3DSPR_RASTOUT:
+ if (reg->idx_count != 1)
+ {
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT,
+ "Invalid index count %u for a RASTOUT register.",
+ reg->idx_count);
+ break;
+ }
+
+ if (reg->idx[0].rel_addr)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX,
+ "Non-NULL relative address for a RASTOUT register.");
+
+ if (reg->idx[0].offset >= 3)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX,
+ "Invalid offset for a RASTOUT register.");
+ break;
+
+ case VKD3DSPR_MISCTYPE:
+ if (reg->idx_count != 1)
+ {
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT,
+ "Invalid index count %u for a MISCTYPE register.",
+ reg->idx_count);
+ break;
+ }
+
+ if (reg->idx[0].rel_addr)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX,
+ "Non-NULL relative address for a MISCTYPE register.");
+
+ if (reg->idx[0].offset >= 2)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX,
+ "Invalid offset for a MISCTYPE register.");
+ break;
+
default:
break;
}
@@ -6842,6 +7110,7 @@ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t
}
vsir_transform(&ctx, vsir_program_insert_alpha_test);
+ vsir_transform(&ctx, vsir_program_insert_clip_planes);
if (TRACE_ON())
vkd3d_shader_trace(program);
diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c
index 0278a6ca232..11c054a28f5 100644
--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c
@@ -1228,6 +1228,13 @@ static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_build
SpvOpConstantComposite, result_type, constituents, constituent_count);
}
+static uint32_t vkd3d_spirv_build_op_spec_constant_composite(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count)
+{
+ return vkd3d_spirv_build_op_trv(builder, &builder->global_stream,
+ SpvOpSpecConstantComposite, result_type, constituents, constituent_count);
+}
+
static uint32_t vkd3d_spirv_get_op_constant_composite(struct vkd3d_spirv_builder *builder,
uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count)
{
@@ -3324,8 +3331,10 @@ static const struct vkd3d_spec_constant_info *get_spec_constant_info(enum vkd3d_
return NULL;
}
-static uint32_t spirv_compiler_alloc_spec_constant_id(struct spirv_compiler *compiler)
+static uint32_t spirv_compiler_alloc_spec_constant_id(struct spirv_compiler *compiler, unsigned int count)
{
+ uint32_t ret;
+
if (!compiler->current_spec_constant_id)
{
unsigned int i, id = 0;
@@ -3335,28 +3344,52 @@ static uint32_t spirv_compiler_alloc_spec_constant_id(struct spirv_compiler *com
const struct vkd3d_shader_parameter1 *current = &compiler->program->parameters[i];
if (current->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT)
- id = max(current->u.specialization_constant.id + 1, id);
+ {
+ switch (current->data_type)
+ {
+ case VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4:
+ id = max(current->u.specialization_constant.id + 4, id);
+ break;
+
+ default:
+ id = max(current->u.specialization_constant.id + 1, id);
+ break;
+ }
+ }
}
compiler->current_spec_constant_id = id;
}
- return compiler->current_spec_constant_id++;
+ ret = compiler->current_spec_constant_id;
+ compiler->current_spec_constant_id += count;
+ return ret;
}
static uint32_t spirv_compiler_emit_spec_constant(struct spirv_compiler *compiler,
- enum vkd3d_shader_parameter_name name, uint32_t spec_id, enum vkd3d_data_type type)
+ enum vkd3d_shader_parameter_name name, uint32_t spec_id,
+ enum vkd3d_data_type type, unsigned int component_count)
{
+ uint32_t scalar_type_id, vector_type_id, id, default_value, components[4];
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_spec_constant_info *info;
- uint32_t type_id, id, default_value;
info = get_spec_constant_info(name);
default_value = info ? info->default_value : 0;
- type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), 1);
- id = vkd3d_spirv_build_op_spec_constant(builder, type_id, default_value);
- vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationSpecId, spec_id);
+ scalar_type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), 1);
+ vector_type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), component_count);
+
+ for (unsigned int i = 0; i < component_count; ++i)
+ {
+ components[i] = vkd3d_spirv_build_op_spec_constant(builder, scalar_type_id, default_value);
+ vkd3d_spirv_build_op_decorate1(builder, components[i], SpvDecorationSpecId, spec_id + i);
+ }
+
+ if (component_count == 1)
+ id = components[0];
+ else
+ id = vkd3d_spirv_build_op_spec_constant_composite(builder, vector_type_id, components, component_count);
if (info)
vkd3d_spirv_build_op_name(builder, id, "%s", info->debug_name);
@@ -3373,7 +3406,8 @@ static uint32_t spirv_compiler_emit_spec_constant(struct spirv_compiler *compile
}
static uint32_t spirv_compiler_get_spec_constant(struct spirv_compiler *compiler,
- enum vkd3d_shader_parameter_name name, uint32_t spec_id, enum vkd3d_data_type type)
+ enum vkd3d_shader_parameter_name name, uint32_t spec_id,
+ enum vkd3d_data_type type, unsigned int component_count)
{
unsigned int i;
@@ -3383,17 +3417,17 @@ static uint32_t spirv_compiler_get_spec_constant(struct spirv_compiler *compiler
return compiler->spec_constants[i].id;
}
- return spirv_compiler_emit_spec_constant(compiler, name, spec_id, type);
+ return spirv_compiler_emit_spec_constant(compiler, name, spec_id, type, component_count);
}
static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compiler,
- const struct vkd3d_shader_parameter1 *parameter, enum vkd3d_data_type type)
+ const struct vkd3d_shader_parameter1 *parameter, enum vkd3d_data_type type, unsigned int component_count)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
unsigned int index = parameter - compiler->program->parameters;
uint32_t type_id, ptr_id, ptr_type_id;
- type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), 1);
+ type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), component_count);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id);
ptr_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id,
compiler->spirv_parameter_info[index].buffer_id,
@@ -3401,48 +3435,49 @@ static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compi
return vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone);
}
+static const struct
+{
+ enum vkd3d_data_type type;
+ unsigned int component_count;
+}
+parameter_data_type_map[] =
+{
+ [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32] = {VKD3D_DATA_FLOAT, 1},
+ [VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32] = {VKD3D_DATA_UINT, 1},
+ [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4] = {VKD3D_DATA_FLOAT, 4},
+};
+
static uint32_t spirv_compiler_emit_shader_parameter(struct spirv_compiler *compiler,
- enum vkd3d_shader_parameter_name name, enum vkd3d_data_type type)
+ enum vkd3d_shader_parameter_name name, enum vkd3d_data_type type, unsigned int component_count)
{
const struct vkd3d_shader_parameter1 *parameter;
- static const struct
- {
- enum vkd3d_data_type type;
- }
- type_map[] =
- {
- [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32] = {VKD3D_DATA_FLOAT},
- [VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32] = {VKD3D_DATA_UINT},
- };
-
if (!(parameter = vsir_program_get_parameter(compiler->program, name)))
{
WARN("Unresolved shader parameter %#x.\n", name);
goto default_parameter;
}
- if (type_map[parameter->data_type].type != type)
- ERR("Expected data type %#x for parameter %#x, got %#x.\n", type, name, parameter->data_type);
+ if (parameter_data_type_map[parameter->data_type].type != type
+ || parameter_data_type_map[parameter->data_type].component_count != component_count)
+ ERR("Expected type %#x, count %u for parameter %#x, got %#x.\n",
+ type, component_count, name, parameter->data_type);
if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT)
- {
- if (parameter->data_type == VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32)
- return spirv_compiler_get_constant_float(compiler, parameter->u.immediate_constant.u.f32);
- else
- return spirv_compiler_get_constant_uint(compiler, parameter->u.immediate_constant.u.u32);
- }
+ return spirv_compiler_get_constant(compiler, vkd3d_component_type_from_data_type(type),
+ component_count, (const uint32_t *)&parameter->u.immediate_constant);
if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT)
- return spirv_compiler_get_spec_constant(compiler, name, parameter->u.specialization_constant.id, type);
+ return spirv_compiler_get_spec_constant(compiler, name,
+ parameter->u.specialization_constant.id, type, component_count);
if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_BUFFER)
- return spirv_compiler_get_buffer_parameter(compiler, parameter, type);
+ return spirv_compiler_get_buffer_parameter(compiler, parameter, type, component_count);
FIXME("Unhandled parameter type %#x.\n", parameter->type);
default_parameter:
return spirv_compiler_get_spec_constant(compiler,
- name, spirv_compiler_alloc_spec_constant_id(compiler), type);
+ name, spirv_compiler_alloc_spec_constant_id(compiler, component_count), type, component_count);
}
static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *compiler,
@@ -4218,7 +4253,8 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler,
else if (reg->type == VKD3DSPR_UNDEF)
return spirv_compiler_emit_load_undef(compiler, reg, write_mask);
else if (reg->type == VKD3DSPR_PARAMETER)
- return spirv_compiler_emit_shader_parameter(compiler, reg->idx[0].offset, reg->data_type);
+ return spirv_compiler_emit_shader_parameter(compiler, reg->idx[0].offset,
+ reg->data_type, reg->dimension == VSIR_DIMENSION_VEC4 ? 4 : 1);
component_count = vsir_write_mask_component_count(write_mask);
component_type = vkd3d_component_type_from_data_type(reg->data_type);
@@ -4508,9 +4544,24 @@ static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler,
static void spirv_compiler_emit_store_dst(struct spirv_compiler *compiler,
const struct vkd3d_shader_dst_param *dst, uint32_t val_id)
{
- VKD3D_ASSERT(!(dst->modifiers & ~VKD3DSPDM_SATURATE));
- if (dst->modifiers & VKD3DSPDM_SATURATE)
+ uint32_t modifiers = dst->modifiers;
+
+ /* It is always legitimate to ignore _pp. */
+ modifiers &= ~VKD3DSPDM_PARTIALPRECISION;
+
+ if (modifiers & VKD3DSPDM_SATURATE)
+ {
val_id = spirv_compiler_emit_sat(compiler, &dst->reg, dst->write_mask, val_id);
+ modifiers &= ~VKD3DSPDM_SATURATE;
+ }
+
+ if (dst->modifiers & VKD3DSPDM_MSAMPCENTROID)
+ {
+ FIXME("Ignoring _centroid modifier.\n");
+ modifiers &= ~VKD3DSPDM_MSAMPCENTROID;
+ }
+
+ VKD3D_ASSERT(!modifiers);
spirv_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, val_id);
}
@@ -9563,7 +9614,7 @@ static uint32_t spirv_compiler_emit_query_sample_count(struct spirv_compiler *co
if (src->reg.type == VKD3DSPR_RASTERIZER)
{
val_id = spirv_compiler_emit_shader_parameter(compiler,
- VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT, VKD3D_DATA_UINT);
+ VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT, VKD3D_DATA_UINT, 1);
}
else
{
@@ -10611,7 +10662,9 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct
{
uint32_t type_id, struct_id, ptr_type_id, var_id;
- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
+ type_id = vkd3d_spirv_get_type_id(builder,
+ vkd3d_component_type_from_data_type(parameter_data_type_map[parameter->data_type].type),
+ parameter_data_type_map[parameter->data_type].component_count);
struct_id = vkd3d_spirv_build_op_type_struct(builder, &type_id, 1);
vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBlock, NULL, 0);
diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c
index 389946e2c2f..00a525c9ac3 100644
--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c
+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c
@@ -3649,6 +3649,48 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un
return extern_resources;
}
+/* For some reason, for matrices, values from default value initializers end up in different
+ * components than from regular initializers. Default value initializers fill the matrix in
+ * vertical reading order (left-to-right top-to-bottom) instead of regular reading order
+ * (top-to-bottom left-to-right), so they have to be adjusted.
+ * An exception is that the order of matrix initializers for function parameters are row-major
+ * (top-to-bottom left-to-right). */
+static unsigned int get_component_index_from_default_initializer_index(struct hlsl_type *type, unsigned int index)
+{
+ unsigned int element_comp_count, element, x, y, i;
+ unsigned int base = 0;
+
+ switch (type->class)
+ {
+ case HLSL_CLASS_MATRIX:
+ x = index / type->dimy;
+ y = index % type->dimy;
+ return y * type->dimx + x;
+
+ case HLSL_CLASS_ARRAY:
+ element_comp_count = hlsl_type_component_count(type->e.array.type);
+ element = index / element_comp_count;
+ base = element * element_comp_count;
+ return base + get_component_index_from_default_initializer_index(type->e.array.type, index - base);
+
+ case HLSL_CLASS_STRUCT:
+ for (i = 0; i < type->e.record.field_count; ++i)
+ {
+ struct hlsl_type *field_type = type->e.record.fields[i].type;
+
+ element_comp_count = hlsl_type_component_count(field_type);
+ if (index - base < element_comp_count)
+ return base + get_component_index_from_default_initializer_index(field_type, index - base);
+ base += element_comp_count;
+ }
+ break;
+
+ default:
+ return index;
+ }
+ vkd3d_unreachable();
+}
+
static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
{
uint32_t binding_desc_size = (hlsl_version_ge(ctx, 5, 1) ? 10 : 8) * sizeof(uint32_t);
@@ -3849,7 +3891,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
for (k = 0; k < comp_count; ++k)
{
struct hlsl_type *comp_type = hlsl_type_get_component_type(ctx, var->data_type, k);
- unsigned int comp_offset;
+ unsigned int comp_offset, comp_index;
enum hlsl_regset regset;
if (comp_type->class == HLSL_CLASS_STRING)
@@ -3859,7 +3901,8 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
continue;
}
- comp_offset = hlsl_type_get_component_offset(ctx, var->data_type, k, &regset);
+ comp_index = get_component_index_from_default_initializer_index(var->data_type, k);
+ comp_offset = hlsl_type_get_component_offset(ctx, var->data_type, comp_index, &regset);
if (regset == HLSL_REGSET_NUMERIC)
{
if (comp_type->e.numeric.type == HLSL_TYPE_DOUBLE)
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
index 112bdc4da7f..d9d5b4a405e 100644
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -161,6 +161,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT = 5036,
VKD3D_SHADER_ERROR_HLSL_INVALID_OUTPUT_PRIMITIVE = 5037,
VKD3D_SHADER_ERROR_HLSL_INVALID_PARTITIONING = 5038,
+ VKD3D_SHADER_ERROR_HLSL_MISPLACED_SAMPLER_STATE = 5039,
VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300,
VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301,
@@ -241,6 +242,8 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE = 9017,
VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION = 9018,
VKD3D_SHADER_ERROR_VSIR_INVALID_GS = 9019,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER = 9020,
+ VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC = 9021,
VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300,
--
2.45.2