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
vk_format_is_depth_and_stencil(VkFormat format)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
vk_format_is_stencil_only(VkFormat 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
vk_format_is_depth_only(VkFormat 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
VkRenderFramework()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
~VkRenderFramework()87 VkRenderFramework::~VkRenderFramework() {}
88
InitFramework()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
InitFramework(std::vector<const char * > instance_layer_names,std::vector<const char * > instance_extension_names,std::vector<const char * > device_extension_names,PFN_vkDebugReportCallbackEXT dbgFunction,void * userData)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
ShutdownFramework()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
InitState(VkPhysicalDeviceFeatures * features)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
InitViewport(float width,float height)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
InitViewport()250 void VkRenderFramework::InitViewport() { InitViewport(m_width, m_height); }
InitRenderTarget()251 void VkRenderFramework::InitRenderTarget() { InitRenderTarget(1); }
252
InitRenderTarget(uint32_t targets)253 void VkRenderFramework::InitRenderTarget(uint32_t targets) { InitRenderTarget(targets, NULL); }
254
InitRenderTarget(VkImageView * dsBinding)255 void VkRenderFramework::InitRenderTarget(VkImageView *dsBinding) { InitRenderTarget(1, dsBinding); }
256
InitRenderTarget(uint32_t targets,VkImageView * dsBinding)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
VkDeviceObj(uint32_t id,VkPhysicalDevice obj)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
VkDeviceObj(uint32_t id,VkPhysicalDevice obj,std::vector<const char * > & extension_names,VkPhysicalDeviceFeatures * features)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
get_device_queue()397 void VkDeviceObj::get_device_queue() {
398 ASSERT_NE(true, graphics_queues().empty());
399 m_queue = graphics_queues()[0]->handle();
400 }
401
VkDescriptorSetObj(VkDeviceObj * device)402 VkDescriptorSetObj::VkDescriptorSetObj(VkDeviceObj *device) : m_device(device), m_nextSlot(0) {}
403
~VkDescriptorSetObj()404 VkDescriptorSetObj::~VkDescriptorSetObj() {
405 if (m_set) {
406 delete m_set;
407 }
408 }
409
AppendDummy()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
AppendBuffer(VkDescriptorType type,VkConstantBufferObj & constantBuffer)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
AppendSamplerTexture(VkSamplerObj * sampler,VkTextureObj * texture)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
GetPipelineLayout() const464 VkPipelineLayout VkDescriptorSetObj::GetPipelineLayout() const { return m_pipeline_layout.handle(); }
465
GetDescriptorSetHandle() const466 VkDescriptorSet VkDescriptorSetObj::GetDescriptorSetHandle() const { return m_set->handle(); }
467
CreateVKDescriptorSet(VkCommandBufferObj * commandBuffer)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
VkRenderpassObj(VkDeviceObj * dev)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
~VkRenderpassObj()549 VkRenderpassObj::~VkRenderpassObj() { vkDestroyRenderPass(device, m_renderpass, NULL); }
550
VkImageObj(VkDeviceObj * dev)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
ImageMemoryBarrier(VkCommandBufferObj * cmd_buf,VkImageAspectFlags aspect,VkFlags output_mask,VkFlags input_mask,VkImageLayout image_layout)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
SetLayout(VkCommandBufferObj * cmd_buf,VkImageAspectFlags aspect,VkImageLayout image_layout)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
SetLayout(VkImageAspectFlags aspect,VkImageLayout image_layout)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
IsCompatible(VkFlags usage,VkFlags features)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
init_no_layout(uint32_t w,uint32_t h,VkFormat fmt,VkFlags usage,VkImageTiling requested_tiling,VkMemoryPropertyFlags reqs)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
init(uint32_t w,uint32_t h,VkFormat fmt,VkFlags usage,VkImageTiling requested_tiling,VkMemoryPropertyFlags reqs)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
CopyImage(VkImageObj & src_image)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, ©_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
VkTextureObj(VkDeviceObj * device,uint32_t * colors)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
VkSamplerObj(VkDeviceObj * device)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 */
VkConstantBufferObj(VkDeviceObj * device,VkBufferUsageFlags usage)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
~VkConstantBufferObj()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
VkConstantBufferObj(VkDeviceObj * device,int constantCount,int constantSize,const void * data,VkBufferUsageFlags usage)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
Bind(VkCommandBuffer commandBuffer,VkDeviceSize offset,uint32_t binding)941 void VkConstantBufferObj::Bind(VkCommandBuffer commandBuffer, VkDeviceSize offset, uint32_t binding) {
942 vkCmdBindVertexBuffers(commandBuffer, binding, 1, &handle(), &offset);
943 }
944
BufferMemoryBarrier(VkFlags srcAccessMask,VkFlags dstAccessMask)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
VkIndexBufferObj(VkDeviceObj * device)1026 VkIndexBufferObj::VkIndexBufferObj(VkDeviceObj *device) : VkConstantBufferObj(device) {}
1027
CreateAndInitBuffer(int numIndexes,VkIndexType indexType,const void * data)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
Bind(VkCommandBuffer commandBuffer,VkDeviceSize offset)1058 void VkIndexBufferObj::Bind(VkCommandBuffer commandBuffer, VkDeviceSize offset) {
1059 vkCmdBindIndexBuffer(commandBuffer, handle(), offset, m_indexType);
1060 }
1061
GetIndexType()1062 VkIndexType VkIndexBufferObj::GetIndexType() { return m_indexType; }
1063
GetStageCreateInfo() const1064 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
VkShaderObj(VkDeviceObj * device,const char * shader_code,VkShaderStageFlagBits stage,VkRenderFramework * framework,char const * name)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
VkPipelineObj(VkDeviceObj * device)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
AddShader(VkShaderObj * shader)1177 void VkPipelineObj::AddShader(VkShaderObj *shader) { m_shaderObjs.push_back(shader); }
1178
AddVertexInputAttribs(VkVertexInputAttributeDescription * vi_attrib,uint32_t count)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
AddVertexInputBindings(VkVertexInputBindingDescription * vi_binding,uint32_t count)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
AddColorAttachment(uint32_t binding,const VkPipelineColorBlendAttachmentState * att)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
SetDepthStencil(const VkPipelineDepthStencilStateCreateInfo * ds_state)1196 void VkPipelineObj::SetDepthStencil(const VkPipelineDepthStencilStateCreateInfo *ds_state) {
1197 m_ds_state = ds_state;
1198 }
1199
SetViewport(const vector<VkViewport> viewports)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
SetScissor(const vector<VkRect2D> scissors)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
MakeDynamic(VkDynamicState state)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
SetMSAA(const VkPipelineMultisampleStateCreateInfo * ms_state)1227 void VkPipelineObj::SetMSAA(const VkPipelineMultisampleStateCreateInfo *ms_state) { m_ms_state = *ms_state; }
1228
SetInputAssembly(const VkPipelineInputAssemblyStateCreateInfo * ia_state)1229 void VkPipelineObj::SetInputAssembly(const VkPipelineInputAssemblyStateCreateInfo *ia_state) { m_ia_state = *ia_state; }
1230
SetRasterization(const VkPipelineRasterizationStateCreateInfo * rs_state)1231 void VkPipelineObj::SetRasterization(const VkPipelineRasterizationStateCreateInfo *rs_state) { m_rs_state = *rs_state; }
1232
SetTessellation(const VkPipelineTessellationStateCreateInfo * te_state)1233 void VkPipelineObj::SetTessellation(const VkPipelineTessellationStateCreateInfo *te_state) { m_te_state = *te_state; }
1234
CreateVKPipeline(VkPipelineLayout layout,VkRenderPass render_pass)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
VkCommandBufferObj(VkDeviceObj * device,VkCommandPool pool)1299 VkCommandBufferObj::VkCommandBufferObj(VkDeviceObj *device, VkCommandPool pool) {
1300 m_device = device;
1301
1302 init(*device, vk_testing::CommandBuffer::create_info(pool));
1303 }
1304
GetBufferHandle()1305 VkCommandBuffer VkCommandBufferObj::GetBufferHandle() { return handle(); }
1306
BeginCommandBuffer(VkCommandBufferBeginInfo * pInfo)1307 VkResult VkCommandBufferObj::BeginCommandBuffer(VkCommandBufferBeginInfo *pInfo) {
1308 begin(pInfo);
1309 return VK_SUCCESS;
1310 }
1311
BeginCommandBuffer()1312 VkResult VkCommandBufferObj::BeginCommandBuffer() {
1313 begin();
1314 return VK_SUCCESS;
1315 }
1316
EndCommandBuffer()1317 VkResult VkCommandBufferObj::EndCommandBuffer() {
1318 end();
1319 return VK_SUCCESS;
1320 }
1321
PipelineBarrier(VkPipelineStageFlags src_stages,VkPipelineStageFlags dest_stages,VkDependencyFlags dependencyFlags,uint32_t memoryBarrierCount,const VkMemoryBarrier * pMemoryBarriers,uint32_t bufferMemoryBarrierCount,const VkBufferMemoryBarrier * pBufferMemoryBarriers,uint32_t imageMemoryBarrierCount,const VkImageMemoryBarrier * pImageMemoryBarriers)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
ClearAllBuffers(VkClearColorValue clear_color,float depth_clear_color,uint32_t stencil_clear_color,VkDepthStencilObj * depthStencilObj)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
FillBuffer(VkBuffer buffer,VkDeviceSize offset,VkDeviceSize fill_size,uint32_t data)1395 void VkCommandBufferObj::FillBuffer(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize fill_size, uint32_t data) {
1396 vkCmdFillBuffer(handle(), buffer, offset, fill_size, data);
1397 }
1398
UpdateBuffer(VkBuffer buffer,VkDeviceSize dstOffset,VkDeviceSize dataSize,const void * pData)1399 void VkCommandBufferObj::UpdateBuffer(VkBuffer buffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void *pData) {
1400 vkCmdUpdateBuffer(handle(), buffer, dstOffset, dataSize, pData);
1401 }
1402
CopyImage(VkImage srcImage,VkImageLayout srcImageLayout,VkImage dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageCopy * pRegions)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
ResolveImage(VkImage srcImage,VkImageLayout srcImageLayout,VkImage dstImage,VkImageLayout dstImageLayout,uint32_t regionCount,const VkImageResolve * pRegions)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
PrepareAttachments()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
BeginRenderPass(const VkRenderPassBeginInfo & info)1448 void VkCommandBufferObj::BeginRenderPass(const VkRenderPassBeginInfo &info) {
1449 vkCmdBeginRenderPass(handle(), &info, VK_SUBPASS_CONTENTS_INLINE);
1450 }
1451
EndRenderPass()1452 void VkCommandBufferObj::EndRenderPass() { vkCmdEndRenderPass(handle()); }
1453
SetViewport(uint32_t firstViewport,uint32_t viewportCount,const VkViewport * pViewports)1454 void VkCommandBufferObj::SetViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports) {
1455 vkCmdSetViewport(handle(), firstViewport, viewportCount, pViewports);
1456 }
1457
SetScissor(uint32_t firstScissor,uint32_t scissorCount,const VkRect2D * pScissors)1458 void VkCommandBufferObj::SetScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors) {
1459 vkCmdSetScissor(handle(), firstScissor, scissorCount, pScissors);
1460 }
1461
SetLineWidth(float lineWidth)1462 void VkCommandBufferObj::SetLineWidth(float lineWidth) { vkCmdSetLineWidth(handle(), lineWidth); }
1463
SetDepthBias(float depthBiasConstantFactor,float depthBiasClamp,float depthBiasSlopeFactor)1464 void VkCommandBufferObj::SetDepthBias(float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) {
1465 vkCmdSetDepthBias(handle(), depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
1466 }
1467
SetBlendConstants(const float blendConstants[4])1468 void VkCommandBufferObj::SetBlendConstants(const float blendConstants[4]) { vkCmdSetBlendConstants(handle(), blendConstants); }
1469
SetDepthBounds(float minDepthBounds,float maxDepthBounds)1470 void VkCommandBufferObj::SetDepthBounds(float minDepthBounds, float maxDepthBounds) {
1471 vkCmdSetDepthBounds(handle(), minDepthBounds, maxDepthBounds);
1472 }
1473
SetStencilReadMask(VkStencilFaceFlags faceMask,uint32_t compareMask)1474 void VkCommandBufferObj::SetStencilReadMask(VkStencilFaceFlags faceMask, uint32_t compareMask) {
1475 vkCmdSetStencilCompareMask(handle(), faceMask, compareMask);
1476 }
1477
SetStencilWriteMask(VkStencilFaceFlags faceMask,uint32_t writeMask)1478 void VkCommandBufferObj::SetStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t writeMask) {
1479 vkCmdSetStencilWriteMask(handle(), faceMask, writeMask);
1480 }
1481
SetStencilReference(VkStencilFaceFlags faceMask,uint32_t reference)1482 void VkCommandBufferObj::SetStencilReference(VkStencilFaceFlags faceMask, uint32_t reference) {
1483 vkCmdSetStencilReference(handle(), faceMask, reference);
1484 }
1485
AddRenderTarget(VkImageObj * renderTarget)1486 void VkCommandBufferObj::AddRenderTarget(VkImageObj *renderTarget) { m_renderTargets.push_back(renderTarget); }
1487
DrawIndexed(uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)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
Draw(uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)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
QueueCommandBuffer(bool checkSuccess)1497 void VkCommandBufferObj::QueueCommandBuffer(bool checkSuccess) {
1498 VkFence nullFence = {VK_NULL_HANDLE};
1499 QueueCommandBuffer(nullFence, checkSuccess);
1500 }
1501
QueueCommandBuffer(VkFence fence,bool checkSuccess)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
BindPipeline(VkPipelineObj & pipeline)1531 void VkCommandBufferObj::BindPipeline(VkPipelineObj &pipeline) {
1532 vkCmdBindPipeline(handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.handle());
1533 }
1534
BindDescriptorSet(VkDescriptorSetObj & descriptorSet)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
BindIndexBuffer(VkIndexBufferObj * indexBuffer,VkDeviceSize offset)1543 void VkCommandBufferObj::BindIndexBuffer(VkIndexBufferObj *indexBuffer, VkDeviceSize offset) {
1544 vkCmdBindIndexBuffer(handle(), indexBuffer->handle(), offset, indexBuffer->GetIndexType());
1545 }
1546
BindVertexBuffer(VkConstantBufferObj * vertexBuffer,VkDeviceSize offset,uint32_t binding)1547 void VkCommandBufferObj::BindVertexBuffer(VkConstantBufferObj *vertexBuffer, VkDeviceSize offset, uint32_t binding) {
1548 vkCmdBindVertexBuffers(handle(), binding, 1, &vertexBuffer->handle(), &offset);
1549 }
1550
Initialized()1551 bool VkDepthStencilObj::Initialized() { return m_initialized; }
VkDepthStencilObj(VkDeviceObj * device)1552 VkDepthStencilObj::VkDepthStencilObj(VkDeviceObj *device) : VkImageObj(device) { m_initialized = false; }
1553
BindInfo()1554 VkImageView *VkDepthStencilObj::BindInfo() { return &m_attachmentBindInfo; }
1555
Init(VkDeviceObj * device,int32_t width,int32_t height,VkFormat format,VkImageUsageFlags usage)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 }
1589