Suppress all build warnings
[platform/upstream/Vulkan-LoaderAndValidationLayers.git] / tests / vkrenderframework.cpp
1 /*
2  * Copyright (c) 2015-2016 The Khronos Group Inc.
3  * Copyright (c) 2015-2016 Valve Corporation
4  * Copyright (c) 2015-2016 LunarG, Inc.
5  * Copyright (c) 2015-2016 Google, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
20  * Author: Tony Barbour <tony@LunarG.com>
21  */
22
23 #include "vkrenderframework.h"
24
25 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
26 #define GET_DEVICE_PROC_ADDR(dev, entrypoint)                                                                                      \
27     {                                                                                                                              \
28         fp##entrypoint = (PFN_vk##entrypoint)vkGetDeviceProcAddr(dev, "vk" #entrypoint);                                           \
29         assert(fp##entrypoint != NULL);                                                                                            \
30     }
31
32 // TODO : These functions are duplicated is vk_layer_utils.cpp, share code
33 // Return true if format contains depth and stencil information
34 bool vk_format_is_depth_and_stencil(VkFormat format) {
35     bool is_ds = false;
36
37     switch (format) {
38     case VK_FORMAT_D16_UNORM_S8_UINT:
39     case VK_FORMAT_D24_UNORM_S8_UINT:
40     case VK_FORMAT_D32_SFLOAT_S8_UINT:
41         is_ds = true;
42         break;
43     default:
44         break;
45     }
46     return is_ds;
47 }
48
49 // Return true if format is a stencil-only format
50 bool vk_format_is_stencil_only(VkFormat format) { return (format == VK_FORMAT_S8_UINT); }
51
52 // Return true if format is a depth-only format
53 bool vk_format_is_depth_only(VkFormat format) {
54     bool is_depth = false;
55
56     switch (format) {
57     case VK_FORMAT_D16_UNORM:
58     case VK_FORMAT_X8_D24_UNORM_PACK32:
59     case VK_FORMAT_D32_SFLOAT:
60         is_depth = true;
61         break;
62     default:
63         break;
64     }
65
66     return is_depth;
67 }
68
69 VkRenderFramework::VkRenderFramework()
70     : inst(VK_NULL_HANDLE), m_device(NULL), m_commandPool(VK_NULL_HANDLE), m_commandBuffer(NULL), m_renderPass(VK_NULL_HANDLE),
71       m_framebuffer(VK_NULL_HANDLE), m_width(256.0), // default window width
72       m_height(256.0),                               // default window height
73       m_render_target_fmt(VK_FORMAT_R8G8B8A8_UNORM), m_depth_stencil_fmt(VK_FORMAT_UNDEFINED), m_clear_via_load_op(true),
74       m_depth_clear_color(1.0), m_stencil_clear_color(0), m_depthStencil(NULL), m_CreateDebugReportCallback(VK_NULL_HANDLE),
75       m_DestroyDebugReportCallback(VK_NULL_HANDLE), m_globalMsgCallback(VK_NULL_HANDLE), m_devMsgCallback(VK_NULL_HANDLE) {
76
77     memset(&m_renderPassBeginInfo, 0, sizeof(m_renderPassBeginInfo));
78     m_renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
79
80     // clear the back buffer to dark grey
81     m_clear_color.float32[0] = 0.25f;
82     m_clear_color.float32[1] = 0.25f;
83     m_clear_color.float32[2] = 0.25f;
84     m_clear_color.float32[3] = 0.0f;
85 }
86
87 VkRenderFramework::~VkRenderFramework() {}
88
89 void VkRenderFramework::InitFramework() {
90     std::vector<const char *> instance_layer_names;
91     std::vector<const char *> instance_extension_names;
92     std::vector<const char *> device_extension_names;
93     instance_extension_names.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
94     device_extension_names.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
95 #ifdef _WIN32
96     instance_extension_names.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
97 #endif
98 #ifdef VK_USE_PLATFORM_XCB_KHR
99     instance_extension_names.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
100 #endif
101     InitFramework(instance_layer_names, instance_extension_names, device_extension_names);
102 }
103
104 void VkRenderFramework::InitFramework(std::vector<const char *> instance_layer_names,
105                                       std::vector<const char *> instance_extension_names,
106                                       std::vector<const char *> device_extension_names, PFN_vkDebugReportCallbackEXT dbgFunction,
107                                       void *userData) {
108     VkInstanceCreateInfo instInfo = {};
109     std::vector<VkExtensionProperties> instance_extensions;
110     std::vector<VkExtensionProperties> device_extensions;
111     VkResult U_ASSERT_ONLY err;
112
113     /* TODO: Verify requested extensions are available */
114
115     instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
116     instInfo.pNext = NULL;
117     instInfo.pApplicationInfo = &app_info;
118     instInfo.enabledLayerCount = instance_layer_names.size();
119     instInfo.ppEnabledLayerNames = instance_layer_names.data();
120     instInfo.enabledExtensionCount = instance_extension_names.size();
121     instInfo.ppEnabledExtensionNames = instance_extension_names.data();
122     err = vkCreateInstance(&instInfo, NULL, &this->inst);
123     ASSERT_VK_SUCCESS(err);
124
125     err = vkEnumeratePhysicalDevices(inst, &this->gpu_count, NULL);
126     ASSERT_LE(this->gpu_count, ARRAY_SIZE(objs)) << "Too many gpus";
127     ASSERT_VK_SUCCESS(err);
128     err = vkEnumeratePhysicalDevices(inst, &this->gpu_count, objs);
129     ASSERT_VK_SUCCESS(err);
130     ASSERT_GE(this->gpu_count, (uint32_t)1) << "No GPU available";
131     if (dbgFunction) {
132         m_CreateDebugReportCallback =
133             (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(this->inst, "vkCreateDebugReportCallbackEXT");
134         ASSERT_NE(m_CreateDebugReportCallback, (PFN_vkCreateDebugReportCallbackEXT)NULL)
135             << "Did not get function pointer for CreateDebugReportCallback";
136         if (m_CreateDebugReportCallback) {
137             VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;
138             memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));
139             dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
140             dbgCreateInfo.flags =
141                 VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
142             dbgCreateInfo.pfnCallback = dbgFunction;
143             dbgCreateInfo.pUserData = userData;
144
145             err = m_CreateDebugReportCallback(this->inst, &dbgCreateInfo, NULL, &m_globalMsgCallback);
146             ASSERT_VK_SUCCESS(err);
147
148             m_DestroyDebugReportCallback =
149                 (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(this->inst, "vkDestroyDebugReportCallbackEXT");
150             ASSERT_NE(m_DestroyDebugReportCallback, (PFN_vkDestroyDebugReportCallbackEXT)NULL)
151                 << "Did not get function pointer for "
152                    "DestroyDebugReportCallback";
153             m_DebugReportMessage = (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(this->inst, "vkDebugReportMessageEXT");
154             ASSERT_NE(m_DebugReportMessage, (PFN_vkDebugReportMessageEXT)NULL)
155                 << "Did not get function pointer for DebugReportMessage";
156         }
157     }
158
159     /* TODO: Verify requested physical device extensions are available */
160     this->device_extension_names = device_extension_names;
161 }
162
163 void VkRenderFramework::ShutdownFramework() {
164     delete m_commandBuffer;
165     if (m_commandPool)
166         vkDestroyCommandPool(device(), m_commandPool, NULL);
167     if (m_framebuffer)
168         vkDestroyFramebuffer(device(), m_framebuffer, NULL);
169     if (m_renderPass)
170         vkDestroyRenderPass(device(), m_renderPass, NULL);
171
172     if (m_globalMsgCallback)
173         m_DestroyDebugReportCallback(this->inst, m_globalMsgCallback, NULL);
174     if (m_devMsgCallback)
175         m_DestroyDebugReportCallback(this->inst, m_devMsgCallback, NULL);
176
177     while (!m_renderTargets.empty()) {
178         vkDestroyImageView(device(), m_renderTargets.back()->targetView(m_render_target_fmt), NULL);
179         vkDestroyImage(device(), m_renderTargets.back()->image(), NULL);
180         vkFreeMemory(device(), m_renderTargets.back()->memory(), NULL);
181         m_renderTargets.pop_back();
182     }
183
184     delete m_depthStencil;
185
186     // reset the driver
187     delete m_device;
188     if (this->inst)
189         vkDestroyInstance(this->inst, NULL);
190 }
191
192 void VkRenderFramework::InitState(VkPhysicalDeviceFeatures *features) {
193     VkResult U_ASSERT_ONLY err;
194
195     m_device = new VkDeviceObj(0, objs[0], device_extension_names, features);
196     m_device->get_device_queue();
197
198     m_depthStencil = new VkDepthStencilObj(m_device);
199
200     m_render_target_fmt = VkTestFramework::GetFormat(inst, m_device);
201
202     m_lineWidth = 1.0f;
203
204     m_depthBiasConstantFactor = 0.0f;
205     m_depthBiasClamp = 0.0f;
206     m_depthBiasSlopeFactor = 0.0f;
207
208     m_blendConstants[0] = 1.0f;
209     m_blendConstants[1] = 1.0f;
210     m_blendConstants[2] = 1.0f;
211     m_blendConstants[3] = 1.0f;
212
213     m_minDepthBounds = 0.f;
214     m_maxDepthBounds = 1.f;
215
216     m_compareMask = 0xff;
217     m_writeMask = 0xff;
218     m_reference = 0;
219
220     VkCommandPoolCreateInfo cmd_pool_info;
221     cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, cmd_pool_info.pNext = NULL,
222     cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
223     cmd_pool_info.flags = 0, err = vkCreateCommandPool(device(), &cmd_pool_info, NULL, &m_commandPool);
224     assert(!err);
225
226     m_commandBuffer = new VkCommandBufferObj(m_device, m_commandPool);
227 }
228
229 void VkRenderFramework::InitViewport(float width, float height) {
230     VkViewport viewport;
231     VkRect2D scissor;
232     viewport.x = 0;
233     viewport.y = 0;
234     viewport.width = 1.f * width;
235     viewport.height = 1.f * height;
236     viewport.minDepth = 0.f;
237     viewport.maxDepth = 1.f;
238     m_viewports.push_back(viewport);
239
240     scissor.extent.width = (int32_t)width;
241     scissor.extent.height = (int32_t)height;
242     scissor.offset.x = 0;
243     scissor.offset.y = 0;
244     m_scissors.push_back(scissor);
245
246     m_width = width;
247     m_height = height;
248 }
249
250 void VkRenderFramework::InitViewport() { InitViewport(m_width, m_height); }
251 void VkRenderFramework::InitRenderTarget() { InitRenderTarget(1); }
252
253 void VkRenderFramework::InitRenderTarget(uint32_t targets) { InitRenderTarget(targets, NULL); }
254
255 void VkRenderFramework::InitRenderTarget(VkImageView *dsBinding) { InitRenderTarget(1, dsBinding); }
256
257 void VkRenderFramework::InitRenderTarget(uint32_t targets, VkImageView *dsBinding) {
258     std::vector<VkAttachmentDescription> attachments;
259     std::vector<VkAttachmentReference> color_references;
260     std::vector<VkImageView> bindings;
261     attachments.reserve(targets + 1); // +1 for dsBinding
262     color_references.reserve(targets);
263     bindings.reserve(targets + 1); // +1 for dsBinding
264
265     VkAttachmentDescription att = {};
266     att.format = m_render_target_fmt;
267     att.samples = VK_SAMPLE_COUNT_1_BIT;
268     att.loadOp = (m_clear_via_load_op) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
269     att.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
270     att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
271     att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
272     att.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
273     att.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
274
275     VkAttachmentReference ref = {};
276     ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
277
278     m_renderPassClearValues.clear();
279     VkClearValue clear = {};
280     clear.color = m_clear_color;
281
282     VkImageView bind = {};
283
284     for (uint32_t i = 0; i < targets; i++) {
285         attachments.push_back(att);
286
287         ref.attachment = i;
288         color_references.push_back(ref);
289
290         m_renderPassClearValues.push_back(clear);
291
292         VkImageObj *img = new VkImageObj(m_device);
293
294         VkFormatProperties props;
295
296         vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), m_render_target_fmt, &props);
297
298         if (props.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
299             img->init((uint32_t)m_width, (uint32_t)m_height, m_render_target_fmt,
300                       VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_LINEAR);
301         } else if (props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
302             img->init((uint32_t)m_width, (uint32_t)m_height, m_render_target_fmt,
303                       VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_OPTIMAL);
304         } else {
305             FAIL() << "Neither Linear nor Optimal allowed for render target";
306         }
307
308         m_renderTargets.push_back(img);
309         bind = img->targetView(m_render_target_fmt);
310         bindings.push_back(bind);
311     }
312
313     VkSubpassDescription subpass = {};
314     subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
315     subpass.flags = 0;
316     subpass.inputAttachmentCount = 0;
317     subpass.pInputAttachments = NULL;
318     subpass.colorAttachmentCount = targets;
319     subpass.pColorAttachments = color_references.data();
320     subpass.pResolveAttachments = NULL;
321
322     VkAttachmentReference ds_reference;
323     if (dsBinding) {
324         att.format = m_depth_stencil_fmt;
325         att.loadOp = (m_clear_via_load_op) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
326         ;
327         att.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
328         att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
329         att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
330         att.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
331         att.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
332         attachments.push_back(att);
333
334         clear.depthStencil.depth = m_depth_clear_color;
335         clear.depthStencil.stencil = m_stencil_clear_color;
336         m_renderPassClearValues.push_back(clear);
337
338         bindings.push_back(*dsBinding);
339
340         ds_reference.attachment = targets;
341         ds_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
342         subpass.pDepthStencilAttachment = &ds_reference;
343     } else {
344         subpass.pDepthStencilAttachment = NULL;
345     }
346
347     subpass.preserveAttachmentCount = 0;
348     subpass.pPreserveAttachments = NULL;
349
350     VkRenderPassCreateInfo rp_info = {};
351     rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
352     rp_info.attachmentCount = attachments.size();
353     rp_info.pAttachments = attachments.data();
354     rp_info.subpassCount = 1;
355     rp_info.pSubpasses = &subpass;
356
357     vkCreateRenderPass(device(), &rp_info, NULL, &m_renderPass);
358
359     // Create Framebuffer and RenderPass with color attachments and any
360     // depth/stencil attachment
361     VkFramebufferCreateInfo fb_info = {};
362     fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
363     fb_info.pNext = NULL;
364     fb_info.renderPass = m_renderPass;
365     fb_info.attachmentCount = bindings.size();
366     fb_info.pAttachments = bindings.data();
367     fb_info.width = (uint32_t)m_width;
368     fb_info.height = (uint32_t)m_height;
369     fb_info.layers = 1;
370
371     vkCreateFramebuffer(device(), &fb_info, NULL, &m_framebuffer);
372
373     m_renderPassBeginInfo.renderPass = m_renderPass;
374     m_renderPassBeginInfo.framebuffer = m_framebuffer;
375     m_renderPassBeginInfo.renderArea.extent.width = (int32_t)m_width;
376     m_renderPassBeginInfo.renderArea.extent.height = (int32_t)m_height;
377     m_renderPassBeginInfo.clearValueCount = m_renderPassClearValues.size();
378     m_renderPassBeginInfo.pClearValues = m_renderPassClearValues.data();
379 }
380
381 VkDeviceObj::VkDeviceObj(uint32_t id, VkPhysicalDevice obj) : vk_testing::Device(obj), id(id) {
382     init();
383
384     props = phy().properties();
385     queue_props = phy().queue_properties();
386 }
387
388 VkDeviceObj::VkDeviceObj(uint32_t id, VkPhysicalDevice obj, std::vector<const char *> &extension_names,
389                          VkPhysicalDeviceFeatures *features)
390     : vk_testing::Device(obj), id(id) {
391     init(extension_names, features);
392
393     props = phy().properties();
394     queue_props = phy().queue_properties();
395 }
396
397 void VkDeviceObj::get_device_queue() {
398     ASSERT_NE(true, graphics_queues().empty());
399     m_queue = graphics_queues()[0]->handle();
400 }
401
402 VkDescriptorSetObj::VkDescriptorSetObj(VkDeviceObj *device) : m_device(device), m_nextSlot(0) {}
403
404 VkDescriptorSetObj::~VkDescriptorSetObj() {
405     if (m_set) {
406         delete m_set;
407     }
408 }
409
410 int VkDescriptorSetObj::AppendDummy() {
411     /* request a descriptor but do not update it */
412     VkDescriptorSetLayoutBinding binding = {};
413     binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
414     binding.descriptorCount = 1;
415     binding.binding = m_layout_bindings.size();
416     binding.stageFlags = VK_SHADER_STAGE_ALL;
417     binding.pImmutableSamplers = NULL;
418
419     m_layout_bindings.push_back(binding);
420     m_type_counts[VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] += binding.descriptorCount;
421
422     return m_nextSlot++;
423 }
424
425 int VkDescriptorSetObj::AppendBuffer(VkDescriptorType type, VkConstantBufferObj &constantBuffer) {
426     assert(type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
427            type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER || type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC);
428     VkDescriptorSetLayoutBinding binding = {};
429     binding.descriptorType = type;
430     binding.descriptorCount = 1;
431     binding.binding = m_layout_bindings.size();
432     binding.stageFlags = VK_SHADER_STAGE_ALL;
433     binding.pImmutableSamplers = NULL;
434
435     m_layout_bindings.push_back(binding);
436     m_type_counts[type] += binding.descriptorCount;
437
438     m_writes.push_back(vk_testing::Device::write_descriptor_set(vk_testing::DescriptorSet(), m_nextSlot, 0, type, 1,
439                                                                 &constantBuffer.m_descriptorBufferInfo));
440
441     return m_nextSlot++;
442 }
443
444 int VkDescriptorSetObj::AppendSamplerTexture(VkSamplerObj *sampler, VkTextureObj *texture) {
445     VkDescriptorSetLayoutBinding binding = {};
446     binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
447     binding.descriptorCount = 1;
448     binding.binding = m_layout_bindings.size();
449     binding.stageFlags = VK_SHADER_STAGE_ALL;
450     binding.pImmutableSamplers = NULL;
451
452     m_layout_bindings.push_back(binding);
453     m_type_counts[VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] += binding.descriptorCount;
454     VkDescriptorImageInfo tmp = texture->m_imageInfo;
455     tmp.sampler = sampler->handle();
456     m_imageSamplerDescriptors.push_back(tmp);
457
458     m_writes.push_back(vk_testing::Device::write_descriptor_set(vk_testing::DescriptorSet(), m_nextSlot, 0,
459                                                                 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &tmp));
460
461     return m_nextSlot++;
462 }
463
464 VkPipelineLayout VkDescriptorSetObj::GetPipelineLayout() const { return m_pipeline_layout.handle(); }
465
466 VkDescriptorSet VkDescriptorSetObj::GetDescriptorSetHandle() const { return m_set->handle(); }
467
468 void VkDescriptorSetObj::CreateVKDescriptorSet(VkCommandBufferObj *commandBuffer) {
469
470     if (m_type_counts.size()) {
471         // create VkDescriptorPool
472         VkDescriptorPoolSize poolSize;
473         vector<VkDescriptorPoolSize> sizes;
474         for (auto it = m_type_counts.begin(); it != m_type_counts.end(); ++it) {
475             poolSize.descriptorCount = it->second;
476             poolSize.type = it->first;
477             sizes.push_back(poolSize);
478         }
479         VkDescriptorPoolCreateInfo pool = {};
480         pool.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
481         pool.poolSizeCount = sizes.size();
482         pool.maxSets = 1;
483         pool.pPoolSizes = sizes.data();
484         init(*m_device, pool);
485     }
486
487     // create VkDescriptorSetLayout
488     VkDescriptorSetLayoutCreateInfo layout = {};
489     layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
490     layout.bindingCount = m_layout_bindings.size();
491     layout.pBindings = m_layout_bindings.data();
492
493     m_layout.init(*m_device, layout);
494     vector<const vk_testing::DescriptorSetLayout *> layouts;
495     layouts.push_back(&m_layout);
496
497     // create VkPipelineLayout
498     VkPipelineLayoutCreateInfo pipeline_layout = {};
499     pipeline_layout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
500     pipeline_layout.setLayoutCount = layouts.size();
501     pipeline_layout.pSetLayouts = NULL;
502
503     m_pipeline_layout.init(*m_device, pipeline_layout, layouts);
504
505     if (m_type_counts.size()) {
506         // create VkDescriptorSet
507         m_set = alloc_sets(*m_device, m_layout);
508
509         // build the update array
510         size_t imageSamplerCount = 0;
511         for (std::vector<VkWriteDescriptorSet>::iterator it = m_writes.begin(); it != m_writes.end(); it++) {
512             it->dstSet = m_set->handle();
513             if (it->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
514                 it->pImageInfo = &m_imageSamplerDescriptors[imageSamplerCount++];
515         }
516
517         // do the updates
518         m_device->update_descriptor_sets(m_writes);
519     }
520 }
521
522 VkRenderpassObj::VkRenderpassObj(VkDeviceObj *dev) {
523     // Create a renderPass with a single color attachment
524     VkAttachmentReference attach = {};
525     attach.layout = VK_IMAGE_LAYOUT_GENERAL;
526
527     VkSubpassDescription subpass = {};
528     subpass.pColorAttachments = &attach;
529     subpass.colorAttachmentCount = 1;
530
531     VkRenderPassCreateInfo rpci = {};
532     rpci.subpassCount = 1;
533     rpci.pSubpasses = &subpass;
534     rpci.attachmentCount = 1;
535
536     VkAttachmentDescription attach_desc = {};
537     attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM;
538     attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
539     attach_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
540     attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
541
542     rpci.pAttachments = &attach_desc;
543     rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
544
545     device = dev->device();
546     vkCreateRenderPass(device, &rpci, NULL, &m_renderpass);
547 }
548
549 VkRenderpassObj::~VkRenderpassObj() { vkDestroyRenderPass(device, m_renderpass, NULL); }
550
551 VkImageObj::VkImageObj(VkDeviceObj *dev) {
552     m_device = dev;
553     m_descriptorImageInfo.imageView = VK_NULL_HANDLE;
554     m_descriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
555 }
556
557 void VkImageObj::ImageMemoryBarrier(VkCommandBufferObj *cmd_buf, VkImageAspectFlags aspect, VkFlags output_mask /*=
558             VK_ACCESS_HOST_WRITE_BIT |
559             VK_ACCESS_SHADER_WRITE_BIT |
560             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
561             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
562             VK_MEMORY_OUTPUT_COPY_BIT*/,
563                                     VkFlags input_mask /*=
564             VK_ACCESS_HOST_READ_BIT |
565             VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
566             VK_ACCESS_INDEX_READ_BIT |
567             VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
568             VK_ACCESS_UNIFORM_READ_BIT |
569             VK_ACCESS_SHADER_READ_BIT |
570             VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
571             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
572             VK_MEMORY_INPUT_COPY_BIT*/, VkImageLayout image_layout) {
573     const VkImageSubresourceRange subresourceRange = subresource_range(aspect, 0, 1, 0, 1);
574     VkImageMemoryBarrier barrier;
575     barrier = image_memory_barrier(output_mask, input_mask, layout(), image_layout, subresourceRange);
576
577     VkImageMemoryBarrier *pmemory_barrier = &barrier;
578
579     VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
580     VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
581
582     // write barrier to the command buffer
583     vkCmdPipelineBarrier(cmd_buf->handle(), src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, pmemory_barrier);
584 }
585
586 void VkImageObj::SetLayout(VkCommandBufferObj *cmd_buf, VkImageAspectFlags aspect, VkImageLayout image_layout) {
587     VkFlags src_mask, dst_mask;
588     const VkFlags all_cache_outputs = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
589                                       VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
590     const VkFlags all_cache_inputs = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_INDEX_READ_BIT |
591                                      VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT |
592                                      VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
593                                      VK_ACCESS_MEMORY_READ_BIT;
594
595     if (image_layout == m_descriptorImageInfo.imageLayout) {
596         return;
597     }
598
599     switch (image_layout) {
600     case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
601         if (m_descriptorImageInfo.imageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
602             src_mask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
603         else
604             src_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
605         dst_mask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT;
606         break;
607
608     case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
609         if (m_descriptorImageInfo.imageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
610             src_mask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
611         else if (m_descriptorImageInfo.imageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
612             src_mask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
613         else
614             src_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
615         dst_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
616         break;
617
618     case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
619         if (m_descriptorImageInfo.imageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
620             src_mask = VK_ACCESS_TRANSFER_WRITE_BIT;
621         else
622             src_mask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
623         dst_mask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_MEMORY_READ_BIT;
624         break;
625
626     case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
627         if (m_descriptorImageInfo.imageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
628             src_mask = VK_ACCESS_TRANSFER_READ_BIT;
629         else
630             src_mask = 0;
631         dst_mask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
632         break;
633
634     case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
635         dst_mask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
636         src_mask = all_cache_outputs;
637         break;
638
639     default:
640         src_mask = all_cache_outputs;
641         dst_mask = all_cache_inputs;
642         break;
643     }
644
645     if (m_descriptorImageInfo.imageLayout == VK_IMAGE_LAYOUT_UNDEFINED)
646         src_mask = 0;
647
648     ImageMemoryBarrier(cmd_buf, aspect, src_mask, dst_mask, image_layout);
649     m_descriptorImageInfo.imageLayout = image_layout;
650 }
651
652 void VkImageObj::SetLayout(VkImageAspectFlags aspect, VkImageLayout image_layout) {
653     VkResult U_ASSERT_ONLY err;
654
655     if (image_layout == m_descriptorImageInfo.imageLayout) {
656         return;
657     }
658
659     VkCommandPoolCreateInfo cmd_pool_info = {};
660     cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
661     cmd_pool_info.pNext = NULL;
662     cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
663     cmd_pool_info.flags = 0;
664     vk_testing::CommandPool pool(*m_device, cmd_pool_info);
665     VkCommandBufferObj cmd_buf(m_device, pool.handle());
666
667     /* Build command buffer to set image layout in the driver */
668     err = cmd_buf.BeginCommandBuffer();
669     assert(!err);
670
671     SetLayout(&cmd_buf, aspect, image_layout);
672
673     err = cmd_buf.EndCommandBuffer();
674     assert(!err);
675
676     cmd_buf.QueueCommandBuffer();
677 }
678
679 bool VkImageObj::IsCompatible(VkFlags usage, VkFlags features) {
680     if ((usage & VK_IMAGE_USAGE_SAMPLED_BIT) && !(features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
681         return false;
682
683     return true;
684 }
685
686 void VkImageObj::init_no_layout(uint32_t w, uint32_t h, VkFormat fmt, VkFlags usage, VkImageTiling requested_tiling,
687                                 VkMemoryPropertyFlags reqs) {
688
689     VkFormatProperties image_fmt;
690     VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
691
692     vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), fmt, &image_fmt);
693
694     if (requested_tiling == VK_IMAGE_TILING_LINEAR) {
695         if (IsCompatible(usage, image_fmt.linearTilingFeatures)) {
696             tiling = VK_IMAGE_TILING_LINEAR;
697         } else if (IsCompatible(usage, image_fmt.optimalTilingFeatures)) {
698             tiling = VK_IMAGE_TILING_OPTIMAL;
699         } else {
700             ASSERT_TRUE(false) << "Error: Cannot find requested tiling configuration";
701         }
702     } else if (IsCompatible(usage, image_fmt.optimalTilingFeatures)) {
703         tiling = VK_IMAGE_TILING_OPTIMAL;
704     } else if (IsCompatible(usage, image_fmt.linearTilingFeatures)) {
705         tiling = VK_IMAGE_TILING_LINEAR;
706     } else {
707         ASSERT_TRUE(false) << "Error: Cannot find requested tiling configuration";
708     }
709
710     VkImageCreateInfo imageCreateInfo = vk_testing::Image::create_info();
711     imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
712     imageCreateInfo.format = fmt;
713     imageCreateInfo.extent.width = w;
714     imageCreateInfo.extent.height = h;
715     imageCreateInfo.mipLevels = 1;
716     imageCreateInfo.tiling = tiling;
717     imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
718
719     layout(imageCreateInfo.initialLayout);
720     imageCreateInfo.usage = usage;
721
722     vk_testing::Image::init(*m_device, imageCreateInfo, reqs);
723 }
724
725 void VkImageObj::init(uint32_t w, uint32_t h, VkFormat fmt, VkFlags usage, VkImageTiling requested_tiling,
726                       VkMemoryPropertyFlags reqs) {
727
728     init_no_layout(w, h, fmt, usage, requested_tiling, reqs);
729
730     VkImageLayout newLayout;
731     if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
732         newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
733     else if (usage & VK_IMAGE_USAGE_SAMPLED_BIT)
734         newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
735     else
736         newLayout = m_descriptorImageInfo.imageLayout;
737
738     VkImageAspectFlags image_aspect = 0;
739     if (vk_format_is_depth_and_stencil(fmt)) {
740         image_aspect = VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
741     } else if (vk_format_is_depth_only(fmt)) {
742         image_aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
743     } else if (vk_format_is_stencil_only(fmt)) {
744         image_aspect = VK_IMAGE_ASPECT_STENCIL_BIT;
745     } else { // color
746         image_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
747     }
748     SetLayout(image_aspect, newLayout);
749 }
750
751 VkResult VkImageObj::CopyImage(VkImageObj &src_image) {
752     VkResult U_ASSERT_ONLY err;
753     VkImageLayout src_image_layout, dest_image_layout;
754
755     VkCommandPoolCreateInfo cmd_pool_info = {};
756     cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
757     cmd_pool_info.pNext = NULL;
758     cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
759     cmd_pool_info.flags = 0;
760     vk_testing::CommandPool pool(*m_device, cmd_pool_info);
761     VkCommandBufferObj cmd_buf(m_device, pool.handle());
762
763     /* Build command buffer to copy staging texture to usable texture */
764     err = cmd_buf.BeginCommandBuffer();
765     assert(!err);
766
767     /* TODO: Can we determine image aspect from image object? */
768     src_image_layout = src_image.layout();
769     src_image.SetLayout(&cmd_buf, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
770
771     dest_image_layout = (this->layout() == VK_IMAGE_LAYOUT_UNDEFINED) ? VK_IMAGE_LAYOUT_GENERAL : this->layout();
772     this->SetLayout(&cmd_buf, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
773
774     VkImageCopy copy_region = {};
775     copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
776     copy_region.srcSubresource.baseArrayLayer = 0;
777     copy_region.srcSubresource.mipLevel = 0;
778     copy_region.srcSubresource.layerCount = 1;
779     copy_region.srcOffset.x = 0;
780     copy_region.srcOffset.y = 0;
781     copy_region.srcOffset.z = 0;
782     copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
783     copy_region.dstSubresource.baseArrayLayer = 0;
784     copy_region.dstSubresource.mipLevel = 0;
785     copy_region.dstSubresource.layerCount = 1;
786     copy_region.dstOffset.x = 0;
787     copy_region.dstOffset.y = 0;
788     copy_region.dstOffset.z = 0;
789     copy_region.extent = src_image.extent();
790
791     vkCmdCopyImage(cmd_buf.handle(), src_image.handle(), src_image.layout(), handle(), layout(), 1, &copy_region);
792
793     src_image.SetLayout(&cmd_buf, VK_IMAGE_ASPECT_COLOR_BIT, src_image_layout);
794
795     this->SetLayout(&cmd_buf, VK_IMAGE_ASPECT_COLOR_BIT, dest_image_layout);
796
797     err = cmd_buf.EndCommandBuffer();
798     assert(!err);
799
800     cmd_buf.QueueCommandBuffer();
801
802     return VK_SUCCESS;
803 }
804
805 VkTextureObj::VkTextureObj(VkDeviceObj *device, uint32_t *colors) : VkImageObj(device) {
806     m_device = device;
807     const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
808     uint32_t tex_colors[2] = {0xffff0000, 0xff00ff00};
809     void *data;
810     uint32_t x, y;
811     VkImageObj stagingImage(device);
812     VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
813
814     stagingImage.init(16, 16, tex_format, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_TILING_LINEAR,
815                       reqs);
816     VkSubresourceLayout layout = stagingImage.subresource_layout(subresource(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0));
817
818     if (colors == NULL)
819         colors = tex_colors;
820
821     memset(&m_imageInfo, 0, sizeof(m_imageInfo));
822
823     VkImageViewCreateInfo view = {};
824     view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
825     view.pNext = NULL;
826     view.image = VK_NULL_HANDLE;
827     view.viewType = VK_IMAGE_VIEW_TYPE_2D;
828     view.format = tex_format;
829     view.components.r = VK_COMPONENT_SWIZZLE_R;
830     view.components.g = VK_COMPONENT_SWIZZLE_G;
831     view.components.b = VK_COMPONENT_SWIZZLE_B;
832     view.components.a = VK_COMPONENT_SWIZZLE_A;
833     view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
834     view.subresourceRange.baseMipLevel = 0;
835     view.subresourceRange.levelCount = 1;
836     view.subresourceRange.baseArrayLayer = 0;
837     view.subresourceRange.layerCount = 1;
838
839     /* create image */
840     init(16, 16, tex_format, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL);
841     stagingImage.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_GENERAL);
842
843     /* create image view */
844     view.image = handle();
845     m_textureView.init(*m_device, view);
846     m_imageInfo.imageView = m_textureView.handle();
847
848     data = stagingImage.MapMemory();
849
850     for (y = 0; y < extent().height; y++) {
851         uint32_t *row = (uint32_t *)((char *)data + layout.rowPitch * y);
852         for (x = 0; x < extent().width; x++)
853             row[x] = colors[(x & 1) ^ (y & 1)];
854     }
855     stagingImage.UnmapMemory();
856     stagingImage.SetLayout(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
857     VkImageObj::CopyImage(stagingImage);
858 }
859
860 VkSamplerObj::VkSamplerObj(VkDeviceObj *device) {
861     m_device = device;
862
863     VkSamplerCreateInfo samplerCreateInfo;
864     memset(&samplerCreateInfo, 0, sizeof(samplerCreateInfo));
865     samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
866     samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
867     samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
868     samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
869     samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
870     samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
871     samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
872     samplerCreateInfo.mipLodBias = 0.0;
873     samplerCreateInfo.anisotropyEnable = VK_FALSE;
874     samplerCreateInfo.maxAnisotropy = 1;
875     samplerCreateInfo.compareOp = VK_COMPARE_OP_NEVER;
876     samplerCreateInfo.minLod = 0.0;
877     samplerCreateInfo.maxLod = 0.0;
878     samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
879     samplerCreateInfo.unnormalizedCoordinates = VK_FALSE;
880
881     init(*m_device, samplerCreateInfo);
882 }
883
884 /*
885  * Basic ConstantBuffer constructor. Then use create methods to fill in the
886  * details.
887  */
888 VkConstantBufferObj::VkConstantBufferObj(VkDeviceObj *device, VkBufferUsageFlags usage) {
889     m_device = device;
890     m_commandBuffer = 0;
891
892     memset(&m_descriptorBufferInfo, 0, sizeof(m_descriptorBufferInfo));
893
894     // Special case for usages outside of original limits of framework
895     if ((VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) != usage) {
896         init_no_mem(*m_device, create_info(0, usage));
897     }
898 }
899
900 VkConstantBufferObj::~VkConstantBufferObj() {
901     // TODO: Should we call QueueRemoveMemReference for the constant buffer
902     // memory here?
903     if (m_commandBuffer) {
904         delete m_commandBuffer;
905         delete m_commandPool;
906     }
907 }
908
909 VkConstantBufferObj::VkConstantBufferObj(VkDeviceObj *device, int constantCount, int constantSize, const void *data,
910                                          VkBufferUsageFlags usage) {
911     m_device = device;
912     m_commandBuffer = 0;
913
914     memset(&m_descriptorBufferInfo, 0, sizeof(m_descriptorBufferInfo));
915     m_numVertices = constantCount;
916     m_stride = constantSize;
917
918     VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
919     const VkDeviceSize allocationSize = static_cast<VkDeviceSize>(constantCount * constantSize);
920
921     if ((VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT) == usage) {
922         init_as_src_and_dst(*m_device, allocationSize, reqs);
923     } else {
924         init(*m_device, create_info(allocationSize, usage), reqs);
925     }
926
927     void *pData = memory().map();
928     memcpy(pData, data, static_cast<size_t>(allocationSize));
929     memory().unmap();
930
931     /*
932      * Constant buffers are going to be used as vertex input buffers
933      * or as shader uniform buffers. So, we'll create the shaderbuffer
934      * descriptor here so it's ready if needed.
935      */
936     this->m_descriptorBufferInfo.buffer = handle();
937     this->m_descriptorBufferInfo.offset = 0;
938     this->m_descriptorBufferInfo.range = allocationSize;
939 }
940
941 void VkConstantBufferObj::Bind(VkCommandBuffer commandBuffer, VkDeviceSize offset, uint32_t binding) {
942     vkCmdBindVertexBuffers(commandBuffer, binding, 1, &handle(), &offset);
943 }
944
945 void VkConstantBufferObj::BufferMemoryBarrier(VkFlags srcAccessMask /*=
946             VK_ACCESS_HOST_WRITE_BIT |
947             VK_ACCESS_SHADER_WRITE_BIT |
948             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
949             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
950             VK_MEMORY_OUTPUT_COPY_BIT*/, VkFlags dstAccessMask /*=
951             VK_ACCESS_HOST_READ_BIT |
952             VK_ACCESS_INDIRECT_COMMAND_READ_BIT |
953             VK_ACCESS_INDEX_READ_BIT |
954             VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
955             VK_ACCESS_UNIFORM_READ_BIT |
956             VK_ACCESS_SHADER_READ_BIT |
957             VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
958             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
959             VK_MEMORY_INPUT_COPY_BIT*/) {
960     VkResult err = VK_SUCCESS;
961
962     if (!m_commandBuffer) {
963         m_fence.init(*m_device, vk_testing::Fence::create_info());
964         VkCommandPoolCreateInfo cmd_pool_info = {};
965         cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
966         cmd_pool_info.pNext = NULL;
967         cmd_pool_info.queueFamilyIndex = m_device->graphics_queue_node_index_;
968         cmd_pool_info.flags = 0;
969         m_commandPool = new vk_testing::CommandPool(*m_device, cmd_pool_info);
970         m_commandBuffer = new VkCommandBufferObj(m_device, m_commandPool->handle());
971     } else {
972         m_device->wait(m_fence);
973     }
974
975     // open the command buffer
976     VkCommandBufferBeginInfo cmd_buf_info = {};
977     VkCommandBufferInheritanceInfo cmd_buf_hinfo = {};
978     cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
979     cmd_buf_info.pNext = NULL;
980     cmd_buf_info.flags = 0;
981     cmd_buf_info.pInheritanceInfo = &cmd_buf_hinfo;
982
983     cmd_buf_hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
984     cmd_buf_hinfo.pNext = NULL;
985     cmd_buf_hinfo.renderPass = VK_NULL_HANDLE;
986     cmd_buf_hinfo.subpass = 0;
987     cmd_buf_hinfo.framebuffer = VK_NULL_HANDLE;
988     cmd_buf_hinfo.occlusionQueryEnable = VK_FALSE;
989     cmd_buf_hinfo.queryFlags = 0;
990     cmd_buf_hinfo.pipelineStatistics = 0;
991
992     err = m_commandBuffer->BeginCommandBuffer(&cmd_buf_info);
993     ASSERT_VK_SUCCESS(err);
994
995     VkBufferMemoryBarrier memory_barrier = buffer_memory_barrier(srcAccessMask, dstAccessMask, 0, m_numVertices * m_stride);
996     VkBufferMemoryBarrier *pmemory_barrier = &memory_barrier;
997
998     VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
999     VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1000
1001     // write barrier to the command buffer
1002     m_commandBuffer->PipelineBarrier(src_stages, dest_stages, 0, 0, NULL, 1, pmemory_barrier, 0, NULL);
1003
1004     // finish recording the command buffer
1005     err = m_commandBuffer->EndCommandBuffer();
1006     ASSERT_VK_SUCCESS(err);
1007
1008     // submit the command buffer to the universal queue
1009     VkCommandBuffer bufferArray[1];
1010     bufferArray[0] = m_commandBuffer->GetBufferHandle();
1011     VkSubmitInfo submit_info;
1012     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1013     submit_info.pNext = NULL;
1014     submit_info.waitSemaphoreCount = 0;
1015     submit_info.pWaitSemaphores = NULL;
1016     submit_info.pWaitDstStageMask = NULL;
1017     submit_info.commandBufferCount = 1;
1018     submit_info.pCommandBuffers = bufferArray;
1019     submit_info.signalSemaphoreCount = 0;
1020     submit_info.pSignalSemaphores = NULL;
1021
1022     err = vkQueueSubmit(m_device->m_queue, 1, &submit_info, m_fence.handle());
1023     ASSERT_VK_SUCCESS(err);
1024 }
1025
1026 VkIndexBufferObj::VkIndexBufferObj(VkDeviceObj *device) : VkConstantBufferObj(device) {}
1027
1028 void VkIndexBufferObj::CreateAndInitBuffer(int numIndexes, VkIndexType indexType, const void *data) {
1029     m_numVertices = numIndexes;
1030     m_indexType = indexType;
1031     switch (indexType) {
1032     case VK_INDEX_TYPE_UINT16:
1033         m_stride = 2;
1034         break;
1035     case VK_INDEX_TYPE_UINT32:
1036         m_stride = 4;
1037         break;
1038     default:
1039         assert(!"unknown index type");
1040         m_stride = 2;
1041         break;
1042     }
1043
1044     const size_t allocationSize = numIndexes * m_stride;
1045     VkMemoryPropertyFlags reqs = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
1046     init_as_src_and_dst(*m_device, allocationSize, reqs);
1047
1048     void *pData = memory().map();
1049     memcpy(pData, data, allocationSize);
1050     memory().unmap();
1051
1052     // set up the descriptor for the constant buffer
1053     this->m_descriptorBufferInfo.buffer = handle();
1054     this->m_descriptorBufferInfo.offset = 0;
1055     this->m_descriptorBufferInfo.range = allocationSize;
1056 }
1057
1058 void VkIndexBufferObj::Bind(VkCommandBuffer commandBuffer, VkDeviceSize offset) {
1059     vkCmdBindIndexBuffer(commandBuffer, handle(), offset, m_indexType);
1060 }
1061
1062 VkIndexType VkIndexBufferObj::GetIndexType() { return m_indexType; }
1063
1064 VkPipelineShaderStageCreateInfo VkShaderObj::GetStageCreateInfo() const {
1065     VkPipelineShaderStageCreateInfo stageInfo = {};
1066
1067     stageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1068     stageInfo.stage = m_stage;
1069     stageInfo.module = handle();
1070     stageInfo.pName = m_name;
1071
1072     return stageInfo;
1073 }
1074
1075 VkShaderObj::VkShaderObj(VkDeviceObj *device, const char *shader_code, VkShaderStageFlagBits stage, VkRenderFramework *framework,
1076                          char const *name) {
1077     VkResult U_ASSERT_ONLY err = VK_SUCCESS;
1078     std::vector<unsigned int> spv;
1079     VkShaderModuleCreateInfo moduleCreateInfo;
1080     size_t shader_len;
1081
1082     m_stage = stage;
1083     m_device = device;
1084     m_name = name;
1085
1086     moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
1087     moduleCreateInfo.pNext = NULL;
1088
1089     if (framework->m_use_glsl) {
1090
1091         shader_len = strlen(shader_code);
1092         moduleCreateInfo.codeSize = 3 * sizeof(uint32_t) + shader_len + 1;
1093         moduleCreateInfo.pCode = (uint32_t *)malloc(moduleCreateInfo.codeSize);
1094         moduleCreateInfo.flags = 0;
1095
1096         /* try version 0 first: VkShaderStage followed by GLSL */
1097         ((uint32_t *)moduleCreateInfo.pCode)[0] = ICD_SPV_MAGIC;
1098         ((uint32_t *)moduleCreateInfo.pCode)[1] = 0;
1099         ((uint32_t *)moduleCreateInfo.pCode)[2] = stage;
1100         memcpy(((uint32_t *)moduleCreateInfo.pCode + 3), shader_code, shader_len + 1);
1101
1102     } else {
1103
1104         // Use Reference GLSL to SPV compiler
1105         framework->GLSLtoSPV(stage, shader_code, spv);
1106         moduleCreateInfo.pCode = spv.data();
1107         moduleCreateInfo.codeSize = spv.size() * sizeof(unsigned int);
1108         moduleCreateInfo.flags = 0;
1109     }
1110
1111     err = init_try(*m_device, moduleCreateInfo);
1112     assert(VK_SUCCESS == err);
1113 }
1114
1115 VkPipelineObj::VkPipelineObj(VkDeviceObj *device) {
1116     m_device = device;
1117
1118     m_vi_state.pNext = VK_NULL_HANDLE;
1119     m_vi_state.flags = 0;
1120     m_vi_state.vertexBindingDescriptionCount = 0;
1121     m_vi_state.pVertexBindingDescriptions = VK_NULL_HANDLE;
1122     m_vi_state.vertexAttributeDescriptionCount = 0;
1123     m_vi_state.pVertexAttributeDescriptions = VK_NULL_HANDLE;
1124
1125     m_vertexBufferCount = 0;
1126
1127     m_ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
1128     m_ia_state.pNext = VK_NULL_HANDLE;
1129     m_ia_state.flags = 0;
1130     m_ia_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1131     m_ia_state.primitiveRestartEnable = VK_FALSE;
1132
1133     m_rs_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1134     m_rs_state.pNext = VK_NULL_HANDLE;
1135     m_rs_state.flags = 0;
1136     m_rs_state.depthClampEnable = VK_TRUE;
1137     m_rs_state.rasterizerDiscardEnable = VK_FALSE;
1138     m_rs_state.polygonMode = VK_POLYGON_MODE_FILL;
1139     m_rs_state.cullMode = VK_CULL_MODE_BACK_BIT;
1140     m_rs_state.frontFace = VK_FRONT_FACE_CLOCKWISE;
1141     m_rs_state.depthBiasEnable = VK_FALSE;
1142     m_rs_state.lineWidth = 1.0f;
1143     m_rs_state.depthBiasConstantFactor = 0.0f;
1144     m_rs_state.depthBiasClamp = 0.0f;
1145     m_rs_state.depthBiasSlopeFactor = 0.0f;
1146
1147     memset(&m_cb_state, 0, sizeof(m_cb_state));
1148     m_cb_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1149     m_cb_state.pNext = VK_NULL_HANDLE;
1150     m_cb_state.logicOp = VK_LOGIC_OP_COPY;
1151     m_cb_state.blendConstants[0] = 1.0f;
1152     m_cb_state.blendConstants[1] = 1.0f;
1153     m_cb_state.blendConstants[2] = 1.0f;
1154     m_cb_state.blendConstants[3] = 1.0f;
1155
1156     m_ms_state.pNext = VK_NULL_HANDLE;
1157     m_ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1158     m_ms_state.flags = 0;
1159     m_ms_state.pSampleMask = NULL;
1160     m_ms_state.alphaToCoverageEnable = VK_FALSE;
1161     m_ms_state.alphaToOneEnable = VK_FALSE;
1162     m_ms_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
1163     m_ms_state.minSampleShading = 0;
1164     m_ms_state.sampleShadingEnable = 0;
1165
1166     m_vp_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
1167     m_vp_state.pNext = VK_NULL_HANDLE;
1168     m_vp_state.flags = 0;
1169     m_vp_state.viewportCount = 1;
1170     m_vp_state.scissorCount = 1;
1171     m_vp_state.pViewports = NULL;
1172     m_vp_state.pScissors = NULL;
1173
1174     m_ds_state = nullptr;
1175 };
1176
1177 void VkPipelineObj::AddShader(VkShaderObj *shader) { m_shaderObjs.push_back(shader); }
1178
1179 void VkPipelineObj::AddVertexInputAttribs(VkVertexInputAttributeDescription *vi_attrib, uint32_t count) {
1180     m_vi_state.pVertexAttributeDescriptions = vi_attrib;
1181     m_vi_state.vertexAttributeDescriptionCount = count;
1182 }
1183
1184 void VkPipelineObj::AddVertexInputBindings(VkVertexInputBindingDescription *vi_binding, uint32_t count) {
1185     m_vi_state.pVertexBindingDescriptions = vi_binding;
1186     m_vi_state.vertexBindingDescriptionCount = count;
1187 }
1188
1189 void VkPipelineObj::AddColorAttachment(uint32_t binding, const VkPipelineColorBlendAttachmentState *att) {
1190     if (binding + 1 > m_colorAttachments.size()) {
1191         m_colorAttachments.resize(binding + 1);
1192     }
1193     m_colorAttachments[binding] = *att;
1194 }
1195
1196 void VkPipelineObj::SetDepthStencil(const VkPipelineDepthStencilStateCreateInfo *ds_state) {
1197     m_ds_state = ds_state;
1198 }
1199
1200 void VkPipelineObj::SetViewport(const vector<VkViewport> viewports) {
1201     m_viewports = viewports;
1202     // If we explicitly set a null viewport, pass it through to create info
1203     // but preserve viewportCount because it musn't change
1204     if (m_viewports.size() == 0) {
1205         m_vp_state.pViewports = nullptr;
1206     }
1207 }
1208
1209 void VkPipelineObj::SetScissor(const vector<VkRect2D> scissors) {
1210     m_scissors = scissors;
1211     // If we explicitly set a null scissors, pass it through to create info
1212     // but preserve viewportCount because it musn't change
1213     if (m_scissors.size() == 0) {
1214         m_vp_state.pScissors = nullptr;
1215     }
1216 }
1217
1218 void VkPipelineObj::MakeDynamic(VkDynamicState state) {
1219     /* Only add a state once */
1220     for (auto it = m_dynamic_state_enables.begin(); it != m_dynamic_state_enables.end(); it++) {
1221         if ((*it) == state)
1222             return;
1223     }
1224     m_dynamic_state_enables.push_back(state);
1225 }
1226
1227 void VkPipelineObj::SetMSAA(const VkPipelineMultisampleStateCreateInfo *ms_state) { m_ms_state = *ms_state; }
1228
1229 void VkPipelineObj::SetInputAssembly(const VkPipelineInputAssemblyStateCreateInfo *ia_state) { m_ia_state = *ia_state; }
1230
1231 void VkPipelineObj::SetRasterization(const VkPipelineRasterizationStateCreateInfo *rs_state) { m_rs_state = *rs_state; }
1232
1233 void VkPipelineObj::SetTessellation(const VkPipelineTessellationStateCreateInfo *te_state) { m_te_state = *te_state; }
1234
1235 VkResult VkPipelineObj::CreateVKPipeline(VkPipelineLayout layout, VkRenderPass render_pass) {
1236     VkGraphicsPipelineCreateInfo info = {};
1237     VkPipelineDynamicStateCreateInfo dsci = {};
1238
1239     info.stageCount = m_shaderObjs.size();
1240     info.pStages = new VkPipelineShaderStageCreateInfo[info.stageCount];
1241
1242     for (size_t i = 0; i < m_shaderObjs.size(); i++) {
1243         ((VkPipelineShaderStageCreateInfo *)info.pStages)[i] = m_shaderObjs[i]->GetStageCreateInfo();
1244     }
1245
1246     m_vi_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
1247     info.pVertexInputState = &m_vi_state;
1248
1249     m_ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
1250     info.pInputAssemblyState = &m_ia_state;
1251
1252     info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
1253     info.pNext = NULL;
1254     info.flags = 0;
1255     info.layout = layout;
1256
1257     m_cb_state.attachmentCount = m_colorAttachments.size();
1258     m_cb_state.pAttachments = m_colorAttachments.data();
1259
1260     if (m_viewports.size() > 0) {
1261         m_vp_state.viewportCount = m_viewports.size();
1262         m_vp_state.pViewports = m_viewports.data();
1263     } else {
1264         MakeDynamic(VK_DYNAMIC_STATE_VIEWPORT);
1265     }
1266
1267     if (m_scissors.size() > 0) {
1268         m_vp_state.scissorCount = m_scissors.size();
1269         m_vp_state.pScissors = m_scissors.data();
1270     } else {
1271         MakeDynamic(VK_DYNAMIC_STATE_SCISSOR);
1272     }
1273
1274     if (m_dynamic_state_enables.size() > 0) {
1275         dsci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
1276         dsci.dynamicStateCount = m_dynamic_state_enables.size();
1277         dsci.pDynamicStates = m_dynamic_state_enables.data();
1278         info.pDynamicState = &dsci;
1279     }
1280
1281     info.renderPass = render_pass;
1282     info.subpass = 0;
1283     info.pViewportState = &m_vp_state;
1284     info.pRasterizationState = &m_rs_state;
1285     info.pMultisampleState = &m_ms_state;
1286     info.pDepthStencilState = m_ds_state;
1287     info.pColorBlendState = &m_cb_state;
1288
1289     if (m_ia_state.topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) {
1290         m_te_state.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
1291         info.pTessellationState = &m_te_state;
1292     } else {
1293         info.pTessellationState = nullptr;
1294     }
1295
1296     return init_try(*m_device, info);
1297 }
1298
1299 VkCommandBufferObj::VkCommandBufferObj(VkDeviceObj *device, VkCommandPool pool) {
1300     m_device = device;
1301
1302     init(*device, vk_testing::CommandBuffer::create_info(pool));
1303 }
1304
1305 VkCommandBuffer VkCommandBufferObj::GetBufferHandle() { return handle(); }
1306
1307 VkResult VkCommandBufferObj::BeginCommandBuffer(VkCommandBufferBeginInfo *pInfo) {
1308     begin(pInfo);
1309     return VK_SUCCESS;
1310 }
1311
1312 VkResult VkCommandBufferObj::BeginCommandBuffer() {
1313     begin();
1314     return VK_SUCCESS;
1315 }
1316
1317 VkResult VkCommandBufferObj::EndCommandBuffer() {
1318     end();
1319     return VK_SUCCESS;
1320 }
1321
1322 void VkCommandBufferObj::PipelineBarrier(VkPipelineStageFlags src_stages, VkPipelineStageFlags dest_stages,
1323                                          VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount,
1324                                          const VkMemoryBarrier *pMemoryBarriers, uint32_t bufferMemoryBarrierCount,
1325                                          const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
1326                                          const VkImageMemoryBarrier *pImageMemoryBarriers) {
1327     vkCmdPipelineBarrier(handle(), src_stages, dest_stages, dependencyFlags, memoryBarrierCount, pMemoryBarriers,
1328                          bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
1329 }
1330
1331 void VkCommandBufferObj::ClearAllBuffers(VkClearColorValue clear_color, float depth_clear_color, uint32_t stencil_clear_color,
1332                                          VkDepthStencilObj *depthStencilObj) {
1333     uint32_t i;
1334     const VkFlags output_mask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1335                                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
1336     const VkFlags input_mask = 0;
1337
1338     // whatever we want to do, we do it to the whole buffer
1339     VkImageSubresourceRange srRange = {};
1340     srRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1341     srRange.baseMipLevel = 0;
1342     srRange.levelCount = VK_REMAINING_MIP_LEVELS;
1343     srRange.baseArrayLayer = 0;
1344     srRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
1345
1346     VkImageMemoryBarrier memory_barrier = {};
1347     memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1348     memory_barrier.srcAccessMask = output_mask;
1349     memory_barrier.dstAccessMask = input_mask;
1350     memory_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
1351     memory_barrier.subresourceRange = srRange;
1352     VkImageMemoryBarrier *pmemory_barrier = &memory_barrier;
1353
1354     VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1355     VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1356
1357     for (i = 0; i < m_renderTargets.size(); i++) {
1358         memory_barrier.image = m_renderTargets[i]->image();
1359         memory_barrier.oldLayout = m_renderTargets[i]->layout();
1360         vkCmdPipelineBarrier(handle(), src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, pmemory_barrier);
1361         m_renderTargets[i]->layout(memory_barrier.newLayout);
1362
1363         vkCmdClearColorImage(handle(), m_renderTargets[i]->image(), VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &srRange);
1364     }
1365
1366     if (depthStencilObj) {
1367         VkImageSubresourceRange dsRange = {};
1368         dsRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
1369         dsRange.baseMipLevel = 0;
1370         dsRange.levelCount = VK_REMAINING_MIP_LEVELS;
1371         dsRange.baseArrayLayer = 0;
1372         dsRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
1373
1374         // prepare the depth buffer for clear
1375
1376         memory_barrier.oldLayout = memory_barrier.newLayout;
1377         memory_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
1378         memory_barrier.image = depthStencilObj->handle();
1379         memory_barrier.subresourceRange = dsRange;
1380
1381         vkCmdPipelineBarrier(handle(), src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, pmemory_barrier);
1382
1383         VkClearDepthStencilValue clear_value = {depth_clear_color, stencil_clear_color};
1384         vkCmdClearDepthStencilImage(handle(), depthStencilObj->handle(), VK_IMAGE_LAYOUT_GENERAL, &clear_value, 1, &dsRange);
1385
1386         // prepare depth buffer for rendering
1387         memory_barrier.image = depthStencilObj->handle();
1388         memory_barrier.newLayout = memory_barrier.oldLayout;
1389         memory_barrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
1390         memory_barrier.subresourceRange = dsRange;
1391         vkCmdPipelineBarrier(handle(), src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, pmemory_barrier);
1392     }
1393 }
1394
1395 void VkCommandBufferObj::FillBuffer(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize fill_size, uint32_t data) {
1396     vkCmdFillBuffer(handle(), buffer, offset, fill_size, data);
1397 }
1398
1399 void VkCommandBufferObj::UpdateBuffer(VkBuffer buffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void *pData) {
1400     vkCmdUpdateBuffer(handle(), buffer, dstOffset, dataSize, pData);
1401 }
1402
1403 void VkCommandBufferObj::CopyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
1404                                    uint32_t regionCount, const VkImageCopy *pRegions) {
1405     vkCmdCopyImage(handle(), srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
1406 }
1407
1408 void VkCommandBufferObj::ResolveImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
1409                                       VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *pRegions) {
1410     vkCmdResolveImage(handle(), srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
1411 }
1412
1413 void VkCommandBufferObj::PrepareAttachments() {
1414     uint32_t i;
1415     const VkFlags output_mask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
1416                                 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
1417     const VkFlags input_mask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_INDEX_READ_BIT |
1418                                VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT |
1419                                VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
1420                                VK_ACCESS_MEMORY_READ_BIT;
1421
1422     VkImageSubresourceRange srRange = {};
1423     srRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1424     srRange.baseMipLevel = 0;
1425     srRange.levelCount = VK_REMAINING_MIP_LEVELS;
1426     srRange.baseArrayLayer = 0;
1427     srRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
1428
1429     VkImageMemoryBarrier memory_barrier = {};
1430     memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1431     memory_barrier.srcAccessMask = output_mask;
1432     memory_barrier.dstAccessMask = input_mask;
1433     memory_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1434     memory_barrier.subresourceRange = srRange;
1435     VkImageMemoryBarrier *pmemory_barrier = &memory_barrier;
1436
1437     VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1438     VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1439
1440     for (i = 0; i < m_renderTargets.size(); i++) {
1441         memory_barrier.image = m_renderTargets[i]->image();
1442         memory_barrier.oldLayout = m_renderTargets[i]->layout();
1443         vkCmdPipelineBarrier(handle(), src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, pmemory_barrier);
1444         m_renderTargets[i]->layout(memory_barrier.newLayout);
1445     }
1446 }
1447
1448 void VkCommandBufferObj::BeginRenderPass(const VkRenderPassBeginInfo &info) {
1449     vkCmdBeginRenderPass(handle(), &info, VK_SUBPASS_CONTENTS_INLINE);
1450 }
1451
1452 void VkCommandBufferObj::EndRenderPass() { vkCmdEndRenderPass(handle()); }
1453
1454 void VkCommandBufferObj::SetViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports) {
1455     vkCmdSetViewport(handle(), firstViewport, viewportCount, pViewports);
1456 }
1457
1458 void VkCommandBufferObj::SetScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors) {
1459     vkCmdSetScissor(handle(), firstScissor, scissorCount, pScissors);
1460 }
1461
1462 void VkCommandBufferObj::SetLineWidth(float lineWidth) { vkCmdSetLineWidth(handle(), lineWidth); }
1463
1464 void VkCommandBufferObj::SetDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) {
1465     vkCmdSetDepthBias(handle(), depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
1466 }
1467
1468 void VkCommandBufferObj::SetBlendConstants(const float blendConstants[4]) { vkCmdSetBlendConstants(handle(), blendConstants); }
1469
1470 void VkCommandBufferObj::SetDepthBounds(float minDepthBounds, float maxDepthBounds) {
1471     vkCmdSetDepthBounds(handle(), minDepthBounds, maxDepthBounds);
1472 }
1473
1474 void VkCommandBufferObj::SetStencilReadMask(VkStencilFaceFlags faceMask, uint32_t compareMask) {
1475     vkCmdSetStencilCompareMask(handle(), faceMask, compareMask);
1476 }
1477
1478 void VkCommandBufferObj::SetStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask) {
1479     vkCmdSetStencilWriteMask(handle(), faceMask, writeMask);
1480 }
1481
1482 void VkCommandBufferObj::SetStencilReference(VkStencilFaceFlags faceMask, uint32_t reference) {
1483     vkCmdSetStencilReference(handle(), faceMask, reference);
1484 }
1485
1486 void VkCommandBufferObj::AddRenderTarget(VkImageObj *renderTarget) { m_renderTargets.push_back(renderTarget); }
1487
1488 void VkCommandBufferObj::DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset,
1489                                      uint32_t firstInstance) {
1490     vkCmdDrawIndexed(handle(), indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
1491 }
1492
1493 void VkCommandBufferObj::Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
1494     vkCmdDraw(handle(), vertexCount, instanceCount, firstVertex, firstInstance);
1495 }
1496
1497 void VkCommandBufferObj::QueueCommandBuffer(bool checkSuccess) {
1498     VkFence nullFence = {VK_NULL_HANDLE};
1499     QueueCommandBuffer(nullFence, checkSuccess);
1500 }
1501
1502 void VkCommandBufferObj::QueueCommandBuffer(VkFence fence, bool checkSuccess) {
1503     VkResult err = VK_SUCCESS;
1504
1505     // submit the command buffer to the universal queue
1506     VkSubmitInfo submit_info;
1507     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1508     submit_info.pNext = NULL;
1509     submit_info.waitSemaphoreCount = 0;
1510     submit_info.pWaitSemaphores = NULL;
1511     submit_info.pWaitDstStageMask = NULL;
1512     submit_info.commandBufferCount = 1;
1513     submit_info.pCommandBuffers = &handle();
1514     submit_info.signalSemaphoreCount = 0;
1515     submit_info.pSignalSemaphores = NULL;
1516
1517     err = vkQueueSubmit(m_device->m_queue, 1, &submit_info, fence);
1518     if (checkSuccess) {
1519         ASSERT_VK_SUCCESS(err);
1520     }
1521
1522     err = vkQueueWaitIdle(m_device->m_queue);
1523     if (checkSuccess) {
1524         ASSERT_VK_SUCCESS(err);
1525     }
1526
1527     // Wait for work to finish before cleaning up.
1528     vkDeviceWaitIdle(m_device->device());
1529 }
1530
1531 void VkCommandBufferObj::BindPipeline(VkPipelineObj &pipeline) {
1532     vkCmdBindPipeline(handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.handle());
1533 }
1534
1535 void VkCommandBufferObj::BindDescriptorSet(VkDescriptorSetObj &descriptorSet) {
1536     VkDescriptorSet set_obj = descriptorSet.GetDescriptorSetHandle();
1537
1538     // bind pipeline, vertex buffer (descriptor set) and WVP (dynamic buffer
1539     // view)
1540     vkCmdBindDescriptorSets(handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, descriptorSet.GetPipelineLayout(), 0, 1, &set_obj, 0, NULL);
1541 }
1542
1543 void VkCommandBufferObj::BindIndexBuffer(VkIndexBufferObj *indexBuffer, VkDeviceSize offset) {
1544     vkCmdBindIndexBuffer(handle(), indexBuffer->handle(), offset, indexBuffer->GetIndexType());
1545 }
1546
1547 void VkCommandBufferObj::BindVertexBuffer(VkConstantBufferObj *vertexBuffer, VkDeviceSize offset, uint32_t binding) {
1548     vkCmdBindVertexBuffers(handle(), binding, 1, &vertexBuffer->handle(), &offset);
1549 }
1550
1551 bool VkDepthStencilObj::Initialized() { return m_initialized; }
1552 VkDepthStencilObj::VkDepthStencilObj(VkDeviceObj *device) : VkImageObj(device) { m_initialized = false; }
1553
1554 VkImageView *VkDepthStencilObj::BindInfo() { return &m_attachmentBindInfo; }
1555
1556 void VkDepthStencilObj::Init(VkDeviceObj *device, int32_t width, int32_t height, VkFormat format, VkImageUsageFlags usage) {
1557
1558     VkImageViewCreateInfo view_info = {};
1559
1560     m_device = device;
1561     m_initialized = true;
1562     m_depth_stencil_fmt = format;
1563
1564     /* create image */
1565     init(width, height, m_depth_stencil_fmt, usage, VK_IMAGE_TILING_OPTIMAL);
1566
1567     VkImageAspectFlags aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
1568     if (vk_format_is_depth_and_stencil(format))
1569         aspect |= VK_IMAGE_ASPECT_STENCIL_BIT;
1570
1571     SetLayout(aspect, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
1572
1573     view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1574     view_info.pNext = NULL;
1575     view_info.image = VK_NULL_HANDLE;
1576     view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
1577     view_info.subresourceRange.baseMipLevel = 0;
1578     view_info.subresourceRange.levelCount = 1;
1579     view_info.subresourceRange.baseArrayLayer = 0;
1580     view_info.subresourceRange.layerCount = 1;
1581     view_info.flags = 0;
1582     view_info.format = m_depth_stencil_fmt;
1583     view_info.image = handle();
1584     view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
1585     m_imageView.init(*m_device, view_info);
1586
1587     m_attachmentBindInfo = m_imageView.handle();
1588 }