diff --git a/src/imagination/vulkan/pvr_clear.c b/src/imagination/vulkan/pvr_clear.c index 96e8e755859..5e6dbf2ffd9 100644 --- a/src/imagination/vulkan/pvr_clear.c +++ b/src/imagination/vulkan/pvr_clear.c @@ -24,12 +24,333 @@ #include #include +#include "hwdef/rogue_hw_utils.h" #include "pvr_clear.h" +#include "pvr_hardcode.h" #include "pvr_pds.h" #include "pvr_private.h" #include "vk_alloc.h" #include "vk_log.h" +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 + } +} + +/** + * \brief Emit geom state from a configurable template. + * + * Note that the state is emitted by joining the template with a base so the + * base must have been setup before calling this. + * + * \param[in] csb Control stream to emit to. + * \param[in] template The configured template. + * \param[out] pvr_bo_out Uploaded state's pvr_bo object. + * + * \return VK_SUCCESS if the state was successfully uploaded. + */ +VkResult pvr_emit_ppp_from_template( + struct pvr_csb *const csb, + const struct pvr_static_clear_ppp_template *const template, + struct pvr_bo **const pvr_bo_out) +{ + const uint32_t dword_count = + pvr_cmd_length(TA_STATE_HEADER) + pvr_cmd_length(TA_STATE_ISPCTL) + + pvr_cmd_length(TA_STATE_ISPA) + pvr_cmd_length(TA_STATE_ISPB) + + (template->requires_pds_state ? PVR_STATIC_CLEAR_PDS_STATE_COUNT : 0) + + pvr_cmd_length(TA_REGION_CLIP0) + pvr_cmd_length(TA_REGION_CLIP1) + + pvr_cmd_length(TA_WCLAMP) + pvr_cmd_length(TA_OUTPUT_SEL) + + pvr_cmd_length(TA_STATE_VARYING0) + pvr_cmd_length(TA_STATE_VARYING1) + + pvr_cmd_length(TA_STATE_VARYING2) + pvr_cmd_length(TA_STATE_PPP_CTRL) + + pvr_cmd_length(TA_STATE_STREAM_OUT0); + + struct pvr_device *const device = csb->device; + const uint32_t cache_line_size = + rogue_get_slc_cache_line_size(&device->pdevice->dev_info); + const struct pvr_static_clear_ppp_base *const base = + &device->static_clear_state.ppp_base; + struct pvr_bo *pvr_bo; + uint32_t *stream; + VkResult result; + + result = pvr_bo_alloc(device, + device->heaps.general_heap, + dword_count * sizeof(uint32_t), + cache_line_size, + PVR_BO_ALLOC_FLAG_CPU_MAPPED, + &pvr_bo); + if (result != VK_SUCCESS) { + *pvr_bo_out = NULL; + return result; + } + + stream = (uint32_t *)pvr_bo->bo->map; + + pvr_csb_write_value(stream, TA_STATE_HEADER, template->header); + pvr_csb_write_struct(stream, TA_STATE_ISPCTL, &template->config.ispctl); + pvr_csb_write_struct(stream, TA_STATE_ISPA, &template->config.ispa); + pvr_csb_write_value(stream, TA_STATE_ISPB, template->ispb); + + if (template->requires_pds_state) { + static_assert(sizeof(*stream) == sizeof((*template->config.pds_state)[0]), + "Size mismatch"); + for (uint32_t i = 0; i < PVR_STATIC_CLEAR_PDS_STATE_COUNT; i++) + *stream++ = (*template->config.pds_state)[i]; + } + + pvr_csb_write_struct(stream, + TA_REGION_CLIP0, + &template->config.region_clip0); + pvr_csb_write_struct(stream, + TA_REGION_CLIP1, + &template->config.region_clip1); + pvr_csb_write_value(stream, TA_WCLAMP, base->wclamp); + pvr_csb_write_struct(stream, TA_OUTPUT_SEL, &template->config.output_sel); + pvr_csb_write_value(stream, TA_STATE_VARYING0, base->varying_word[0]); + pvr_csb_write_value(stream, TA_STATE_VARYING1, base->varying_word[1]); + pvr_csb_write_value(stream, TA_STATE_VARYING2, base->varying_word[2]); + pvr_csb_write_value(stream, TA_STATE_PPP_CTRL, base->ppp_ctrl); + pvr_csb_write_value(stream, TA_STATE_STREAM_OUT0, base->stream_out0); + + assert((uint64_t)(stream - (uint32_t *)pvr_bo->bo->map) == dword_count); + + pvr_bo_cpu_unmap(device, pvr_bo); + stream = NULL; + + pvr_csb_emit (csb, VDMCTRL_PPP_STATE0, state) { + state.word_count = dword_count; + state.addrmsb = pvr_bo->vma->dev_addr; + } + + pvr_csb_emit (csb, VDMCTRL_PPP_STATE1, state) { + state.addrlsb = pvr_bo->vma->dev_addr; + } + + *pvr_bo_out = pvr_bo; + + return VK_SUCCESS; +} + +VkResult pvr_device_init_graphics_static_clear_state(struct pvr_device *device) +{ + struct pvr_device_static_clear_state *state = &device->static_clear_state; + const struct pvr_device_info *dev_info = &device->pdevice->dev_info; + const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info); + const float vf_x_max = (float)rogue_get_param_vf_max_x(dev_info); + const float vf_y_max = (float)rogue_get_param_vf_max_y(dev_info); + const struct rogue_shader_binary *passthrough_vert_shader; + struct pvr_pds_vertex_shader_program pds_program; + VkResult result; + + const float vertices[4][3] = { { 0.0f, 0.0f, 0.0f }, + { vf_x_max, 0.0f, 0.0f }, + { 0.0f, vf_y_max, 0.0f }, + { vf_x_max, vf_y_max, 0.0f } }; + + static_assert(ARRAY_SIZE(vertices) == PVR_CLEAR_VERTEX_COUNT, + "Size mismatch"); + static_assert(ARRAY_SIZE(vertices[0]) == PVR_CLEAR_VERTEX_COORDINATES, + "Size mismatch"); + + if (PVR_HAS_FEATURE(dev_info, gs_rta_support)) { + struct util_dynarray passthrough_rta_vert_shader; + + util_dynarray_init(&passthrough_rta_vert_shader, NULL); + pvr_hard_code_get_passthrough_rta_vertex_shader( + dev_info, + &passthrough_rta_vert_shader); + + result = pvr_gpu_upload_usc(device, + passthrough_rta_vert_shader.data, + passthrough_rta_vert_shader.size, + cache_line_size, + &state->usc_multi_layer_vertex_shader_bo); + if (result != VK_SUCCESS) { + util_dynarray_fini(&passthrough_rta_vert_shader); + return result; + } + + util_dynarray_fini(&passthrough_rta_vert_shader); + } else { + state->usc_multi_layer_vertex_shader_bo = NULL; + } + + pvr_hard_code_get_passthrough_vertex_shader(dev_info, + &passthrough_vert_shader); + + result = pvr_gpu_upload_usc(device, + passthrough_vert_shader->data, + passthrough_vert_shader->size, + cache_line_size, + &state->usc_vertex_shader_bo); + if (result != VK_SUCCESS) + goto err_free_usc_multi_layer_shader; + + result = pvr_gpu_upload(device, + device->heaps.general_heap, + vertices, + sizeof(vertices), + sizeof(vertices[0][0]), + &state->vertices_bo); + if (result != VK_SUCCESS) + goto err_free_usc_shader; + + pvr_pds_clear_vertex_shader_program_init_base(&pds_program, + state->usc_vertex_shader_bo); + + result = + pvr_pds_clear_vertex_shader_program_create_and_upload(&pds_program, + device, + state->vertices_bo, + &state->pds); + if (result != VK_SUCCESS) + goto err_free_verices_buffer; + + pvr_device_setup_graphics_static_clear_ppp_base(&state->ppp_base); + pvr_device_setup_graphics_static_clear_ppp_templates(state->ppp_templates); + + assert(pds_program.code_size <= state->pds.code_size); + + /* TODO: The difference between the large and normal words is only the last + * word. The value is 3 or 4 depending on the amount of indices. Should we + * dedup this? + */ + + /* TODO: Figure out where the 4 * sizeof(uint32_t) comes from. */ + pvr_pack_clear_vdm_state(&device->pdevice->dev_info, + &state->pds, + pds_program.temps_used, + 3, + 4 * sizeof(uint32_t), + 1, + state->vdm_words); + + /* TODO: Figure out where the 4 * sizeof(uint32_t) comes from. */ + pvr_pack_clear_vdm_state(&device->pdevice->dev_info, + &state->pds, + pds_program.temps_used, + 4, + 4 * sizeof(uint32_t), + 1, + state->large_clear_vdm_words); + + return VK_SUCCESS; + +err_free_verices_buffer: + pvr_bo_free(device, state->vertices_bo); + +err_free_usc_shader: + pvr_bo_free(device, state->usc_vertex_shader_bo); + +err_free_usc_multi_layer_shader: + pvr_bo_free(device, state->usc_multi_layer_vertex_shader_bo); + + return result; +} + +void pvr_device_finish_graphics_static_clear_state(struct pvr_device *device) +{ + struct pvr_device_static_clear_state *state = &device->static_clear_state; + + pvr_bo_free(device, state->pds.pvr_bo); + pvr_bo_free(device, state->vertices_bo); + pvr_bo_free(device, state->usc_vertex_shader_bo); + pvr_bo_free(device, state->usc_multi_layer_vertex_shader_bo); +} + void pvr_pds_clear_vertex_shader_program_init_base( struct pvr_pds_vertex_shader_program *program, const struct pvr_bo *usc_shader_bo) diff --git a/src/imagination/vulkan/pvr_clear.h b/src/imagination/vulkan/pvr_clear.h index f8d2b53c2f1..f0c6ddd93e4 100644 --- a/src/imagination/vulkan/pvr_clear.h +++ b/src/imagination/vulkan/pvr_clear.h @@ -24,10 +24,12 @@ #ifndef PVR_CLEAR_H #define PVR_CLEAR_H +#include #include #include #include "pvr_csb.h" +#include "util/macros.h" #define PVR_CLEAR_VERTEX_COUNT 4 #define PVR_CLEAR_VERTEX_COORDINATES 3 @@ -42,6 +44,45 @@ pvr_cmd_length(VDMCTRL_VDM_STATE5) + pvr_cmd_length(VDMCTRL_INDEX_LIST0) + \ pvr_cmd_length(VDMCTRL_INDEX_LIST2) + pvr_cmd_length(VDMCTRL_INDEX_LIST3)) +#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_cmd_buffer; struct pvr_device; @@ -49,6 +90,50 @@ struct pvr_device_info; struct pvr_pds_upload; struct pvr_pds_vertex_shader_program; +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; +}; + +VkResult pvr_device_init_graphics_static_clear_state(struct pvr_device *device); +void pvr_device_finish_graphics_static_clear_state(struct pvr_device *device); + +VkResult pvr_emit_ppp_from_template( + struct pvr_csb *const csb, + const struct pvr_static_clear_ppp_template *const template, + struct pvr_bo **const pvr_bo_out); + void pvr_pds_clear_vertex_shader_program_init_base( struct pvr_pds_vertex_shader_program *program, const struct pvr_bo *usc_shader_bo); diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c index 1b1b6817602..0660842aacb 100644 --- a/src/imagination/vulkan/pvr_device.c +++ b/src/imagination/vulkan/pvr_device.c @@ -1492,327 +1492,6 @@ 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 - } -} - -/** - * \brief Emit geom state from a configurable template. - * - * Note that the state is emitted by joining the template with a base so the - * base must have been setup before calling this. - * - * \param[in] csb Control stream to emit to. - * \param[in] template The configured template. - * \param[out] pvr_bo_out Uploaded state's pvr_bo object. - * - * \return VK_SUCCESS if the state was successfully uploaded. - */ -VkResult pvr_emit_ppp_from_template( - struct pvr_csb *const csb, - const struct pvr_static_clear_ppp_template *const template, - struct pvr_bo **const pvr_bo_out) -{ - const uint32_t dword_count = - pvr_cmd_length(TA_STATE_HEADER) + pvr_cmd_length(TA_STATE_ISPCTL) + - pvr_cmd_length(TA_STATE_ISPA) + pvr_cmd_length(TA_STATE_ISPB) + - (template->requires_pds_state ? PVR_STATIC_CLEAR_PDS_STATE_COUNT : 0) + - pvr_cmd_length(TA_REGION_CLIP0) + pvr_cmd_length(TA_REGION_CLIP1) + - pvr_cmd_length(TA_WCLAMP) + pvr_cmd_length(TA_OUTPUT_SEL) + - pvr_cmd_length(TA_STATE_VARYING0) + pvr_cmd_length(TA_STATE_VARYING1) + - pvr_cmd_length(TA_STATE_VARYING2) + pvr_cmd_length(TA_STATE_PPP_CTRL) + - pvr_cmd_length(TA_STATE_STREAM_OUT0); - - struct pvr_device *const device = csb->device; - const uint32_t cache_line_size = - rogue_get_slc_cache_line_size(&device->pdevice->dev_info); - const struct pvr_static_clear_ppp_base *const base = - &device->static_clear_state.ppp_base; - struct pvr_bo *pvr_bo; - uint32_t *stream; - VkResult result; - - result = pvr_bo_alloc(device, - device->heaps.general_heap, - dword_count * sizeof(uint32_t), - cache_line_size, - PVR_BO_ALLOC_FLAG_CPU_MAPPED, - &pvr_bo); - if (result != VK_SUCCESS) { - *pvr_bo_out = NULL; - return result; - } - - stream = (uint32_t *)pvr_bo->bo->map; - - pvr_csb_write_value(stream, TA_STATE_HEADER, template->header); - pvr_csb_write_struct(stream, TA_STATE_ISPCTL, &template->config.ispctl); - pvr_csb_write_struct(stream, TA_STATE_ISPA, &template->config.ispa); - pvr_csb_write_value(stream, TA_STATE_ISPB, template->ispb); - - if (template->requires_pds_state) { - static_assert(sizeof(*stream) == sizeof((*template->config.pds_state)[0]), - "Size mismatch"); - for (uint32_t i = 0; i < PVR_STATIC_CLEAR_PDS_STATE_COUNT; i++) - *stream++ = (*template->config.pds_state)[i]; - } - - pvr_csb_write_struct(stream, - TA_REGION_CLIP0, - &template->config.region_clip0); - pvr_csb_write_struct(stream, - TA_REGION_CLIP1, - &template->config.region_clip1); - pvr_csb_write_value(stream, TA_WCLAMP, base->wclamp); - pvr_csb_write_struct(stream, TA_OUTPUT_SEL, &template->config.output_sel); - pvr_csb_write_value(stream, TA_STATE_VARYING0, base->varying_word[0]); - pvr_csb_write_value(stream, TA_STATE_VARYING1, base->varying_word[1]); - pvr_csb_write_value(stream, TA_STATE_VARYING2, base->varying_word[2]); - pvr_csb_write_value(stream, TA_STATE_PPP_CTRL, base->ppp_ctrl); - pvr_csb_write_value(stream, TA_STATE_STREAM_OUT0, base->stream_out0); - - assert((uint64_t)(stream - (uint32_t *)pvr_bo->bo->map) == dword_count); - - pvr_bo_cpu_unmap(device, pvr_bo); - stream = NULL; - - pvr_csb_emit (csb, VDMCTRL_PPP_STATE0, state) { - state.word_count = dword_count; - state.addrmsb = pvr_bo->vma->dev_addr; - } - - pvr_csb_emit (csb, VDMCTRL_PPP_STATE1, state) { - state.addrlsb = pvr_bo->vma->dev_addr; - } - - *pvr_bo_out = pvr_bo; - - return VK_SUCCESS; -} - -static VkResult -pvr_device_init_graphics_static_clear_state(struct pvr_device *device) -{ - struct pvr_device_static_clear_state *state = &device->static_clear_state; - const struct pvr_device_info *dev_info = &device->pdevice->dev_info; - const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info); - const float vf_x_max = (float)rogue_get_param_vf_max_x(dev_info); - const float vf_y_max = (float)rogue_get_param_vf_max_y(dev_info); - const struct rogue_shader_binary *passthrough_vert_shader; - struct pvr_pds_vertex_shader_program pds_program; - VkResult result; - - const float vertices[4][3] = { { 0.0f, 0.0f, 0.0f }, - { vf_x_max, 0.0f, 0.0f }, - { 0.0f, vf_y_max, 0.0f }, - { vf_x_max, vf_y_max, 0.0f } }; - - static_assert(ARRAY_SIZE(vertices) == PVR_CLEAR_VERTEX_COUNT, - "Size mismatch"); - static_assert(ARRAY_SIZE(vertices[0]) == PVR_CLEAR_VERTEX_COORDINATES, - "Size mismatch"); - - if (PVR_HAS_FEATURE(dev_info, gs_rta_support)) { - struct util_dynarray passthrough_rta_vert_shader; - - util_dynarray_init(&passthrough_rta_vert_shader, NULL); - pvr_hard_code_get_passthrough_rta_vertex_shader( - dev_info, - &passthrough_rta_vert_shader); - - result = pvr_gpu_upload_usc(device, - passthrough_rta_vert_shader.data, - passthrough_rta_vert_shader.size, - cache_line_size, - &state->usc_multi_layer_vertex_shader_bo); - if (result != VK_SUCCESS) { - util_dynarray_fini(&passthrough_rta_vert_shader); - return result; - } - - util_dynarray_fini(&passthrough_rta_vert_shader); - } else { - state->usc_multi_layer_vertex_shader_bo = NULL; - } - - pvr_hard_code_get_passthrough_vertex_shader(dev_info, - &passthrough_vert_shader); - - result = pvr_gpu_upload_usc(device, - passthrough_vert_shader->data, - passthrough_vert_shader->size, - cache_line_size, - &state->usc_vertex_shader_bo); - if (result != VK_SUCCESS) - goto err_free_usc_multi_layer_shader; - - result = pvr_gpu_upload(device, - device->heaps.general_heap, - vertices, - sizeof(vertices), - sizeof(vertices[0][0]), - &state->vertices_bo); - if (result != VK_SUCCESS) - goto err_free_usc_shader; - - pvr_pds_clear_vertex_shader_program_init_base(&pds_program, - state->usc_vertex_shader_bo); - - result = - pvr_pds_clear_vertex_shader_program_create_and_upload(&pds_program, - device, - state->vertices_bo, - &state->pds); - if (result != VK_SUCCESS) - goto err_free_verices_buffer; - - pvr_device_setup_graphics_static_clear_ppp_base(&state->ppp_base); - pvr_device_setup_graphics_static_clear_ppp_templates(state->ppp_templates); - - assert(pds_program.code_size <= state->pds.code_size); - - /* TODO: The difference between the large and normal words is only the last - * word. The value is 3 or 4 depending on the amount of indices. Should we - * dedup this? - */ - - /* TODO: Figure out where the 4 * sizeof(uint32_t) comes from. */ - pvr_pack_clear_vdm_state(&device->pdevice->dev_info, - &state->pds, - pds_program.temps_used, - 3, - 4 * sizeof(uint32_t), - 1, - state->vdm_words); - - /* TODO: Figure out where the 4 * sizeof(uint32_t) comes from. */ - pvr_pack_clear_vdm_state(&device->pdevice->dev_info, - &state->pds, - pds_program.temps_used, - 4, - 4 * sizeof(uint32_t), - 1, - state->large_clear_vdm_words); - - return VK_SUCCESS; - -err_free_verices_buffer: - pvr_bo_free(device, state->vertices_bo); - -err_free_usc_shader: - pvr_bo_free(device, state->usc_vertex_shader_bo); - -err_free_usc_multi_layer_shader: - pvr_bo_free(device, state->usc_multi_layer_vertex_shader_bo); - - return result; -} - -static void -pvr_device_finish_graphics_static_clear_state(struct pvr_device *device) -{ - struct pvr_device_static_clear_state *state = &device->static_clear_state; - - pvr_bo_free(device, state->pds.pvr_bo); - pvr_bo_free(device, state->vertices_bo); - pvr_bo_free(device, state->usc_vertex_shader_bo); - pvr_bo_free(device, state->usc_multi_layer_vertex_shader_bo); -} - /* FIXME: We should be calculating the size when we upload the code in * pvr_srv_setup_static_pixel_event_program(). */ diff --git a/src/imagination/vulkan/pvr_private.h b/src/imagination/vulkan/pvr_private.h index 23f16b6396f..c1a0b9f4be9 100644 --- a/src/imagination/vulkan/pvr_private.h +++ b/src/imagination/vulkan/pvr_private.h @@ -171,45 +171,6 @@ enum pvr_stage_allocation { PVR_STAGE_ALLOCATION_COUNT }; -#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) - enum pvr_event_state { PVR_EVENT_STATE_SET_BY_HOST, PVR_EVENT_STATE_RESET_BY_HOST, @@ -308,42 +269,6 @@ 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_compute_query_shader { struct pvr_bo *usc_bo; @@ -1516,11 +1441,6 @@ void pvr_calculate_vertex_cam_size(const struct pvr_device_info *dev_info, uint32_t *const cam_size_out, uint32_t *const vs_max_instances_out); -VkResult pvr_emit_ppp_from_template( - struct pvr_csb *const csb, - const struct pvr_static_clear_ppp_template *const template, - struct pvr_bo **const pvr_bo_out); - VkResult pvr_copy_or_resolve_color_image_region(struct pvr_cmd_buffer *cmd_buffer, const struct pvr_image *src,