[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