1 /*
2 * Copyright © 2024 Collabora Ltd.
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "panvk_cmd_alloc.h"
7 #include "panvk_cmd_buffer.h"
8 #include "panvk_entrypoints.h"
9
10 VkResult
panvk_per_arch(cmd_prepare_push_uniforms)11 panvk_per_arch(cmd_prepare_push_uniforms)(struct panvk_cmd_buffer *cmdbuf,
12 const struct panvk_shader *shader)
13 {
14 uint64_t *push_ptr;
15
16 switch (shader->vk.stage) {
17 case MESA_SHADER_COMPUTE:
18 if (!compute_state_dirty(cmdbuf, PUSH_UNIFORMS))
19 return VK_SUCCESS;
20 push_ptr = &cmdbuf->state.compute.push_uniforms;
21 break;
22 case MESA_SHADER_VERTEX:
23 if (!gfx_state_dirty(cmdbuf, VS_PUSH_UNIFORMS))
24 return VK_SUCCESS;
25 push_ptr = &cmdbuf->state.gfx.vs.push_uniforms;
26 break;
27 case MESA_SHADER_FRAGMENT:
28 if (!gfx_state_dirty(cmdbuf, FS_PUSH_UNIFORMS))
29 return VK_SUCCESS;
30 push_ptr = &cmdbuf->state.gfx.fs.push_uniforms;
31 break;
32 default:
33 assert(!"Invalid stage");
34 return VK_SUCCESS;
35 }
36
37 if (!shader->fau.total_count) {
38 *push_ptr = 0;
39 return VK_SUCCESS;
40 }
41
42 struct panfrost_ptr push_uniforms = panvk_cmd_alloc_dev_mem(
43 cmdbuf, desc, shader->fau.total_count * sizeof(uint64_t),
44 sizeof(uint64_t));
45
46 if (!push_uniforms.gpu)
47 return VK_ERROR_OUT_OF_DEVICE_MEMORY;
48
49 if (shader->vk.stage == MESA_SHADER_COMPUTE) {
50 cmdbuf->state.compute.sysvals.push_consts =
51 push_uniforms.gpu + (shader->fau.sysval_count * FAU_WORD_SIZE);
52 } else {
53 cmdbuf->state.gfx.sysvals.push_consts =
54 push_uniforms.gpu + (shader->fau.sysval_count * FAU_WORD_SIZE);
55 }
56
57 uint64_t *sysvals = shader->vk.stage == MESA_SHADER_COMPUTE
58 ? (uint64_t *)&cmdbuf->state.compute.sysvals
59 : (uint64_t *)&cmdbuf->state.gfx.sysvals;
60 uint64_t *push_consts = cmdbuf->state.push_constants.data;
61 uint64_t *faus = push_uniforms.cpu;
62 uint32_t w, fau = 0;
63
64 /* After packing, the sysvals come first, followed by the user push constants.
65 * The ordering is encoded shader side, so don't re-order these loops. */
66 BITSET_FOREACH_SET(w, shader->fau.used_sysvals, MAX_SYSVAL_FAUS)
67 faus[fau++] = sysvals[w];
68
69 BITSET_FOREACH_SET(w, shader->fau.used_push_consts, MAX_PUSH_CONST_FAUS)
70 faus[fau++] = push_consts[w];
71
72 *push_ptr = push_uniforms.gpu;
73 return VK_SUCCESS;
74 }
75
76 VKAPI_ATTR void VKAPI_CALL
panvk_per_arch(CmdPushConstants2KHR)77 panvk_per_arch(CmdPushConstants2KHR)(
78 VkCommandBuffer commandBuffer,
79 const VkPushConstantsInfoKHR *pPushConstantsInfo)
80 {
81 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
82
83 if (pPushConstantsInfo->stageFlags & VK_SHADER_STAGE_VERTEX_BIT)
84 gfx_state_set_dirty(cmdbuf, VS_PUSH_UNIFORMS);
85
86 if (pPushConstantsInfo->stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT)
87 gfx_state_set_dirty(cmdbuf, FS_PUSH_UNIFORMS);
88
89 if (pPushConstantsInfo->stageFlags & VK_SHADER_STAGE_COMPUTE_BIT)
90 compute_state_set_dirty(cmdbuf, PUSH_UNIFORMS);
91
92 uint8_t *data =
93 (uint8_t *)cmdbuf->state.push_constants.data + pPushConstantsInfo->offset;
94
95 memcpy(data, pPushConstantsInfo->pValues, pPushConstantsInfo->size);
96 }
97