mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
1978 lines
83 KiB
Diff
1978 lines
83 KiB
Diff
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 *)¶meter->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, ®set);
|
|
+ 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, ®set);
|
|
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
|
|
|