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;