microsoft/compiler: For store_output from HS, use storePatchConstant
authorJesse Natalie <jenatali@microsoft.com>
Sun, 2 Jan 2022 17:56:08 +0000 (09:56 -0800)
committerMarge Bot <emma+marge@anholt.net>
Wed, 26 Jan 2022 01:31:35 +0000 (01:31 +0000)
In HS, store_per_vertex_output maps to storeOutput in DXIL. The data
that isn't per-vertex is patch constants.

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Bill Kristiansen <billkris@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14399>

src/microsoft/compiler/dxil_function.c
src/microsoft/compiler/nir_to_dxil.c

index 5429231..7b92bd8 100644 (file)
@@ -84,6 +84,7 @@ static struct  predefined_func_descr predefined_funcs[] = {
 {"dx.op.evalCentroid", "O", "iiic", DXIL_ATTR_KIND_READ_NONE},
 {"dx.op.evalSampleIndex", "O", "iiici", DXIL_ATTR_KIND_READ_NONE},
 {"dx.op.coverage", "i", "i", DXIL_ATTR_KIND_READ_NONE},
+{"dx.op.storePatchConstant", "v", "iiicO", DXIL_ATTR_KIND_NO_UNWIND},
 };
 
 struct func_descr {
index 8ade0da..e31963f 100644 (file)
@@ -288,6 +288,7 @@ enum dxil_intr {
    DXIL_INTR_MAKE_DOUBLE = 101,
    DXIL_INTR_SPLIT_DOUBLE = 102,
 
+   DXIL_INTR_STORE_PATCH_CONSTANT = 106,
    DXIL_INTR_OUTPUT_CONTROL_POINT_ID = 107,
    DXIL_INTR_PRIMITIVE_ID = 108,
 
@@ -2996,23 +2997,44 @@ emit_store_output_via_intrinsic(struct ntd_context *ctx, nir_intrinsic_instr *in
 {
    assert(intr->intrinsic == nir_intrinsic_store_output ||
           ctx->mod.shader_kind == DXIL_HULL_SHADER);
+   bool is_patch_constant = intr->intrinsic == nir_intrinsic_store_output &&
+      ctx->mod.shader_kind == DXIL_HULL_SHADER;
    nir_alu_type out_type = nir_intrinsic_src_type(intr);
    enum overload_type overload = get_overload(out_type, intr->src[0].ssa->bit_size);
-   const struct dxil_func *func = dxil_get_function(&ctx->mod, "dx.op.storeOutput", overload);
+   const struct dxil_func *func = dxil_get_function(&ctx->mod, is_patch_constant ?
+      "dx.op.storePatchConstant" : "dx.op.storeOutput",
+      overload);
 
    if (!func)
       return false;
 
-   const struct dxil_value *opcode = dxil_module_get_int32_const(&ctx->mod, DXIL_INTR_STORE_OUTPUT);
+   const struct dxil_value *opcode = dxil_module_get_int32_const(&ctx->mod, is_patch_constant ?
+      DXIL_INTR_STORE_PATCH_CONSTANT : DXIL_INTR_STORE_OUTPUT);
    const struct dxil_value *output_id = dxil_module_get_int32_const(&ctx->mod, nir_intrinsic_base(intr));
    unsigned row_index = intr->intrinsic == nir_intrinsic_store_output ? 1 : 2;
-   const struct dxil_value *row = get_src(ctx, &intr->src[row_index], 0, nir_type_int);
+
+   /* NIR has these as 1 row, N cols, but DXIL wants them as N rows, 1 col. We muck with these in the signature
+    * generation, so muck with them here too.
+    */
+   nir_io_semantics semantics = nir_intrinsic_io_semantics(intr);
+   bool is_tess_level = semantics.location == VARYING_SLOT_TESS_LEVEL_INNER ||
+                        semantics.location == VARYING_SLOT_TESS_LEVEL_OUTER;
+
+   const struct dxil_value *row = NULL;
+   const struct dxil_value *col = NULL;
+   if (is_tess_level)
+      col = dxil_module_get_int8_const(&ctx->mod, 0);
+   else
+      row = get_src(ctx, &intr->src[row_index], 0, nir_type_int);
 
    bool success = true;
    uint32_t writemask = nir_intrinsic_write_mask(intr);
    for (unsigned i = 0; i < intr->num_components && success; ++i) {
       if (writemask & (1 << i)) {
-         const struct dxil_value *col = dxil_module_get_int8_const(&ctx->mod, i + nir_intrinsic_component(intr));
+         if (is_tess_level)
+            row = dxil_module_get_int32_const(&ctx->mod, i + nir_intrinsic_component(intr));
+         else
+            col = dxil_module_get_int8_const(&ctx->mod, i + nir_intrinsic_component(intr));
          const struct dxil_value *value = get_src(ctx, &intr->src[0], i, out_type);
          if (!col || !value)
             return false;