diff --git a/src/imagination/common/pvr_limits.h b/src/imagination/common/pvr_limits.h index fc0deba9efe..5c5f3f3ce98 100644 --- a/src/imagination/common/pvr_limits.h +++ b/src/imagination/common/pvr_limits.h @@ -39,6 +39,10 @@ #define PVR_MAX_PUSH_CONSTANTS_SIZE 256U +#define PVR_POINT_SIZE_RANGE_MIN 1.0f +#define PVR_POINT_SIZE_RANGE_MAX 511.0f +#define PVR_POINT_SIZE_GRANULARITY 0.0625f + #define PVR_MAX_TEXTURE_EXTENT_Z \ (ROGUE_TEXSTATE_IMAGE_WORD1_DEPTH_MAX_SIZE + 1U) diff --git a/src/imagination/pco/pco_internal.h b/src/imagination/pco/pco_internal.h index 6328b689215..6bbe48ba70b 100644 --- a/src/imagination/pco/pco_internal.h +++ b/src/imagination/pco/pco_internal.h @@ -1225,6 +1225,7 @@ bool pco_nir_lower_algebraic(nir_shader *shader); bool pco_nir_lower_algebraic_late(nir_shader *shader); bool pco_nir_lower_vk(nir_shader *shader, pco_common_data *common); bool pco_nir_pfo(nir_shader *shader, pco_fs_data *fs); +bool pco_nir_point_size(nir_shader *shader); bool pco_nir_pvi(nir_shader *shader, pco_vs_data *vs); bool pco_opt(pco_shader *shader); bool pco_ra(pco_shader *shader); diff --git a/src/imagination/pco/pco_nir.c b/src/imagination/pco/pco_nir.c index a0a02b06100..38bd9576c87 100644 --- a/src/imagination/pco/pco_nir.c +++ b/src/imagination/pco/pco_nir.c @@ -219,6 +219,15 @@ void pco_lower_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data) if (nir->info.stage == MESA_SHADER_FRAGMENT) { NIR_PASS(_, nir, pco_nir_pfo, &data->fs); } else if (nir->info.stage == MESA_SHADER_VERTEX) { + NIR_PASS(_, + nir, + nir_lower_point_size, + PVR_POINT_SIZE_RANGE_MIN, + PVR_POINT_SIZE_RANGE_MAX); + + if (!nir->info.internal) + NIR_PASS(_, nir, pco_nir_point_size); + NIR_PASS(_, nir, pco_nir_pvi, &data->vs); } diff --git a/src/imagination/pco/pco_nir_pvfio.c b/src/imagination/pco/pco_nir_pvfio.c index c793521edb5..8aafb8a600f 100644 --- a/src/imagination/pco/pco_nir_pvfio.c +++ b/src/imagination/pco/pco_nir_pvfio.c @@ -215,3 +215,73 @@ bool pco_nir_pvi(nir_shader *shader, pco_vs_data *vs) return false; } + +/** + * \brief Checks if the point size is written. + * + * \param[in] b NIR builder. + * \param[in] intr NIR intrinsic instruction. + * \param[in] cb_data User callback data. + * \return True if the instruction was lowered. + */ +static bool +check_psiz_write(nir_builder *b, nir_intrinsic_instr *intr, void *cb_data) +{ + if (intr->intrinsic != nir_intrinsic_store_output) + return false; + + bool *writes_psiz = cb_data; + + struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr); + *writes_psiz |= (io_semantics.location == VARYING_SLOT_PSIZ); + + return false; +} + +/** + * \brief Vertex shader point size pass. + * + * \param[in,out] shader NIR shader. + * \return True if the pass made progress. + */ +bool pco_nir_point_size(nir_shader *shader) +{ + assert(shader->info.stage == MESA_SHADER_VERTEX); + if (shader->info.internal) + return false; + + bool writes_psiz = false; + nir_shader_intrinsics_pass(shader, + check_psiz_write, + nir_metadata_all, + &writes_psiz); + + /* Nothing to do if the shader already writes the point size. */ + if (writes_psiz) + return false; + + /* Create a point size variable if there isn't one. */ + nir_get_variable_with_location(shader, + nir_var_shader_out, + VARYING_SLOT_PSIZ, + glsl_float_type()); + + /* Add a point size write. */ + nir_builder b = nir_builder_at( + nir_after_block(nir_impl_last_block(nir_shader_get_entrypoint(shader)))); + + nir_store_output(&b, + nir_imm_float(&b, PVR_POINT_SIZE_RANGE_MIN), + nir_imm_int(&b, 0), + .base = 0, + .range = 1, + .write_mask = 1, + .component = 0, + .src_type = nir_type_float32, + .io_semantics = (nir_io_semantics){ + .location = VARYING_SLOT_PSIZ, + .num_slots = 1, + }); + + return true; +} diff --git a/src/imagination/vulkan/pvr_cmd_buffer.c b/src/imagination/vulkan/pvr_cmd_buffer.c index 861e11ca7d7..532220e2e10 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_cmd_buffer.c @@ -4095,8 +4095,6 @@ static void pvr_setup_output_select(struct pvr_cmd_buffer *const cmd_buffer) { const struct pvr_graphics_pipeline *const gfx_pipeline = cmd_buffer->state.gfx_pipeline; - struct vk_dynamic_graphics_state *const dynamic_state = - &cmd_buffer->vk.dynamic_graphics_state; struct ROGUE_TA_STATE_HEADER *const header = &cmd_buffer->state.emit_header; struct pvr_ppp_state *const ppp_state = &cmd_buffer->state.ppp_state; const pco_data *const vs_data = &gfx_pipeline->vs_data; @@ -4106,9 +4104,7 @@ static void pvr_setup_output_select(struct pvr_cmd_buffer *const cmd_buffer) const pco_range *varyings = vs_data->vs.varyings; - const bool has_point_size = dynamic_state->ia.primitive_topology == - VK_PRIMITIVE_TOPOLOGY_POINT_LIST && - varyings[VARYING_SLOT_PSIZ].count > 0; + const bool has_point_size = varyings[VARYING_SLOT_PSIZ].count > 0; const bool has_viewport = varyings[VARYING_SLOT_VIEWPORT].count > 0; diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c index 11664845024..4ea61f017fa 100644 --- a/src/imagination/vulkan/pvr_device.c +++ b/src/imagination/vulkan/pvr_device.c @@ -219,7 +219,7 @@ static void pvr_physical_device_get_supported_features( .fillModeNonSolid = false, .depthBounds = false, .wideLines = false, - .largePoints = false, + .largePoints = true, .alphaToOne = false, .multiViewport = false, .samplerAnisotropy = false, @@ -515,10 +515,9 @@ static bool pvr_physical_device_get_properties( .discreteQueuePriorities = 2U, - /* Requires largePoints */ - .pointSizeRange[0] = 1.0f, - .pointSizeRange[1] = 1.0f, - .pointSizeGranularity = 0.0f, + .pointSizeRange[0] = PVR_POINT_SIZE_RANGE_MIN, + .pointSizeRange[1] = PVR_POINT_SIZE_RANGE_MAX, + .pointSizeGranularity = PVR_POINT_SIZE_GRANULARITY, /* Requires wideLines */ .lineWidthRange[0] = 1.0f,