diff --git a/.pick_status.json b/.pick_status.json index 6c07d332257..562ac4b9593 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -454,7 +454,7 @@ "description": "pvr: Add support for fragment pass through shader", "nominated": true, "nomination_type": 4, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null, "notes": null diff --git a/src/imagination/ci/bxs-4-64-fails.txt b/src/imagination/ci/bxs-4-64-fails.txt index 6aa94c80955..dae68619d9d 100644 --- a/src/imagination/ci/bxs-4-64-fails.txt +++ b/src/imagination/ci/bxs-4-64-fails.txt @@ -34,7 +34,6 @@ dEQP-VK.multiview.renderpass2.input_attachments.no_queries.5_10_5_10,Fail dEQP-VK.multiview.renderpass2.input_attachments.no_queries.8_1_1_8,Fail dEQP-VK.multiview.renderpass2.input_attachments.no_queries.8,Fail dEQP-VK.multiview.renderpass2.input_attachments.no_queries.max_multi_view_view_count,Fail -dEQP-VK.pipeline.monolithic.empty_fs.masked_samples,Fail dEQP-VK.pipeline.monolithic.stencil.no_stencil_att.dynamic_rendering.dynamic_enable.d24_unorm_s8_uint,Fail dEQP-VK.pipeline.monolithic.stencil.no_stencil_att.dynamic_rendering.dynamic_enable.d32_sfloat_s8_uint,Fail dEQP-VK.pipeline.monolithic.stencil.no_stencil_att.dynamic_rendering.static_enable.d24_unorm_s8_uint,Fail diff --git a/src/imagination/vulkan/pvr_arch_cmd_buffer.c b/src/imagination/vulkan/pvr_arch_cmd_buffer.c index 69d1edbbad8..fce50393758 100644 --- a/src/imagination/vulkan/pvr_arch_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_arch_cmd_buffer.c @@ -6548,6 +6548,21 @@ static void pvr_setup_output_select(struct pvr_cmd_buffer *const cmd_buffer) } } +static bool +pvr_needs_fs_passthrough(const struct vk_dynamic_graphics_state *dynamic_state) +{ + if (dynamic_state->rs.rasterizer_discard_enable) + return false; + + uint32_t full_sample_mask = + BITFIELD_MASK(dynamic_state->ms.rasterization_samples); + + bool partial_sample_mask = + (dynamic_state->ms.sample_mask & full_sample_mask) != full_sample_mask; + + return partial_sample_mask; +} + static void pvr_setup_isp_faces_and_control(struct pvr_cmd_buffer *const cmd_buffer, struct ROGUE_TA_STATE_ISPA *const ispa_out) @@ -6560,6 +6575,8 @@ pvr_setup_isp_faces_and_control(struct pvr_cmd_buffer *const cmd_buffer, struct vk_dynamic_graphics_state *dynamic_state = &cmd_buffer->vk.dynamic_graphics_state; struct pvr_ppp_state *const ppp_state = &cmd_buffer->state.ppp_state; + bool skip_fs = fragment_shader_state->is_passthrough && + !pvr_needs_fs_passthrough(dynamic_state); const bool rasterizer_discard = dynamic_state->rs.rasterizer_discard_enable; const uint32_t subpass_idx = pass_info->subpass_idx; @@ -6635,6 +6652,9 @@ pvr_setup_isp_faces_and_control(struct pvr_cmd_buffer *const cmd_buffer, fragment_shader_state->pass_type == ROGUE_TA_PASSTYPE_OPAQUE) ispa.passtype = ROGUE_TA_PASSTYPE_TRANSLUCENT; + if (skip_fs) + ispa.passtype = ROGUE_TA_PASSTYPE_OPAQUE; + ispa.objtype = obj_type; /* Return unpacked ispa structure. dcmpmode, dwritedisable, passtype and @@ -6749,7 +6769,7 @@ pvr_setup_isp_faces_and_control(struct pvr_cmd_buffer *const cmd_buffer, /* TODO: is shader_bo ever NULL? Figure out what to do. */ ispctl.tagwritedisable = rasterizer_discard || - !fragment_shader_state->shader_bo; + !fragment_shader_state->shader_bo || skip_fs; ispctl.two_sided = is_two_sided; ispctl.bpres = header->pres_ispctl_fb || header->pres_ispctl_bb; @@ -7865,10 +7885,12 @@ pvr_emit_dirty_ppp_state(struct pvr_cmd_buffer *const cmd_buffer, pvr_setup_isp_faces_and_control(cmd_buffer, NULL); } + bool skip_fs = fragment_state->is_passthrough && + !pvr_needs_fs_passthrough(dynamic_state); if (!dynamic_state->rs.rasterizer_discard_enable && state->dirty.fragment_descriptors && state->gfx_pipeline->shader_state.fragment.shader_bo && - !state->gfx_pipeline->fs_data.common.uses.empty) { + !state->gfx_pipeline->fs_data.common.uses.empty && !skip_fs) { result = pvr_setup_fragment_state_pointers(cmd_buffer, sub_cmd); if (result != VK_SUCCESS) return result; @@ -7906,7 +7928,8 @@ pvr_emit_dirty_ppp_state(struct pvr_cmd_buffer *const cmd_buffer, return result; if (state->gfx_pipeline && - fragment_state->pass_type == ROGUE_TA_PASSTYPE_DEPTH_FEEDBACK) { + fragment_state->pass_type == ROGUE_TA_PASSTYPE_DEPTH_FEEDBACK && + !skip_fs) { assert(state->current_sub_cmd->type == PVR_SUB_CMD_TYPE_GRAPHICS); state->current_sub_cmd->gfx.has_depth_feedback = true; } @@ -8235,7 +8258,12 @@ static VkResult pvr_validate_draw_state(struct pvr_cmd_buffer *cmd_buffer) state->dirty.fragment_descriptors = true; } - if (state->dirty.fragment_descriptors) { + const struct pvr_fragment_shader_state *const fragment_shader_state = + &gfx_pipeline->shader_state.fragment; + bool skip_fs = fragment_shader_state->is_passthrough && + !pvr_needs_fs_passthrough(dynamic_state); + + if (state->dirty.fragment_descriptors && !skip_fs) { result = pvr_setup_descriptor_mappings( cmd_buffer, PVR_STAGE_ALLOCATION_FRAGMENT, diff --git a/src/imagination/vulkan/pvr_arch_pipeline.c b/src/imagination/vulkan/pvr_arch_pipeline.c index b352eae0d39..7185a48cda8 100644 --- a/src/imagination/vulkan/pvr_arch_pipeline.c +++ b/src/imagination/vulkan/pvr_arch_pipeline.c @@ -2591,7 +2591,9 @@ pvr_preprocess_shader_data(pco_data *data, pvr_init_fs_blend(data, state->cb); pvr_init_fs_tile_buffers(data); - data->fs.uses.alpha_to_coverage = state->ms->alpha_to_coverage_enable; + data->fs.uses.alpha_to_coverage = false; + if (state->ms) + data->fs.uses.alpha_to_coverage = state->ms->alpha_to_coverage_enable; if (BITSET_TEST(state->dynamic, MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES) || (state->cb && state->cb->color_write_enables != @@ -2715,6 +2717,14 @@ static void pvr_early_init_shader_data(pco_data *data, } } +static bool pvr_build_fs_passthrough(bool no_fragment_shader, + const struct pvr_device_info *dev_info) +{ + bool is_arch_rogue = dev_info->ident.arch == PVR_DEVICE_ARCH_ROGUE; + + return is_arch_rogue && no_fragment_shader; +} + /* Compiles and uploads shaders and PDS programs. */ static VkResult pvr_graphics_pipeline_compile(struct pvr_device *const device, @@ -2761,6 +2771,7 @@ pvr_graphics_pipeline_compile(struct pvr_device *const device, struct pvr_pds_vertex_dma vtx_dma_descriptions[PVR_MAX_VERTEX_ATTRIB_DMAS]; uint32_t vtx_dma_count = 0; + bool build_fs_passthrough = false; for (mesa_shader_stage stage = 0; stage < MESA_SHADER_STAGES; ++stage) { size_t stage_index = gfx_pipeline->stage_indices[stage]; @@ -2811,6 +2822,17 @@ pvr_graphics_pipeline_compile(struct pvr_device *const device, consumer = nir_shaders[stage]; } + /* Check if the fragment passthrough shader should be built. */ + build_fs_passthrough = + pvr_build_fs_passthrough(!nir_shaders[MESA_SHADER_FRAGMENT], + &device->pdevice->dev_info); + + if (build_fs_passthrough) { + nir_shader *fs_pass = pvr_usc_fs_pfo_passthrough_nir(pco_ctx); + ralloc_steal(shader_mem_ctx, fs_pass); + nir_shaders[MESA_SHADER_FRAGMENT] = fs_pass; + } + for (mesa_shader_stage stage = 0; stage < MESA_SHADER_STAGES; ++stage) { if (!nir_shaders[stage]) continue; @@ -2874,6 +2896,7 @@ pvr_graphics_pipeline_compile(struct pvr_device *const device, if (*fs) { pvr_fragment_state_save(gfx_pipeline, *fs); + fragment_state->is_passthrough = build_fs_passthrough; pvr_graphics_pipeline_setup_fragment_coeff_program( gfx_pipeline, diff --git a/src/imagination/vulkan/pvr_pipeline.h b/src/imagination/vulkan/pvr_pipeline.h index d926ab9c1ed..f0072c1df87 100644 --- a/src/imagination/vulkan/pvr_pipeline.h +++ b/src/imagination/vulkan/pvr_pipeline.h @@ -84,6 +84,8 @@ struct pvr_fragment_shader_state { struct pvr_pds_kickusc_program pds_fragment_program; uint32_t *pds_fragment_program_buffer; + + bool is_passthrough; }; struct pvr_pipeline { diff --git a/src/imagination/vulkan/pvr_usc.c b/src/imagination/vulkan/pvr_usc.c index 4f52d82d43b..39771ebf48e 100644 --- a/src/imagination/vulkan/pvr_usc.c +++ b/src/imagination/vulkan/pvr_usc.c @@ -52,6 +52,30 @@ static pco_shader *build_shader(pco_ctx *ctx, nir_shader *nir, pco_data *data) return shader; } +/** + * Generate a fragment passthrough shader that does a dummy store. + * + * \param ctx PCO context. + * \return The fragment passthrough shader. + */ +nir_shader *pvr_usc_fs_pfo_passthrough_nir(pco_ctx *ctx) +{ + nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, + pco_nir_options(), + "fs_pfo_passthrough"); + + /* Need to mark the shader as not internal for the compiler to + * emit the pfo code for the sample mask. + */ + b.shader->info.internal = false; + nir_frag_store_pco(&b, nir_imm_int(&b, 0), .base = 0); + nir_jump(&b, nir_jump_return); + + pco_preprocess_nir(ctx, b.shader); + + return b.shader; +} + /** * Generate an end-of-tile shader. * diff --git a/src/imagination/vulkan/pvr_usc.h b/src/imagination/vulkan/pvr_usc.h index 6e0dfa37272..67b3ccda361 100644 --- a/src/imagination/vulkan/pvr_usc.h +++ b/src/imagination/vulkan/pvr_usc.h @@ -37,6 +37,8 @@ struct pvr_eot_props { uint64_t tile_buffer_addrs[PVR_MAX_COLOR_ATTACHMENTS]; }; +nir_shader *pvr_usc_fs_pfo_passthrough_nir (pco_ctx *ctx); + pco_shader *pvr_usc_eot(pco_ctx *ctx, struct pvr_eot_props *props, const struct pvr_device_info *dev_info);