mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
1534 lines
66 KiB
Diff
1534 lines
66 KiB
Diff
From 52de9a875b2a75a0d32486b990e685fed075bcab Mon Sep 17 00:00:00 2001
|
|
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
|
Date: Fri, 11 Oct 2024 07:30:59 +1100
|
|
Subject: [PATCH] Updated vkd3d to cd249a47b86545fe0b3a4b477f854965e858b744.
|
|
|
|
---
|
|
libs/vkd3d/include/vkd3d_shader.h | 52 +++
|
|
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 26 +-
|
|
libs/vkd3d/libs/vkd3d-shader/glsl.c | 297 +++++++++++++--
|
|
libs/vkd3d/libs/vkd3d-shader/ir.c | 349 ++++++++++++++++--
|
|
libs/vkd3d/libs/vkd3d-shader/msl.c | 226 +++++++++++-
|
|
libs/vkd3d/libs/vkd3d-shader/spirv.c | 35 +-
|
|
.../libs/vkd3d-shader/vkd3d_shader_main.c | 5 +-
|
|
.../libs/vkd3d-shader/vkd3d_shader_private.h | 11 +
|
|
8 files changed, 921 insertions(+), 80 deletions(-)
|
|
|
|
diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h
|
|
index d08ee74a3a0..e22f236ecd1 100644
|
|
--- a/libs/vkd3d/include/vkd3d_shader.h
|
|
+++ b/libs/vkd3d/include/vkd3d_shader.h
|
|
@@ -648,6 +648,58 @@ enum vkd3d_shader_parameter_name
|
|
VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_5,
|
|
VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_6,
|
|
VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_7,
|
|
+ /**
|
|
+ * Point size.
|
|
+ *
|
|
+ * When this parameter is provided to a vertex, tessellation, or geometry
|
|
+ * shader, and the source shader does not write point size, it specifies a
|
|
+ * uniform value which will be written to point size.
|
|
+ * If the source shader writes point size, this parameter is ignored.
|
|
+ *
|
|
+ * This parameter can be used to implement fixed function point size, as
|
|
+ * present in Direct3D versions 8 and 9, if the target environment does not
|
|
+ * support point size as part of its own fixed-function API (as Vulkan and
|
|
+ * core OpenGL).
|
|
+ *
|
|
+ * The data type for this parameter must be
|
|
+ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32.
|
|
+ *
|
|
+ * \since 1.14
|
|
+ */
|
|
+ VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE,
|
|
+ /**
|
|
+ * Minimum point size.
|
|
+ *
|
|
+ * When this parameter is provided to a vertex, tessellation, or geometry
|
|
+ * shader, and the source shader writes point size or uses the
|
|
+ * VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE parameter, the point size will
|
|
+ * be clamped to the provided minimum value.
|
|
+ * If point size is not written in one of these ways,
|
|
+ * this parameter is ignored.
|
|
+ * If this parameter is not provided, the point size will not be clamped
|
|
+ * to a minimum size by vkd3d-shader.
|
|
+ *
|
|
+ * This parameter can be used to implement fixed function point size, as
|
|
+ * present in Direct3D versions 8 and 9, if the target environment does not
|
|
+ * support point size as part of its own fixed-function API (as Vulkan and
|
|
+ * core OpenGL).
|
|
+ *
|
|
+ * The data type for this parameter must be
|
|
+ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32.
|
|
+ *
|
|
+ * \since 1.14
|
|
+ */
|
|
+ VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MIN,
|
|
+ /**
|
|
+ * Maximum point size.
|
|
+ *
|
|
+ * This parameter has identical behaviour to
|
|
+ * VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MIN, except that it provides
|
|
+ * the maximum size rather than the minimum.
|
|
+ *
|
|
+ * \since 1.14
|
|
+ */
|
|
+ VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MAX,
|
|
|
|
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME),
|
|
};
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
index 589b800f8c9..44b1714b56b 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
@@ -110,13 +110,6 @@ enum vkd3d_sm1_misc_register
|
|
VKD3D_SM1_MISC_FACE = 0x1,
|
|
};
|
|
|
|
-enum vkd3d_sm1_rastout_register
|
|
-{
|
|
- VKD3D_SM1_RASTOUT_POSITION = 0x0,
|
|
- VKD3D_SM1_RASTOUT_FOG = 0x1,
|
|
- VKD3D_SM1_RASTOUT_POINT_SIZE = 0x2,
|
|
-};
|
|
-
|
|
enum vkd3d_sm1_opcode
|
|
{
|
|
VKD3D_SM1_OP_NOP = 0x00,
|
|
@@ -957,6 +950,9 @@ static void shader_sm1_read_dst_param(struct vkd3d_shader_sm1_parser *sm1, const
|
|
shader_sm1_parse_src_param(addr_token, NULL, dst_rel_addr);
|
|
}
|
|
shader_sm1_parse_dst_param(token, dst_rel_addr, dst_param);
|
|
+
|
|
+ if (dst_param->reg.type == VKD3DSPR_RASTOUT && dst_param->reg.idx[0].offset == VSIR_RASTOUT_POINT_SIZE)
|
|
+ sm1->p.program->has_point_size = true;
|
|
}
|
|
|
|
static void shader_sm1_read_semantic(struct vkd3d_shader_sm1_parser *sm1,
|
|
@@ -1434,17 +1430,17 @@ bool hlsl_sm1_register_from_semantic(const struct vkd3d_shader_version *version,
|
|
{"vpos", false, VKD3D_SHADER_TYPE_PIXEL, 3, VKD3DSPR_MISCTYPE, VKD3D_SM1_MISC_POSITION},
|
|
|
|
{"color", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_ATTROUT},
|
|
- {"fog", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_FOG},
|
|
- {"position", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_POSITION},
|
|
- {"psize", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_POINT_SIZE},
|
|
- {"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_POSITION},
|
|
+ {"fog", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VSIR_RASTOUT_FOG},
|
|
+ {"position", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VSIR_RASTOUT_POSITION},
|
|
+ {"psize", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VSIR_RASTOUT_POINT_SIZE},
|
|
+ {"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VSIR_RASTOUT_POSITION},
|
|
{"texcoord", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_TEXCRDOUT},
|
|
|
|
{"color", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_ATTROUT},
|
|
- {"fog", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_FOG},
|
|
- {"position", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_POSITION},
|
|
- {"psize", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_POINT_SIZE},
|
|
- {"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_POSITION},
|
|
+ {"fog", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VSIR_RASTOUT_FOG},
|
|
+ {"position", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VSIR_RASTOUT_POSITION},
|
|
+ {"psize", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VSIR_RASTOUT_POINT_SIZE},
|
|
+ {"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VSIR_RASTOUT_POSITION},
|
|
{"texcoord", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_TEXCRDOUT},
|
|
};
|
|
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c
|
|
index 91ee355ed39..c8efdae3386 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/glsl.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c
|
|
@@ -22,7 +22,7 @@ struct glsl_resource_type_info
|
|
{
|
|
size_t coord_size;
|
|
bool shadow;
|
|
- const char *sampler_type;
|
|
+ const char *type_suffix;
|
|
};
|
|
|
|
struct glsl_src
|
|
@@ -102,17 +102,17 @@ static const struct glsl_resource_type_info *shader_glsl_get_resource_type_info(
|
|
{
|
|
static const struct glsl_resource_type_info info[] =
|
|
{
|
|
- {0, 0, "samplerNone"}, /* VKD3D_SHADER_RESOURCE_NONE */
|
|
- {1, 0, "samplerBuffer"}, /* VKD3D_SHADER_RESOURCE_BUFFER */
|
|
- {1, 1, "sampler1D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1D */
|
|
- {2, 1, "sampler2D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2D */
|
|
- {2, 0, "sampler2DMS"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMS */
|
|
- {3, 0, "sampler3D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_3D */
|
|
- {3, 1, "samplerCube"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBE */
|
|
- {2, 1, "sampler1DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY */
|
|
- {3, 1, "sampler2DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY */
|
|
- {3, 0, "sampler2DMSArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY */
|
|
- {4, 1, "samplerCubeArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY */
|
|
+ {0, 0, "None"}, /* VKD3D_SHADER_RESOURCE_NONE */
|
|
+ {1, 0, "Buffer"}, /* VKD3D_SHADER_RESOURCE_BUFFER */
|
|
+ {1, 1, "1D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1D */
|
|
+ {2, 1, "2D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2D */
|
|
+ {2, 0, "2DMS"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMS */
|
|
+ {3, 0, "3D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_3D */
|
|
+ {3, 1, "Cube"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBE */
|
|
+ {2, 1, "1DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY */
|
|
+ {3, 1, "2DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY */
|
|
+ {3, 0, "2DMSArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY */
|
|
+ {4, 1, "CubeArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY */
|
|
};
|
|
|
|
if (!t || t >= ARRAY_SIZE(info))
|
|
@@ -173,6 +173,14 @@ static void shader_glsl_print_combined_sampler_name(struct vkd3d_string_buffer *
|
|
}
|
|
}
|
|
|
|
+static void shader_glsl_print_image_name(struct vkd3d_string_buffer *buffer,
|
|
+ struct vkd3d_glsl_generator *gen, unsigned int idx, unsigned int space)
|
|
+{
|
|
+ vkd3d_string_buffer_printf(buffer, "%s_image_%u", gen->prefix, idx);
|
|
+ if (space)
|
|
+ vkd3d_string_buffer_printf(buffer, "_%u", space);
|
|
+}
|
|
+
|
|
static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer,
|
|
struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_register *reg)
|
|
{
|
|
@@ -363,15 +371,14 @@ static void shader_glsl_print_bitcast(struct vkd3d_string_buffer *dst, struct vk
|
|
vkd3d_string_buffer_printf(dst, "%s", src);
|
|
}
|
|
|
|
-static void glsl_src_init(struct glsl_src *glsl_src, struct vkd3d_glsl_generator *gen,
|
|
- const struct vkd3d_shader_src_param *vsir_src, uint32_t mask)
|
|
+static void shader_glsl_print_src(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen,
|
|
+ const struct vkd3d_shader_src_param *vsir_src, uint32_t mask, enum vkd3d_data_type data_type)
|
|
{
|
|
const struct vkd3d_shader_register *reg = &vsir_src->reg;
|
|
struct vkd3d_string_buffer *register_name, *str;
|
|
enum vkd3d_data_type src_data_type;
|
|
unsigned int size;
|
|
|
|
- glsl_src->str = vkd3d_string_buffer_get(&gen->string_buffers);
|
|
register_name = vkd3d_string_buffer_get(&gen->string_buffers);
|
|
|
|
if (reg->non_uniform)
|
|
@@ -386,12 +393,12 @@ static void glsl_src_init(struct glsl_src *glsl_src, struct vkd3d_glsl_generator
|
|
shader_glsl_print_register_name(register_name, gen, reg);
|
|
|
|
if (!vsir_src->modifiers)
|
|
- str = glsl_src->str;
|
|
+ str = buffer;
|
|
else
|
|
str = vkd3d_string_buffer_get(&gen->string_buffers);
|
|
|
|
size = reg->dimension == VSIR_DIMENSION_VEC4 ? 4 : 1;
|
|
- shader_glsl_print_bitcast(str, gen, register_name->buffer, reg->data_type, src_data_type, size);
|
|
+ shader_glsl_print_bitcast(str, gen, register_name->buffer, data_type, src_data_type, size);
|
|
if (reg->dimension == VSIR_DIMENSION_VEC4)
|
|
shader_glsl_print_swizzle(str, vsir_src->swizzle, mask);
|
|
|
|
@@ -400,24 +407,31 @@ static void glsl_src_init(struct glsl_src *glsl_src, struct vkd3d_glsl_generator
|
|
case VKD3DSPSM_NONE:
|
|
break;
|
|
case VKD3DSPSM_NEG:
|
|
- vkd3d_string_buffer_printf(glsl_src->str, "-%s", str->buffer);
|
|
+ vkd3d_string_buffer_printf(buffer, "-%s", str->buffer);
|
|
break;
|
|
case VKD3DSPSM_ABS:
|
|
- vkd3d_string_buffer_printf(glsl_src->str, "abs(%s)", str->buffer);
|
|
+ vkd3d_string_buffer_printf(buffer, "abs(%s)", str->buffer);
|
|
break;
|
|
default:
|
|
- vkd3d_string_buffer_printf(glsl_src->str, "<unhandled modifier %#x>(%s)",
|
|
+ vkd3d_string_buffer_printf(buffer, "<unhandled modifier %#x>(%s)",
|
|
vsir_src->modifiers, str->buffer);
|
|
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
|
|
"Internal compiler error: Unhandled source modifier(s) %#x.", vsir_src->modifiers);
|
|
break;
|
|
}
|
|
|
|
- if (str != glsl_src->str)
|
|
+ if (str != buffer)
|
|
vkd3d_string_buffer_release(&gen->string_buffers, str);
|
|
vkd3d_string_buffer_release(&gen->string_buffers, register_name);
|
|
}
|
|
|
|
+static void glsl_src_init(struct glsl_src *glsl_src, struct vkd3d_glsl_generator *gen,
|
|
+ const struct vkd3d_shader_src_param *vsir_src, uint32_t mask)
|
|
+{
|
|
+ glsl_src->str = vkd3d_string_buffer_get(&gen->string_buffers);
|
|
+ shader_glsl_print_src(glsl_src->str, gen, vsir_src, mask, vsir_src->reg.data_type);
|
|
+}
|
|
+
|
|
static void glsl_dst_cleanup(struct glsl_dst *dst, struct vkd3d_string_buffer_cache *cache)
|
|
{
|
|
vkd3d_string_buffer_release(cache, dst->mask);
|
|
@@ -892,6 +906,85 @@ static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vk
|
|
glsl_dst_cleanup(&dst, &gen->string_buffers);
|
|
}
|
|
|
|
+static void shader_glsl_store_uav_typed(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins)
|
|
+{
|
|
+ const struct glsl_resource_type_info *resource_type_info;
|
|
+ enum vkd3d_shader_component_type component_type;
|
|
+ const struct vkd3d_shader_descriptor_info1 *d;
|
|
+ enum vkd3d_shader_resource_type resource_type;
|
|
+ unsigned int uav_id, uav_idx, uav_space;
|
|
+ struct vkd3d_string_buffer *image_data;
|
|
+ struct glsl_src image_coord;
|
|
+ uint32_t coord_mask;
|
|
+
|
|
+ if (ins->dst[0].reg.idx[0].rel_addr || ins->dst[0].reg.idx[1].rel_addr)
|
|
+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED,
|
|
+ "Descriptor indexing is not supported.");
|
|
+
|
|
+ uav_id = ins->dst[0].reg.idx[0].offset;
|
|
+ uav_idx = ins->dst[0].reg.idx[1].offset;
|
|
+ if ((d = shader_glsl_get_descriptor_by_id(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, uav_id)))
|
|
+ {
|
|
+ resource_type = d->resource_type;
|
|
+ uav_space = d->register_space;
|
|
+ component_type = vkd3d_component_type_from_resource_data_type(d->resource_data_type);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
|
|
+ "Internal compiler error: Undeclared UAV descriptor %u.", uav_id);
|
|
+ uav_space = 0;
|
|
+ resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D;
|
|
+ component_type = VKD3D_SHADER_COMPONENT_FLOAT;
|
|
+ }
|
|
+
|
|
+ if ((resource_type_info = shader_glsl_get_resource_type_info(resource_type)))
|
|
+ {
|
|
+ coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled UAV type %#x.", resource_type);
|
|
+ coord_mask = vkd3d_write_mask_from_component_count(2);
|
|
+ }
|
|
+
|
|
+ glsl_src_init(&image_coord, gen, &ins->src[0], coord_mask);
|
|
+ image_data = vkd3d_string_buffer_get(&gen->string_buffers);
|
|
+
|
|
+ if (ins->src[1].reg.dimension == VSIR_DIMENSION_SCALAR)
|
|
+ {
|
|
+ switch (component_type)
|
|
+ {
|
|
+ case VKD3D_SHADER_COMPONENT_UINT:
|
|
+ vkd3d_string_buffer_printf(image_data, "uvec4(");
|
|
+ break;
|
|
+ case VKD3D_SHADER_COMPONENT_INT:
|
|
+ vkd3d_string_buffer_printf(image_data, "ivec4(");
|
|
+ break;
|
|
+ default:
|
|
+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled component type %#x.", component_type);
|
|
+ /* fall through */
|
|
+ case VKD3D_SHADER_COMPONENT_FLOAT:
|
|
+ vkd3d_string_buffer_printf(image_data, "vec4(");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ shader_glsl_print_src(image_data, gen, &ins->src[1], VKD3DSP_WRITEMASK_ALL,
|
|
+ vkd3d_data_type_from_component_type(component_type));
|
|
+ if (ins->src[1].reg.dimension == VSIR_DIMENSION_SCALAR)
|
|
+ vkd3d_string_buffer_printf(image_data, ", 0, 0, 0)");
|
|
+
|
|
+ shader_glsl_print_indent(gen->buffer, gen->indent);
|
|
+ vkd3d_string_buffer_printf(gen->buffer, "imageStore(");
|
|
+ shader_glsl_print_image_name(gen->buffer, gen, uav_idx, uav_space);
|
|
+ vkd3d_string_buffer_printf(gen->buffer, ", %s, %s);\n", image_coord.str->buffer, image_data->buffer);
|
|
+
|
|
+ vkd3d_string_buffer_release(&gen->string_buffers, image_data);
|
|
+ glsl_src_cleanup(&image_coord, &gen->string_buffers);
|
|
+}
|
|
+
|
|
static void shader_glsl_unary_op(struct vkd3d_glsl_generator *gen,
|
|
const struct vkd3d_shader_instruction *ins, const char *op)
|
|
{
|
|
@@ -1336,6 +1429,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen,
|
|
case VKD3DSIH_SQRT:
|
|
shader_glsl_intrinsic(gen, ins, "sqrt");
|
|
break;
|
|
+ case VKD3DSIH_STORE_UAV_TYPED:
|
|
+ shader_glsl_store_uav_typed(gen, ins);
|
|
+ break;
|
|
case VKD3DSIH_SWITCH:
|
|
shader_glsl_switch(gen, ins);
|
|
break;
|
|
@@ -1372,6 +1468,137 @@ static bool shader_glsl_check_shader_visibility(const struct vkd3d_glsl_generato
|
|
}
|
|
}
|
|
|
|
+static bool shader_glsl_get_uav_binding(const struct vkd3d_glsl_generator *gen, unsigned int register_space,
|
|
+ unsigned int register_idx, enum vkd3d_shader_resource_type resource_type, unsigned int *binding_idx)
|
|
+{
|
|
+ const struct vkd3d_shader_interface_info *interface_info = gen->interface_info;
|
|
+ const struct vkd3d_shader_resource_binding *binding;
|
|
+ enum vkd3d_shader_binding_flag resource_type_flag;
|
|
+ unsigned int i;
|
|
+
|
|
+ if (!interface_info)
|
|
+ return false;
|
|
+
|
|
+ resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER
|
|
+ ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE;
|
|
+
|
|
+ for (i = 0; i < interface_info->binding_count; ++i)
|
|
+ {
|
|
+ binding = &interface_info->bindings[i];
|
|
+
|
|
+ if (binding->type != VKD3D_SHADER_DESCRIPTOR_TYPE_UAV)
|
|
+ continue;
|
|
+ if (binding->register_space != register_space)
|
|
+ continue;
|
|
+ if (binding->register_index != register_idx)
|
|
+ continue;
|
|
+ if (!shader_glsl_check_shader_visibility(gen, binding->shader_visibility))
|
|
+ continue;
|
|
+ if (!(binding->flags & resource_type_flag))
|
|
+ continue;
|
|
+ *binding_idx = i;
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static void shader_glsl_generate_uav_declaration(struct vkd3d_glsl_generator *gen,
|
|
+ const struct vkd3d_shader_descriptor_info1 *uav)
|
|
+{
|
|
+ const struct glsl_resource_type_info *resource_type_info;
|
|
+ const char *image_type_prefix, *image_type, *read_format;
|
|
+ const struct vkd3d_shader_descriptor_binding *binding;
|
|
+ const struct vkd3d_shader_descriptor_offset *offset;
|
|
+ struct vkd3d_string_buffer *buffer = gen->buffer;
|
|
+ enum vkd3d_shader_component_type component_type;
|
|
+ unsigned int binding_idx;
|
|
+
|
|
+ if (uav->count != 1)
|
|
+ {
|
|
+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED,
|
|
+ "UAV %u has unsupported descriptor array size %u.", uav->register_id, uav->count);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (!shader_glsl_get_uav_binding(gen, uav->register_space,
|
|
+ uav->register_index, uav->resource_type, &binding_idx))
|
|
+ {
|
|
+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND,
|
|
+ "No descriptor binding specified for UAV %u.", uav->register_id);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ binding = &gen->interface_info->bindings[binding_idx].binding;
|
|
+
|
|
+ if (binding->set != 0)
|
|
+ {
|
|
+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND,
|
|
+ "Unsupported binding set %u specified for UAV %u.", binding->set, uav->register_id);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (binding->count != 1)
|
|
+ {
|
|
+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND,
|
|
+ "Unsupported binding count %u specified for UAV %u.", binding->count, uav->register_id);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (gen->offset_info && gen->offset_info->binding_offsets)
|
|
+ {
|
|
+ offset = &gen->offset_info->binding_offsets[binding_idx];
|
|
+ if (offset->static_offset || offset->dynamic_offset_index != ~0u)
|
|
+ {
|
|
+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled descriptor offset specified for UAV %u.",
|
|
+ uav->register_id);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if ((resource_type_info = shader_glsl_get_resource_type_info(uav->resource_type)))
|
|
+ {
|
|
+ image_type = resource_type_info->type_suffix;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled UAV type %#x.", uav->resource_type);
|
|
+ image_type = "<unhandled image type>";
|
|
+ }
|
|
+
|
|
+ switch ((component_type = vkd3d_component_type_from_resource_data_type(uav->resource_data_type)))
|
|
+ {
|
|
+ case VKD3D_SHADER_COMPONENT_UINT:
|
|
+ image_type_prefix = "u";
|
|
+ read_format = "r32ui";
|
|
+ break;
|
|
+ case VKD3D_SHADER_COMPONENT_INT:
|
|
+ image_type_prefix = "i";
|
|
+ read_format = "r32i";
|
|
+ break;
|
|
+ default:
|
|
+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled component type %#x for UAV %u.",
|
|
+ component_type, uav->register_id);
|
|
+ /* fall through */
|
|
+ case VKD3D_SHADER_COMPONENT_FLOAT:
|
|
+ image_type_prefix = "";
|
|
+ read_format = "r32f";
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ vkd3d_string_buffer_printf(buffer, "layout(binding = %u", binding->binding);
|
|
+ if (uav->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ)
|
|
+ vkd3d_string_buffer_printf(buffer, ", %s) ", read_format);
|
|
+ else
|
|
+ vkd3d_string_buffer_printf(buffer, ") writeonly ");
|
|
+ vkd3d_string_buffer_printf(buffer, "uniform %simage%s ", image_type_prefix, image_type);
|
|
+ shader_glsl_print_image_name(buffer, gen, uav->register_index, uav->register_space);
|
|
+ vkd3d_string_buffer_printf(buffer, ";\n");
|
|
+}
|
|
+
|
|
static bool shader_glsl_get_cbv_binding(const struct vkd3d_glsl_generator *gen,
|
|
unsigned int register_space, unsigned int register_idx, unsigned int *binding_idx)
|
|
{
|
|
@@ -1415,7 +1642,7 @@ static void shader_glsl_generate_cbv_declaration(struct vkd3d_glsl_generator *ge
|
|
|
|
if (cbv->count != 1)
|
|
{
|
|
- vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND,
|
|
+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED,
|
|
"Constant buffer %u has unsupported descriptor array size %u.", cbv->register_id, cbv->count);
|
|
return;
|
|
}
|
|
@@ -1540,7 +1767,7 @@ static void shader_glsl_generate_sampler_declaration(struct vkd3d_glsl_generator
|
|
|
|
if ((resource_type_info = shader_glsl_get_resource_type_info(srv->resource_type)))
|
|
{
|
|
- sampler_type = resource_type_info->sampler_type;
|
|
+ sampler_type = resource_type_info->type_suffix;
|
|
if (shadow && !resource_type_info->shadow)
|
|
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED,
|
|
"Comparison samplers are not supported with resource type %#x.", srv->resource_type);
|
|
@@ -1603,7 +1830,7 @@ static void shader_glsl_generate_sampler_declaration(struct vkd3d_glsl_generator
|
|
return;
|
|
}
|
|
|
|
- vkd3d_string_buffer_printf(buffer, "layout(binding = %u) uniform %s%s%s ",
|
|
+ vkd3d_string_buffer_printf(buffer, "layout(binding = %u) uniform %ssampler%s%s ",
|
|
binding->binding, sampler_type_prefix, sampler_type, shadow ? "Shadow" : "");
|
|
shader_glsl_print_combined_sampler_name(buffer, gen, crs->resource_index,
|
|
crs->resource_space, crs->sampler_index, crs->sampler_space);
|
|
@@ -1628,6 +1855,10 @@ static void shader_glsl_generate_descriptor_declarations(struct vkd3d_glsl_gener
|
|
/* GLSL uses combined resource/sampler descriptors.*/
|
|
break;
|
|
|
|
+ case VKD3D_SHADER_DESCRIPTOR_TYPE_UAV:
|
|
+ shader_glsl_generate_uav_declaration(gen, descriptor);
|
|
+ break;
|
|
+
|
|
case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV:
|
|
shader_glsl_generate_cbv_declaration(gen, descriptor);
|
|
break;
|
|
@@ -1820,7 +2051,7 @@ static void shader_glsl_generate_output_declarations(struct vkd3d_glsl_generator
|
|
"Internal compiler error: Unhandled output component type %#x.", e->component_type);
|
|
break;
|
|
}
|
|
- vkd3d_string_buffer_printf(buffer, " shader_out_%u;\n", i);
|
|
+ vkd3d_string_buffer_printf(buffer, " shader_out_%u;\n", e->semantic_index);
|
|
++count;
|
|
}
|
|
if (count)
|
|
@@ -1837,6 +2068,14 @@ static void shader_glsl_generate_declarations(struct vkd3d_glsl_generator *gen)
|
|
{
|
|
const struct vsir_program *program = gen->program;
|
|
struct vkd3d_string_buffer *buffer = gen->buffer;
|
|
+ const struct vsir_thread_group_size *group_size;
|
|
+
|
|
+ if (program->shader_version.type == VKD3D_SHADER_TYPE_COMPUTE)
|
|
+ {
|
|
+ group_size = &program->thread_group_size;
|
|
+ vkd3d_string_buffer_printf(buffer, "layout(local_size_x = %u, local_size_y = %u, local_size_z = %u) in;\n\n",
|
|
+ group_size->x, group_size->y, group_size->z);
|
|
+ }
|
|
|
|
shader_glsl_generate_descriptor_declarations(gen);
|
|
shader_glsl_generate_input_declarations(gen);
|
|
@@ -1918,6 +2157,10 @@ static void shader_glsl_init_limits(struct vkd3d_glsl_generator *gen, const stru
|
|
limits->input_count = 32;
|
|
limits->output_count = 8;
|
|
break;
|
|
+ case VKD3D_SHADER_TYPE_COMPUTE:
|
|
+ limits->input_count = 0;
|
|
+ limits->output_count = 0;
|
|
+ break;
|
|
default:
|
|
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
|
|
"Internal compiler error: Unhandled shader type %#x.", version->type);
|
|
@@ -1948,8 +2191,8 @@ static void vkd3d_glsl_generator_init(struct vkd3d_glsl_generator *gen,
|
|
gen->prefix = "unknown";
|
|
}
|
|
shader_glsl_init_limits(gen, &program->shader_version);
|
|
- gen->interstage_input = type != VKD3D_SHADER_TYPE_VERTEX;
|
|
- gen->interstage_output = type != VKD3D_SHADER_TYPE_PIXEL;
|
|
+ gen->interstage_input = type != VKD3D_SHADER_TYPE_VERTEX && type != VKD3D_SHADER_TYPE_COMPUTE;
|
|
+ gen->interstage_output = type != VKD3D_SHADER_TYPE_PIXEL && type != VKD3D_SHADER_TYPE_COMPUTE;
|
|
|
|
gen->interface_info = vkd3d_find_struct(compile_info->next, INTERFACE_INFO);
|
|
gen->offset_info = vkd3d_find_struct(compile_info->next, DESCRIPTOR_OFFSET_INFO);
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
index affbae3ea4e..9d24126fba8 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
@@ -203,6 +203,12 @@ static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned
|
|
src->reg.idx[0].offset = idx;
|
|
}
|
|
|
|
+static void src_param_init_ssa_float(struct vkd3d_shader_src_param *src, unsigned int idx)
|
|
+{
|
|
+ vsir_src_param_init(src, VKD3DSPR_SSA, VKD3D_DATA_FLOAT, 1);
|
|
+ src->reg.idx[0].offset = idx;
|
|
+}
|
|
+
|
|
static void src_param_init_temp_bool(struct vkd3d_shader_src_param *src, unsigned int idx)
|
|
{
|
|
vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_BOOL, 1);
|
|
@@ -244,6 +250,12 @@ static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned
|
|
dst->reg.idx[0].offset = idx;
|
|
}
|
|
|
|
+static void dst_param_init_ssa_float(struct vkd3d_shader_dst_param *dst, unsigned int idx)
|
|
+{
|
|
+ vsir_dst_param_init(dst, VKD3DSPR_SSA, VKD3D_DATA_FLOAT, 1);
|
|
+ dst->reg.idx[0].offset = idx;
|
|
+}
|
|
+
|
|
static void dst_param_init_temp_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx)
|
|
{
|
|
vsir_dst_param_init(dst, VKD3DSPR_TEMP, VKD3D_DATA_BOOL, 1);
|
|
@@ -254,7 +266,6 @@ static void dst_param_init_temp_uint(struct vkd3d_shader_dst_param *dst, unsigne
|
|
{
|
|
vsir_dst_param_init(dst, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1);
|
|
dst->reg.idx[0].offset = idx;
|
|
- dst->write_mask = VKD3DSP_WRITEMASK_0;
|
|
}
|
|
|
|
void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location,
|
|
@@ -682,6 +693,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr
|
|
case VKD3DSIH_DCL_SAMPLER:
|
|
case VKD3DSIH_DCL_TEMPS:
|
|
case VKD3DSIH_DCL_THREAD_GROUP:
|
|
+ case VKD3DSIH_DCL_UAV_TYPED:
|
|
vkd3d_shader_instruction_make_nop(ins);
|
|
break;
|
|
|
|
@@ -1221,7 +1233,7 @@ static bool shader_signature_find_element_for_reg(const struct shader_signature
|
|
unsigned int reg_idx, unsigned int write_mask, unsigned int *element_idx)
|
|
{
|
|
const struct signature_element *e;
|
|
- unsigned int i, base_write_mask;
|
|
+ unsigned int i;
|
|
|
|
for (i = 0; i < signature->element_count; ++i)
|
|
{
|
|
@@ -1234,14 +1246,6 @@ static bool shader_signature_find_element_for_reg(const struct shader_signature
|
|
}
|
|
}
|
|
|
|
- /* Validated in the TPF reader, but failure in signature_element_range_expand_mask()
|
|
- * can land us here on an unmatched vector mask. */
|
|
- FIXME("Failed to find signature element for register index %u, mask %#x; using scalar mask.\n",
|
|
- reg_idx, write_mask);
|
|
- base_write_mask = 1u << vsir_write_mask_get_component_idx(write_mask);
|
|
- if (base_write_mask != write_mask)
|
|
- return shader_signature_find_element_for_reg(signature, reg_idx, base_write_mask, element_idx);
|
|
-
|
|
return false;
|
|
}
|
|
|
|
@@ -1655,6 +1659,9 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par
|
|
break;
|
|
|
|
case VKD3DSPR_RASTOUT:
|
|
+ /* Leave point size as a system value for the backends to consume. */
|
|
+ if (reg->idx[0].offset == VSIR_RASTOUT_POINT_SIZE)
|
|
+ return true;
|
|
reg_idx = SM1_RASTOUT_REGISTER_OFFSET + reg->idx[0].offset;
|
|
signature = normaliser->output_signature;
|
|
reg->type = VKD3DSPR_OUTPUT;
|
|
@@ -5777,11 +5784,12 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog
|
|
return VKD3D_OK;
|
|
}
|
|
|
|
-static bool find_position_signature_idx(const struct shader_signature *signature, uint32_t *idx)
|
|
+static bool find_sysval_signature_idx(const struct shader_signature *signature,
|
|
+ enum vkd3d_shader_sysval_semantic sysval, uint32_t *idx)
|
|
{
|
|
for (unsigned int i = 0; i < signature->element_count; ++i)
|
|
{
|
|
- if (signature->elements[i].sysval_semantic == VKD3D_SHADER_SV_POSITION)
|
|
+ if (signature->elements[i].sysval_semantic == sysval)
|
|
{
|
|
*idx = i;
|
|
return true;
|
|
@@ -5846,7 +5854,7 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr
|
|
}
|
|
}
|
|
|
|
- if (!find_position_signature_idx(signature, &position_signature_idx))
|
|
+ if (!find_sysval_signature_idx(signature, VKD3D_SHADER_SV_POSITION, &position_signature_idx))
|
|
{
|
|
vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC,
|
|
"Shader does not write position.");
|
|
@@ -5923,6 +5931,191 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr
|
|
return VKD3D_OK;
|
|
}
|
|
|
|
+static enum vkd3d_result insert_point_size_before_ret(struct vsir_program *program,
|
|
+ const struct vkd3d_shader_instruction *ret, size_t *ret_pos)
|
|
+{
|
|
+ struct vkd3d_shader_instruction_array *instructions = &program->instructions;
|
|
+ size_t pos = ret - instructions->elements;
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+
|
|
+ if (!shader_instruction_array_insert_at(&program->instructions, pos, 1))
|
|
+ return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
+
|
|
+ ins = &program->instructions.elements[pos];
|
|
+
|
|
+ vsir_instruction_init_with_params(program, ins, &ret->location, VKD3DSIH_MOV, 1, 1);
|
|
+ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1);
|
|
+ ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE;
|
|
+ src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE, VKD3D_DATA_FLOAT);
|
|
+
|
|
+ *ret_pos = pos + 1;
|
|
+ return VKD3D_OK;
|
|
+}
|
|
+
|
|
+static enum vkd3d_result vsir_program_insert_point_size(struct vsir_program *program,
|
|
+ struct vsir_transformation_context *ctx)
|
|
+{
|
|
+ const struct vkd3d_shader_parameter1 *size_parameter = NULL;
|
|
+ static const struct vkd3d_shader_location no_loc;
|
|
+
|
|
+ if (program->has_point_size)
|
|
+ return VKD3D_OK;
|
|
+
|
|
+ if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX
|
|
+ && program->shader_version.type != VKD3D_SHADER_TYPE_GEOMETRY
|
|
+ && program->shader_version.type != VKD3D_SHADER_TYPE_HULL
|
|
+ && program->shader_version.type != VKD3D_SHADER_TYPE_DOMAIN)
|
|
+ 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_POINT_SIZE)
|
|
+ size_parameter = parameter;
|
|
+ }
|
|
+
|
|
+ if (!size_parameter)
|
|
+ return VKD3D_OK;
|
|
+
|
|
+ if (size_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32)
|
|
+ {
|
|
+ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE,
|
|
+ "Invalid point size parameter data type %#x.", size_parameter->data_type);
|
|
+ return VKD3D_ERROR_INVALID_ARGUMENT;
|
|
+ }
|
|
+
|
|
+ program->has_point_size = true;
|
|
+
|
|
+ /* Append a point size write before each ret. */
|
|
+ for (size_t i = 0; i < program->instructions.count; ++i)
|
|
+ {
|
|
+ struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
|
|
+
|
|
+ if (ins->opcode == VKD3DSIH_RET)
|
|
+ {
|
|
+ size_t new_pos;
|
|
+ int ret;
|
|
+
|
|
+ if ((ret = insert_point_size_before_ret(program, ins, &new_pos)) < 0)
|
|
+ return ret;
|
|
+ i = new_pos;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return VKD3D_OK;
|
|
+}
|
|
+
|
|
+static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_program *program,
|
|
+ struct vsir_transformation_context *ctx)
|
|
+{
|
|
+ const struct vkd3d_shader_parameter1 *min_parameter = NULL, *max_parameter = NULL;
|
|
+ static const struct vkd3d_shader_location no_loc;
|
|
+
|
|
+ if (!program->has_point_size)
|
|
+ return VKD3D_OK;
|
|
+
|
|
+ if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX
|
|
+ && program->shader_version.type != VKD3D_SHADER_TYPE_GEOMETRY
|
|
+ && program->shader_version.type != VKD3D_SHADER_TYPE_HULL
|
|
+ && program->shader_version.type != VKD3D_SHADER_TYPE_DOMAIN)
|
|
+ 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_POINT_SIZE_MIN)
|
|
+ min_parameter = parameter;
|
|
+ else if (parameter->name == VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MAX)
|
|
+ max_parameter = parameter;
|
|
+ }
|
|
+
|
|
+ if (!min_parameter && !max_parameter)
|
|
+ return VKD3D_OK;
|
|
+
|
|
+ if (min_parameter && min_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32)
|
|
+ {
|
|
+ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE,
|
|
+ "Invalid minimum point size parameter data type %#x.", min_parameter->data_type);
|
|
+ return VKD3D_ERROR_INVALID_ARGUMENT;
|
|
+ }
|
|
+
|
|
+ if (max_parameter && max_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32)
|
|
+ {
|
|
+ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE,
|
|
+ "Invalid maximum point size parameter data type %#x.", max_parameter->data_type);
|
|
+ return VKD3D_ERROR_INVALID_ARGUMENT;
|
|
+ }
|
|
+
|
|
+ /* Replace writes to the point size by inserting a clamp before each write. */
|
|
+
|
|
+ for (size_t i = 0; i < program->instructions.count; ++i)
|
|
+ {
|
|
+ struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
|
|
+ const struct vkd3d_shader_location *loc;
|
|
+ unsigned int ssa_value;
|
|
+ bool clamp = false;
|
|
+
|
|
+ if (vsir_instruction_is_dcl(ins))
|
|
+ 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_RASTOUT)
|
|
+ {
|
|
+ dst_param_init_ssa_float(dst, program->ssa_count);
|
|
+ ssa_value = program->ssa_count++;
|
|
+ clamp = true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!clamp)
|
|
+ continue;
|
|
+
|
|
+ if (!shader_instruction_array_insert_at(&program->instructions, i + 1, !!min_parameter + !!max_parameter))
|
|
+ return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
+
|
|
+ loc = &program->instructions.elements[i].location;
|
|
+ ins = &program->instructions.elements[i + 1];
|
|
+
|
|
+ if (min_parameter)
|
|
+ {
|
|
+ vsir_instruction_init_with_params(program, ins, loc, VKD3DSIH_MAX, 1, 2);
|
|
+ src_param_init_ssa_float(&ins->src[0], ssa_value);
|
|
+ src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MIN, VKD3D_DATA_FLOAT);
|
|
+ if (max_parameter)
|
|
+ {
|
|
+ dst_param_init_ssa_float(&ins->dst[0], program->ssa_count);
|
|
+ ssa_value = program->ssa_count++;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1);
|
|
+ ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE;
|
|
+ }
|
|
+ ++ins;
|
|
+ ++i;
|
|
+ }
|
|
+
|
|
+ if (max_parameter)
|
|
+ {
|
|
+ vsir_instruction_init_with_params(program, ins, loc, VKD3DSIH_MIN, 1, 2);
|
|
+ src_param_init_ssa_float(&ins->src[0], ssa_value);
|
|
+ src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MAX, VKD3D_DATA_FLOAT);
|
|
+ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1);
|
|
+ ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE;
|
|
+
|
|
+ ++i;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return VKD3D_OK;
|
|
+}
|
|
+
|
|
struct validation_context
|
|
{
|
|
struct vkd3d_shader_message_context *message_context;
|
|
@@ -6395,23 +6588,18 @@ static void vsir_validate_dst_param(struct validation_context *ctx,
|
|
break;
|
|
|
|
case VKD3DSPR_IMMCONST:
|
|
- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
- "Invalid IMMCONST register used as destination parameter.");
|
|
- break;
|
|
-
|
|
case VKD3DSPR_IMMCONST64:
|
|
- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
- "Invalid IMMCONST64 register used as destination parameter.");
|
|
- break;
|
|
-
|
|
case VKD3DSPR_SAMPLER:
|
|
+ case VKD3DSPR_RESOURCE:
|
|
+ case VKD3DSPR_INPUT:
|
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
- "Invalid SAMPLER register used as destination parameter.");
|
|
+ "Invalid %#x register used as destination parameter.", dst->reg.type);
|
|
break;
|
|
|
|
- case VKD3DSPR_RESOURCE:
|
|
- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
- "Invalid RESOURCE register used as destination parameter.");
|
|
+ case VKD3DSPR_PATCHCONST:
|
|
+ if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
+ "PATCHCONST register used as destination parameters are only allowed in Hull Shaders.");
|
|
break;
|
|
|
|
default:
|
|
@@ -6454,6 +6642,20 @@ static void vsir_validate_src_param(struct validation_context *ctx,
|
|
"Invalid NULL register used as source parameter.");
|
|
break;
|
|
|
|
+ case VKD3DSPR_OUTPUT:
|
|
+ if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL
|
|
+ || (ctx->phase != VKD3DSIH_HS_FORK_PHASE && ctx->phase != VKD3DSIH_HS_JOIN_PHASE))
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
+ "Invalid OUTPUT register used as source parameter.");
|
|
+ break;
|
|
+
|
|
+ case VKD3DSPR_PATCHCONST:
|
|
+ if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_DOMAIN
|
|
+ && ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE,
|
|
+ "PATCHCONST register used as source parameters are only allowed in Hull and Domain Shaders.");
|
|
+ break;
|
|
+
|
|
default:
|
|
break;
|
|
}
|
|
@@ -6510,6 +6712,7 @@ static void vsir_validate_signature_element(struct validation_context *ctx,
|
|
unsigned int idx)
|
|
{
|
|
const struct signature_element *element = &signature->elements[idx];
|
|
+ bool integer_type = false;
|
|
|
|
if (element->register_count == 0)
|
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
@@ -6518,6 +6721,97 @@ static void vsir_validate_signature_element(struct validation_context *ctx,
|
|
if (element->mask == 0 || (element->mask & ~0xf))
|
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
"element %u of %s signature: Invalid mask %#x.", idx, signature_type, element->mask);
|
|
+
|
|
+ /* Here we'd likely want to validate that the usage mask is a subset of the
|
|
+ * signature mask. Unfortunately the D3DBC parser sometimes violates this.
|
|
+ * For example I've seen a shader like this:
|
|
+ * ps_3_0
|
|
+ * [...]
|
|
+ * dcl_texcoord0 v0
|
|
+ * [...]
|
|
+ * texld r2.xyzw, v0.xyzw, s1.xyzw
|
|
+ * [...]
|
|
+ *
|
|
+ * The dcl_textcoord0 instruction secretly has a .xy mask, which is used to
|
|
+ * compute the signature mask, but the texld instruction apparently uses all
|
|
+ * the components. Of course the last two components are ignored, but
|
|
+ * formally they seem to be used. So we end up with a signature element with
|
|
+ * mask .xy and usage mask .xyzw.
|
|
+ *
|
|
+ * The correct fix would probably be to make the D3DBC parser aware of which
|
|
+ * components are really used for each instruction, but that would take some
|
|
+ * time. */
|
|
+ if (element->used_mask & ~0xf)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
+ "element %u of %s signature: Invalid usage mask %#x.",
|
|
+ idx, signature_type, element->used_mask);
|
|
+
|
|
+ switch (element->sysval_semantic)
|
|
+ {
|
|
+ case VKD3D_SHADER_SV_NONE:
|
|
+ case VKD3D_SHADER_SV_POSITION:
|
|
+ case VKD3D_SHADER_SV_CLIP_DISTANCE:
|
|
+ case VKD3D_SHADER_SV_CULL_DISTANCE:
|
|
+ case VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX:
|
|
+ case VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX:
|
|
+ case VKD3D_SHADER_SV_VERTEX_ID:
|
|
+ case VKD3D_SHADER_SV_PRIMITIVE_ID:
|
|
+ case VKD3D_SHADER_SV_INSTANCE_ID:
|
|
+ case VKD3D_SHADER_SV_IS_FRONT_FACE:
|
|
+ case VKD3D_SHADER_SV_SAMPLE_INDEX:
|
|
+ case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE:
|
|
+ case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT:
|
|
+ case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE:
|
|
+ case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT:
|
|
+ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET:
|
|
+ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN:
|
|
+ case VKD3D_SHADER_SV_TARGET:
|
|
+ case VKD3D_SHADER_SV_DEPTH:
|
|
+ case VKD3D_SHADER_SV_COVERAGE:
|
|
+ case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL:
|
|
+ case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL:
|
|
+ case VKD3D_SHADER_SV_STENCIL_REF:
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
+ "element %u of %s signature: Invalid system value semantic %#x.",
|
|
+ idx, signature_type, element->sysval_semantic);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (element->component_type)
|
|
+ {
|
|
+ case VKD3D_SHADER_COMPONENT_INT:
|
|
+ case VKD3D_SHADER_COMPONENT_UINT:
|
|
+ integer_type = true;
|
|
+ break;
|
|
+
|
|
+ case VKD3D_SHADER_COMPONENT_FLOAT:
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
+ "element %u of %s signature: Invalid component type %#x.",
|
|
+ idx, signature_type, element->component_type);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (element->min_precision >= VKD3D_SHADER_MINIMUM_PRECISION_COUNT)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
+ "element %u of %s signature: Invalid minimum precision %#x.",
|
|
+ idx, signature_type, element->min_precision);
|
|
+
|
|
+ if (element->interpolation_mode >= VKD3DSIM_COUNT)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
+ "element %u of %s signature: Invalid interpolation mode %#x.",
|
|
+ idx, signature_type, element->interpolation_mode);
|
|
+
|
|
+ if (integer_type && element->interpolation_mode != VKD3DSIM_NONE
|
|
+ && element->interpolation_mode != VKD3DSIM_CONSTANT)
|
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
|
+ "element %u of %s signature: Invalid interpolation mode %#x for integer component type.",
|
|
+ idx, signature_type, element->interpolation_mode);
|
|
}
|
|
|
|
static void vsir_validate_signature(struct validation_context *ctx,
|
|
@@ -7060,6 +7354,7 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c
|
|
.null_location = {.source_name = source_name},
|
|
.status = VKD3D_OK,
|
|
.phase = VKD3DSIH_INVALID,
|
|
+ .invalid_instruction_idx = true,
|
|
};
|
|
unsigned int i;
|
|
|
|
@@ -7088,6 +7383,8 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c
|
|
if (!(ctx.ssas = vkd3d_calloc(ctx.program->ssa_count, sizeof(*ctx.ssas))))
|
|
goto fail;
|
|
|
|
+ ctx.invalid_instruction_idx = false;
|
|
+
|
|
for (ctx.instruction_idx = 0; ctx.instruction_idx < program->instructions.count
|
|
&& ctx.status != VKD3D_ERROR_OUT_OF_MEMORY; ++ctx.instruction_idx)
|
|
vsir_validate_instruction(&ctx);
|
|
@@ -7190,6 +7487,8 @@ 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);
|
|
+ vsir_transform(&ctx, vsir_program_insert_point_size);
|
|
+ vsir_transform(&ctx, vsir_program_insert_point_size_clamp);
|
|
|
|
if (TRACE_ON())
|
|
vsir_program_trace(program);
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c
|
|
index bfc013959e7..36750de1fd8 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/msl.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c
|
|
@@ -39,6 +39,8 @@ struct msl_generator
|
|
struct vkd3d_shader_message_context *message_context;
|
|
unsigned int indent;
|
|
const char *prefix;
|
|
+ const struct vkd3d_shader_interface_info *interface_info;
|
|
+ const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info;
|
|
};
|
|
|
|
static void VKD3D_PRINTF_FUNC(3, 4) msl_compiler_error(struct msl_generator *gen,
|
|
@@ -109,6 +111,64 @@ static void msl_print_register_name(struct vkd3d_string_buffer *buffer,
|
|
vkd3d_string_buffer_printf(buffer, "r[%u]", reg->idx[0].offset);
|
|
msl_print_register_datatype(buffer, gen, reg->data_type);
|
|
break;
|
|
+
|
|
+ case VKD3DSPR_INPUT:
|
|
+ if (reg->idx_count != 1)
|
|
+ {
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled input register index count %u.", reg->idx_count);
|
|
+ vkd3d_string_buffer_printf(buffer, "<unhandled register %#x>", reg->type);
|
|
+ break;
|
|
+ }
|
|
+ if (reg->idx[0].rel_addr)
|
|
+ {
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled input register indirect addressing.");
|
|
+ vkd3d_string_buffer_printf(buffer, "<unhandled register %#x>", reg->type);
|
|
+ break;
|
|
+ }
|
|
+ vkd3d_string_buffer_printf(buffer, "v[%u]", reg->idx[0].offset);
|
|
+ msl_print_register_datatype(buffer, gen, reg->data_type);
|
|
+ break;
|
|
+
|
|
+ case VKD3DSPR_OUTPUT:
|
|
+ if (reg->idx_count != 1)
|
|
+ {
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled output register index count %u.", reg->idx_count);
|
|
+ vkd3d_string_buffer_printf(buffer, "<unhandled register %#x>", reg->type);
|
|
+ break;
|
|
+ }
|
|
+ if (reg->idx[0].rel_addr)
|
|
+ {
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled output register indirect addressing.");
|
|
+ vkd3d_string_buffer_printf(buffer, "<unhandled register %#x>", reg->type);
|
|
+ break;
|
|
+ }
|
|
+ vkd3d_string_buffer_printf(buffer, "o[%u]", reg->idx[0].offset);
|
|
+ msl_print_register_datatype(buffer, gen, reg->data_type);
|
|
+ break;
|
|
+
|
|
+ case VKD3DSPR_CONSTBUFFER:
|
|
+ if (reg->idx_count != 3)
|
|
+ {
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled constant buffer register index count %u.", reg->idx_count);
|
|
+ vkd3d_string_buffer_printf(buffer, "<unhandled register %#x>", reg->type);
|
|
+ break;
|
|
+ }
|
|
+ if (reg->idx[0].rel_addr || reg->idx[2].rel_addr)
|
|
+ {
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled constant buffer register indirect addressing.");
|
|
+ vkd3d_string_buffer_printf(buffer, "<unhandled register %#x>", reg->type);
|
|
+ break;
|
|
+ }
|
|
+ vkd3d_string_buffer_printf(buffer, "descriptors.cb_%u[%u]", reg->idx[0].offset, reg->idx[2].offset);
|
|
+ msl_print_register_datatype(buffer, gen, reg->data_type);
|
|
+ break;
|
|
+
|
|
default:
|
|
msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
"Internal compiler error: Unhandled register type %#x.", reg->type);
|
|
@@ -266,6 +326,144 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d
|
|
}
|
|
}
|
|
|
|
+static bool msl_check_shader_visibility(const struct msl_generator *gen,
|
|
+ enum vkd3d_shader_visibility visibility)
|
|
+{
|
|
+ enum vkd3d_shader_type t = gen->program->shader_version.type;
|
|
+
|
|
+ switch (visibility)
|
|
+ {
|
|
+ case VKD3D_SHADER_VISIBILITY_ALL:
|
|
+ return true;
|
|
+ case VKD3D_SHADER_VISIBILITY_VERTEX:
|
|
+ return t == VKD3D_SHADER_TYPE_VERTEX;
|
|
+ case VKD3D_SHADER_VISIBILITY_HULL:
|
|
+ return t == VKD3D_SHADER_TYPE_HULL;
|
|
+ case VKD3D_SHADER_VISIBILITY_DOMAIN:
|
|
+ return t == VKD3D_SHADER_TYPE_DOMAIN;
|
|
+ case VKD3D_SHADER_VISIBILITY_GEOMETRY:
|
|
+ return t == VKD3D_SHADER_TYPE_GEOMETRY;
|
|
+ case VKD3D_SHADER_VISIBILITY_PIXEL:
|
|
+ return t == VKD3D_SHADER_TYPE_PIXEL;
|
|
+ case VKD3D_SHADER_VISIBILITY_COMPUTE:
|
|
+ return t == VKD3D_SHADER_TYPE_COMPUTE;
|
|
+ default:
|
|
+ WARN("Invalid shader visibility %#x.\n", visibility);
|
|
+ return false;
|
|
+ }
|
|
+}
|
|
+
|
|
+static bool msl_get_cbv_binding(const struct msl_generator *gen,
|
|
+ unsigned int register_space, unsigned int register_idx, unsigned int *binding_idx)
|
|
+{
|
|
+ const struct vkd3d_shader_interface_info *interface_info = gen->interface_info;
|
|
+ const struct vkd3d_shader_resource_binding *binding;
|
|
+ unsigned int i;
|
|
+
|
|
+ if (!interface_info)
|
|
+ return false;
|
|
+
|
|
+ for (i = 0; i < interface_info->binding_count; ++i)
|
|
+ {
|
|
+ binding = &interface_info->bindings[i];
|
|
+
|
|
+ if (binding->type != VKD3D_SHADER_DESCRIPTOR_TYPE_CBV)
|
|
+ continue;
|
|
+ if (binding->register_space != register_space)
|
|
+ continue;
|
|
+ if (binding->register_index != register_idx)
|
|
+ continue;
|
|
+ if (!msl_check_shader_visibility(gen, binding->shader_visibility))
|
|
+ continue;
|
|
+ if (!(binding->flags & VKD3D_SHADER_BINDING_FLAG_BUFFER))
|
|
+ continue;
|
|
+ *binding_idx = i;
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static void msl_generate_cbv_declaration(struct msl_generator *gen,
|
|
+ const struct vkd3d_shader_descriptor_info1 *cbv)
|
|
+{
|
|
+ const struct vkd3d_shader_descriptor_binding *binding;
|
|
+ struct vkd3d_string_buffer *buffer = gen->buffer;
|
|
+ unsigned int binding_idx;
|
|
+ size_t size;
|
|
+
|
|
+ if (cbv->count != 1)
|
|
+ {
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND,
|
|
+ "Constant buffer %u has unsupported descriptor array size %u.", cbv->register_id, cbv->count);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (!msl_get_cbv_binding(gen, cbv->register_space, cbv->register_index, &binding_idx))
|
|
+ {
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND,
|
|
+ "No descriptor binding specified for constant buffer %u.", cbv->register_id);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ binding = &gen->interface_info->bindings[binding_idx].binding;
|
|
+
|
|
+ if (binding->set != 0)
|
|
+ {
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND,
|
|
+ "Unsupported binding set %u specified for constant buffer %u.", binding->set, cbv->register_id);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (binding->count != 1)
|
|
+ {
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND,
|
|
+ "Unsupported binding count %u specified for constant buffer %u.", binding->count, cbv->register_id);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ size = align(cbv->buffer_size, VKD3D_VEC4_SIZE * sizeof(uint32_t));
|
|
+ size /= VKD3D_VEC4_SIZE * sizeof(uint32_t);
|
|
+
|
|
+ vkd3d_string_buffer_printf(buffer,
|
|
+ "constant vkd3d_vec4 (&cb_%u)[%zu] [[id(%u)]];", cbv->register_id, size, binding->binding);
|
|
+};
|
|
+
|
|
+static void msl_generate_descriptor_struct_declarations(struct msl_generator *gen)
|
|
+{
|
|
+ const struct vkd3d_shader_scan_descriptor_info1 *info = gen->descriptor_info;
|
|
+ const struct vkd3d_shader_descriptor_info1 *descriptor;
|
|
+ struct vkd3d_string_buffer *buffer = gen->buffer;
|
|
+ unsigned int i;
|
|
+
|
|
+ if (!info->descriptor_count)
|
|
+ return;
|
|
+
|
|
+ vkd3d_string_buffer_printf(buffer, "struct vkd3d_%s_descriptors\n{\n", gen->prefix);
|
|
+
|
|
+ for (i = 0; i < info->descriptor_count; ++i)
|
|
+ {
|
|
+ descriptor = &info->descriptors[i];
|
|
+
|
|
+ msl_print_indent(buffer, 1);
|
|
+ switch (descriptor->type)
|
|
+ {
|
|
+ case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV:
|
|
+ msl_generate_cbv_declaration(gen, descriptor);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ vkd3d_string_buffer_printf(buffer, "/* <unhandled descriptor type %#x> */", descriptor->type);
|
|
+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL,
|
|
+ "Internal compiler error: Unhandled descriptor type %#x.", descriptor->type);
|
|
+ break;
|
|
+ }
|
|
+ vkd3d_string_buffer_printf(buffer, "\n");
|
|
+ }
|
|
+
|
|
+ vkd3d_string_buffer_printf(buffer, "};\n\n");
|
|
+}
|
|
+
|
|
static void msl_generate_input_struct_declarations(struct msl_generator *gen)
|
|
{
|
|
const struct shader_signature *signature = &gen->program->input_signature;
|
|
@@ -550,9 +748,15 @@ static void msl_generate_entrypoint(struct msl_generator *gen)
|
|
|
|
vkd3d_string_buffer_printf(gen->buffer, "vkd3d_%s_out shader_entry(\n", gen->prefix);
|
|
|
|
- /* TODO: descriptor declaration */
|
|
+ if (gen->descriptor_info->descriptor_count)
|
|
+ {
|
|
+ msl_print_indent(gen->buffer, 2);
|
|
+ /* TODO: Configurable argument buffer binding location. */
|
|
+ vkd3d_string_buffer_printf(gen->buffer,
|
|
+ "constant vkd3d_%s_descriptors& descriptors [[buffer(0)]],\n", gen->prefix);
|
|
+ }
|
|
|
|
- msl_print_indent(gen->buffer, 1);
|
|
+ msl_print_indent(gen->buffer, 2);
|
|
vkd3d_string_buffer_printf(gen->buffer, "vkd3d_%s_in input [[stage_in]])\n{\n", gen->prefix);
|
|
|
|
/* TODO: declare #maximum_register + 1 */
|
|
@@ -562,7 +766,10 @@ static void msl_generate_entrypoint(struct msl_generator *gen)
|
|
|
|
msl_generate_entrypoint_prologue(gen);
|
|
|
|
- vkd3d_string_buffer_printf(gen->buffer, " %s_main(%s_in, %s_out);\n", gen->prefix, gen->prefix, gen->prefix);
|
|
+ vkd3d_string_buffer_printf(gen->buffer, " %s_main(%s_in, %s_out", gen->prefix, gen->prefix, gen->prefix);
|
|
+ if (gen->descriptor_info->descriptor_count)
|
|
+ vkd3d_string_buffer_printf(gen->buffer, ", descriptors");
|
|
+ vkd3d_string_buffer_printf(gen->buffer, ");\n");
|
|
|
|
msl_generate_entrypoint_epilogue(gen);
|
|
|
|
@@ -583,13 +790,17 @@ static void msl_generator_generate(struct msl_generator *gen)
|
|
vkd3d_string_buffer_printf(gen->buffer, " int4 i;\n");
|
|
vkd3d_string_buffer_printf(gen->buffer, " float4 f;\n};\n\n");
|
|
|
|
+ msl_generate_descriptor_struct_declarations(gen);
|
|
msl_generate_input_struct_declarations(gen);
|
|
msl_generate_output_struct_declarations(gen);
|
|
|
|
vkd3d_string_buffer_printf(gen->buffer,
|
|
"void %s_main(thread vkd3d_vec4 *v, "
|
|
- "thread vkd3d_vec4 *o)\n{\n",
|
|
+ "thread vkd3d_vec4 *o",
|
|
gen->prefix);
|
|
+ if (gen->descriptor_info->descriptor_count)
|
|
+ vkd3d_string_buffer_printf(gen->buffer, ", constant vkd3d_%s_descriptors& descriptors", gen->prefix);
|
|
+ vkd3d_string_buffer_printf(gen->buffer, ")\n{\n");
|
|
|
|
++gen->indent;
|
|
|
|
@@ -621,6 +832,8 @@ static void msl_generator_cleanup(struct msl_generator *gen)
|
|
}
|
|
|
|
static int msl_generator_init(struct msl_generator *gen, struct vsir_program *program,
|
|
+ const struct vkd3d_shader_compile_info *compile_info,
|
|
+ const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info,
|
|
struct vkd3d_shader_message_context *message_context)
|
|
{
|
|
enum vkd3d_shader_type type = program->shader_version.type;
|
|
@@ -640,11 +853,14 @@ static int msl_generator_init(struct msl_generator *gen, struct vsir_program *pr
|
|
"Internal compiler error: Unhandled shader type %#x.", type);
|
|
return VKD3D_ERROR_INVALID_SHADER;
|
|
}
|
|
+ gen->interface_info = vkd3d_find_struct(compile_info->next, INTERFACE_INFO);
|
|
+ gen->descriptor_info = descriptor_info;
|
|
|
|
return VKD3D_OK;
|
|
}
|
|
|
|
int msl_compile(struct vsir_program *program, uint64_t config_flags,
|
|
+ const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info,
|
|
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context)
|
|
{
|
|
struct msl_generator generator;
|
|
@@ -653,7 +869,7 @@ int msl_compile(struct vsir_program *program, uint64_t config_flags,
|
|
if ((ret = vsir_program_transform(program, config_flags, compile_info, message_context)) < 0)
|
|
return ret;
|
|
|
|
- if ((ret = msl_generator_init(&generator, program, message_context)) < 0)
|
|
+ if ((ret = msl_generator_init(&generator, program, compile_info, descriptor_info, message_context)) < 0)
|
|
return ret;
|
|
msl_generator_generate(&generator);
|
|
msl_generator_cleanup(&generator);
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
|
index 692432d5513..1efd717e970 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
|
@@ -2662,8 +2662,6 @@ static struct spirv_compiler *spirv_compiler_create(const struct vsir_program *p
|
|
if ((shader_interface = vkd3d_find_struct(compile_info->next, INTERFACE_INFO)))
|
|
{
|
|
compiler->xfb_info = vkd3d_find_struct(compile_info->next, TRANSFORM_FEEDBACK_INFO);
|
|
- compiler->emit_point_size = compiler->xfb_info && compiler->xfb_info->element_count
|
|
- && compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY;
|
|
|
|
compiler->shader_interface = *shader_interface;
|
|
if (shader_interface->push_constant_buffer_count)
|
|
@@ -2690,6 +2688,11 @@ static struct spirv_compiler *spirv_compiler_create(const struct vsir_program *p
|
|
}
|
|
}
|
|
|
|
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_VERTEX)
|
|
+ compiler->emit_point_size = true;
|
|
+ else if (compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY)
|
|
+ compiler->emit_point_size = compiler->xfb_info && compiler->xfb_info->element_count;
|
|
+
|
|
compiler->scan_descriptor_info = scan_descriptor_info;
|
|
|
|
compiler->phase = VKD3DSIH_INVALID;
|
|
@@ -4860,6 +4863,10 @@ static const struct vkd3d_spirv_builtin vkd3d_pixel_shader_position_builtin =
|
|
{
|
|
VKD3D_SHADER_COMPONENT_FLOAT, 4, SpvBuiltInFragCoord, frag_coord_fixup,
|
|
};
|
|
+static const struct vkd3d_spirv_builtin vkd3d_output_point_size_builtin =
|
|
+{
|
|
+ VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInPointSize,
|
|
+};
|
|
static const struct
|
|
{
|
|
enum vkd3d_shader_register_type reg_type;
|
|
@@ -5449,7 +5456,11 @@ static void spirv_compiler_emit_output_register(struct spirv_compiler *compiler,
|
|
VKD3D_ASSERT(!reg->idx_count || !reg->idx[0].rel_addr);
|
|
VKD3D_ASSERT(reg->idx_count < 2);
|
|
|
|
- if (!(builtin = get_spirv_builtin_for_register(reg->type)))
|
|
+ if (reg->type == VKD3DSPR_RASTOUT && reg->idx[0].offset == VSIR_RASTOUT_POINT_SIZE)
|
|
+ {
|
|
+ builtin = &vkd3d_output_point_size_builtin;
|
|
+ }
|
|
+ else if (!(builtin = get_spirv_builtin_for_register(reg->type)))
|
|
{
|
|
FIXME("Unhandled register %#x.\n", reg->type);
|
|
return;
|
|
@@ -6746,7 +6757,8 @@ static void spirv_compiler_emit_dcl_input_primitive(struct spirv_compiler *compi
|
|
|
|
static void spirv_compiler_emit_point_size(struct spirv_compiler *compiler)
|
|
{
|
|
- static const struct vkd3d_spirv_builtin point_size = {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInPointSize};
|
|
+ if (compiler->program->has_point_size)
|
|
+ return;
|
|
|
|
/* Set the point size. Point sprites are not supported in d3d10+, but
|
|
* point primitives can still be used with e.g. stream output. Vulkan
|
|
@@ -6760,7 +6772,8 @@ static void spirv_compiler_emit_point_size(struct spirv_compiler *compiler)
|
|
|| compiler->write_tess_geom_point_size)
|
|
{
|
|
vkd3d_spirv_build_op_store(&compiler->spirv_builder,
|
|
- spirv_compiler_emit_builtin_variable(compiler, &point_size, SpvStorageClassOutput, 0),
|
|
+ spirv_compiler_emit_builtin_variable(compiler,
|
|
+ &vkd3d_output_point_size_builtin, SpvStorageClassOutput, 0),
|
|
spirv_compiler_get_constant_float(compiler, 1.0f), SpvMemoryAccessMaskNone);
|
|
}
|
|
}
|
|
@@ -7427,7 +7440,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler,
|
|
uint32_t components[VKD3D_VEC4_SIZE];
|
|
|
|
if (register_is_constant_or_undef(&src->reg) || src->reg.type == VKD3DSPR_SSA || dst->reg.type == VKD3DSPR_SSA
|
|
- || dst->modifiers || src->modifiers)
|
|
+ || src->reg.type == VKD3DSPR_PARAMETER || dst->modifiers || src->modifiers)
|
|
goto general_implementation;
|
|
|
|
spirv_compiler_get_register_info(compiler, &dst->reg, &dst_reg_info);
|
|
@@ -10538,7 +10551,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
|
|
case VKD3DSIH_DCL_RESOURCE_STRUCTURED:
|
|
case VKD3DSIH_DCL_UAV_RAW:
|
|
case VKD3DSIH_DCL_UAV_STRUCTURED:
|
|
- case VKD3DSIH_DCL_UAV_TYPED:
|
|
case VKD3DSIH_HS_DECLS:
|
|
case VKD3DSIH_NOP:
|
|
/* nothing to do */
|
|
@@ -10575,6 +10587,15 @@ static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler)
|
|
else
|
|
spirv_compiler_emit_input(compiler, VKD3DSPR_PATCHCONST, i);
|
|
}
|
|
+
|
|
+ if (compiler->program->has_point_size)
|
|
+ {
|
|
+ struct vkd3d_shader_dst_param dst;
|
|
+
|
|
+ vsir_dst_param_init(&dst, VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1);
|
|
+ dst.reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE;
|
|
+ spirv_compiler_emit_output_register(compiler, &dst);
|
|
+ }
|
|
}
|
|
|
|
static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *compiler)
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
index f84ac551272..cde8dc3146c 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
@@ -1655,7 +1655,10 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags,
|
|
break;
|
|
|
|
case VKD3D_SHADER_TARGET_MSL:
|
|
- ret = msl_compile(program, config_flags, compile_info, message_context);
|
|
+ if ((ret = vsir_program_scan(program, &scan_info, message_context, &scan_descriptor_info)) < 0)
|
|
+ return ret;
|
|
+ ret = msl_compile(program, config_flags, &scan_descriptor_info, compile_info, message_context);
|
|
+ vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info);
|
|
break;
|
|
|
|
default:
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
index 41b879af4b4..9ca3c328147 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
@@ -60,6 +60,7 @@
|
|
#define VKD3D_DVEC2_SIZE 2
|
|
|
|
#define VKD3D_SHADER_COMPONENT_TYPE_COUNT (VKD3D_SHADER_COMPONENT_UINT64 + 1)
|
|
+#define VKD3D_SHADER_MINIMUM_PRECISION_COUNT (VKD3D_SHADER_MINIMUM_PRECISION_UINT_16 + 1)
|
|
|
|
enum vkd3d_shader_error
|
|
{
|
|
@@ -250,6 +251,7 @@ enum vkd3d_shader_error
|
|
VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300,
|
|
|
|
VKD3D_SHADER_ERROR_MSL_INTERNAL = 10000,
|
|
+ VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND = 10001,
|
|
};
|
|
|
|
enum vkd3d_shader_opcode
|
|
@@ -648,6 +650,13 @@ enum vkd3d_shader_register_type
|
|
VKD3DSPR_INVALID = ~0u,
|
|
};
|
|
|
|
+enum vsir_rastout_register
|
|
+{
|
|
+ VSIR_RASTOUT_POSITION = 0x0,
|
|
+ VSIR_RASTOUT_FOG = 0x1,
|
|
+ VSIR_RASTOUT_POINT_SIZE = 0x2,
|
|
+};
|
|
+
|
|
enum vkd3d_shader_register_precision
|
|
{
|
|
VKD3D_SHADER_REGISTER_PRECISION_DEFAULT,
|
|
@@ -1400,6 +1409,7 @@ struct vsir_program
|
|
unsigned int temp_count;
|
|
unsigned int ssa_count;
|
|
bool use_vocp;
|
|
+ bool has_point_size;
|
|
enum vsir_control_flow_type cf_type;
|
|
|
|
const char **block_names;
|
|
@@ -1617,6 +1627,7 @@ int spirv_compile(struct vsir_program *program, uint64_t config_flags,
|
|
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context);
|
|
|
|
int msl_compile(struct vsir_program *program, uint64_t config_flags,
|
|
+ const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info,
|
|
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context);
|
|
|
|
enum vkd3d_md5_variant
|
|
--
|
|
2.45.2
|
|
|