vk/meta: Save/restore more stuff in cmd_buffer_restore
[mesa.git] / src / vulkan / meta.c
1 /*
2 * Copyright © 2015 Intel Corporation
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 <assert.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include "private.h"
31
32 #define GLSL(src) "#version 330\n" #src
33
34 static void
35 anv_device_init_meta_clear_state(struct anv_device *device)
36 {
37 VkPipelineIaStateCreateInfo ia_create_info = {
38 .sType = VK_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO,
39 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
40 .disableVertexReuse = false,
41 .primitiveRestartEnable = false,
42 .primitiveRestartIndex = 0
43 };
44
45 /* We don't use a vertex shader for clearing, but instead build and pass
46 * the VUEs directly to the rasterization backend.
47 */
48 static const char fs_source[] = GLSL(
49 out vec4 f_color;
50 flat in vec4 v_color;
51 void main()
52 {
53 f_color = v_color;
54 });
55
56 VkShader fs;
57 vkCreateShader((VkDevice) device,
58 &(VkShaderCreateInfo) {
59 .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
60 .codeSize = sizeof(fs_source),
61 .pCode = fs_source,
62 .flags = 0
63 },
64 &fs);
65
66 VkPipelineShaderStageCreateInfo fs_create_info = {
67 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
68 .pNext = &ia_create_info,
69 .shader = {
70 .stage = VK_SHADER_STAGE_FRAGMENT,
71 .shader = fs,
72 .linkConstBufferCount = 0,
73 .pLinkConstBufferInfo = NULL,
74 .pSpecializationInfo = NULL
75 }
76 };
77
78 /* We use instanced rendering to clear multiple render targets. We have two
79 * vertex buffers: the first vertex buffer holds per-vertex data and
80 * provides the vertices for the clear rectangle. The second one holds
81 * per-instance data, which consists of the VUE header (which selects the
82 * layer) and the color (Vulkan supports per-RT clear colors).
83 */
84 VkPipelineVertexInputCreateInfo vi_create_info = {
85 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_CREATE_INFO,
86 .pNext = &fs_create_info,
87 .bindingCount = 2,
88 .pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
89 {
90 .binding = 0,
91 .strideInBytes = 8,
92 .stepRate = VK_VERTEX_INPUT_STEP_RATE_VERTEX
93 },
94 {
95 .binding = 1,
96 .strideInBytes = 32,
97 .stepRate = VK_VERTEX_INPUT_STEP_RATE_INSTANCE
98 },
99 },
100 .attributeCount = 3,
101 .pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
102 {
103 /* VUE Header */
104 .location = 0,
105 .binding = 1,
106 .format = VK_FORMAT_R32G32B32A32_UINT,
107 .offsetInBytes = 0
108 },
109 {
110 /* Position */
111 .location = 1,
112 .binding = 0,
113 .format = VK_FORMAT_R32G32_SFLOAT,
114 .offsetInBytes = 0
115 },
116 {
117 /* Color */
118 .location = 2,
119 .binding = 1,
120 .format = VK_FORMAT_R32G32B32A32_SFLOAT,
121 .offsetInBytes = 16
122 }
123 }
124 };
125
126 VkPipelineRsStateCreateInfo rs_create_info = {
127 .sType = VK_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO,
128 .pNext = &vi_create_info,
129 .depthClipEnable = true,
130 .rasterizerDiscardEnable = false,
131 .fillMode = VK_FILL_MODE_SOLID,
132 .cullMode = VK_CULL_MODE_NONE,
133 .frontFace = VK_FRONT_FACE_CCW
134 };
135
136 anv_pipeline_create((VkDevice) device,
137 &(VkGraphicsPipelineCreateInfo) {
138 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
139 .pNext = &rs_create_info,
140 .flags = 0,
141 .layout = 0
142 },
143 &(struct anv_pipeline_create_info) {
144 .use_repclear = true,
145 .disable_viewport = true,
146 .use_rectlist = true
147 },
148 &device->clear_state.pipeline);
149
150 vkDestroyObject((VkDevice) device, VK_OBJECT_TYPE_SHADER, fs);
151
152 vkCreateDynamicRasterState((VkDevice) device,
153 &(VkDynamicRsStateCreateInfo) {
154 .sType = VK_STRUCTURE_TYPE_DYNAMIC_RS_STATE_CREATE_INFO,
155 },
156 &device->clear_state.rs_state);
157 }
158
159 struct anv_saved_state {
160 struct {
161 struct anv_buffer *buffer;
162 VkDeviceSize offset;
163 } vb[2];
164 struct anv_descriptor_set *dsets[1];
165 struct anv_pipeline *pipeline;
166 };
167
168 static void
169 anv_cmd_buffer_save(struct anv_cmd_buffer *cmd_buffer,
170 struct anv_saved_state *state)
171 {
172 memcpy(state->vb, cmd_buffer->vb, sizeof(state->vb));
173 memcpy(state->dsets, cmd_buffer->descriptor_sets, sizeof(state->dsets));
174 state->pipeline = cmd_buffer->pipeline;
175 }
176
177 static void
178 anv_cmd_buffer_restore(struct anv_cmd_buffer *cmd_buffer,
179 const struct anv_saved_state *state)
180 {
181 memcpy(cmd_buffer->vb, state->vb, sizeof(state->vb));
182 memcpy(cmd_buffer->descriptor_sets, state->dsets, sizeof(state->dsets));
183 cmd_buffer->pipeline = state->pipeline;
184
185 cmd_buffer->vb_dirty |= (1 << ARRAY_SIZE(state->vb)) - 1;
186 cmd_buffer->dirty |= ANV_CMD_BUFFER_PIPELINE_DIRTY |
187 ANV_CMD_BUFFER_DESCRIPTOR_SET_DIRTY;
188 }
189
190 void
191 anv_cmd_buffer_clear(struct anv_cmd_buffer *cmd_buffer,
192 struct anv_render_pass *pass)
193 {
194 struct anv_device *device = cmd_buffer->device;
195 struct anv_framebuffer *fb = cmd_buffer->framebuffer;
196 struct anv_saved_state saved_state;
197 struct anv_state state;
198 uint32_t size;
199
200 struct instance_data {
201 struct {
202 uint32_t Reserved;
203 uint32_t RTAIndex;
204 uint32_t ViewportIndex;
205 float PointWidth;
206 } vue_header;
207 float color[4];
208 } *instance_data;
209
210 const float vertex_data[] = {
211 /* Rect-list coordinates */
212 0.0, 0.0,
213 fb->width, 0.0,
214 fb->width, fb->height,
215
216 /* Align to 16 bytes */
217 0.0, 0.0,
218 };
219
220 size = sizeof(vertex_data) + pass->num_clear_layers * sizeof(instance_data[0]);
221 state = anv_state_stream_alloc(&cmd_buffer->surface_state_stream, size, 16);
222
223 memcpy(state.map, vertex_data, sizeof(vertex_data));
224 instance_data = state.map + sizeof(vertex_data);
225
226 for (uint32_t i = 0; i < pass->num_layers; i++) {
227 if (pass->layers[i].color_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
228 *instance_data++ = (struct instance_data) {
229 .vue_header = {
230 .RTAIndex = i,
231 .ViewportIndex = 0,
232 .PointWidth = 0.0
233 },
234 .color = {
235 pass->layers[i].clear_color.color.floatColor[0],
236 pass->layers[i].clear_color.color.floatColor[1],
237 pass->layers[i].clear_color.color.floatColor[2],
238 pass->layers[i].clear_color.color.floatColor[3],
239 }
240 };
241 }
242 }
243
244 struct anv_buffer vertex_buffer = {
245 .device = cmd_buffer->device,
246 .size = size,
247 .bo = &device->surface_state_block_pool.bo,
248 .offset = state.offset
249 };
250
251 anv_cmd_buffer_save(cmd_buffer, &saved_state);
252
253 vkCmdBindVertexBuffers((VkCmdBuffer) cmd_buffer, 0, 2,
254 (VkBuffer[]) {
255 (VkBuffer) &vertex_buffer,
256 (VkBuffer) &vertex_buffer
257 },
258 (VkDeviceSize[]) {
259 0,
260 sizeof(vertex_data)
261 });
262
263 if ((VkPipeline) cmd_buffer->pipeline != device->clear_state.pipeline)
264 vkCmdBindPipeline((VkCmdBuffer) cmd_buffer,
265 VK_PIPELINE_BIND_POINT_GRAPHICS, device->clear_state.pipeline);
266
267 /* We don't need anything here, only set if not already set. */
268 if (cmd_buffer->rs_state == NULL)
269 vkCmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
270 VK_STATE_BIND_POINT_RASTER,
271 device->clear_state.rs_state);
272
273 if (cmd_buffer->vp_state == NULL)
274 vkCmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
275 VK_STATE_BIND_POINT_VIEWPORT,
276 cmd_buffer->framebuffer->vp_state);
277
278 vkCmdDraw((VkCmdBuffer) cmd_buffer, 0, 3, 0, pass->num_clear_layers);
279
280 /* Restore API state */
281 anv_cmd_buffer_restore(cmd_buffer, &saved_state);
282
283 }
284
285 void VKAPI vkCmdCopyBuffer(
286 VkCmdBuffer cmdBuffer,
287 VkBuffer srcBuffer,
288 VkBuffer destBuffer,
289 uint32_t regionCount,
290 const VkBufferCopy* pRegions)
291 {
292 stub();
293 }
294
295 void VKAPI vkCmdCopyImage(
296 VkCmdBuffer cmdBuffer,
297 VkImage srcImage,
298 VkImageLayout srcImageLayout,
299 VkImage destImage,
300 VkImageLayout destImageLayout,
301 uint32_t regionCount,
302 const VkImageCopy* pRegions)
303 {
304 stub();
305 }
306
307 void VKAPI vkCmdBlitImage(
308 VkCmdBuffer cmdBuffer,
309 VkImage srcImage,
310 VkImageLayout srcImageLayout,
311 VkImage destImage,
312 VkImageLayout destImageLayout,
313 uint32_t regionCount,
314 const VkImageBlit* pRegions)
315 {
316 stub();
317 }
318
319 void VKAPI vkCmdCopyBufferToImage(
320 VkCmdBuffer cmdBuffer,
321 VkBuffer srcBuffer,
322 VkImage destImage,
323 VkImageLayout destImageLayout,
324 uint32_t regionCount,
325 const VkBufferImageCopy* pRegions)
326 {
327 stub();
328 }
329
330 void VKAPI vkCmdCopyImageToBuffer(
331 VkCmdBuffer cmdBuffer,
332 VkImage srcImage,
333 VkImageLayout srcImageLayout,
334 VkBuffer destBuffer,
335 uint32_t regionCount,
336 const VkBufferImageCopy* pRegions)
337 {
338 stub();
339 }
340
341 void VKAPI vkCmdCloneImageData(
342 VkCmdBuffer cmdBuffer,
343 VkImage srcImage,
344 VkImageLayout srcImageLayout,
345 VkImage destImage,
346 VkImageLayout destImageLayout)
347 {
348 stub();
349 }
350
351 void VKAPI vkCmdUpdateBuffer(
352 VkCmdBuffer cmdBuffer,
353 VkBuffer destBuffer,
354 VkDeviceSize destOffset,
355 VkDeviceSize dataSize,
356 const uint32_t* pData)
357 {
358 stub();
359 }
360
361 void VKAPI vkCmdFillBuffer(
362 VkCmdBuffer cmdBuffer,
363 VkBuffer destBuffer,
364 VkDeviceSize destOffset,
365 VkDeviceSize fillSize,
366 uint32_t data)
367 {
368 stub();
369 }
370
371 void VKAPI vkCmdClearColorImage(
372 VkCmdBuffer cmdBuffer,
373 VkImage image,
374 VkImageLayout imageLayout,
375 const VkClearColor* color,
376 uint32_t rangeCount,
377 const VkImageSubresourceRange* pRanges)
378 {
379 stub();
380 }
381
382 void VKAPI vkCmdClearDepthStencil(
383 VkCmdBuffer cmdBuffer,
384 VkImage image,
385 VkImageLayout imageLayout,
386 float depth,
387 uint32_t stencil,
388 uint32_t rangeCount,
389 const VkImageSubresourceRange* pRanges)
390 {
391 stub();
392 }
393
394 void VKAPI vkCmdResolveImage(
395 VkCmdBuffer cmdBuffer,
396 VkImage srcImage,
397 VkImageLayout srcImageLayout,
398 VkImage destImage,
399 VkImageLayout destImageLayout,
400 uint32_t regionCount,
401 const VkImageResolve* pRegions)
402 {
403 stub();
404 }
405
406 void
407 anv_device_init_meta(struct anv_device *device)
408 {
409 anv_device_init_meta_clear_state(device);
410 }