mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-01 18:20:10 +01:00
tu: Implement extendedDynamicState2PatchControlPoints
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18773>
This commit is contained in:
parent
1bd3d28050
commit
68f3c38c80
6 changed files with 211 additions and 107 deletions
|
|
@ -760,7 +760,7 @@ r3d_common(struct tu_cmd_buffer *cmd, struct tu_cs *cs, bool blit,
|
|||
}
|
||||
tu_cs_emit_regs(cs, A6XX_VFD_MULTIVIEW_CNTL());
|
||||
|
||||
tu6_emit_vpc(cs, vs, NULL, NULL, NULL, fs, 0);
|
||||
tu6_emit_vpc(cs, vs, NULL, NULL, NULL, fs);
|
||||
|
||||
/* REPL_MODE for varying with RECTLIST (2 vertices only) */
|
||||
tu_cs_emit_regs(cs, A6XX_VPC_VARYING_INTERP_MODE(0, 0));
|
||||
|
|
|
|||
|
|
@ -2564,15 +2564,11 @@ tu_CmdBindPipeline(VkCommandBuffer commandBuffer,
|
|||
if (pipeline->active_stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {
|
||||
cmd->state.rp.has_tess = true;
|
||||
|
||||
/* maximum number of patches that can fit in tess factor/param buffers */
|
||||
uint32_t subdraw_size = MIN2(TU_TESS_FACTOR_SIZE / ir3_tess_factor_stride(pipeline->tess.patch_type),
|
||||
TU_TESS_PARAM_SIZE / pipeline->program.hs_param_stride);
|
||||
/* convert from # of patches to draw count */
|
||||
subdraw_size *= pipeline->tess.patch_control_points;
|
||||
|
||||
/* TODO: Move this packet to pipeline state, since it's constant based on the pipeline. */
|
||||
tu_cs_emit_pkt7(cs, CP_SET_SUBDRAW_SIZE, 1);
|
||||
tu_cs_emit(cs, subdraw_size);
|
||||
if (!(pipeline->dynamic_state_mask &
|
||||
BIT(TU_DYNAMIC_STATE_PATCH_CONTROL_POINTS)))
|
||||
cmd->state.patch_control_points = pipeline->tess.patch_control_points;
|
||||
else
|
||||
cmd->state.dirty |= TU_CMD_DIRTY_PATCH_CONTROL_POINTS;
|
||||
}
|
||||
|
||||
cmd->state.line_mode = pipeline->rast.line_mode;
|
||||
|
|
@ -3030,7 +3026,11 @@ VKAPI_ATTR void VKAPI_CALL
|
|||
tu_CmdSetPatchControlPointsEXT(VkCommandBuffer commandBuffer,
|
||||
uint32_t patchControlPoints)
|
||||
{
|
||||
tu_stub();
|
||||
TU_FROM_HANDLE(tu_cmd_buffer, cmd, commandBuffer);
|
||||
|
||||
cmd->state.patch_control_points = patchControlPoints;
|
||||
|
||||
cmd->state.dirty |= TU_CMD_DIRTY_PATCH_CONTROL_POINTS;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
|
|
@ -4465,6 +4465,15 @@ tu6_draw_common(struct tu_cmd_buffer *cmd,
|
|||
tu6_emit_blend(&cs, cmd);
|
||||
}
|
||||
|
||||
if (cmd->state.dirty & TU_CMD_DIRTY_PATCH_CONTROL_POINTS) {
|
||||
bool tess = cmd->state.pipeline->active_stages &
|
||||
VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
|
||||
struct tu_cs cs = tu_cmd_dynamic_state(cmd, TU_DYNAMIC_STATE_PATCH_CONTROL_POINTS,
|
||||
tess ? TU6_EMIT_PATCH_CONTROL_POINTS_DWORDS : 0);
|
||||
tu6_emit_patch_control_points(&cs, cmd->state.pipeline,
|
||||
cmd->state.patch_control_points);
|
||||
}
|
||||
|
||||
/* for the first draw in a renderpass, re-emit all the draw states
|
||||
*
|
||||
* and if a draw-state disabling path (CmdClearAttachments 3D fallback) was
|
||||
|
|
@ -4502,7 +4511,8 @@ tu6_draw_common(struct tu_cmd_buffer *cmd,
|
|||
/* emit draw states that were just updated
|
||||
* note we eventually don't want to have to emit anything here
|
||||
*/
|
||||
bool emit_binding_stride = false, emit_blend = false;
|
||||
bool emit_binding_stride = false, emit_blend = false,
|
||||
emit_patch_control_points = false;
|
||||
uint32_t draw_state_count =
|
||||
((cmd->state.dirty & TU_CMD_DIRTY_SHADER_CONSTS) ? 1 : 0) +
|
||||
((cmd->state.dirty & TU_CMD_DIRTY_DESC_SETS_LOAD) ? 1 : 0) +
|
||||
|
|
@ -4522,6 +4532,13 @@ tu6_draw_common(struct tu_cmd_buffer *cmd,
|
|||
draw_state_count += 1;
|
||||
}
|
||||
|
||||
if ((cmd->state.dirty & TU_CMD_DIRTY_PATCH_CONTROL_POINTS) &&
|
||||
(pipeline->dynamic_state_mask &
|
||||
BIT(TU_DYNAMIC_STATE_PATCH_CONTROL_POINTS))) {
|
||||
emit_patch_control_points = true;
|
||||
draw_state_count += 1;
|
||||
}
|
||||
|
||||
if (draw_state_count > 0)
|
||||
tu_cs_emit_pkt7(cs, CP_SET_DRAW_STATE, 3 * draw_state_count);
|
||||
|
||||
|
|
@ -4539,6 +4556,10 @@ tu6_draw_common(struct tu_cmd_buffer *cmd,
|
|||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_DYNAMIC + TU_DYNAMIC_STATE_BLEND,
|
||||
cmd->state.dynamic_state[TU_DYNAMIC_STATE_BLEND]);
|
||||
}
|
||||
if (emit_patch_control_points) {
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_DYNAMIC + TU_DYNAMIC_STATE_PATCH_CONTROL_POINTS,
|
||||
cmd->state.dynamic_state[TU_DYNAMIC_STATE_PATCH_CONTROL_POINTS]);
|
||||
}
|
||||
if (cmd->state.dirty & TU_CMD_DIRTY_VS_PARAMS)
|
||||
tu_cs_emit_draw_state(cs, TU_DRAW_STATE_VS_PARAMS, cmd->state.vs_params);
|
||||
|
||||
|
|
@ -4564,7 +4585,7 @@ tu_draw_initiator(struct tu_cmd_buffer *cmd, enum pc_di_src_sel src_sel)
|
|||
enum pc_di_primtype primtype = cmd->state.primtype;
|
||||
|
||||
if (primtype == DI_PT_PATCHES0)
|
||||
primtype += pipeline->tess.patch_control_points;
|
||||
primtype += cmd->state.patch_control_points;
|
||||
|
||||
uint32_t initiator =
|
||||
CP_DRAW_INDX_OFFSET_0_PRIM_TYPE(primtype) |
|
||||
|
|
|
|||
|
|
@ -66,8 +66,9 @@ enum tu_cmd_dirty_bits
|
|||
TU_CMD_DIRTY_RASTERIZER_DISCARD = BIT(10),
|
||||
TU_CMD_DIRTY_VIEWPORTS = BIT(11),
|
||||
TU_CMD_DIRTY_BLEND = BIT(12),
|
||||
TU_CMD_DIRTY_PATCH_CONTROL_POINTS = BIT(13),
|
||||
/* all draw states were disabled and need to be re-enabled: */
|
||||
TU_CMD_DIRTY_DRAW_STATE = BIT(13)
|
||||
TU_CMD_DIRTY_DRAW_STATE = BIT(14)
|
||||
};
|
||||
|
||||
/* There are only three cache domains we have to care about: the CCU, or
|
||||
|
|
@ -408,6 +409,8 @@ struct tu_cmd_state
|
|||
bool msaa_disable;
|
||||
bool z_negative_one_to_one;
|
||||
|
||||
unsigned patch_control_points;
|
||||
|
||||
/* VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT and
|
||||
* VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT are allowed to run simultaniously,
|
||||
* but they use the same {START,STOP}_PRIMITIVE_CTRS control.
|
||||
|
|
|
|||
|
|
@ -754,7 +754,7 @@ tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
|
|||
(VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *)ext;
|
||||
features->extendedDynamicState2 = true;
|
||||
features->extendedDynamicState2LogicOp = true;
|
||||
features->extendedDynamicState2PatchControlPoints = false;
|
||||
features->extendedDynamicState2PatchControlPoints = true;
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: {
|
||||
|
|
|
|||
|
|
@ -1165,8 +1165,7 @@ tu6_emit_vpc(struct tu_cs *cs,
|
|||
const struct ir3_shader_variant *hs,
|
||||
const struct ir3_shader_variant *ds,
|
||||
const struct ir3_shader_variant *gs,
|
||||
const struct ir3_shader_variant *fs,
|
||||
uint32_t patch_control_points)
|
||||
const struct ir3_shader_variant *fs)
|
||||
{
|
||||
/* note: doesn't compile as static because of the array regs.. */
|
||||
const struct reg_config {
|
||||
|
|
@ -1417,39 +1416,6 @@ tu6_emit_vpc(struct tu_cs *cs,
|
|||
tu_cs_emit_pkt4(cs, REG_A6XX_PC_TESS_NUM_VERTEX, 1);
|
||||
tu_cs_emit(cs, hs->tess.tcs_vertices_out);
|
||||
|
||||
uint32_t patch_local_mem_size_16b =
|
||||
patch_control_points * vs->output_size / 4;
|
||||
|
||||
/* Total attribute slots in HS incoming patch. */
|
||||
tu_cs_emit_pkt4(cs, REG_A6XX_PC_HS_INPUT_SIZE, 1);
|
||||
tu_cs_emit(cs, patch_local_mem_size_16b);
|
||||
|
||||
const uint32_t wavesize = 64;
|
||||
const uint32_t vs_hs_local_mem_size = 16384;
|
||||
|
||||
uint32_t max_patches_per_wave;
|
||||
if (cs->device->physical_device->info->a6xx.tess_use_shared) {
|
||||
/* HS invocations for a patch are always within the same wave,
|
||||
* making barriers less expensive. VS can't have barriers so we
|
||||
* don't care about VS invocations being in the same wave.
|
||||
*/
|
||||
max_patches_per_wave = wavesize / hs->tess.tcs_vertices_out;
|
||||
} else {
|
||||
/* VS is also in the same wave */
|
||||
max_patches_per_wave =
|
||||
wavesize / MAX2(patch_control_points, hs->tess.tcs_vertices_out);
|
||||
}
|
||||
|
||||
uint32_t patches_per_wave =
|
||||
MIN2(vs_hs_local_mem_size / (patch_local_mem_size_16b * 16),
|
||||
max_patches_per_wave);
|
||||
|
||||
uint32_t wave_input_size = DIV_ROUND_UP(
|
||||
patches_per_wave * patch_local_mem_size_16b * 16, 256);
|
||||
|
||||
tu_cs_emit_pkt4(cs, REG_A6XX_SP_HS_WAVE_INPUT_SIZE, 1);
|
||||
tu_cs_emit(cs, wave_input_size);
|
||||
|
||||
/* In SPIR-V generated from GLSL, the tessellation primitive params are
|
||||
* are specified in the tess eval shader, but in SPIR-V generated from
|
||||
* HLSL, they are specified in the tess control shader. */
|
||||
|
|
@ -1723,55 +1689,140 @@ tu6_emit_fs_outputs(struct tu_cs *cs,
|
|||
}
|
||||
|
||||
static void
|
||||
tu6_emit_geom_tess_consts(struct tu_cs *cs,
|
||||
const struct ir3_shader_variant *vs,
|
||||
const struct ir3_shader_variant *hs,
|
||||
const struct ir3_shader_variant *ds,
|
||||
const struct ir3_shader_variant *gs,
|
||||
uint32_t cps_per_patch)
|
||||
tu6_emit_vs_params(struct tu_cs *cs,
|
||||
const struct ir3_const_state *const_state,
|
||||
unsigned constlen,
|
||||
unsigned param_stride,
|
||||
unsigned num_vertices)
|
||||
{
|
||||
struct tu_device *dev = cs->device;
|
||||
|
||||
uint32_t num_vertices =
|
||||
hs ? cps_per_patch : gs->gs.vertices_in;
|
||||
|
||||
uint32_t vs_params[4] = {
|
||||
vs->output_size * num_vertices * 4, /* vs primitive stride */
|
||||
vs->output_size * 4, /* vs vertex stride */
|
||||
param_stride * num_vertices * 4, /* vs primitive stride */
|
||||
param_stride * 4, /* vs vertex stride */
|
||||
0,
|
||||
0,
|
||||
};
|
||||
uint32_t vs_base = ir3_const_state(vs)->offsets.primitive_param;
|
||||
uint32_t vs_base = const_state->offsets.primitive_param;
|
||||
tu6_emit_const(cs, CP_LOAD_STATE6_GEOM, vs_base, SB6_VS_SHADER, 0,
|
||||
ARRAY_SIZE(vs_params), vs_params);
|
||||
}
|
||||
|
||||
if (hs) {
|
||||
assert(ds->type != MESA_SHADER_NONE);
|
||||
|
||||
/* Create the shared tess factor BO the first time tess is used on the device. */
|
||||
static void
|
||||
tu_get_tess_iova(struct tu_device *dev,
|
||||
uint64_t *tess_factor_iova,
|
||||
uint64_t *tess_param_iova)
|
||||
{
|
||||
/* Create the shared tess factor BO the first time tess is used on the device. */
|
||||
if (!dev->tess_bo) {
|
||||
mtx_lock(&dev->mutex);
|
||||
if (!dev->tess_bo)
|
||||
tu_bo_init_new(dev, &dev->tess_bo, TU_TESS_BO_SIZE, TU_BO_ALLOC_NO_FLAGS, "tess");
|
||||
mtx_unlock(&dev->mutex);
|
||||
}
|
||||
|
||||
uint64_t tess_factor_iova = dev->tess_bo->iova;
|
||||
uint64_t tess_param_iova = tess_factor_iova + TU_TESS_FACTOR_SIZE;
|
||||
*tess_factor_iova = dev->tess_bo->iova;
|
||||
*tess_param_iova = dev->tess_bo->iova + TU_TESS_FACTOR_SIZE;
|
||||
}
|
||||
|
||||
uint32_t hs_params[8] = {
|
||||
vs->output_size * num_vertices * 4, /* hs primitive stride */
|
||||
vs->output_size * 4, /* hs vertex stride */
|
||||
hs->output_size,
|
||||
cps_per_patch,
|
||||
tess_param_iova,
|
||||
tess_param_iova >> 32,
|
||||
tess_factor_iova,
|
||||
tess_factor_iova >> 32,
|
||||
};
|
||||
void
|
||||
tu6_emit_patch_control_points(struct tu_cs *cs,
|
||||
const struct tu_pipeline *pipeline,
|
||||
unsigned patch_control_points)
|
||||
{
|
||||
if (!(pipeline->active_stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT))
|
||||
return;
|
||||
|
||||
uint32_t hs_base = hs->const_state->offsets.primitive_param;
|
||||
uint32_t hs_param_dwords = MIN2((hs->constlen - hs_base) * 4, ARRAY_SIZE(hs_params));
|
||||
tu6_emit_const(cs, CP_LOAD_STATE6_GEOM, hs_base, SB6_HS_SHADER, 0,
|
||||
hs_param_dwords, hs_params);
|
||||
struct tu_device *dev = cs->device;
|
||||
|
||||
tu6_emit_vs_params(cs,
|
||||
&pipeline->program.link[MESA_SHADER_VERTEX].const_state,
|
||||
pipeline->program.link[MESA_SHADER_VERTEX].constlen,
|
||||
pipeline->program.vs_param_stride,
|
||||
patch_control_points);
|
||||
|
||||
uint64_t tess_factor_iova, tess_param_iova;
|
||||
tu_get_tess_iova(dev, &tess_factor_iova, &tess_param_iova);
|
||||
|
||||
uint32_t hs_params[8] = {
|
||||
pipeline->program.vs_param_stride * patch_control_points * 4, /* hs primitive stride */
|
||||
pipeline->program.vs_param_stride * 4, /* hs vertex stride */
|
||||
pipeline->program.hs_param_stride,
|
||||
patch_control_points,
|
||||
tess_param_iova,
|
||||
tess_param_iova >> 32,
|
||||
tess_factor_iova,
|
||||
tess_factor_iova >> 32,
|
||||
};
|
||||
|
||||
const struct ir3_const_state *hs_const =
|
||||
&pipeline->program.link[MESA_SHADER_TESS_CTRL].const_state;
|
||||
unsigned hs_constlen =
|
||||
pipeline->program.link[MESA_SHADER_TESS_CTRL].constlen;
|
||||
uint32_t hs_base = hs_const->offsets.primitive_param;
|
||||
uint32_t hs_param_dwords = MIN2((hs_constlen - hs_base) * 4, ARRAY_SIZE(hs_params));
|
||||
tu6_emit_const(cs, CP_LOAD_STATE6_GEOM, hs_base, SB6_HS_SHADER, 0,
|
||||
hs_param_dwords, hs_params);
|
||||
|
||||
uint32_t patch_local_mem_size_16b =
|
||||
patch_control_points * pipeline->program.vs_param_stride / 4;
|
||||
|
||||
/* Total attribute slots in HS incoming patch. */
|
||||
tu_cs_emit_pkt4(cs, REG_A6XX_PC_HS_INPUT_SIZE, 1);
|
||||
tu_cs_emit(cs, patch_local_mem_size_16b);
|
||||
|
||||
const uint32_t wavesize = 64;
|
||||
const uint32_t vs_hs_local_mem_size = 16384;
|
||||
|
||||
uint32_t max_patches_per_wave;
|
||||
if (dev->physical_device->info->a6xx.tess_use_shared) {
|
||||
/* HS invocations for a patch are always within the same wave,
|
||||
* making barriers less expensive. VS can't have barriers so we
|
||||
* don't care about VS invocations being in the same wave.
|
||||
*/
|
||||
max_patches_per_wave = wavesize / pipeline->program.hs_vertices_out;
|
||||
} else {
|
||||
/* VS is also in the same wave */
|
||||
max_patches_per_wave =
|
||||
wavesize / MAX2(patch_control_points,
|
||||
pipeline->program.hs_vertices_out);
|
||||
}
|
||||
|
||||
uint32_t patches_per_wave =
|
||||
MIN2(vs_hs_local_mem_size / (patch_local_mem_size_16b * 16),
|
||||
max_patches_per_wave);
|
||||
|
||||
uint32_t wave_input_size = DIV_ROUND_UP(
|
||||
patches_per_wave * patch_local_mem_size_16b * 16, 256);
|
||||
|
||||
tu_cs_emit_pkt4(cs, REG_A6XX_SP_HS_WAVE_INPUT_SIZE, 1);
|
||||
tu_cs_emit(cs, wave_input_size);
|
||||
|
||||
/* maximum number of patches that can fit in tess factor/param buffers */
|
||||
uint32_t subdraw_size = MIN2(TU_TESS_FACTOR_SIZE / ir3_tess_factor_stride(pipeline->tess.patch_type),
|
||||
TU_TESS_PARAM_SIZE / (pipeline->program.hs_param_stride * 4));
|
||||
/* convert from # of patches to draw count */
|
||||
subdraw_size *= patch_control_points;
|
||||
|
||||
tu_cs_emit_pkt7(cs, CP_SET_SUBDRAW_SIZE, 1);
|
||||
tu_cs_emit(cs, subdraw_size);
|
||||
}
|
||||
|
||||
static void
|
||||
tu6_emit_geom_tess_consts(struct tu_cs *cs,
|
||||
const struct ir3_shader_variant *vs,
|
||||
const struct ir3_shader_variant *hs,
|
||||
const struct ir3_shader_variant *ds,
|
||||
const struct ir3_shader_variant *gs)
|
||||
{
|
||||
struct tu_device *dev = cs->device;
|
||||
|
||||
if (gs && !hs) {
|
||||
tu6_emit_vs_params(cs, ir3_const_state(vs), vs->constlen,
|
||||
vs->output_size, gs->gs.vertices_in);
|
||||
}
|
||||
|
||||
if (hs) {
|
||||
uint64_t tess_factor_iova, tess_param_iova;
|
||||
tu_get_tess_iova(dev, &tess_factor_iova, &tess_param_iova);
|
||||
|
||||
uint32_t ds_params[8] = {
|
||||
gs ? ds->output_size * gs->gs.vertices_in * 4 : 0, /* ds primitive stride */
|
||||
|
|
@ -1793,7 +1844,7 @@ tu6_emit_geom_tess_consts(struct tu_cs *cs,
|
|||
if (gs) {
|
||||
const struct ir3_shader_variant *prev = ds ? ds : vs;
|
||||
uint32_t gs_params[4] = {
|
||||
prev->output_size * num_vertices * 4, /* gs primitive stride */
|
||||
prev->output_size * gs->gs.vertices_in * 4, /* gs primitive stride */
|
||||
prev->output_size * 4, /* gs vertex stride */
|
||||
0,
|
||||
0,
|
||||
|
|
@ -1842,7 +1893,6 @@ tu6_emit_program(struct tu_cs *cs,
|
|||
const struct ir3_shader_variant *gs = builder->variants[MESA_SHADER_GEOMETRY];
|
||||
const struct ir3_shader_variant *fs = builder->variants[MESA_SHADER_FRAGMENT];
|
||||
gl_shader_stage stage = MESA_SHADER_VERTEX;
|
||||
uint32_t cps_per_patch = pipeline->tess.patch_control_points;
|
||||
bool multi_pos_output = vs->multi_pos_output;
|
||||
|
||||
/* Don't use the binning pass variant when GS is present because we don't
|
||||
|
|
@ -1899,7 +1949,7 @@ tu6_emit_program(struct tu_cs *cs,
|
|||
|
||||
tu6_emit_vfd_dest(cs, vs);
|
||||
|
||||
tu6_emit_vpc(cs, vs, hs, ds, gs, fs, cps_per_patch);
|
||||
tu6_emit_vpc(cs, vs, hs, ds, gs, fs);
|
||||
|
||||
if (fs) {
|
||||
tu6_emit_fs_inputs(cs, fs);
|
||||
|
|
@ -1912,7 +1962,7 @@ tu6_emit_program(struct tu_cs *cs,
|
|||
}
|
||||
|
||||
if (gs || hs) {
|
||||
tu6_emit_geom_tess_consts(cs, vs, hs, ds, gs, cps_per_patch);
|
||||
tu6_emit_geom_tess_consts(cs, vs, hs, ds, gs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3644,6 +3694,10 @@ tu_pipeline_builder_parse_dynamic(struct tu_pipeline_builder *builder,
|
|||
pipeline->dynamic_state_mask |= BIT(TU_DYNAMIC_STATE_VERTEX_INPUT) |
|
||||
BIT(TU_DYNAMIC_STATE_VB_STRIDE);
|
||||
break;
|
||||
case VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT:
|
||||
pipeline->dynamic_state_mask |=
|
||||
BIT(TU_DYNAMIC_STATE_PATCH_CONTROL_POINTS);
|
||||
break;
|
||||
default:
|
||||
assert(!"unsupported dynamic state");
|
||||
break;
|
||||
|
|
@ -3699,7 +3753,8 @@ tu_pipeline_builder_parse_libraries(struct tu_pipeline_builder *builder,
|
|||
BIT(VK_DYNAMIC_STATE_SCISSOR) |
|
||||
BIT(VK_DYNAMIC_STATE_LINE_WIDTH) |
|
||||
BIT(VK_DYNAMIC_STATE_DEPTH_BIAS) |
|
||||
BIT(TU_DYNAMIC_STATE_RASTERIZER_DISCARD);
|
||||
BIT(TU_DYNAMIC_STATE_RASTERIZER_DISCARD) |
|
||||
BIT(TU_DYNAMIC_STATE_PATCH_CONTROL_POINTS);
|
||||
}
|
||||
|
||||
if (library->state &
|
||||
|
|
@ -3819,6 +3874,19 @@ tu_pipeline_set_linkage(struct tu_program_descriptor_linkage *link,
|
|||
link->constlen = v->constlen;
|
||||
}
|
||||
|
||||
static bool
|
||||
tu_pipeline_static_state(struct tu_pipeline *pipeline, struct tu_cs *cs,
|
||||
uint32_t id, uint32_t size)
|
||||
{
|
||||
assert(id < ARRAY_SIZE(pipeline->dynamic_state));
|
||||
|
||||
if (pipeline->dynamic_state_mask & BIT(id))
|
||||
return false;
|
||||
|
||||
pipeline->dynamic_state[id] = tu_cs_draw_state(&pipeline->cs, cs, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
tu_pipeline_builder_parse_shader_stages(struct tu_pipeline_builder *builder,
|
||||
struct tu_pipeline *pipeline)
|
||||
|
|
@ -3857,22 +3925,21 @@ tu_pipeline_builder_parse_shader_stages(struct tu_pipeline_builder *builder,
|
|||
builder->variants[i]);
|
||||
}
|
||||
|
||||
struct ir3_shader_variant *vs = builder->variants[MESA_SHADER_VERTEX];
|
||||
struct ir3_shader_variant *hs = builder->variants[MESA_SHADER_TESS_CTRL];
|
||||
if (hs)
|
||||
pipeline->program.hs_param_stride = hs->output_size * 4;
|
||||
}
|
||||
if (hs) {
|
||||
pipeline->program.vs_param_stride = vs->output_size;
|
||||
pipeline->program.hs_param_stride = hs->output_size;
|
||||
pipeline->program.hs_vertices_out = hs->tess.tcs_vertices_out;
|
||||
|
||||
static bool
|
||||
tu_pipeline_static_state(struct tu_pipeline *pipeline, struct tu_cs *cs,
|
||||
uint32_t id, uint32_t size)
|
||||
{
|
||||
assert(id < ARRAY_SIZE(pipeline->dynamic_state));
|
||||
|
||||
if (pipeline->dynamic_state_mask & BIT(id))
|
||||
return false;
|
||||
|
||||
pipeline->dynamic_state[id] = tu_cs_draw_state(&pipeline->cs, cs, size);
|
||||
return true;
|
||||
struct tu_cs cs;
|
||||
if (tu_pipeline_static_state(pipeline, &cs,
|
||||
TU_DYNAMIC_STATE_PATCH_CONTROL_POINTS,
|
||||
TU6_EMIT_PATCH_CONTROL_POINTS_DWORDS)) {
|
||||
tu6_emit_patch_control_points(&cs, pipeline,
|
||||
pipeline->tess.patch_control_points);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3970,8 +4037,12 @@ tu_pipeline_builder_parse_tessellation(struct tu_pipeline_builder *builder,
|
|||
const VkPipelineTessellationStateCreateInfo *tess_info =
|
||||
builder->create_info->pTessellationState;
|
||||
|
||||
assert(tess_info->patchControlPoints <= 32);
|
||||
pipeline->tess.patch_control_points = tess_info->patchControlPoints;
|
||||
if (!(pipeline->dynamic_state_mask &
|
||||
BIT(TU_DYNAMIC_STATE_PATCH_CONTROL_POINTS))) {
|
||||
assert(tess_info->patchControlPoints <= 32);
|
||||
pipeline->tess.patch_control_points = tess_info->patchControlPoints;
|
||||
}
|
||||
|
||||
const VkPipelineTessellationDomainOriginStateCreateInfo *domain_info =
|
||||
vk_find_struct_const(tess_info->pNext, PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO);
|
||||
pipeline->tess.upper_left_domain_origin = !domain_info ||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ enum tu_dynamic_state
|
|||
TU_DYNAMIC_STATE_RASTERIZER_DISCARD,
|
||||
TU_DYNAMIC_STATE_BLEND,
|
||||
TU_DYNAMIC_STATE_VERTEX_INPUT,
|
||||
TU_DYNAMIC_STATE_PATCH_CONTROL_POINTS,
|
||||
TU_DYNAMIC_STATE_COUNT,
|
||||
/* no associated draw state: */
|
||||
TU_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY = TU_DYNAMIC_STATE_COUNT,
|
||||
|
|
@ -206,7 +207,9 @@ struct tu_pipeline
|
|||
|
||||
struct tu_program_descriptor_linkage link[MESA_SHADER_STAGES];
|
||||
|
||||
uint32_t vs_param_stride;
|
||||
uint32_t hs_param_stride;
|
||||
uint32_t hs_vertices_out;
|
||||
} program;
|
||||
|
||||
struct
|
||||
|
|
@ -290,6 +293,13 @@ void tu6_emit_vertex_input(struct tu_cs *cs,
|
|||
uint32_t attr_count,
|
||||
const VkVertexInputAttributeDescription2EXT *attrs);
|
||||
|
||||
#define EMIT_CONST_DWORDS(const_dwords) (4 + const_dwords)
|
||||
#define TU6_EMIT_PATCH_CONTROL_POINTS_DWORDS \
|
||||
(EMIT_CONST_DWORDS(4) + EMIT_CONST_DWORDS(8) + 2 + 2 + 2)
|
||||
void tu6_emit_patch_control_points(struct tu_cs *cs,
|
||||
const struct tu_pipeline *pipeline,
|
||||
unsigned patch_control_points);
|
||||
|
||||
uint32_t tu6_rb_mrt_control_rop(VkLogicOp op, bool *rop_reads_dst);
|
||||
|
||||
struct tu_pvtmem_config {
|
||||
|
|
@ -317,8 +327,7 @@ tu6_emit_vpc(struct tu_cs *cs,
|
|||
const struct ir3_shader_variant *hs,
|
||||
const struct ir3_shader_variant *ds,
|
||||
const struct ir3_shader_variant *gs,
|
||||
const struct ir3_shader_variant *fs,
|
||||
uint32_t patch_control_points);
|
||||
const struct ir3_shader_variant *fs);
|
||||
|
||||
void
|
||||
tu6_emit_fs_inputs(struct tu_cs *cs, const struct ir3_shader_variant *fs);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue