[PATCH vkd3d 1/9] vkd3d-shader: Translate samplepos instructions.
Józef Kucia
joseph.kucia at gmail.com
Mon Apr 29 04:38:10 CDT 2019
From: Józef Kucia <jkucia at codeweavers.com>
This returns standard sample locations. DXC and glslang do the same thing.
https://github.com/khronosgroup/glslang/commit/d4d0b29752c173d2aa8d2d105f2f1844676bc165
In the long term, we could also add a shader parameter to pass sample
positions to the shader compiler.
Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
libs/vkd3d-shader/spirv.c | 171 ++++++++++++++++++++++++++++++++++----
1 file changed, 154 insertions(+), 17 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index 6332ef50394b..22e02f9ffa01 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -1129,6 +1129,12 @@ static uint32_t vkd3d_spirv_build_op_in_bounds_access_chain(struct vkd3d_spirv_b
SpvOpInBoundsAccessChain, result_type, base_id, indexes, index_count);
}
+static uint32_t vkd3d_spirv_build_op_in_bounds_access_chain1(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t base_id, uint32_t index)
+{
+ return vkd3d_spirv_build_op_in_bounds_access_chain(builder, result_type, base_id, &index, 1);
+}
+
static uint32_t vkd3d_spirv_build_op_vector_shuffle(struct vkd3d_spirv_builder *builder,
uint32_t result_type, uint32_t vector1_id, uint32_t vector2_id,
const uint32_t *components, uint32_t component_count)
@@ -1340,6 +1346,27 @@ static uint32_t vkd3d_spirv_build_op_shift_right_logical(struct vkd3d_spirv_buil
SpvOpShiftRightLogical, result_type, base, shift);
}
+static uint32_t vkd3d_spirv_build_op_logical_and(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpLogicalAnd, result_type, operand0, operand1);
+}
+
+static uint32_t vkd3d_spirv_build_op_uless_than(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpULessThan, result_type, operand0, operand1);
+}
+
+static uint32_t vkd3d_spirv_build_op_uless_than_equal(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t operand0, uint32_t operand1)
+{
+ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
+ SpvOpULessThanEqual, result_type, operand0, operand1);
+}
+
static uint32_t vkd3d_spirv_build_op_convert_utof(struct vkd3d_spirv_builder *builder,
uint32_t result_type, uint32_t unsigned_value)
{
@@ -1989,6 +2016,7 @@ struct vkd3d_dxbc_compiler
uint32_t temp_id;
unsigned int temp_count;
struct vkd3d_hull_shader_variables hs;
+ uint32_t sample_positions_id;
enum vkd3d_shader_type shader_type;
@@ -2917,7 +2945,7 @@ static uint32_t vkd3d_dxbc_compiler_emit_load_scalar(struct vkd3d_dxbc_compiler
const struct vkd3d_shader_register_info *reg_info)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
- uint32_t type_id, ptr_type_id, indexes[1], reg_id, val_id;
+ uint32_t type_id, ptr_type_id, index, reg_id, val_id;
unsigned int component_idx, reg_component_count;
enum vkd3d_component_type component_type;
unsigned int skipped_component_mask;
@@ -2945,9 +2973,8 @@ static uint32_t vkd3d_dxbc_compiler_emit_load_scalar(struct vkd3d_dxbc_compiler
if (reg_component_count != 1)
{
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info->storage_class, type_id);
- indexes[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx);
- reg_id = vkd3d_spirv_build_op_in_bounds_access_chain(builder,
- ptr_type_id, reg_id, indexes, ARRAY_SIZE(indexes));
+ index = vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx);
+ reg_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, reg_id, index);
}
val_id = vkd3d_spirv_build_op_load(builder, type_id, reg_id, SpvMemoryAccessMaskNone);
@@ -3104,7 +3131,7 @@ static void vkd3d_dxbc_compiler_emit_store_scalar(struct vkd3d_dxbc_compiler *co
SpvStorageClass storage_class, unsigned int write_mask, uint32_t val_id)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
- uint32_t type_id, ptr_type_id, index[1];
+ uint32_t type_id, ptr_type_id, index;
unsigned int component_idx;
if (vkd3d_write_mask_component_count(dst_write_mask) > 1)
@@ -3113,8 +3140,8 @@ static void vkd3d_dxbc_compiler_emit_store_scalar(struct vkd3d_dxbc_compiler *co
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
component_idx = vkd3d_write_mask_get_component_idx(write_mask);
component_idx -= vkd3d_write_mask_get_component_idx(dst_write_mask);
- index[0] = vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx);
- dst_id = vkd3d_spirv_build_op_in_bounds_access_chain(builder, ptr_type_id, dst_id, index, ARRAY_SIZE(index));
+ index = vkd3d_dxbc_compiler_get_constant_uint(compiler, component_idx);
+ dst_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, dst_id, index);
}
vkd3d_spirv_build_op_store(builder, dst_id, val_id, SpvMemoryAccessMaskNone);
@@ -3870,8 +3897,7 @@ static uint32_t vkd3d_dxbc_compiler_emit_input(struct vkd3d_dxbc_compiler *compi
{
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassInput, type_id);
index = vkd3d_dxbc_compiler_get_constant_uint(compiler, i);
- val_id = vkd3d_spirv_build_op_in_bounds_access_chain(builder,
- ptr_type_id, input_id, &index, 1);
+ val_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, input_id, index);
dst_reg.idx[0].offset = i;
}
val_id = vkd3d_spirv_build_op_load(builder, type_id, val_id, SpvMemoryAccessMaskNone);
@@ -7704,15 +7730,12 @@ static void vkd3d_dxbc_compiler_emit_resinfo(struct vkd3d_dxbc_compiler *compile
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
}
-static void vkd3d_dxbc_compiler_emit_sample_info(struct vkd3d_dxbc_compiler *compiler,
- const struct vkd3d_shader_instruction *instruction)
+static uint32_t vkd3d_dxbc_compiler_emit_query_sample_count(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_src_param *src)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
- const struct vkd3d_shader_dst_param *dst = instruction->dst;
- const struct vkd3d_shader_src_param *src = instruction->src;
- uint32_t constituents[VKD3D_VEC4_SIZE];
+ struct vkd3d_shader_image image;
uint32_t type_id, val_id;
- unsigned int i;
if (src->reg.type == VKD3DSPR_RASTERIZER)
{
@@ -7721,8 +7744,6 @@ static void vkd3d_dxbc_compiler_emit_sample_info(struct vkd3d_dxbc_compiler *com
}
else
{
- struct vkd3d_shader_image image;
-
vkd3d_spirv_enable_capability(builder, SpvCapabilityImageQuery);
vkd3d_dxbc_compiler_prepare_image(compiler, &image, &src->reg, NULL, VKD3D_IMAGE_FLAG_NONE);
@@ -7730,6 +7751,21 @@ static void vkd3d_dxbc_compiler_emit_sample_info(struct vkd3d_dxbc_compiler *com
val_id = vkd3d_spirv_build_op_image_query_samples(builder, type_id, image.image_id);
}
+ return val_id;
+}
+
+static void vkd3d_dxbc_compiler_emit_sample_info(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t constituents[VKD3D_VEC4_SIZE];
+ uint32_t type_id, val_id;
+ unsigned int i;
+
+ val_id = vkd3d_dxbc_compiler_emit_query_sample_count(compiler, src);
+
constituents[0] = val_id;
for (i = 1; i < VKD3D_VEC4_SIZE; ++i)
constituents[i] = vkd3d_dxbc_compiler_get_constant_uint(compiler, 0);
@@ -7754,6 +7790,104 @@ static void vkd3d_dxbc_compiler_emit_sample_info(struct vkd3d_dxbc_compiler *com
vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, val_id);
}
+/* XXX: This is correct only when standard sample positions are used. */
+static void vkd3d_dxbc_compiler_emit_sample_position(struct vkd3d_dxbc_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ /* Standard sample locations from the Vulkan spec. */
+ static const float standard_sample_positions[][2] =
+ {
+ /* 1 sample */
+ { 0.0 / 16.0, 0.0 / 16.0},
+ /* 2 samples */
+ { 4.0 / 16.0, 4.0 / 16.0},
+ {-4.0 / 16.0, -4.0 / 16.0},
+ /* 4 samples */
+ {-2.0 / 16.0, -6.0 / 16.0},
+ { 6.0 / 16.0, -2.0 / 16.0},
+ {-6.0 / 16.0, 2.0 / 16.0},
+ { 2.0 / 16.0, 6.0 / 16.0},
+ /* 8 samples */
+ { 1.0 / 16.0, -3.0 / 16.0},
+ {-1.0 / 16.0, 3.0 / 16.0},
+ { 5.0 / 16.0, 1.0 / 16.0},
+ {-3.0 / 16.0, -5.0 / 16.0},
+ {-5.0 / 16.0, 5.0 / 16.0},
+ {-7.0 / 16.0, -1.0 / 16.0},
+ { 3.0 / 16.0, 7.0 / 16.0},
+ { 7.0 / 16.0, -7.0 / 16.0},
+ /* 16 samples */
+ { 1.0 / 16.0, 1.0 / 16.0},
+ {-1.0 / 16.0, -3.0 / 16.0},
+ {-3.0 / 16.0, 2.0 / 16.0},
+ { 4.0 / 16.0, -1.0 / 16.0},
+ {-5.0 / 16.0, -2.0 / 16.0},
+ { 2.0 / 16.0, 5.0 / 16.0},
+ { 5.0 / 16.0, 3.0 / 16.0},
+ { 3.0 / 16.0, -5.0 / 16.0},
+ {-2.0 / 16.0, 6.0 / 16.0},
+ { 0.0 / 16.0, -7.0 / 16.0},
+ {-4.0 / 16.0, -6.0 / 16.0},
+ {-6.0 / 16.0, 4.0 / 16.0},
+ {-8.0 / 16.0, 0.0 / 16.0},
+ { 7.0 / 16.0, -4.0 / 16.0},
+ { 6.0 / 16.0, 7.0 / 16.0},
+ {-7.0 / 16.0, -8.0 / 16.0},
+ };
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t constituents[ARRAY_SIZE(standard_sample_positions)];
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ uint32_t array_type_id, length_id, index_id, id;
+ uint32_t sample_count_id, sample_index_id;
+ uint32_t type_id, bool_id, ptr_type_id;
+ unsigned int i;
+
+ sample_count_id = vkd3d_dxbc_compiler_emit_query_sample_count(compiler, &instruction->src[0]);
+ sample_index_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &instruction->src[1], VKD3DSP_WRITEMASK_0);
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_UINT, 1);
+ index_id = vkd3d_spirv_build_op_iadd(builder, type_id, sample_count_id, sample_index_id);
+ index_id = vkd3d_spirv_build_op_isub(builder,
+ type_id, index_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, 1));
+
+ /* Validate sample index. */
+ bool_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_BOOL, 1);
+ id = vkd3d_spirv_build_op_logical_and(builder, bool_id,
+ vkd3d_spirv_build_op_uless_than(builder, bool_id, sample_index_id, sample_count_id),
+ vkd3d_spirv_build_op_uless_than_equal(builder,
+ bool_id, sample_index_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, 16)));
+ index_id = vkd3d_spirv_build_op_select(builder, type_id,
+ id, index_id, vkd3d_dxbc_compiler_get_constant_uint(compiler, 0));
+
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, 2);
+ if (!(id = compiler->sample_positions_id))
+ {
+ length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, ARRAY_SIZE(standard_sample_positions));
+ array_type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id);
+
+ for (i = 0; i < ARRAY_SIZE(standard_sample_positions); ++ i)
+ {
+ constituents[i] = vkd3d_dxbc_compiler_get_constant(compiler,
+ VKD3D_TYPE_FLOAT, 2, (const uint32_t *)standard_sample_positions[i]);
+ }
+
+ id = vkd3d_spirv_build_op_constant_composite(builder, array_type_id, constituents, ARRAY_SIZE(constituents));
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, array_type_id);
+ id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, ptr_type_id, SpvStorageClassPrivate, id);
+ vkd3d_spirv_build_op_name(builder, id, "sample_pos");
+ compiler->sample_positions_id = id;
+ }
+
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id);
+ id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, id, index_id);
+ id = vkd3d_spirv_build_op_load(builder, type_id, id, SpvMemoryAccessMaskNone);
+
+ id = vkd3d_dxbc_compiler_emit_swizzle(compiler,
+ id, VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1, VKD3D_TYPE_FLOAT,
+ instruction->src[0].swizzle, dst->write_mask);
+ vkd3d_dxbc_compiler_emit_store_dst(compiler, dst, id);
+}
+
static void vkd3d_dxbc_compiler_emit_eval_attrib(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
@@ -8208,6 +8342,9 @@ int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler,
case VKD3DSIH_SAMPLE_INFO:
vkd3d_dxbc_compiler_emit_sample_info(compiler, instruction);
break;
+ case VKD3DSIH_SAMPLE_POS:
+ vkd3d_dxbc_compiler_emit_sample_position(compiler, instruction);
+ break;
case VKD3DSIH_EVAL_CENTROID:
case VKD3DSIH_EVAL_SAMPLE_INDEX:
vkd3d_dxbc_compiler_emit_eval_attrib(compiler, instruction);
--
2.21.0
More information about the wine-devel
mailing list