1 /*
2 * Copyright © 2019 Red Hat.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "lvp_private.h"
25 #include "util/format/u_format.h"
26 #include "util/u_inlines.h"
27 #include "pipe/p_state.h"
28
29 VkResult
lvp_image_create(VkDevice _device,const struct lvp_image_create_info * create_info,const VkAllocationCallbacks * alloc,VkImage * pImage)30 lvp_image_create(VkDevice _device,
31 const struct lvp_image_create_info *create_info,
32 const VkAllocationCallbacks* alloc,
33 VkImage *pImage)
34 {
35 LVP_FROM_HANDLE(lvp_device, device, _device);
36 const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
37 struct lvp_image *image;
38
39 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
40
41 image = vk_zalloc2(&device->vk.alloc, alloc, sizeof(*image), 8,
42 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
43 if (image == NULL)
44 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
45
46 vk_object_base_init(&device->vk, &image->base, VK_OBJECT_TYPE_IMAGE);
47 image->alignment = 16;
48 image->type = pCreateInfo->imageType;
49 {
50 struct pipe_resource template;
51
52 memset(&template, 0, sizeof(template));
53
54 template.screen = device->pscreen;
55 switch (pCreateInfo->imageType) {
56 case VK_IMAGE_TYPE_1D:
57 template.target = pCreateInfo->arrayLayers > 1 ? PIPE_TEXTURE_1D_ARRAY : PIPE_TEXTURE_1D;
58 break;
59 default:
60 case VK_IMAGE_TYPE_2D:
61 template.target = pCreateInfo->arrayLayers > 1 ? PIPE_TEXTURE_2D_ARRAY : PIPE_TEXTURE_2D;
62 if (pCreateInfo->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
63 template.target = pCreateInfo->arrayLayers == 6 ? PIPE_TEXTURE_CUBE : PIPE_TEXTURE_CUBE_ARRAY;
64 break;
65 case VK_IMAGE_TYPE_3D:
66 template.target = PIPE_TEXTURE_3D;
67 break;
68 }
69
70 template.format = vk_format_to_pipe(pCreateInfo->format);
71 template.width0 = pCreateInfo->extent.width;
72 template.height0 = pCreateInfo->extent.height;
73 template.depth0 = pCreateInfo->extent.depth;
74 template.array_size = pCreateInfo->arrayLayers;
75 template.last_level = pCreateInfo->mipLevels - 1;
76 template.nr_samples = pCreateInfo->samples;
77 template.nr_storage_samples = pCreateInfo->samples;
78 if (create_info->bind_flags)
79 template.bind = create_info->bind_flags;
80 image->bo = device->pscreen->resource_create_unbacked(device->pscreen,
81 &template,
82 &image->size);
83 }
84 *pImage = lvp_image_to_handle(image);
85
86 return VK_SUCCESS;
87 }
88
89 VkResult
lvp_CreateImage(VkDevice device,const VkImageCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImage * pImage)90 lvp_CreateImage(VkDevice device,
91 const VkImageCreateInfo *pCreateInfo,
92 const VkAllocationCallbacks *pAllocator,
93 VkImage *pImage)
94 {
95 return lvp_image_create(device,
96 &(struct lvp_image_create_info) {
97 .vk_info = pCreateInfo,
98 .bind_flags = 0,
99 },
100 pAllocator,
101 pImage);
102 }
103
104 void
lvp_DestroyImage(VkDevice _device,VkImage _image,const VkAllocationCallbacks * pAllocator)105 lvp_DestroyImage(VkDevice _device, VkImage _image,
106 const VkAllocationCallbacks *pAllocator)
107 {
108 LVP_FROM_HANDLE(lvp_device, device, _device);
109 LVP_FROM_HANDLE(lvp_image, image, _image);
110
111 if (!_image)
112 return;
113 pipe_resource_reference(&image->bo, NULL);
114 vk_object_base_finish(&image->base);
115 vk_free2(&device->vk.alloc, pAllocator, image);
116 }
117
118 VkResult
lvp_CreateImageView(VkDevice _device,const VkImageViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkImageView * pView)119 lvp_CreateImageView(VkDevice _device,
120 const VkImageViewCreateInfo *pCreateInfo,
121 const VkAllocationCallbacks *pAllocator,
122 VkImageView *pView)
123 {
124 LVP_FROM_HANDLE(lvp_device, device, _device);
125 LVP_FROM_HANDLE(lvp_image, image, pCreateInfo->image);
126 struct lvp_image_view *view;
127
128 view = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*view), 8,
129 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
130 if (view == NULL)
131 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
132
133 vk_object_base_init(&device->vk, &view->base,
134 VK_OBJECT_TYPE_IMAGE_VIEW);
135 view->view_type = pCreateInfo->viewType;
136 view->format = pCreateInfo->format;
137 view->pformat = vk_format_to_pipe(pCreateInfo->format);
138 view->components = pCreateInfo->components;
139 view->subresourceRange = pCreateInfo->subresourceRange;
140 view->image = image;
141 view->surface = NULL;
142 *pView = lvp_image_view_to_handle(view);
143
144 return VK_SUCCESS;
145 }
146
147 void
lvp_DestroyImageView(VkDevice _device,VkImageView _iview,const VkAllocationCallbacks * pAllocator)148 lvp_DestroyImageView(VkDevice _device, VkImageView _iview,
149 const VkAllocationCallbacks *pAllocator)
150 {
151 LVP_FROM_HANDLE(lvp_device, device, _device);
152 LVP_FROM_HANDLE(lvp_image_view, iview, _iview);
153
154 if (!_iview)
155 return;
156
157 pipe_surface_reference(&iview->surface, NULL);
158 vk_object_base_finish(&iview->base);
159 vk_free2(&device->vk.alloc, pAllocator, iview);
160 }
161
lvp_GetImageSubresourceLayout(VkDevice _device,VkImage _image,const VkImageSubresource * pSubresource,VkSubresourceLayout * pLayout)162 void lvp_GetImageSubresourceLayout(
163 VkDevice _device,
164 VkImage _image,
165 const VkImageSubresource* pSubresource,
166 VkSubresourceLayout* pLayout)
167 {
168 LVP_FROM_HANDLE(lvp_device, device, _device);
169 LVP_FROM_HANDLE(lvp_image, image, _image);
170 uint64_t value;
171
172 device->pscreen->resource_get_param(device->pscreen,
173 NULL,
174 image->bo,
175 0,
176 pSubresource->arrayLayer,
177 pSubresource->mipLevel,
178 PIPE_RESOURCE_PARAM_STRIDE,
179 0, &value);
180
181 pLayout->rowPitch = value;
182
183 device->pscreen->resource_get_param(device->pscreen,
184 NULL,
185 image->bo,
186 0,
187 pSubresource->arrayLayer,
188 pSubresource->mipLevel,
189 PIPE_RESOURCE_PARAM_OFFSET,
190 0, &value);
191
192 pLayout->offset = value;
193
194 device->pscreen->resource_get_param(device->pscreen,
195 NULL,
196 image->bo,
197 0,
198 pSubresource->arrayLayer,
199 pSubresource->mipLevel,
200 PIPE_RESOURCE_PARAM_LAYER_STRIDE,
201 0, &value);
202
203 if (image->bo->target == PIPE_TEXTURE_3D) {
204 pLayout->depthPitch = value;
205 pLayout->arrayPitch = 0;
206 } else {
207 pLayout->depthPitch = 0;
208 pLayout->arrayPitch = value;
209 }
210 pLayout->size = image->size;
211
212 switch (pSubresource->aspectMask) {
213 case VK_IMAGE_ASPECT_COLOR_BIT:
214 break;
215 case VK_IMAGE_ASPECT_DEPTH_BIT:
216 break;
217 case VK_IMAGE_ASPECT_STENCIL_BIT:
218 break;
219 default:
220 assert(!"Invalid image aspect");
221 }
222 }
223
lvp_CreateBuffer(VkDevice _device,const VkBufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBuffer * pBuffer)224 VkResult lvp_CreateBuffer(
225 VkDevice _device,
226 const VkBufferCreateInfo* pCreateInfo,
227 const VkAllocationCallbacks* pAllocator,
228 VkBuffer* pBuffer)
229 {
230 LVP_FROM_HANDLE(lvp_device, device, _device);
231 struct lvp_buffer *buffer;
232
233 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
234
235 /* gallium has max 32-bit buffer sizes */
236 if (pCreateInfo->size > UINT32_MAX)
237 return VK_ERROR_OUT_OF_DEVICE_MEMORY;
238
239 buffer = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*buffer), 8,
240 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
241 if (buffer == NULL)
242 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
243
244 vk_object_base_init(&device->vk, &buffer->base, VK_OBJECT_TYPE_BUFFER);
245 buffer->size = pCreateInfo->size;
246 buffer->usage = pCreateInfo->usage;
247 buffer->offset = 0;
248
249 {
250 struct pipe_resource template;
251 memset(&template, 0, sizeof(struct pipe_resource));
252 template.screen = device->pscreen;
253 template.target = PIPE_BUFFER;
254 template.format = PIPE_FORMAT_R8_UNORM;
255 template.width0 = buffer->size;
256 template.height0 = 1;
257 template.depth0 = 1;
258 template.array_size = 1;
259 template.flags = PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE;
260 buffer->bo = device->pscreen->resource_create_unbacked(device->pscreen,
261 &template,
262 &buffer->total_size);
263 if (!buffer->bo) {
264 vk_free2(&device->vk.alloc, pAllocator, buffer);
265 return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
266 }
267 }
268 *pBuffer = lvp_buffer_to_handle(buffer);
269
270 return VK_SUCCESS;
271 }
272
lvp_DestroyBuffer(VkDevice _device,VkBuffer _buffer,const VkAllocationCallbacks * pAllocator)273 void lvp_DestroyBuffer(
274 VkDevice _device,
275 VkBuffer _buffer,
276 const VkAllocationCallbacks* pAllocator)
277 {
278 LVP_FROM_HANDLE(lvp_device, device, _device);
279 LVP_FROM_HANDLE(lvp_buffer, buffer, _buffer);
280
281 if (!_buffer)
282 return;
283
284 pipe_resource_reference(&buffer->bo, NULL);
285 vk_object_base_finish(&buffer->base);
286 vk_free2(&device->vk.alloc, pAllocator, buffer);
287 }
288
289 VkResult
lvp_CreateBufferView(VkDevice _device,const VkBufferViewCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBufferView * pView)290 lvp_CreateBufferView(VkDevice _device,
291 const VkBufferViewCreateInfo *pCreateInfo,
292 const VkAllocationCallbacks *pAllocator,
293 VkBufferView *pView)
294 {
295 LVP_FROM_HANDLE(lvp_device, device, _device);
296 LVP_FROM_HANDLE(lvp_buffer, buffer, pCreateInfo->buffer);
297 struct lvp_buffer_view *view;
298 view = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*view), 8,
299 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
300 if (!view)
301 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
302
303 vk_object_base_init(&device->vk, &view->base,
304 VK_OBJECT_TYPE_BUFFER_VIEW);
305 view->buffer = buffer;
306 view->format = pCreateInfo->format;
307 view->pformat = vk_format_to_pipe(pCreateInfo->format);
308 view->offset = pCreateInfo->offset;
309 view->range = pCreateInfo->range;
310 *pView = lvp_buffer_view_to_handle(view);
311
312 return VK_SUCCESS;
313 }
314
315 void
lvp_DestroyBufferView(VkDevice _device,VkBufferView bufferView,const VkAllocationCallbacks * pAllocator)316 lvp_DestroyBufferView(VkDevice _device, VkBufferView bufferView,
317 const VkAllocationCallbacks *pAllocator)
318 {
319 LVP_FROM_HANDLE(lvp_device, device, _device);
320 LVP_FROM_HANDLE(lvp_buffer_view, view, bufferView);
321
322 if (!bufferView)
323 return;
324 vk_object_base_finish(&view->base);
325 vk_free2(&device->vk.alloc, pAllocator, view);
326 }
327