[PATCH vkd3d 05/11] vkd3d-shader: Use private array variable for patch constant outputs.

Philip Rebohle philip.rebohle at tu-dortmund.de
Wed Oct 16 14:55:39 CDT 2019


Fork and join phases in hulll shaders allow dynamic indexing for
all output registers, not just the tessellation factor built-ins.

Moreover, the patch constant output register space is shared with
join phases, which can read back the outputs computed in the fork
phases, also allowing dynamic indexing.

In order to support this in a not overly complex way, use a private
array representing the entire patch constant space, and use epilogue
functions to assign them to the actual output variables.

Signed-off-by: Philip Rebohle <philip.rebohle at tu-dortmund.de>
---
 libs/vkd3d-shader/spirv.c | 40 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 37 insertions(+), 3 deletions(-)

diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index c83d05f..76df8fc 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -2029,6 +2029,7 @@ struct vkd3d_hull_shader_variables
 {
     uint32_t tess_level_outer_id;
     uint32_t tess_level_inner_id;
+    uint32_t patch_constants_id;
 };
 
 struct vkd3d_dxbc_compiler
@@ -4322,7 +4323,8 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler
         write_mask = dst->write_mask;
     else if (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_NO_SWIZZLE
             || needs_private_io_variable(shader_signature, signature_element->register_index,
-            builtin, &output_component_count, &write_mask))
+            builtin, &output_component_count, &write_mask)
+            || is_patch_constant)
     {
         use_private_variable = true;
         write_mask = VKD3DSP_WRITEMASK_ALL;
@@ -4394,6 +4396,8 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler
         var_id = RB_ENTRY_VALUE(entry, const struct vkd3d_symbol, entry)->id;
     else if (!use_private_variable)
         var_id = id;
+    else if (is_patch_constant)
+        var_id = compiler->hs.patch_constants_id;
     else
         var_id = vkd3d_dxbc_compiler_emit_variable(compiler, &builder->global_stream,
                 storage_class, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE);
@@ -4401,15 +4405,19 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler
     {
         vkd3d_symbol_set_register_info(&reg_symbol, var_id, storage_class,
                 use_private_variable ? VKD3D_TYPE_FLOAT : component_type, write_mask);
-        reg_symbol.info.reg.is_aggregate = use_private_variable ? false : array_size;
+        reg_symbol.info.reg.is_aggregate = use_private_variable ? is_patch_constant : array_size;
         if (!use_private_variable && is_control_point_phase(phase))
         {
             reg_symbol.info.reg.member_idx = vkd3d_dxbc_compiler_get_invocation_id(compiler);
             reg_symbol.info.reg.is_dynamically_indexed = true;
         }
+        else if (is_patch_constant)
+            reg_symbol.info.reg.member_idx = reg->idx[0].offset;
+
         vkd3d_dxbc_compiler_put_symbol(compiler, &reg_symbol);
 
-        vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
+        if (!is_patch_constant)
+            vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
     }
 
     if (use_private_variable)
@@ -4417,6 +4425,10 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler
         unsigned int idx = vkd3d_dxbc_compiler_get_output_variable_index(compiler, reg->idx[0].offset);
         compiler->private_output_variable[idx] = var_id;
         compiler->private_output_variable_write_mask[idx] |= dst->write_mask;
+        if (is_patch_constant) {
+            compiler->private_output_variable_array_idx[idx] = vkd3d_dxbc_compiler_get_constant_uint(
+                    compiler, reg->idx[0].offset);
+        }
         if (!compiler->epilogue_function_id)
             compiler->epilogue_function_id = vkd3d_spirv_alloc_id(builder);
     }
@@ -4627,6 +4639,27 @@ static void vkd3d_dxbc_compiler_emit_hull_shader_builtins(struct vkd3d_dxbc_comp
     vkd3d_dxbc_compiler_emit_input_register(compiler, &dst);
 }
 
+static void vkd3d_dxbc_compiler_emit_hull_shader_patch_constants(struct vkd3d_dxbc_compiler *compiler)
+{
+    const struct vkd3d_shader_signature *signature = compiler->patch_constant_signature;
+    struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+    unsigned int signature_idx;
+    uint32_t register_count;
+
+    register_count = 0;
+
+    for (signature_idx = 0; signature_idx < signature->element_count; signature_idx++)
+        register_count = max(register_count, signature->elements[signature_idx].register_index + 1);
+
+    if (register_count)
+    {
+        compiler->hs.patch_constants_id = vkd3d_dxbc_compiler_emit_array_variable(compiler,
+                &builder->global_stream, SpvStorageClassPrivate, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE,
+                register_count);
+        vkd3d_spirv_build_op_name(builder, compiler->hs.patch_constants_id, "opc");
+    }
+}
+
 static void vkd3d_dxbc_compiler_emit_initial_declarations(struct vkd3d_dxbc_compiler *compiler)
 {
     const struct vkd3d_shader_transform_feedback_info *xfb_info = compiler->xfb_info;
@@ -4640,6 +4673,7 @@ static void vkd3d_dxbc_compiler_emit_initial_declarations(struct vkd3d_dxbc_comp
         case VKD3D_SHADER_TYPE_HULL:
             vkd3d_spirv_set_execution_model(builder, SpvExecutionModelTessellationControl);
             vkd3d_dxbc_compiler_emit_hull_shader_builtins(compiler);
+            vkd3d_dxbc_compiler_emit_hull_shader_patch_constants(compiler);
             break;
         case VKD3D_SHADER_TYPE_DOMAIN:
             vkd3d_spirv_set_execution_model(builder, SpvExecutionModelTessellationEvaluation);
-- 
2.23.0




More information about the wine-devel mailing list