if (var->data.location == VARYING_SLOT_POS) {
emit_fragcoord_input(c, loc);
+ } else if (var->data.location == VARYING_SLOT_PRIMITIVE_ID &&
+ !c->fs_key->has_gs) {
+ /* If the fragment shader reads gl_PrimitiveID and we
+ * don't have a geometry shader in the pipeline to write
+ * it then we program the hardware to inject it as
+ * an implicit varying. Take it from there.
+ */
+ c->inputs[loc * 4] = c->primitive_id;
} else if (util_varying_is_point_coord(var->data.location,
c->fs_key->point_sprite_mask)) {
c->inputs[loc * 4 + 0] = c->point_x;
* VPM output header. According to docs, we should read this
* using ldvpm(v,d)_in (See Table 71).
*/
+ assert(c->s->info.stage == MESA_SHADER_GEOMETRY);
ntq_store_dest(c, &instr->dest, 0,
vir_LDVPMV_IN(c, vir_uniform_ui(c, 0)));
break;
c->payload_w_centroid = vir_MOV(c, vir_reg(QFILE_REG, 1));
c->payload_z = vir_MOV(c, vir_reg(QFILE_REG, 2));
- /* V3D 4.x can disable implicit point coordinate varyings if
- * they are not used.
- */
+ /* V3D 4.x can disable implicit varyings if they are not used */
+ c->fs_uses_primitive_id =
+ nir_find_variable_with_location(c->s, nir_var_shader_in,
+ VARYING_SLOT_PRIMITIVE_ID);
+ if (c->fs_uses_primitive_id && !c->fs_key->has_gs) {
+ c->primitive_id =
+ emit_fragment_varying(c, NULL, -1, 0, 0);
+ }
+
if (c->fs_key->is_points &&
(c->devinfo->ver < 40 || program_reads_point_coord(c))) {
c->point_x = emit_fragment_varying(c, NULL, -1, 0, 0);
uint32_t point_sprite_mask;
struct pipe_rt_blend_state blend;
+
+ /* If the fragment shader reads gl_PrimitiveID then we have 2 scenarios:
+ *
+ * - If there is a geometry shader, then gl_PrimitiveID must be written
+ * by it and the fragment shader loads it as a regular explicit input
+ * varying. This is the only valid use case in GLES 3.1.
+ *
+ * - If there is not a geometry shader (allowed since GLES 3.2 and
+ * Vulkan 1.0), then gl_PrimitiveID must be implicitly written by
+ * hardware and is considered an implicit input varying in the
+ * fragment shader.
+ */
+ bool has_gs;
};
struct v3d_gs_key {
bool writes_z;
bool uses_implicit_point_line_varyings;
+ /* True if a fragment shader reads gl_PrimitiveID */
+ bool fs_uses_primitive_id;
+
/* If the fragment shader does anything that requires to force
* per-sample MSAA, such as reading gl_SampleID.
*/
struct qreg execute;
bool in_control_flow;
- struct qreg line_x, point_x, point_y;
+ struct qreg line_x, point_x, point_y, primitive_id;
/**
* Instance ID, which comes in before the vertex attribute payload if
struct v3d_fs_prog_data {
struct v3d_prog_data base;
+ /* Whether the program reads gl_PrimitiveID */
+ bool uses_pid;
+
struct v3d_varying_slot input_slots[V3D_MAX_FS_INPUTS];
/* Array of flat shade flags.
prog_data->lock_scoreboard_on_first_thrsw =
c->lock_scoreboard_on_first_thrsw;
prog_data->force_per_sample_msaa = c->force_per_sample_msaa;
+ prog_data->uses_pid = c->fs_uses_primitive_id;
}
static void
pipeline_populate_v3d_fs_key(struct v3d_fs_key *key,
const VkGraphicsPipelineCreateInfo *pCreateInfo,
const struct v3dv_pipeline_stage *p_stage,
+ bool has_geometry_shader,
uint32_t ucp_enables)
{
assert(p_stage->stage == BROADCOM_SHADER_FRAGMENT);
key->is_points = (topology == PIPE_PRIM_POINTS);
key->is_lines = (topology >= PIPE_PRIM_LINES &&
topology <= PIPE_PRIM_LINE_STRIP);
+ key->has_gs = has_geometry_shader;
const VkPipelineColorBlendStateCreateInfo *cb_info =
pCreateInfo->pColorBlendState;
struct v3d_fs_key key;
pipeline_populate_v3d_fs_key(&key, pCreateInfo, p_stage,
+ pipeline->gs != NULL,
get_ucp_enable_mask(pipeline->vs));
VkResult vk_result;
v3dv_cl_address(default_attribute_values, 0);
shader.any_shader_reads_hardware_written_primitive_id =
- pipeline->has_gs ? prog_data_gs->uses_pid : false;
+ (pipeline->has_gs && prog_data_gs->uses_pid) || prog_data_fs->uses_pid;
+ shader.insert_primitive_id_as_first_varying_to_fragment_shader =
+ !pipeline->has_gs && prog_data_fs->uses_pid;
}
/* Upload vertex element attributes (SHADER_STATE_ATTRIBUTE_RECORD) */
prim_mode <= PIPE_PRIM_LINE_STRIP);
key->line_smoothing = (key->is_lines &&
v3d_line_smoothing_enabled(v3d));
+ key->has_gs = v3d->prog.bind_gs != NULL;
if (v3d->blend->base.logicop_enable) {
key->logicop_func = v3d->blend->base.logicop_func;
} else {
#if V3D_VERSION >= 41
shader.any_shader_reads_hardware_written_primitive_id =
- v3d->prog.gs ? v3d->prog.gs->prog_data.gs->uses_pid :
- false;
+ (v3d->prog.gs && v3d->prog.gs->prog_data.gs->uses_pid) ||
+ v3d->prog.fs->prog_data.fs->uses_pid;
+ shader.insert_primitive_id_as_first_varying_to_fragment_shader =
+ !v3d->prog.gs && v3d->prog.fs->prog_data.fs->uses_pid;
#endif
#if V3D_VERSION >= 40