2 * Copyright © 2019 Red Hat.
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:
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
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
24 #include "val_private.h"
27 val_render_pass_compile(struct val_render_pass
*pass
)
29 for (uint32_t i
= 0; i
< pass
->subpass_count
; i
++) {
30 struct val_subpass
*subpass
= &pass
->subpasses
[i
];
32 for (uint32_t j
= 0; j
< subpass
->attachment_count
; j
++) {
33 struct val_subpass_attachment
*subpass_att
=
34 &subpass
->attachments
[j
];
35 if (subpass_att
->attachment
== VK_ATTACHMENT_UNUSED
)
38 struct val_render_pass_attachment
*pass_att
=
39 &pass
->attachments
[subpass_att
->attachment
];
41 pass_att
->first_subpass_idx
= UINT32_MAX
;
45 for (uint32_t i
= 0; i
< pass
->subpass_count
; i
++) {
46 struct val_subpass
*subpass
= &pass
->subpasses
[i
];
47 uint32_t color_sample_count
= 1, depth_sample_count
= 1;
49 /* We don't allow depth_stencil_attachment to be non-NULL and
50 * be VK_ATTACHMENT_UNUSED. This way something can just check
51 * for NULL and be guaranteed that they have a valid
54 if (subpass
->depth_stencil_attachment
&&
55 subpass
->depth_stencil_attachment
->attachment
== VK_ATTACHMENT_UNUSED
)
56 subpass
->depth_stencil_attachment
= NULL
;
58 if (subpass
->ds_resolve_attachment
&&
59 subpass
->ds_resolve_attachment
->attachment
== VK_ATTACHMENT_UNUSED
)
60 subpass
->ds_resolve_attachment
= NULL
;
62 for (uint32_t j
= 0; j
< subpass
->attachment_count
; j
++) {
63 struct val_subpass_attachment
*subpass_att
=
64 &subpass
->attachments
[j
];
65 if (subpass_att
->attachment
== VK_ATTACHMENT_UNUSED
)
68 struct val_render_pass_attachment
*pass_att
=
69 &pass
->attachments
[subpass_att
->attachment
];
71 if (i
< pass_att
->first_subpass_idx
)
72 pass_att
->first_subpass_idx
= i
;
73 pass_att
->last_subpass_idx
= i
;
76 subpass
->has_color_att
= false;
77 for (uint32_t j
= 0; j
< subpass
->color_count
; j
++) {
78 struct val_subpass_attachment
*subpass_att
=
79 &subpass
->color_attachments
[j
];
80 if (subpass_att
->attachment
== VK_ATTACHMENT_UNUSED
)
83 subpass
->has_color_att
= true;
85 struct val_render_pass_attachment
*pass_att
=
86 &pass
->attachments
[subpass_att
->attachment
];
88 color_sample_count
= pass_att
->samples
;
91 if (subpass
->depth_stencil_attachment
) {
93 subpass
->depth_stencil_attachment
->attachment
;
94 struct val_render_pass_attachment
*pass_att
=
95 &pass
->attachments
[a
];
96 depth_sample_count
= pass_att
->samples
;
99 subpass
->max_sample_count
= MAX2(color_sample_count
,
102 /* We have to handle resolve attachments specially */
103 subpass
->has_color_resolve
= false;
104 if (subpass
->resolve_attachments
) {
105 for (uint32_t j
= 0; j
< subpass
->color_count
; j
++) {
106 struct val_subpass_attachment
*resolve_att
=
107 &subpass
->resolve_attachments
[j
];
109 if (resolve_att
->attachment
== VK_ATTACHMENT_UNUSED
)
112 subpass
->has_color_resolve
= true;
116 for (uint32_t j
= 0; j
< subpass
->input_count
; ++j
) {
117 if (subpass
->input_attachments
[j
].attachment
== VK_ATTACHMENT_UNUSED
)
120 for (uint32_t k
= 0; k
< subpass
->color_count
; ++k
) {
121 if (subpass
->color_attachments
[k
].attachment
== subpass
->input_attachments
[j
].attachment
) {
122 subpass
->input_attachments
[j
].in_render_loop
= true;
123 subpass
->color_attachments
[k
].in_render_loop
= true;
127 if (subpass
->depth_stencil_attachment
&&
128 subpass
->depth_stencil_attachment
->attachment
== subpass
->input_attachments
[j
].attachment
) {
129 subpass
->input_attachments
[j
].in_render_loop
= true;
130 subpass
->depth_stencil_attachment
->in_render_loop
= true;
137 val_num_subpass_attachments(const VkSubpassDescription
*desc
)
139 return desc
->inputAttachmentCount
+
140 desc
->colorAttachmentCount
+
141 (desc
->pResolveAttachments
? desc
->colorAttachmentCount
: 0) +
142 (desc
->pDepthStencilAttachment
!= NULL
);
145 VkResult
val_CreateRenderPass(
147 const VkRenderPassCreateInfo
* pCreateInfo
,
148 const VkAllocationCallbacks
* pAllocator
,
149 VkRenderPass
* pRenderPass
)
151 VAL_FROM_HANDLE(val_device
, device
, _device
);
152 struct val_render_pass
*pass
;
154 size_t attachments_offset
;
156 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
);
158 size
= sizeof(*pass
);
159 size
+= pCreateInfo
->subpassCount
* sizeof(pass
->subpasses
[0]);
160 attachments_offset
= size
;
161 size
+= pCreateInfo
->attachmentCount
* sizeof(pass
->attachments
[0]);
163 pass
= vk_alloc2(&device
->alloc
, pAllocator
, size
, 8,
164 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
166 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
168 /* Clear the subpasses along with the parent pass. This required because
169 * each array member of val_subpass must be a valid pointer if not NULL.
171 memset(pass
, 0, size
);
173 vk_object_base_init(&device
->vk
, &pass
->base
,
174 VK_OBJECT_TYPE_RENDER_PASS
);
175 pass
->attachment_count
= pCreateInfo
->attachmentCount
;
176 pass
->subpass_count
= pCreateInfo
->subpassCount
;
177 pass
->attachments
= (void *) pass
+ attachments_offset
;
179 for (uint32_t i
= 0; i
< pCreateInfo
->attachmentCount
; i
++) {
180 struct val_render_pass_attachment
*att
= &pass
->attachments
[i
];
182 att
->format
= pCreateInfo
->pAttachments
[i
].format
;
183 att
->samples
= pCreateInfo
->pAttachments
[i
].samples
;
184 att
->load_op
= pCreateInfo
->pAttachments
[i
].loadOp
;
185 att
->stencil_load_op
= pCreateInfo
->pAttachments
[i
].stencilLoadOp
;
186 att
->final_layout
= pCreateInfo
->pAttachments
[i
].finalLayout
;
187 att
->first_subpass_idx
= UINT32_MAX
;
190 uint32_t subpass_attachment_count
= 0;
191 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
192 subpass_attachment_count
+= val_num_subpass_attachments(&pCreateInfo
->pSubpasses
[i
]);
195 if (subpass_attachment_count
) {
196 pass
->subpass_attachments
=
197 vk_alloc2(&device
->alloc
, pAllocator
,
198 subpass_attachment_count
* sizeof(struct val_subpass_attachment
), 8,
199 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
200 if (pass
->subpass_attachments
== NULL
) {
201 vk_free2(&device
->alloc
, pAllocator
, pass
);
202 return vk_error(device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
205 pass
->subpass_attachments
= NULL
;
207 struct val_subpass_attachment
*p
= pass
->subpass_attachments
;
208 for (uint32_t i
= 0; i
< pCreateInfo
->subpassCount
; i
++) {
209 const VkSubpassDescription
*desc
= &pCreateInfo
->pSubpasses
[i
];
210 struct val_subpass
*subpass
= &pass
->subpasses
[i
];
212 subpass
->input_count
= desc
->inputAttachmentCount
;
213 subpass
->color_count
= desc
->colorAttachmentCount
;
214 subpass
->attachment_count
= val_num_subpass_attachments(desc
);
215 subpass
->attachments
= p
;
217 if (desc
->inputAttachmentCount
> 0) {
218 subpass
->input_attachments
= p
;
219 p
+= desc
->inputAttachmentCount
;
221 for (uint32_t j
= 0; j
< desc
->inputAttachmentCount
; j
++) {
222 subpass
->input_attachments
[j
] = (struct val_subpass_attachment
) {
223 .attachment
= desc
->pInputAttachments
[j
].attachment
,
224 .layout
= desc
->pInputAttachments
[j
].layout
,
229 if (desc
->colorAttachmentCount
> 0) {
230 subpass
->color_attachments
= p
;
231 p
+= desc
->colorAttachmentCount
;
233 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
234 subpass
->color_attachments
[j
] = (struct val_subpass_attachment
) {
235 .attachment
= desc
->pColorAttachments
[j
].attachment
,
236 .layout
= desc
->pColorAttachments
[j
].layout
,
241 if (desc
->pResolveAttachments
) {
242 subpass
->resolve_attachments
= p
;
243 p
+= desc
->colorAttachmentCount
;
245 for (uint32_t j
= 0; j
< desc
->colorAttachmentCount
; j
++) {
246 subpass
->resolve_attachments
[j
] = (struct val_subpass_attachment
) {
247 .attachment
= desc
->pResolveAttachments
[j
].attachment
,
248 .layout
= desc
->pResolveAttachments
[j
].layout
,
253 if (desc
->pDepthStencilAttachment
) {
254 subpass
->depth_stencil_attachment
= p
++;
256 *subpass
->depth_stencil_attachment
= (struct val_subpass_attachment
) {
257 .attachment
= desc
->pDepthStencilAttachment
->attachment
,
258 .layout
= desc
->pDepthStencilAttachment
->layout
,
263 val_render_pass_compile(pass
);
264 *pRenderPass
= val_render_pass_to_handle(pass
);
269 void val_DestroyRenderPass(
272 const VkAllocationCallbacks
* pAllocator
)
274 VAL_FROM_HANDLE(val_device
, device
, _device
);
275 VAL_FROM_HANDLE(val_render_pass
, pass
, _pass
);
279 vk_object_base_finish(&pass
->base
);
280 vk_free2(&device
->alloc
, pAllocator
, pass
->subpass_attachments
);
281 vk_free2(&device
->alloc
, pAllocator
, pass
);
284 void val_GetRenderAreaGranularity(
286 VkRenderPass renderPass
,
287 VkExtent2D
* pGranularity
)
289 *pGranularity
= (VkExtent2D
) { 1, 1 };