broadcom/compiler: implement gl_PrimitiveID in FS without a GS
OpenGL ES 3.1 specifies that a geometry shader can write to gl_PrimitiveID, which can then be read by a fragment shader. OpenGL ES 3.2 additionally adds the capacity for the fragment shader to read gl_PrimitiveID even if there is no geometry shader. This commit adds support for this feature, which is also implicitly expected by the geometry shader feature in Vulkan 1.0. Fixes: dEQP-VK.pipeline.framebuffer_attachment.no_attachments dEQP-VK.pipeline.framebuffer_attachment.no_attachments_ms Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11874>
This commit is contained in:
parent
82fadbd3ab
commit
940725a7d9
|
@ -2101,6 +2101,14 @@ ntq_setup_fs_inputs(struct v3d_compile *c)
|
|||
|
||||
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;
|
||||
|
@ -3143,6 +3151,7 @@ ntq_emit_intrinsic(struct v3d_compile *c, nir_intrinsic_instr *instr)
|
|||
* 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;
|
||||
|
@ -3764,9 +3773,15 @@ nir_to_vir(struct v3d_compile *c)
|
|||
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);
|
||||
|
|
|
@ -421,6 +421,19 @@ struct v3d_fs_key {
|
|||
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 {
|
||||
|
@ -636,6 +649,9 @@ struct v3d_compile {
|
|||
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.
|
||||
*/
|
||||
|
@ -701,7 +717,7 @@ struct v3d_compile {
|
|||
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
|
||||
|
@ -925,6 +941,9 @@ struct v3d_gs_prog_data {
|
|||
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.
|
||||
|
|
|
@ -800,6 +800,7 @@ v3d_fs_set_prog_data(struct v3d_compile *c,
|
|||
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
|
||||
|
|
|
@ -1156,6 +1156,7 @@ 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);
|
||||
|
@ -1172,6 +1173,7 @@ pipeline_populate_v3d_fs_key(struct v3d_fs_key *key,
|
|||
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;
|
||||
|
@ -1969,6 +1971,7 @@ pipeline_compile_fragment_shader(struct v3dv_pipeline *pipeline,
|
|||
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;
|
||||
|
|
|
@ -1869,7 +1869,9 @@ v3dX(cmd_buffer_emit_gl_shader_state)(struct v3dv_cmd_buffer *cmd_buffer)
|
|||
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) */
|
||||
|
|
|
@ -543,6 +543,7 @@ v3d_update_compiled_fs(struct v3d_context *v3d, uint8_t prim_mode)
|
|||
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 {
|
||||
|
|
|
@ -618,8 +618,10 @@ v3d_emit_gl_shader_state(struct v3d_context *v3d,
|
|||
|
||||
#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
|
||||
|
|
Loading…
Reference in New Issue