diff --git a/src/imagination/csbgen/rogue_ppp.xml b/src/imagination/csbgen/rogue_ppp.xml
index 75c02f7132e..9bd15f3d246 100644
--- a/src/imagination/csbgen/rogue_ppp.xml
+++ b/src/imagination/csbgen/rogue_ppp.xml
@@ -154,7 +154,9 @@ SOFTWARE.
-
+
+
+
@@ -177,6 +179,10 @@ SOFTWARE.
+
+
+
+
@@ -226,6 +232,14 @@ SOFTWARE.
+
+
+
+
+
+
+
+
@@ -245,6 +259,14 @@ SOFTWARE.
+
+
+
+
+
+
+
+
diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c
index b26ff89368c..b87bda0a488 100644
--- a/src/imagination/vulkan/pvr_device.c
+++ b/src/imagination/vulkan/pvr_device.c
@@ -57,6 +57,7 @@
#include "rogue/rogue_compiler.h"
#include "util/build_id.h"
#include "util/log.h"
+#include "util/macros.h"
#include "util/mesa-sha1.h"
#include "util/os_misc.h"
#include "util/u_math.h"
@@ -1474,6 +1475,104 @@ static void pvr_device_finish_compute_idfwdf_state(struct pvr_device *device)
pvr_bo_free(device, device->idfwdf_state.usc);
}
+static void pvr_device_setup_graphics_static_clear_ppp_base(
+ struct pvr_static_clear_ppp_base *const base)
+{
+ pvr_csb_pack (&base->wclamp, TA_WCLAMP, wclamp) {
+ wclamp.val = fui(0.00001f);
+ }
+
+ /* clang-format off */
+ pvr_csb_pack (&base->varying_word[0], TA_STATE_VARYING0, varying0);
+ pvr_csb_pack (&base->varying_word[1], TA_STATE_VARYING1, varying1);
+ pvr_csb_pack (&base->varying_word[2], TA_STATE_VARYING2, varying2);
+ /* clang-format on */
+
+ pvr_csb_pack (&base->ppp_ctrl, TA_STATE_PPP_CTRL, ppp_ctrl) {
+ ppp_ctrl.pretransform = true;
+ ppp_ctrl.cullmode = PVRX(TA_CULLMODE_NO_CULLING);
+ }
+
+ /* clang-format off */
+ pvr_csb_pack (&base->stream_out0, TA_STATE_STREAM_OUT0, stream_out0);
+ /* clang-format on */
+}
+
+static void pvr_device_setup_graphics_static_clear_ppp_templates(
+ struct pvr_static_clear_ppp_template
+ templates[static PVR_STATIC_CLEAR_VARIANT_COUNT])
+{
+ for (uint32_t i = 0; i < PVR_STATIC_CLEAR_VARIANT_COUNT; i++) {
+ const bool has_depth = !!(i & PVR_STATIC_CLEAR_DEPTH_BIT);
+ const bool has_stencil = !!(i & PVR_STATIC_CLEAR_STENCIL_BIT);
+ const bool has_color = !!(i & PVR_STATIC_CLEAR_COLOR_BIT);
+
+ struct pvr_static_clear_ppp_template *const template = &templates[i];
+
+ template->requires_pds_state = has_color;
+
+ pvr_csb_pack (&template->header, TA_STATE_HEADER, header) {
+ header.pres_stream_out_size = true;
+ header.pres_ppp_ctrl = true;
+ header.pres_varying_word2 = true;
+ header.pres_varying_word1 = true;
+ header.pres_varying_word0 = true;
+ header.pres_outselects = true;
+ header.pres_wclamp = true;
+ header.pres_region_clip = true;
+ header.pres_pds_state_ptr2 = template->requires_pds_state;
+ header.pres_pds_state_ptr1 = template->requires_pds_state;
+ header.pres_pds_state_ptr0 = template->requires_pds_state;
+ header.pres_ispctl_fb = true;
+ header.pres_ispctl_fa = true;
+ header.pres_ispctl = true;
+ }
+
+#define CS_HEADER(cs) \
+ (struct PVRX(cs)) \
+ { \
+ pvr_cmd_header(cs) \
+ }
+
+ template->config.ispctl = CS_HEADER(TA_STATE_ISPCTL);
+ template->config.ispctl.tagwritedisable = !has_color;
+ template->config.ispctl.bpres = true;
+
+ template->config.ispa = CS_HEADER(TA_STATE_ISPA);
+ template->config.ispa.objtype = PVRX(TA_OBJTYPE_TRIANGLE);
+ template->config.ispa.passtype = PVRX(TA_PASSTYPE_TRANSLUCENT);
+ template->config.ispa.dwritedisable = !has_depth;
+ template->config.ispa.dcmpmode = (i == 0) ? PVRX(TA_CMPMODE_NEVER)
+ : PVRX(TA_CMPMODE_ALWAYS);
+ template->config.ispa.sref =
+ has_stencil ? PVRX(TA_STATE_ISPA_SREF_SIZE_MAX) : 0;
+
+ pvr_csb_pack (&template->ispb, TA_STATE_ISPB, ispb) {
+ ispb.scmpmode = PVRX(TA_CMPMODE_ALWAYS);
+ ispb.sop1 = PVRX(TA_ISPB_STENCILOP_KEEP);
+ ispb.sop2 = PVRX(TA_ISPB_STENCILOP_KEEP);
+
+ ispb.sop3 = has_stencil ? PVRX(TA_ISPB_STENCILOP_REPLACE)
+ : PVRX(TA_ISPB_STENCILOP_KEEP);
+
+ ispb.swmask = has_stencil ? 0xFF : 0;
+ }
+
+ template->config.pds_state = NULL;
+
+ template->config.region_clip0 = CS_HEADER(TA_REGION_CLIP0);
+ template->config.region_clip0.mode = PVRX(TA_REGION_CLIP_MODE_NONE);
+
+ template->config.region_clip1 = CS_HEADER(TA_REGION_CLIP1);
+
+ template->config.output_sel = CS_HEADER(TA_OUTPUT_SEL);
+ template->config.output_sel.vtxsize = 4;
+ template->config.output_sel.rhw_pres = true;
+
+#undef CS_HEADER
+ }
+}
+
static VkResult
pvr_device_init_graphics_static_clear_state(struct pvr_device *device)
{
@@ -1571,6 +1670,9 @@ pvr_device_init_graphics_static_clear_state(struct pvr_device *device)
vk_free(&device->vk.alloc, staging_buffer);
+ pvr_device_setup_graphics_static_clear_ppp_base(&state->ppp_base);
+ pvr_device_setup_graphics_static_clear_ppp_templates(state->ppp_templates);
+
return VK_SUCCESS;
err_free_staging_buffer:
diff --git a/src/imagination/vulkan/pvr_private.h b/src/imagination/vulkan/pvr_private.h
index cf797ba7c4c..0102e7dd7bd 100644
--- a/src/imagination/vulkan/pvr_private.h
+++ b/src/imagination/vulkan/pvr_private.h
@@ -175,6 +175,45 @@ enum pvr_scissor_accum_state {
PVR_SCISSOR_ACCUM_ENABLED,
};
+#define PVR_STATIC_CLEAR_PDS_STATE_COUNT \
+ (pvr_cmd_length(TA_STATE_PDS_SHADERBASE) + \
+ pvr_cmd_length(TA_STATE_PDS_TEXUNICODEBASE) + \
+ pvr_cmd_length(TA_STATE_PDS_SIZEINFO1) + \
+ pvr_cmd_length(TA_STATE_PDS_SIZEINFO2) + \
+ pvr_cmd_length(TA_STATE_PDS_VARYINGBASE) + \
+ pvr_cmd_length(TA_STATE_PDS_TEXTUREDATABASE))
+
+/* These can be used as offsets within a PVR_STATIC_CLEAR_PDS_STATE_COUNT dwords
+ * sized array to get the respective state word.
+ *
+ * The values are based on the lengths of the state words.
+ */
+enum pvr_static_clear_ppp_pds_state_type {
+ /* Words enabled by pres_pds_state_ptr0. */
+ PVR_STATIC_CLEAR_PPP_PDS_TYPE_SHADERBASE = 0,
+ PVR_STATIC_CLEAR_PPP_PDS_TYPE_TEXUNICODEBASE = 1,
+ PVR_STATIC_CLEAR_PPP_PDS_TYPE_SIZEINFO1 = 2,
+ PVR_STATIC_CLEAR_PPP_PDS_TYPE_SIZEINFO2 = 3,
+
+ /* Word enabled by pres_pds_state_ptr1. */
+ PVR_STATIC_CLEAR_PPP_PDS_TYPE_VARYINGBASE = 4,
+
+ /* Word enabled by pres_pds_state_ptr2. */
+ PVR_STATIC_CLEAR_PPP_PDS_TYPE_TEXTUREDATABASE = 5,
+};
+
+static_assert(PVR_STATIC_CLEAR_PPP_PDS_TYPE_TEXTUREDATABASE + 1 ==
+ PVR_STATIC_CLEAR_PDS_STATE_COUNT,
+ "pvr_static_clear_ppp_pds_state_type might require fixing.");
+
+enum pvr_static_clear_variant_bits {
+ PVR_STATIC_CLEAR_DEPTH_BIT = BITFIELD_BIT(0),
+ PVR_STATIC_CLEAR_STENCIL_BIT = BITFIELD_BIT(1),
+ PVR_STATIC_CLEAR_COLOR_BIT = BITFIELD_BIT(2),
+};
+
+#define PVR_STATIC_CLEAR_VARIANT_COUNT (PVR_STATIC_CLEAR_COLOR_BIT << 1U)
+
struct pvr_bo;
struct pvr_compute_ctx;
struct pvr_compute_pipeline;
@@ -246,6 +285,42 @@ struct pvr_pds_upload {
uint32_t code_size;
};
+struct pvr_static_clear_ppp_base {
+ uint32_t wclamp;
+ uint32_t varying_word[3];
+ uint32_t ppp_ctrl;
+ uint32_t stream_out0;
+};
+
+struct pvr_static_clear_ppp_template {
+ /* Pre-packed control words. */
+ uint32_t header;
+ uint32_t ispb;
+
+ bool requires_pds_state;
+
+ /* Configurable control words.
+ * These are initialized and can be modified as needed before emitting them.
+ */
+ struct {
+ struct PVRX(TA_STATE_ISPCTL) ispctl;
+ struct PVRX(TA_STATE_ISPA) ispa;
+
+ /* In case the template requires_pds_state this needs to be a valid
+ * pointer to a pre-packed PDS state before emitting.
+ *
+ * Note: this is a pointer to an array of const uint32_t and not an array
+ * of pointers or a function pointer.
+ */
+ const uint32_t (*pds_state)[PVR_STATIC_CLEAR_PDS_STATE_COUNT];
+
+ struct PVRX(TA_REGION_CLIP0) region_clip0;
+ struct PVRX(TA_REGION_CLIP1) region_clip1;
+
+ struct PVRX(TA_OUTPUT_SEL) output_sel;
+ } config;
+};
+
struct pvr_device {
struct vk_device vk;
struct pvr_instance *instance;
@@ -297,6 +372,10 @@ struct pvr_device {
struct pvr_bo *usc_vertex_shader_bo;
struct pvr_bo *vertices_bo;
struct pvr_pds_upload pds;
+
+ struct pvr_static_clear_ppp_base ppp_base;
+ struct pvr_static_clear_ppp_template
+ ppp_templates[PVR_STATIC_CLEAR_VARIANT_COUNT];
} static_clear_state;
VkPhysicalDeviceFeatures features;