diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index 33827c73e43..234b7b097c9 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -123,6 +123,7 @@ const struct radv_dynamic_state default_dynamic_state = { .color_write_enable = 0u, .patch_control_points = 0, .polygon_mode = 0, + .tess_domain_origin = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT, }; static void @@ -258,6 +259,8 @@ radv_bind_dynamic_state(struct radv_cmd_buffer *cmd_buffer, const struct radv_dy RADV_CMP_COPY(polygon_mode, RADV_DYNAMIC_POLYGON_MODE); + RADV_CMP_COPY(tess_domain_origin, RADV_DYNAMIC_TESS_DOMAIN_ORIGIN); + #undef RADV_CMP_COPY cmd_buffer->state.dirty |= dest_mask; @@ -1481,6 +1484,10 @@ radv_emit_graphics_pipeline(struct radv_cmd_buffer *cmd_buffer) cmd_buffer->state.emitted_graphics_pipeline->cb_target_mask != pipeline->cb_target_mask) cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_COLOR_WRITE_ENABLE; + if (!cmd_buffer->state.emitted_graphics_pipeline || + cmd_buffer->state.emitted_graphics_pipeline->vgt_tf_param != pipeline->vgt_tf_param) + cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_TESS_DOMAIN_ORIGIN; + radeon_emit_array(cmd_buffer->cs, pipeline->base.cs.buf, pipeline->base.cs.cdw); if (pipeline->has_ngg_culling && @@ -3292,6 +3299,34 @@ radv_emit_vertex_input(struct radv_cmd_buffer *cmd_buffer, bool pipeline_is_dirt radv_save_vs_prolog(cmd_buffer, prolog); } +static void +radv_emit_tess_domain_origin(struct radv_cmd_buffer *cmd_buffer) +{ + struct radv_graphics_pipeline *pipeline = cmd_buffer->state.graphics_pipeline; + struct radv_shader *tes = radv_get_shader(&pipeline->base, MESA_SHADER_TESS_EVAL); + struct radv_dynamic_state *d = &cmd_buffer->state.dynamic; + unsigned vgt_tf_param = pipeline->vgt_tf_param; + unsigned topology; + + if (tes->info.tes.point_mode) { + topology = V_028B6C_OUTPUT_POINT; + } else if (tes->info.tes._primitive_mode == TESS_PRIMITIVE_ISOLINES) { + topology = V_028B6C_OUTPUT_LINE; + } else { + bool ccw = tes->info.tes.ccw; + + if (d->tess_domain_origin != VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT) { + ccw = !ccw; + } + + topology = ccw ? V_028B6C_OUTPUT_TRIANGLE_CCW : V_028B6C_OUTPUT_TRIANGLE_CW; + } + + vgt_tf_param |= S_028B6C_TOPOLOGY(topology); + + radeon_set_context_reg(cmd_buffer->cs, R_028B6C_VGT_TF_PARAM, vgt_tf_param); +} + static void radv_cmd_buffer_flush_dynamic_state(struct radv_cmd_buffer *cmd_buffer, bool pipeline_is_dirty) { @@ -3368,6 +3403,9 @@ radv_cmd_buffer_flush_dynamic_state(struct radv_cmd_buffer *cmd_buffer, bool pip if (states & RADV_CMD_DIRTY_DYNAMIC_PATCH_CONTROL_POINTS) radv_emit_patch_control_points(cmd_buffer); + if (states & RADV_CMD_DIRTY_DYNAMIC_TESS_DOMAIN_ORIGIN) + radv_emit_tess_domain_origin(cmd_buffer); + cmd_buffer->state.dirty &= ~states; } @@ -5772,6 +5810,18 @@ radv_CmdSetPolygonModeEXT(VkCommandBuffer commandBuffer, VkPolygonMode polygonMo state->dirty |= RADV_CMD_DIRTY_DYNAMIC_POLYGON_MODE; } +VKAPI_ATTR void VKAPI_CALL +radv_CmdSetTessellationDomainOriginEXT(VkCommandBuffer commandBuffer, + VkTessellationDomainOrigin domainOrigin) +{ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + struct radv_cmd_state *state = &cmd_buffer->state; + + state->dynamic.tess_domain_origin = domainOrigin; + + state->dirty |= RADV_CMD_DIRTY_DYNAMIC_TESS_DOMAIN_ORIGIN; +} + VKAPI_ATTR void VKAPI_CALL radv_CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer *pCmdBuffers) diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index 84f8d453154..7e9c988a175 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -1396,7 +1396,7 @@ radv_pipeline_needed_dynamic_state(const struct radv_graphics_pipeline *pipeline RADV_DYNAMIC_VERTEX_INPUT; if (pipeline->active_stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) - states |= RADV_DYNAMIC_PATCH_CONTROL_POINTS; + states |= RADV_DYNAMIC_PATCH_CONTROL_POINTS | RADV_DYNAMIC_TESS_DOMAIN_ORIGIN; return states; } @@ -1433,7 +1433,7 @@ radv_pipeline_needed_dynamic_state(const struct radv_graphics_pipeline *pipeline states &= ~RADV_DYNAMIC_COLOR_WRITE_ENABLE; if (!(pipeline->active_stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)) - states &= ~RADV_DYNAMIC_PATCH_CONTROL_POINTS; + states &= ~(RADV_DYNAMIC_PATCH_CONTROL_POINTS | RADV_DYNAMIC_TESS_DOMAIN_ORIGIN); return states; } @@ -1891,6 +1891,10 @@ radv_pipeline_init_dynamic_state(struct radv_graphics_pipeline *pipeline, dynamic->polygon_mode = si_translate_fill(state->rs->polygon_mode); } + if (states & RADV_DYNAMIC_TESS_DOMAIN_ORIGIN) { + dynamic->tess_domain_origin = state->ts->domain_origin; + } + pipeline->dynamic_state.mask = states; } @@ -5234,70 +5238,6 @@ radv_pipeline_emit_tess_shaders(struct radeon_cmdbuf *ctx_cs, struct radeon_cmdb } } -static void -radv_pipeline_emit_tess_state(struct radeon_cmdbuf *ctx_cs, - const struct radv_graphics_pipeline *pipeline, - const struct vk_graphics_pipeline_state *state) -{ - const struct radv_physical_device *pdevice = pipeline->base.device->physical_device; - struct radv_shader *tes = radv_get_shader(&pipeline->base, MESA_SHADER_TESS_EVAL); - unsigned type = 0, partitioning = 0, topology = 0, distribution_mode = 0; - - switch (tes->info.tes._primitive_mode) { - case TESS_PRIMITIVE_TRIANGLES: - type = V_028B6C_TESS_TRIANGLE; - break; - case TESS_PRIMITIVE_QUADS: - type = V_028B6C_TESS_QUAD; - break; - case TESS_PRIMITIVE_ISOLINES: - type = V_028B6C_TESS_ISOLINE; - break; - default: - break; - } - - switch (tes->info.tes.spacing) { - case TESS_SPACING_EQUAL: - partitioning = V_028B6C_PART_INTEGER; - break; - case TESS_SPACING_FRACTIONAL_ODD: - partitioning = V_028B6C_PART_FRAC_ODD; - break; - case TESS_SPACING_FRACTIONAL_EVEN: - partitioning = V_028B6C_PART_FRAC_EVEN; - break; - default: - break; - } - - bool ccw = tes->info.tes.ccw; - if (state->ts->domain_origin != VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT) - ccw = !ccw; - - if (tes->info.tes.point_mode) - topology = V_028B6C_OUTPUT_POINT; - else if (tes->info.tes._primitive_mode == TESS_PRIMITIVE_ISOLINES) - topology = V_028B6C_OUTPUT_LINE; - else if (ccw) - topology = V_028B6C_OUTPUT_TRIANGLE_CCW; - else - topology = V_028B6C_OUTPUT_TRIANGLE_CW; - - if (pdevice->rad_info.has_distributed_tess) { - if (pdevice->rad_info.family == CHIP_FIJI || pdevice->rad_info.family >= CHIP_POLARIS10) - distribution_mode = V_028B6C_TRAPEZOIDS; - else - distribution_mode = V_028B6C_DONUTS; - } else - distribution_mode = V_028B6C_NO_DIST; - - radeon_set_context_reg(ctx_cs, R_028B6C_VGT_TF_PARAM, - S_028B6C_TYPE(type) | S_028B6C_PARTITIONING(partitioning) | - S_028B6C_TOPOLOGY(topology) | - S_028B6C_DISTRIBUTION_MODE(distribution_mode)); -} - static void radv_pipeline_emit_hw_gs(struct radeon_cmdbuf *ctx_cs, struct radeon_cmdbuf *cs, const struct radv_graphics_pipeline *pipeline, const struct radv_shader *gs) @@ -5890,7 +5830,6 @@ radv_pipeline_emit_pm4(struct radv_graphics_pipeline *pipeline, if (radv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_CTRL)) { radv_pipeline_emit_tess_shaders(ctx_cs, cs, pipeline); - radv_pipeline_emit_tess_state(ctx_cs, pipeline, state); } radv_pipeline_emit_geometry_shader(ctx_cs, cs, pipeline); @@ -6093,6 +6032,54 @@ radv_pipeline_init_vgt_gs_out(struct radv_graphics_pipeline *pipeline, return gs_out; } +static void +radv_pipeline_init_tess_state(struct radv_graphics_pipeline *pipeline, + const struct vk_graphics_pipeline_state *state) +{ + const struct radv_physical_device *pdevice = pipeline->base.device->physical_device; + struct radv_shader *tes = radv_get_shader(&pipeline->base, MESA_SHADER_TESS_EVAL); + unsigned type = 0, partitioning = 0, distribution_mode = 0; + + switch (tes->info.tes._primitive_mode) { + case TESS_PRIMITIVE_TRIANGLES: + type = V_028B6C_TESS_TRIANGLE; + break; + case TESS_PRIMITIVE_QUADS: + type = V_028B6C_TESS_QUAD; + break; + case TESS_PRIMITIVE_ISOLINES: + type = V_028B6C_TESS_ISOLINE; + break; + default: + break; + } + + switch (tes->info.tes.spacing) { + case TESS_SPACING_EQUAL: + partitioning = V_028B6C_PART_INTEGER; + break; + case TESS_SPACING_FRACTIONAL_ODD: + partitioning = V_028B6C_PART_FRAC_ODD; + break; + case TESS_SPACING_FRACTIONAL_EVEN: + partitioning = V_028B6C_PART_FRAC_EVEN; + break; + default: + break; + } + + if (pdevice->rad_info.has_distributed_tess) { + if (pdevice->rad_info.family == CHIP_FIJI || pdevice->rad_info.family >= CHIP_POLARIS10) + distribution_mode = V_028B6C_TRAPEZOIDS; + else + distribution_mode = V_028B6C_DONUTS; + } else + distribution_mode = V_028B6C_NO_DIST; + + pipeline->vgt_tf_param = S_028B6C_TYPE(type) | S_028B6C_PARTITIONING(partitioning) | + S_028B6C_DISTRIBUTION_MODE(distribution_mode); +} + static void radv_pipeline_init_extra(struct radv_graphics_pipeline *pipeline, const struct radv_graphics_pipeline_create_info *extra, @@ -6285,6 +6272,10 @@ radv_graphics_pipeline_init(struct radv_graphics_pipeline *pipeline, struct radv radv_pipeline_init_gs_ring_state(pipeline, &gs->info.gs_ring_info); } + if (radv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_CTRL)) { + radv_pipeline_init_tess_state(pipeline, &state); + } + if (!radv_pipeline_has_stage(pipeline, MESA_SHADER_MESH)) radv_pipeline_init_vertex_input_state(pipeline, &state); diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 2b5df052e87..c73e5522fec 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -1353,6 +1353,8 @@ struct radv_dynamic_state { uint32_t patch_control_points; uint32_t polygon_mode; + + VkTessellationDomainOrigin tess_domain_origin; }; extern const struct radv_dynamic_state default_dynamic_state; @@ -2045,6 +2047,7 @@ struct radv_graphics_pipeline { uint8_t next_vertex_stage : 8; uint32_t vb_desc_usage_mask; uint32_t vb_desc_alloc_size; + uint32_t vgt_tf_param; /* Last pre-PS API stage */ gl_shader_stage last_vgt_api_stage; @@ -3088,6 +3091,9 @@ si_translate_blend_logic_op(VkLogicOp op) } } +uint32_t radv_get_tess_output_topology(const struct radv_graphics_pipeline *pipeline, + VkTessellationDomainOrigin domain_origin); + ALWAYS_INLINE static bool radv_is_streamout_enabled(struct radv_cmd_buffer *cmd_buffer) {