1 /*
2 * Copyright © 2021 Collabora Ltd.
3 *
4 * Derived from tu_image.c which is:
5 * Copyright © 2016 Red Hat.
6 * Copyright © 2016 Bas Nieuwenhuizen
7 * Copyright © 2015 Intel Corporation
8 *
9 * SPDX-License-Identifier: MIT
10 */
11
12 #include "genxml/gen_macros.h"
13
14 #include "panvk_buffer.h"
15 #include "panvk_buffer_view.h"
16 #include "panvk_device.h"
17 #include "panvk_entrypoints.h"
18 #include "panvk_priv_bo.h"
19
20 #include "vk_format.h"
21 #include "vk_log.h"
22
23 VKAPI_ATTR VkResult VKAPI_CALL
panvk_per_arch(CreateBufferView)24 panvk_per_arch(CreateBufferView)(VkDevice _device,
25 const VkBufferViewCreateInfo *pCreateInfo,
26 const VkAllocationCallbacks *pAllocator,
27 VkBufferView *pView)
28 {
29 VK_FROM_HANDLE(panvk_device, device, _device);
30 VK_FROM_HANDLE(panvk_buffer, buffer, pCreateInfo->buffer);
31
32 struct panvk_buffer_view *view = vk_object_zalloc(
33 &device->vk, pAllocator, sizeof(*view), VK_OBJECT_TYPE_BUFFER_VIEW);
34
35 if (!view)
36 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
37
38 vk_buffer_view_init(&device->vk, &view->vk, pCreateInfo);
39
40 enum pipe_format pfmt = vk_format_to_pipe_format(view->vk.format);
41
42 mali_ptr address = panvk_buffer_gpu_ptr(buffer, pCreateInfo->offset);
43 VkBufferUsageFlags tex_usage_mask = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
44
45 #if PAN_ARCH >= 9
46 /* Valhall passes a texture descriptor to LEA_TEX. */
47 tex_usage_mask |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
48 #endif
49
50 assert(!(address & 63));
51
52 if (buffer->vk.usage & tex_usage_mask) {
53 struct panvk_physical_device *physical_device =
54 to_panvk_physical_device(device->vk.physical);
55 unsigned arch = pan_arch(physical_device->kmod.props.gpu_prod_id);
56
57 struct pan_image plane = {
58 .data = {
59 .base = address,
60 .offset = 0,
61 },
62 .layout = {
63 .modifier = DRM_FORMAT_MOD_LINEAR,
64 .format = pfmt,
65 .dim = MALI_TEXTURE_DIMENSION_1D,
66 .width = view->vk.elements,
67 .height = 1,
68 .depth = 1,
69 .array_size = 1,
70 .nr_samples = 1,
71 .nr_slices = 1,
72 },
73 };
74
75 struct pan_image_view pview = {
76 .planes[0] = &plane,
77 .format = pfmt,
78 .dim = MALI_TEXTURE_DIMENSION_1D,
79 .nr_samples = 1,
80 .first_level = 0,
81 .last_level = 0,
82 .first_layer = 0,
83 .last_layer = 0,
84 .swizzle =
85 {
86 PIPE_SWIZZLE_X,
87 PIPE_SWIZZLE_Y,
88 PIPE_SWIZZLE_Z,
89 PIPE_SWIZZLE_W,
90 },
91 };
92
93 pan_image_layout_init(arch, &plane.layout, NULL);
94
95 struct panvk_pool_alloc_info alloc_info = {
96 .alignment = pan_alignment(TEXTURE),
97 .size = GENX(panfrost_estimate_texture_payload_size)(&pview),
98 };
99
100 view->mem = panvk_pool_alloc_mem(&device->mempools.rw, alloc_info);
101
102 struct panfrost_ptr ptr = {
103 .gpu = panvk_priv_mem_dev_addr(view->mem),
104 .cpu = panvk_priv_mem_host_addr(view->mem),
105 };
106
107 GENX(panfrost_new_texture)(&pview, view->descs.tex.opaque, &ptr);
108 }
109
110 #if PAN_ARCH <= 7
111 if (buffer->vk.usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) {
112 unsigned blksz = vk_format_get_blocksize(pCreateInfo->format);
113
114 pan_pack(view->descs.img_attrib_buf[0].opaque, ATTRIBUTE_BUFFER, cfg) {
115 /* The format is the only thing we lack to emit attribute descriptors
116 * when copying from the set to the attribute tables. Instead of
117 * making the descriptor size to store an extra format, we pack
118 * the 22-bit format with the texel stride, which is expected to be
119 * fit in remaining 10 bits.
120 */
121 uint32_t hw_fmt = GENX(panfrost_format_from_pipe_format)(pfmt)->hw;
122
123 assert(blksz < BITFIELD_MASK(10));
124 assert(hw_fmt < BITFIELD_MASK(22));
125
126 cfg.type = MALI_ATTRIBUTE_TYPE_3D_LINEAR;
127 cfg.pointer = address;
128 cfg.stride = blksz | (hw_fmt << 10);
129 cfg.size = view->vk.elements * blksz;
130 }
131
132 pan_pack(view->descs.img_attrib_buf[1].opaque,
133 ATTRIBUTE_BUFFER_CONTINUATION_3D, cfg) {
134 cfg.s_dimension = view->vk.elements;
135 cfg.t_dimension = 1;
136 cfg.r_dimension = 1;
137 cfg.row_stride = view->vk.elements * blksz;
138 }
139 }
140 #endif
141
142 *pView = panvk_buffer_view_to_handle(view);
143 return VK_SUCCESS;
144 }
145
146 VKAPI_ATTR void VKAPI_CALL
panvk_per_arch(DestroyBufferView)147 panvk_per_arch(DestroyBufferView)(VkDevice _device, VkBufferView bufferView,
148 const VkAllocationCallbacks *pAllocator)
149 {
150 VK_FROM_HANDLE(panvk_device, device, _device);
151 VK_FROM_HANDLE(panvk_buffer_view, view, bufferView);
152
153 if (!view)
154 return;
155
156 panvk_pool_free_mem(&device->mempools.rw, view->mem);
157 vk_buffer_view_destroy(&device->vk, pAllocator, &view->vk);
158 }
159