diff --git a/src/imagination/include/hwdef/rogue_hw_utils.h b/src/imagination/include/hwdef/rogue_hw_utils.h index 6f7c8d35fc9..0978f3ebf7a 100644 --- a/src/imagination/include/hwdef/rogue_hw_utils.h +++ b/src/imagination/include/hwdef/rogue_hw_utils.h @@ -257,4 +257,14 @@ rogue_get_compute_max_work_group_size(const struct pvr_device_info *dev_info) return ROGUE_MAX_INSTANCES_PER_TASK * max_tasks_per_usc; } +/* Don't use this directly. Use the x and y define macros. */ +static inline uint32_t +__rogue_get_param_vf_max(const struct pvr_device_info *dev_info) +{ + return (rogue_get_render_size_max(dev_info) * 3 / 2) - 1; +} + +#define rogue_get_param_vf_max_x(dev_info) __rogue_get_param_vf_max(dev_info) +#define rogue_get_param_vf_max_y(dev_info) __rogue_get_param_vf_max(dev_info) + #endif /* ROGUE_HW_UTILS_H */ diff --git a/src/imagination/vulkan/pds/pvr_pds.c b/src/imagination/vulkan/pds/pvr_pds.c index 7cd39b3b4a8..578c0d8a363 100644 --- a/src/imagination/vulkan/pds/pvr_pds.c +++ b/src/imagination/vulkan/pds/pvr_pds.c @@ -695,6 +695,7 @@ static uint32_t pvr_pds_get_bank_based_constants(uint32_t num_backs, * \returns Pointer to just beyond the buffer for the data - i.e the value * of the buffer after writing its contents. */ +/* FIXME: Implement PDS_GENERATE_CODEDATA_SEGMENTS? */ uint32_t * pvr_pds_vertex_shader(struct pvr_pds_vertex_shader_program *restrict program, uint32_t *restrict buffer, diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c index 283fe10831d..b26ff89368c 100644 --- a/src/imagination/vulkan/pvr_device.c +++ b/src/imagination/vulkan/pvr_device.c @@ -1474,6 +1474,127 @@ static void pvr_device_finish_compute_idfwdf_state(struct pvr_device *device) pvr_bo_free(device, device->idfwdf_state.usc); } +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; + size_t staging_buffer_size; + uint32_t *staging_buffer; + 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 } }; + + 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) + return result; + + 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; + + pds_program = (struct pvr_pds_vertex_shader_program) { + .num_streams = 1, + .streams = { + [0] = { + .address = state->vertices_bo->vma->dev_addr.addr, + .stride = sizeof(vertices[0]), + .num_elements = 1, + .elements = { + [0] = { + .size = sizeof(vertices[0]), + }, + }, + }, + }, + }; + + pvr_pds_setup_doutu(&pds_program.usc_task_control, + state->usc_vertex_shader_bo->vma->dev_addr.addr, + 0, + PVRX(PDSINST_DOUTU_SAMPLE_RATE_INSTANCE), + false); + + pvr_pds_vertex_shader(&pds_program, NULL, PDS_GENERATE_SIZES, dev_info); + + staging_buffer_size = + (pds_program.code_size + pds_program.data_size) * sizeof(*staging_buffer); + + staging_buffer = vk_alloc(&device->vk.alloc, + staging_buffer_size, + 8, + VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (!staging_buffer) + goto err_free_verices_buffer; + + pvr_pds_vertex_shader(&pds_program, + staging_buffer, + PDS_GENERATE_DATA_SEGMENT, + dev_info); + pvr_pds_vertex_shader(&pds_program, + &staging_buffer[pds_program.data_size], + PDS_GENERATE_CODE_SEGMENT, + dev_info); + + /* FIXME: Figure out the define for alignment of 16. */ + result = pvr_gpu_upload_pds(device, + &staging_buffer[0], + pds_program.data_size, + 16, + &staging_buffer[pds_program.data_size], + pds_program.code_size, + 16, + 16, + &state->pds); + if (result != VK_SUCCESS) + goto err_free_staging_buffer; + + vk_free(&device->vk.alloc, staging_buffer); + + return VK_SUCCESS; + +err_free_staging_buffer: + vk_free(&device->vk.alloc, staging_buffer); + +err_free_verices_buffer: + pvr_bo_free(device, state->vertices_bo); + +err_free_usc_shader: + pvr_bo_free(device, state->usc_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); +} + /* FIXME: We should be calculating the size when we upload the code in * pvr_srv_setup_static_pixel_event_program(). */ @@ -1659,10 +1780,14 @@ VkResult pvr_CreateDevice(VkPhysicalDevice physicalDevice, if (result != VK_SUCCESS) goto err_pvr_free_compute_fence; - result = pvr_queues_create(device, pCreateInfo); + result = pvr_device_init_graphics_static_clear_state(device); if (result != VK_SUCCESS) goto err_pvr_finish_compute_idfwdf; + result = pvr_queues_create(device, pCreateInfo); + if (result != VK_SUCCESS) + goto err_pvr_finish_graphics_static_clear; + pvr_device_init_default_sampler_state(device); if (pCreateInfo->pEnabledFeatures) @@ -1685,6 +1810,9 @@ VkResult pvr_CreateDevice(VkPhysicalDevice physicalDevice, return VK_SUCCESS; +err_pvr_finish_graphics_static_clear: + pvr_device_finish_graphics_static_clear_state(device); + err_pvr_finish_compute_idfwdf: pvr_device_finish_compute_idfwdf_state(device); @@ -1722,6 +1850,7 @@ void pvr_DestroyDevice(VkDevice _device, PVR_FROM_HANDLE(pvr_device, device, _device); pvr_queues_destroy(device); + pvr_device_finish_graphics_static_clear_state(device); pvr_device_finish_compute_idfwdf_state(device); pvr_bo_free(device, device->pds_compute_fence_program.pvr_bo); pvr_bo_free(device, device->nop_program.pds.pvr_bo); diff --git a/src/imagination/vulkan/pvr_hardcode.c b/src/imagination/vulkan/pvr_hardcode.c index 5296b7db259..f9720b29d50 100644 --- a/src/imagination/vulkan/pvr_hardcode.c +++ b/src/imagination/vulkan/pvr_hardcode.c @@ -349,3 +349,17 @@ void pvr_hard_code_get_idfwdf_program( *usc_shareds_out = 12U; *usc_temps_out = 4U; } + +void pvr_hard_code_get_passthrough_vertex_shader( + const struct pvr_device_info *const dev_info, + const struct rogue_shader_binary **const program_out) +{ + static const struct rogue_shader_binary shader = { + .size = 8U, + .data = { 0, 0, 0, 0, 0, 0, 0, 0 } + }; + + mesa_loge( + "No hard coded passthrough vertex shader. Returning empty shader."); + *program_out = &shader; +}; diff --git a/src/imagination/vulkan/pvr_hardcode.h b/src/imagination/vulkan/pvr_hardcode.h index ea0fecb130b..c59cc118a33 100644 --- a/src/imagination/vulkan/pvr_hardcode.h +++ b/src/imagination/vulkan/pvr_hardcode.h @@ -125,4 +125,8 @@ void pvr_hard_code_get_idfwdf_program( uint32_t *usc_shareds_out, uint32_t *usc_temps_out); +void pvr_hard_code_get_passthrough_vertex_shader( + const struct pvr_device_info *const dev_info, + const struct rogue_shader_binary **const program_out); + #endif /* PVR_HARDCODE_SHADERS_H */ diff --git a/src/imagination/vulkan/pvr_private.h b/src/imagination/vulkan/pvr_private.h index aa0e00264ef..cf797ba7c4c 100644 --- a/src/imagination/vulkan/pvr_private.h +++ b/src/imagination/vulkan/pvr_private.h @@ -293,6 +293,12 @@ struct pvr_device { struct pvr_pds_upload sw_compute_barrier_pds; } idfwdf_state; + struct pvr_device_static_clear_state { + struct pvr_bo *usc_vertex_shader_bo; + struct pvr_bo *vertices_bo; + struct pvr_pds_upload pds; + } static_clear_state; + VkPhysicalDeviceFeatures features; };