vn_render_pass.c revision 7ec681f3
1/*
2 * Copyright 2019 Google LLC
3 * SPDX-License-Identifier: MIT
4 *
5 * based in part on anv and radv which are:
6 * Copyright © 2015 Intel Corporation
7 * Copyright © 2016 Red Hat.
8 * Copyright © 2016 Bas Nieuwenhuizen
9 */
10
11#include "vn_render_pass.h"
12
13#include "venus-protocol/vn_protocol_driver_framebuffer.h"
14#include "venus-protocol/vn_protocol_driver_render_pass.h"
15
16#include "vn_device.h"
17#include "vn_image.h"
18
19#define COUNT_PRESENT_SRC(atts, att_count, initial_count, final_count)       \
20   do {                                                                      \
21      *initial_count = 0;                                                    \
22      *final_count = 0;                                                      \
23      for (uint32_t i = 0; i < att_count; i++) {                             \
24         if (atts[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)       \
25            (*initial_count)++;                                              \
26         if (atts[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)         \
27            (*final_count)++;                                                \
28      }                                                                      \
29   } while (false)
30
31#define REPLACE_PRESENT_SRC(pass, atts, att_count, out_atts)                 \
32   do {                                                                      \
33      struct vn_present_src_attachment *_acquire_atts =                      \
34         pass->present_src_attachments;                                      \
35      struct vn_present_src_attachment *_release_atts =                      \
36         _acquire_atts + pass->acquire_count;                                \
37                                                                             \
38      memcpy(out_atts, atts, sizeof(*atts) * att_count);                     \
39      for (uint32_t i = 0; i < att_count; i++) {                             \
40         if (out_atts[i].initialLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { \
41            out_atts[i].initialLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;      \
42            _acquire_atts->acquire = true;                                   \
43            _acquire_atts->index = i;                                        \
44            _acquire_atts++;                                                 \
45         }                                                                   \
46         if (out_atts[i].finalLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {   \
47            out_atts[i].finalLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT;        \
48            _release_atts->acquire = false;                                  \
49            _release_atts->index = i;                                        \
50            _release_atts++;                                                 \
51         }                                                                   \
52      }                                                                      \
53   } while (false)
54
55static void
56vn_render_pass_count_present_src(const VkRenderPassCreateInfo *create_info,
57                                 uint32_t *initial_count,
58                                 uint32_t *final_count)
59{
60   COUNT_PRESENT_SRC(create_info->pAttachments, create_info->attachmentCount,
61                     initial_count, final_count);
62}
63
64static void
65vn_render_pass_count_present_src2(const VkRenderPassCreateInfo2 *create_info,
66                                  uint32_t *initial_count,
67                                  uint32_t *final_count)
68{
69   COUNT_PRESENT_SRC(create_info->pAttachments, create_info->attachmentCount,
70                     initial_count, final_count);
71}
72
73static void
74vn_render_pass_replace_present_src(struct vn_render_pass *pass,
75                                   const VkRenderPassCreateInfo *create_info,
76                                   VkAttachmentDescription *out_atts)
77{
78   REPLACE_PRESENT_SRC(pass, create_info->pAttachments,
79                       create_info->attachmentCount, out_atts);
80}
81
82static void
83vn_render_pass_replace_present_src2(struct vn_render_pass *pass,
84                                    const VkRenderPassCreateInfo2 *create_info,
85                                    VkAttachmentDescription2 *out_atts)
86{
87   REPLACE_PRESENT_SRC(pass, create_info->pAttachments,
88                       create_info->attachmentCount, out_atts);
89}
90
91static void
92vn_render_pass_setup_present_src_barriers(struct vn_render_pass *pass)
93{
94   /* TODO parse VkSubpassDependency for more accurate barriers */
95   for (uint32_t i = 0; i < pass->present_src_count; i++) {
96      struct vn_present_src_attachment *att =
97         &pass->present_src_attachments[i];
98
99      if (att->acquire) {
100         att->src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
101         att->src_access_mask = 0;
102
103         att->dst_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
104         att->dst_access_mask =
105            VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
106      } else {
107         att->src_stage_mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
108         att->src_access_mask = VK_ACCESS_MEMORY_WRITE_BIT;
109
110         att->dst_stage_mask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
111         att->dst_access_mask = 0;
112      }
113   }
114}
115
116static struct vn_render_pass *
117vn_render_pass_create(struct vn_device *dev,
118                      uint32_t acquire_count,
119                      uint32_t release_count,
120                      const VkAllocationCallbacks *alloc)
121{
122   const uint32_t total_count = acquire_count + release_count;
123   struct vn_render_pass *pass = vk_zalloc(
124      alloc,
125      sizeof(*pass) + sizeof(pass->present_src_attachments[0]) * total_count,
126      VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
127   if (!pass)
128      return NULL;
129
130   vn_object_base_init(&pass->base, VK_OBJECT_TYPE_RENDER_PASS, &dev->base);
131
132   pass->acquire_count = acquire_count;
133   pass->release_count = release_count;
134   pass->present_src_count = total_count;
135
136   return pass;
137}
138
139/* render pass commands */
140
141VkResult
142vn_CreateRenderPass(VkDevice device,
143                    const VkRenderPassCreateInfo *pCreateInfo,
144                    const VkAllocationCallbacks *pAllocator,
145                    VkRenderPass *pRenderPass)
146{
147   struct vn_device *dev = vn_device_from_handle(device);
148   const VkAllocationCallbacks *alloc =
149      pAllocator ? pAllocator : &dev->base.base.alloc;
150
151   uint32_t acquire_count;
152   uint32_t release_count;
153   vn_render_pass_count_present_src(pCreateInfo, &acquire_count,
154                                    &release_count);
155
156   struct vn_render_pass *pass =
157      vn_render_pass_create(dev, acquire_count, release_count, alloc);
158   if (!pass)
159      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
160
161   VkRenderPassCreateInfo local_pass_info;
162   if (pass->present_src_count) {
163      VkAttachmentDescription *temp_atts =
164         vk_alloc(alloc, sizeof(*temp_atts) * pCreateInfo->attachmentCount,
165                  VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
166      if (!temp_atts) {
167         vk_free(alloc, pass);
168         return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
169      }
170
171      vn_render_pass_replace_present_src(pass, pCreateInfo, temp_atts);
172      vn_render_pass_setup_present_src_barriers(pass);
173
174      local_pass_info = *pCreateInfo;
175      local_pass_info.pAttachments = temp_atts;
176      pCreateInfo = &local_pass_info;
177   }
178
179   VkRenderPass pass_handle = vn_render_pass_to_handle(pass);
180   vn_async_vkCreateRenderPass(dev->instance, device, pCreateInfo, NULL,
181                               &pass_handle);
182
183   if (pCreateInfo == &local_pass_info)
184      vk_free(alloc, (void *)local_pass_info.pAttachments);
185
186   *pRenderPass = pass_handle;
187
188   return VK_SUCCESS;
189}
190
191VkResult
192vn_CreateRenderPass2(VkDevice device,
193                     const VkRenderPassCreateInfo2 *pCreateInfo,
194                     const VkAllocationCallbacks *pAllocator,
195                     VkRenderPass *pRenderPass)
196{
197   struct vn_device *dev = vn_device_from_handle(device);
198   const VkAllocationCallbacks *alloc =
199      pAllocator ? pAllocator : &dev->base.base.alloc;
200
201   uint32_t acquire_count;
202   uint32_t release_count;
203   vn_render_pass_count_present_src2(pCreateInfo, &acquire_count,
204                                     &release_count);
205
206   struct vn_render_pass *pass =
207      vn_render_pass_create(dev, acquire_count, release_count, alloc);
208   if (!pass)
209      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
210
211   VkRenderPassCreateInfo2 local_pass_info;
212   if (pass->present_src_count) {
213      VkAttachmentDescription2 *temp_atts =
214         vk_alloc(alloc, sizeof(*temp_atts) * pCreateInfo->attachmentCount,
215                  VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
216      if (!temp_atts) {
217         vk_free(alloc, pass);
218         return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
219      }
220
221      vn_render_pass_replace_present_src2(pass, pCreateInfo, temp_atts);
222      vn_render_pass_setup_present_src_barriers(pass);
223
224      local_pass_info = *pCreateInfo;
225      local_pass_info.pAttachments = temp_atts;
226      pCreateInfo = &local_pass_info;
227   }
228
229   VkRenderPass pass_handle = vn_render_pass_to_handle(pass);
230   vn_async_vkCreateRenderPass2(dev->instance, device, pCreateInfo, NULL,
231                                &pass_handle);
232
233   if (pCreateInfo == &local_pass_info)
234      vk_free(alloc, (void *)local_pass_info.pAttachments);
235
236   *pRenderPass = pass_handle;
237
238   return VK_SUCCESS;
239}
240
241void
242vn_DestroyRenderPass(VkDevice device,
243                     VkRenderPass renderPass,
244                     const VkAllocationCallbacks *pAllocator)
245{
246   struct vn_device *dev = vn_device_from_handle(device);
247   struct vn_render_pass *pass = vn_render_pass_from_handle(renderPass);
248   const VkAllocationCallbacks *alloc =
249      pAllocator ? pAllocator : &dev->base.base.alloc;
250
251   if (!pass)
252      return;
253
254   vn_async_vkDestroyRenderPass(dev->instance, device, renderPass, NULL);
255
256   vn_object_base_fini(&pass->base);
257   vk_free(alloc, pass);
258}
259
260void
261vn_GetRenderAreaGranularity(VkDevice device,
262                            VkRenderPass renderPass,
263                            VkExtent2D *pGranularity)
264{
265   struct vn_device *dev = vn_device_from_handle(device);
266   struct vn_render_pass *pass = vn_render_pass_from_handle(renderPass);
267
268   if (!pass->granularity.width) {
269      vn_call_vkGetRenderAreaGranularity(dev->instance, device, renderPass,
270                                         &pass->granularity);
271   }
272
273   *pGranularity = pass->granularity;
274}
275
276/* framebuffer commands */
277
278VkResult
279vn_CreateFramebuffer(VkDevice device,
280                     const VkFramebufferCreateInfo *pCreateInfo,
281                     const VkAllocationCallbacks *pAllocator,
282                     VkFramebuffer *pFramebuffer)
283{
284   struct vn_device *dev = vn_device_from_handle(device);
285   const VkAllocationCallbacks *alloc =
286      pAllocator ? pAllocator : &dev->base.base.alloc;
287
288   /* Two render passes differ only in attachment image layouts are considered
289    * compatible.  We must not use pCreateInfo->renderPass here.
290    */
291   const bool imageless =
292      pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
293   const uint32_t view_count = imageless ? 0 : pCreateInfo->attachmentCount;
294
295   struct vn_framebuffer *fb =
296      vk_zalloc(alloc, sizeof(*fb) + sizeof(*fb->image_views) * view_count,
297                VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
298   if (!fb)
299      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
300
301   vn_object_base_init(&fb->base, VK_OBJECT_TYPE_FRAMEBUFFER, &dev->base);
302
303   fb->image_view_count = view_count;
304   memcpy(fb->image_views, pCreateInfo->pAttachments,
305          sizeof(*pCreateInfo->pAttachments) * view_count);
306
307   VkFramebuffer fb_handle = vn_framebuffer_to_handle(fb);
308   vn_async_vkCreateFramebuffer(dev->instance, device, pCreateInfo, NULL,
309                                &fb_handle);
310
311   *pFramebuffer = fb_handle;
312
313   return VK_SUCCESS;
314}
315
316void
317vn_DestroyFramebuffer(VkDevice device,
318                      VkFramebuffer framebuffer,
319                      const VkAllocationCallbacks *pAllocator)
320{
321   struct vn_device *dev = vn_device_from_handle(device);
322   struct vn_framebuffer *fb = vn_framebuffer_from_handle(framebuffer);
323   const VkAllocationCallbacks *alloc =
324      pAllocator ? pAllocator : &dev->base.base.alloc;
325
326   if (!fb)
327      return;
328
329   vn_async_vkDestroyFramebuffer(dev->instance, device, framebuffer, NULL);
330
331   vn_object_base_fini(&fb->base);
332   vk_free(alloc, fb);
333}
334