dzn: Handle depth bias for point fill mode emulation
authorJesse Natalie <jenatali@microsoft.com>
Fri, 21 Apr 2023 18:13:12 +0000 (11:13 -0700)
committerMarge Bot <emma+marge@anholt.net>
Tue, 25 Apr 2023 15:36:01 +0000 (15:36 +0000)
Fixes dEQP-VK.draw.renderpass.depth_bias.depth_bias_triangle_list_point

This is not complete, there's no slope scale or clamp handling, but it
does handle static or dynamic (though dynamic is untested).

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22639>

src/microsoft/spirv_to_dxil/spirv_to_dxil.h
src/microsoft/vulkan/dzn_cmd_buffer.c
src/microsoft/vulkan/dzn_nir.c
src/microsoft/vulkan/dzn_nir.h
src/microsoft/vulkan/dzn_pipeline.c
src/microsoft/vulkan/dzn_private.h

index 40adf76..a4baa61 100644 (file)
@@ -120,6 +120,10 @@ struct dxil_spirv_vertex_runtime_data {
    float viewport_width;
    float viewport_height;
    uint32_t view_index;
+   /* When depth bias is dynamic, the constant value to add to point
+    * primitives when emulating triangle point fill mode. Slope-scaled
+    * depth bias is currently unsupported. */
+   float depth_bias;
 };
 
 enum dxil_spirv_yz_flip_mode {
index 794f211..865fcd6 100644 (file)
@@ -3128,6 +3128,9 @@ dzn_cmd_buffer_update_pipeline(struct dzn_cmd_buffer *cmdbuf, uint32_t bindpoint
             ID3D12GraphicsCommandList1_SetViewInstanceMask(cmdbuf->cmdlist, gfx->multiview.view_mask);
          else
             ID3D12GraphicsCommandList1_SetViewInstanceMask(cmdbuf->cmdlist, 1);
+
+         if (gfx->zsa.dynamic_depth_bias && gfx->use_gs_for_polygon_mode_point)
+            cmdbuf->state.bindpoint[bindpoint].dirty |= DZN_CMD_BINDPOINT_DIRTY_SYSVALS;
       }
    }
 
@@ -5692,6 +5695,7 @@ dzn_CmdSetDepthBias(VkCommandBuffer commandBuffer,
    cmdbuf->state.pipeline_variant.depth_bias.constant_factor = depthBiasConstantFactor;
    cmdbuf->state.pipeline_variant.depth_bias.clamp = depthBiasClamp;
    cmdbuf->state.pipeline_variant.depth_bias.slope_factor = depthBiasSlopeFactor;
+   cmdbuf->state.sysvals.gfx.depth_bias = depthBiasConstantFactor;
    if (pdev->options16.DynamicDepthBiasSupported)
       cmdbuf->state.dirty |= DZN_CMD_DIRTY_DEPTH_BIAS;
    else
index 0c2b316..2945bd8 100644 (file)
@@ -28,6 +28,7 @@
 #include "nir_builder.h"
 #include "nir_builtin_builder.h"
 #include "nir_vulkan.h"
+#include "dxil_nir.h"
 
 static nir_ssa_def *
 dzn_nir_create_bo_desc(nir_builder *b,
@@ -784,8 +785,33 @@ copy_vars(nir_builder *b, nir_deref_instr *dst, nir_deref_instr *src)
    }
 }
 
+static nir_ssa_def *
+load_dynamic_depth_bias(nir_builder *b, struct dzn_nir_point_gs_info *info)
+{
+   nir_address_format ubo_format = nir_address_format_32bit_index_offset;
+   unsigned offset = offsetof(struct dxil_spirv_vertex_runtime_data, depth_bias);
+
+   nir_ssa_def *index = nir_vulkan_resource_index(
+      b, nir_address_format_num_components(ubo_format),
+      nir_address_format_bit_size(ubo_format),
+      nir_imm_int(b, 0),
+      .desc_set = info->runtime_data_cbv.register_space,
+      .binding = info->runtime_data_cbv.base_shader_register,
+      .desc_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
+
+   nir_ssa_def *load_desc = nir_load_vulkan_descriptor(
+      b, nir_address_format_num_components(ubo_format),
+      nir_address_format_bit_size(ubo_format),
+      index, .desc_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
+
+   return build_load_ubo_dxil(
+      b, nir_channel(b, load_desc, 0),
+      nir_imm_int(b, offset),
+      1, 32, 4);
+}
+
 nir_shader *
-dzn_nir_polygon_point_mode_gs(const nir_shader *previous_shader, unsigned cull_mode, bool front_ccw)
+dzn_nir_polygon_point_mode_gs(const nir_shader *previous_shader, struct dzn_nir_point_gs_info *info)
 {
    nir_builder builder;
    nir_builder *b = &builder;
@@ -838,6 +864,33 @@ dzn_nir_polygon_point_mode_gs(const nir_shader *previous_shader, unsigned cull_m
    front_facing_var->data.driver_location = num_vars;
    front_facing_var->data.interpolation = INTERP_MODE_FLAT;
 
+   nir_ssa_def *depth_bias_scale = NULL;
+   if (info->depth_bias) {
+      switch (info->ds_fmt) {
+      case DXGI_FORMAT_D16_UNORM:
+         depth_bias_scale = nir_imm_float(b, 1.0f / (1 << 16));
+         break;
+      case DXGI_FORMAT_D24_UNORM_S8_UINT:
+         depth_bias_scale = nir_imm_float(b, 1.0f / (1 << 24));
+         break;
+      case DXGI_FORMAT_D32_FLOAT:
+      case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: {
+         nir_deref_instr *deref_pos = nir_build_deref_var(b, pos_var);
+         nir_ssa_def *max_z = NULL;
+         for (uint32_t i = 0; i < 3; ++i) {
+            nir_ssa_def *pos = nir_load_deref(b, nir_build_deref_array_imm(b, deref_pos, i));
+            nir_ssa_def *z = nir_iand_imm(b, nir_channel(b, pos, 2), 0x7fffffff);
+            max_z = i == 0 ? z : nir_imax(b, z, max_z);
+         }
+         nir_ssa_def *exponent = nir_ishr_imm(b, nir_iand_imm(b, max_z, 0x7f800000), 23);
+         depth_bias_scale = nir_fexp2(b, nir_i2f32(b, nir_iadd_imm(b, exponent, -23)));
+         break;
+      }
+      default:
+         depth_bias_scale = nir_imm_float(b, 0.0f);
+      }
+   }
+
    /* Temporary variable "loop_index" to loop over input vertices */
    nir_function_impl *impl = nir_shader_get_entrypoint(nir);
    nir_variable *loop_index_var =
@@ -847,15 +900,15 @@ dzn_nir_polygon_point_mode_gs(const nir_shader *previous_shader, unsigned cull_m
 
    nir_ssa_def *cull_pass = nir_imm_bool(b, true);
    nir_ssa_def *front_facing;
-   assert(cull_mode != VK_CULL_MODE_FRONT_AND_BACK);
-   if (cull_mode == VK_CULL_MODE_FRONT_BIT) {
-      cull_pass = cull_face(b, pos_var, front_ccw);
+   assert(info->cull_mode != VK_CULL_MODE_FRONT_AND_BACK);
+   if (info->cull_mode == VK_CULL_MODE_FRONT_BIT) {
+      cull_pass = cull_face(b, pos_var, info->front_ccw);
       front_facing = nir_b2i32(b, cull_pass);
-   } else if (cull_mode == VK_CULL_MODE_BACK_BIT) {
-      cull_pass = cull_face(b, pos_var, !front_ccw);
+   } else if (info->cull_mode == VK_CULL_MODE_BACK_BIT) {
+      cull_pass = cull_face(b, pos_var, !info->front_ccw);
       front_facing = nir_inot(b, nir_b2i32(b, cull_pass));
    } else
-      front_facing = nir_i2i32(b, cull_face(b, pos_var, front_ccw));
+      front_facing = nir_i2i32(b, cull_face(b, pos_var, info->front_ccw));
 
    /**
     *  if (cull_pass) {
@@ -880,7 +933,23 @@ dzn_nir_polygon_point_mode_gs(const nir_shader *previous_shader, unsigned cull_m
    for (unsigned i = 0; i < num_vars; ++i) {
       nir_ssa_def *index = loop_index;
       nir_deref_instr *in_value = nir_build_deref_array(b, nir_build_deref_var(b, in[i]), index);
-      copy_vars(b, nir_build_deref_var(b, out[i]), in_value);
+      if (in[i] == pos_var && info->depth_bias) {
+         nir_ssa_def *bias_val;
+         if (info->depth_bias_dynamic) {
+            bias_val = load_dynamic_depth_bias(b, info);
+         } else {
+            assert(info->slope_scaled_depth_bias == 0.0f);
+            bias_val = nir_imm_float(b, info->constant_depth_bias);
+         }
+         bias_val = nir_fmul(b, bias_val, depth_bias_scale);
+         nir_ssa_def *old_val = nir_load_deref(b, in_value);
+         nir_ssa_def *new_val = nir_vector_insert_imm(b, old_val,
+                                                      nir_fadd(b, nir_channel(b, old_val, 2), bias_val),
+                                                      2);
+         nir_store_var(b, out[i], new_val, 0xf);
+      } else {
+         copy_vars(b, nir_build_deref_var(b, out[i]), in_value);
+      }
    }
    nir_store_var(b, front_facing_var, front_facing, 0x1);
    nir_emit_vertex(b, 0);
index 881d8e1..176e019 100644 (file)
@@ -158,7 +158,23 @@ dzn_nir_blit_vs(void);
 nir_shader *
 dzn_nir_blit_fs(const struct dzn_nir_blit_info *info);
 
+struct dzn_nir_point_gs_info {
+   unsigned cull_mode;
+   bool front_ccw;
+   bool depth_bias;
+   bool depth_bias_dynamic;
+   DXGI_FORMAT ds_fmt;
+   /* Constant values */
+   float constant_depth_bias;
+   float slope_scaled_depth_bias;
+   float depth_bias_clamp;
+   /* Used for loading dynamic values */
+   struct {
+      uint32_t register_space;
+      uint32_t base_shader_register;
+   } runtime_data_cbv;
+};
 nir_shader *
-dzn_nir_polygon_point_mode_gs(const nir_shader *vs, unsigned cull_mode, bool front_ccw);
+dzn_nir_polygon_point_mode_gs(const nir_shader *vs, struct dzn_nir_point_gs_info *info);
 
 #endif
index 8181de2..f0ac0b6 100644 (file)
@@ -776,11 +776,11 @@ dzn_graphics_pipeline_compile_shaders(struct dzn_device *device,
       active_stage_mask |= BITFIELD_BIT(stage);
    }
 
-   bool use_gs_for_polygon_mode_point =
+   pipeline->use_gs_for_polygon_mode_point =
       info->pRasterizationState &&
       info->pRasterizationState->polygonMode == VK_POLYGON_MODE_POINT &&
       !(active_stage_mask & (1 << MESA_SHADER_GEOMETRY));
-   if (use_gs_for_polygon_mode_point)
+   if (pipeline->use_gs_for_polygon_mode_point)
       last_raster_stage = MESA_SHADER_GEOMETRY;
 
    enum dxil_spirv_yz_flip_mode yz_flip_mode = DXIL_SPIRV_YZ_FLIP_NONE;
@@ -825,7 +825,7 @@ dzn_graphics_pipeline_compile_shaders(struct dzn_device *device,
       _mesa_sha1_update(&pipeline_hash_ctx, &z_flip_mask, sizeof(z_flip_mask));
       _mesa_sha1_update(&pipeline_hash_ctx, &force_sample_rate_shading, sizeof(force_sample_rate_shading));
       _mesa_sha1_update(&pipeline_hash_ctx, &lower_view_index, sizeof(lower_view_index));
-      _mesa_sha1_update(&pipeline_hash_ctx, &use_gs_for_polygon_mode_point, sizeof(use_gs_for_polygon_mode_point));
+      _mesa_sha1_update(&pipeline_hash_ctx, &pipeline->use_gs_for_polygon_mode_point, sizeof(pipeline->use_gs_for_polygon_mode_point));
 
       u_foreach_bit(stage, active_stage_mask) {
          vk_pipeline_hash_shader_stage(stages[stage].info, NULL, stages[stage].spirv_hash);
@@ -895,12 +895,25 @@ dzn_graphics_pipeline_compile_shaders(struct dzn_device *device,
          return ret;
    }
 
-   if (use_gs_for_polygon_mode_point) {
+   if (pipeline->use_gs_for_polygon_mode_point) {
       /* TODO: Cache; handle TES */
+      struct dzn_nir_point_gs_info gs_info = {
+         .cull_mode = info->pRasterizationState->cullMode,
+         .front_ccw = info->pRasterizationState->frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE,
+         .depth_bias = info->pRasterizationState->depthBiasEnable,
+         .depth_bias_dynamic = pipeline->zsa.dynamic_depth_bias,
+         .ds_fmt = pipeline->zsa.ds_fmt,
+         .constant_depth_bias = info->pRasterizationState->depthBiasConstantFactor,
+         .slope_scaled_depth_bias = info->pRasterizationState->depthBiasSlopeFactor,
+         .depth_bias_clamp = info->pRasterizationState->depthBiasClamp,
+         .runtime_data_cbv = {
+            .register_space = DZN_REGISTER_SPACE_SYSVALS,
+            .base_shader_register = 0,
+         }
+      };
       pipeline->templates.shaders[MESA_SHADER_GEOMETRY].nir =
          dzn_nir_polygon_point_mode_gs(pipeline->templates.shaders[MESA_SHADER_VERTEX].nir,
-                                       info->pRasterizationState->cullMode,
-                                       info->pRasterizationState->frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE);
+                                       &gs_info);
 
       struct dxil_spirv_runtime_conf conf = {
          .runtime_data_cbv = {
@@ -976,7 +989,7 @@ dzn_graphics_pipeline_compile_shaders(struct dzn_device *device,
 
          if (stage == MESA_SHADER_FRAGMENT) {
             _mesa_sha1_update(&dxil_hash_ctx, &force_sample_rate_shading, sizeof(force_sample_rate_shading));
-            _mesa_sha1_update(&dxil_hash_ctx, &use_gs_for_polygon_mode_point, sizeof(use_gs_for_polygon_mode_point));
+            _mesa_sha1_update(&dxil_hash_ctx, &pipeline->use_gs_for_polygon_mode_point, sizeof(pipeline->use_gs_for_polygon_mode_point));
          }
 
          _mesa_sha1_update(&dxil_hash_ctx, stages[stage].spirv_hash, sizeof(stages[stage].spirv_hash));
@@ -1881,10 +1894,10 @@ dzn_graphics_pipeline_create(struct dzn_device *device,
             pipeline->zsa.depth_bounds.dynamic = true;
             break;
          case VK_DYNAMIC_STATE_DEPTH_BIAS:
+            pipeline->zsa.dynamic_depth_bias = true;
             if (pdev->options16.DynamicDepthBiasSupported) {
                *flags |= D3D12_PIPELINE_STATE_FLAG_DYNAMIC_DEPTH_BIAS;
             } else {
-               pipeline->zsa.dynamic_depth_bias = true;
                ret = dzn_graphics_pipeline_prepare_for_variants(device, pipeline);
                if (ret)
                   goto out;
@@ -1961,6 +1974,7 @@ dzn_graphics_pipeline_create(struct dzn_device *device,
                                    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
                                    VK_IMAGE_ASPECT_DEPTH_BIT |
                                    VK_IMAGE_ASPECT_STENCIL_BIT);
+      pipeline->zsa.ds_fmt = *ds_fmt;
    }
 
    pipeline->multiview.view_mask = MAX2(view_mask, 1);
@@ -2144,7 +2158,8 @@ dzn_graphics_pipeline_get_state(struct dzn_graphics_pipeline *pipeline,
    if (dzn_graphics_pipeline_get_desc_template(pipeline, ib_strip_cut))
       masked_key.ib_strip_cut = key->ib_strip_cut;
 
-   if (dzn_graphics_pipeline_get_desc_template(pipeline, rast) &&
+   if (!pdev->options16.DynamicDepthBiasSupported &&
+       dzn_graphics_pipeline_get_desc_template(pipeline, rast) &&
        pipeline->zsa.dynamic_depth_bias)
       masked_key.depth_bias = key->depth_bias;
 
@@ -2174,8 +2189,7 @@ dzn_graphics_pipeline_get_state(struct dzn_graphics_pipeline *pipeline,
 
       D3D12_RASTERIZER_DESC *rast =
          dzn_graphics_pipeline_get_desc(pipeline, stream_buf, rast);
-      if (rast && pipeline->zsa.dynamic_depth_bias) {
-         assert(!pdev->options16.DynamicDepthBiasSupported);
+      if (!pdev->options16.DynamicDepthBiasSupported && rast && pipeline->zsa.dynamic_depth_bias) {
          rast->DepthBias = translate_depth_bias(masked_key.depth_bias.constant_factor);
          rast->DepthBiasClamp = masked_key.depth_bias.clamp;
          rast->SlopeScaledDepthBias = masked_key.depth_bias.slope_factor;
index 946bf27..011ce1f 100644 (file)
@@ -969,6 +969,7 @@ struct dzn_graphics_pipeline {
          float min, max;
       } depth_bounds;
       bool dynamic_depth_bias;
+      DXGI_FORMAT ds_fmt;
    } zsa;
 
    struct {
@@ -977,6 +978,7 @@ struct dzn_graphics_pipeline {
    } blend;
 
    bool rast_disabled_from_missing_position;
+   bool use_gs_for_polygon_mode_point;
 
    struct {
       uint32_t view_mask;