blob: 8a6418e083b482c634f6019b5f5d80059ad3aca8 [file] [log] [blame]
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06001#include <vulkan.h>
2#include <vkDbg.h>
Tony Barbour30486ea2015-04-07 13:44:53 -06003#include "gtest-1.7.0/include/gtest/gtest.h"
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06004#include "vkrenderframework.h"
Mark Lobodzinskia910dc82015-05-14 14:30:48 -05005#include "layers_config.h"
Tony Barbour30486ea2015-04-07 13:44:53 -06006
Mark Lobodzinski5f25be42015-05-14 15:08:13 -05007#define GLM_FORCE_RADIANS
8#include "glm/glm.hpp"
9#include <glm/gtc/matrix_transform.hpp>
10
11//--------------------------------------------------------------------------------------
12// Mesh and VertexFormat Data
13//--------------------------------------------------------------------------------------
14struct Vertex
15{
16 float posX, posY, posZ, posW; // Position data
17 float r, g, b, a; // Color
18};
19
20#define XYZ1(_x_, _y_, _z_) (_x_), (_y_), (_z_), 1.f
21
22typedef enum _BsoFailSelect {
23 BsoFailNone = 0x00000000,
24 BsoFailRaster = 0x00000001,
25 BsoFailViewport = 0x00000002,
26 BsoFailColorBlend = 0x00000004,
27 BsoFailDepthStencil = 0x00000008,
28} BsoFailSelect;
29
30struct vktriangle_vs_uniform {
31 // Must start with MVP
32 float mvp[4][4];
33 float position[3][4];
34 float color[3][4];
35};
36
37static const char *bindStateVertShaderText =
38 "#version 130\n"
39 "vec2 vertices[3];\n"
40 "void main() {\n"
41 " vertices[0] = vec2(-1.0, -1.0);\n"
42 " vertices[1] = vec2( 1.0, -1.0);\n"
43 " vertices[2] = vec2( 0.0, 1.0);\n"
44 " gl_Position = vec4(vertices[gl_VertexID % 3], 0.0, 1.0);\n"
45 "}\n";
46
47static const char *bindStateFragShaderText =
48 "#version 130\n"
49 "void main() {\n"
50 " gl_FragColor = vec4(0,1,0,1);\n"
51 "}\n";
52
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060053void VKAPI myDbgFunc(
54 VK_DBG_MSG_TYPE msgType,
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -060055 VkValidationLevel validationLevel,
Mike Stroyan230e6252015-04-17 12:36:38 -060056 VkObject srcObject,
Tony Barbour30486ea2015-04-07 13:44:53 -060057 size_t location,
58 int32_t msgCode,
59 const char* pMsg,
60 void* pUserData);
61
62class ErrorMonitor {
63public:
Tony Barbour0c1bdc62015-04-29 17:34:29 -060064 ErrorMonitor()
Tony Barbour30486ea2015-04-07 13:44:53 -060065 {
Mike Stroyan09aae812015-05-12 16:00:45 -060066 pthread_mutexattr_t attr;
67 pthread_mutexattr_init(&attr);
68 pthread_mutex_init(&m_mutex, &attr);
69 pthread_mutex_lock(&m_mutex);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060070 m_msgType = VK_DBG_MSG_UNKNOWN;
Mike Stroyan09aae812015-05-12 16:00:45 -060071 m_bailout = NULL;
72 pthread_mutex_unlock(&m_mutex);
Tony Barbour30486ea2015-04-07 13:44:53 -060073 }
74 void ClearState()
75 {
Mike Stroyan09aae812015-05-12 16:00:45 -060076 pthread_mutex_lock(&m_mutex);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060077 m_msgType = VK_DBG_MSG_UNKNOWN;
Tony Barbour30486ea2015-04-07 13:44:53 -060078 m_msgString.clear();
Mike Stroyan09aae812015-05-12 16:00:45 -060079 pthread_mutex_unlock(&m_mutex);
Tony Barbour30486ea2015-04-07 13:44:53 -060080 }
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060081 VK_DBG_MSG_TYPE GetState(std::string *msgString)
Tony Barbour30486ea2015-04-07 13:44:53 -060082 {
Mike Stroyan09aae812015-05-12 16:00:45 -060083 pthread_mutex_lock(&m_mutex);
Tony Barbour30486ea2015-04-07 13:44:53 -060084 *msgString = m_msgString;
Mike Stroyan09aae812015-05-12 16:00:45 -060085 pthread_mutex_unlock(&m_mutex);
Tony Barbour30486ea2015-04-07 13:44:53 -060086 return m_msgType;
87 }
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060088 void SetState(VK_DBG_MSG_TYPE msgType, const char *msgString)
Tony Barbour30486ea2015-04-07 13:44:53 -060089 {
Mike Stroyan09aae812015-05-12 16:00:45 -060090 pthread_mutex_lock(&m_mutex);
91 if (m_bailout != NULL) {
92 *m_bailout = true;
93 }
Tony Barbour30486ea2015-04-07 13:44:53 -060094 m_msgType = msgType;
Tony Barbour8508b8e2015-04-09 10:48:04 -060095 m_msgString.reserve(strlen(msgString));
96 m_msgString = msgString;
Mike Stroyan09aae812015-05-12 16:00:45 -060097 pthread_mutex_unlock(&m_mutex);
98 }
99 void SetBailout(bool *bailout)
100 {
101 m_bailout = bailout;
Tony Barbour30486ea2015-04-07 13:44:53 -0600102 }
103
104private:
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600105 VK_DBG_MSG_TYPE m_msgType;
Mike Stroyan09aae812015-05-12 16:00:45 -0600106 std::string m_msgString;
107 pthread_mutex_t m_mutex;
108 bool* m_bailout;
Tony Barbour30486ea2015-04-07 13:44:53 -0600109};
Mark Lobodzinski5f25be42015-05-14 15:08:13 -0500110
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600111void VKAPI myDbgFunc(
Mike Stroyan230e6252015-04-17 12:36:38 -0600112 VK_DBG_MSG_TYPE msgType,
113 VkValidationLevel validationLevel,
114 VkObject srcObject,
Tony Barbour30486ea2015-04-07 13:44:53 -0600115 size_t location,
116 int32_t msgCode,
117 const char* pMsg,
118 void* pUserData)
119{
Tony Barbour8508b8e2015-04-09 10:48:04 -0600120 if (msgType == VK_DBG_MSG_WARNING || msgType == VK_DBG_MSG_ERROR) {
121 ErrorMonitor *errMonitor = (ErrorMonitor *)pUserData;
122 errMonitor->SetState(msgType, pMsg);
123 }
Tony Barbour30486ea2015-04-07 13:44:53 -0600124}
Mark Lobodzinski5f25be42015-05-14 15:08:13 -0500125
Tony Barbour01999182015-04-09 12:58:51 -0600126class VkLayerTest : public VkRenderFramework
Tony Barbour30486ea2015-04-07 13:44:53 -0600127{
128public:
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600129 VkResult BeginCommandBuffer(VkCommandBufferObj &cmdBuffer);
130 VkResult EndCommandBuffer(VkCommandBufferObj &cmdBuffer);
Mark Lobodzinski5f25be42015-05-14 15:08:13 -0500131 void VKTriangleTest(const char *vertShaderText, const char *fragShaderText, BsoFailSelect failMask);
132 void GenericDrawPreparation(VkCommandBufferObj *cmdBuffer, VkPipelineObj &pipelineobj, VkDescriptorSetObj &descriptorSet, BsoFailSelect failMask);
Tony Barbour30486ea2015-04-07 13:44:53 -0600133
134protected:
Tony Barbour01999182015-04-09 12:58:51 -0600135 VkMemoryRefManager m_memoryRefManager;
136 ErrorMonitor *m_errorMonitor;
Tony Barbour30486ea2015-04-07 13:44:53 -0600137
138 virtual void SetUp() {
Mike Stroyan09aae812015-05-12 16:00:45 -0600139 const char *extension_names[] = {"MemTracker", "ObjectTracker", "Threading"};
140 const std::vector<const char *> extensions(extension_names,
141 extension_names + sizeof(extension_names)/sizeof(extension_names[0]));
Tony Barbour950ebc02015-04-23 12:55:36 -0600142
143 size_t extSize = sizeof(uint32_t);
144 uint32_t extCount = 0;
Tony Barbour04ada4a2015-04-23 15:28:27 -0600145 VkResult U_ASSERT_ONLY err;
Tony Barbour950ebc02015-04-23 12:55:36 -0600146 err = vkGetGlobalExtensionInfo(VK_EXTENSION_INFO_TYPE_COUNT, 0, &extSize, &extCount);
147 assert(!err);
148
149 VkExtensionProperties extProp;
150 extSize = sizeof(VkExtensionProperties);
151 bool32_t extFound;
152
Tony Barbour04ada4a2015-04-23 15:28:27 -0600153 for (uint32_t i = 0; i < extensions.size(); i++) {
Tony Barbour950ebc02015-04-23 12:55:36 -0600154 extFound = 0;
155 for (uint32_t j = 0; j < extCount; j++) {
156 err = vkGetGlobalExtensionInfo(VK_EXTENSION_INFO_TYPE_PROPERTIES, j, &extSize, &extProp);
Tony Barbour04ada4a2015-04-23 15:28:27 -0600157 assert(!err);
158 if (!strcmp(extensions[i], extProp.extName)) {
Tony Barbour950ebc02015-04-23 12:55:36 -0600159 extFound = 1;
160 break;
161 }
162 }
Tony Barbour04ada4a2015-04-23 15:28:27 -0600163 ASSERT_EQ(extFound, 1) << "ERROR: Cannot find extension named " << extensions[i] << " which is necessary to pass this test";
Tony Barbour950ebc02015-04-23 12:55:36 -0600164 }
Tony Barbour30486ea2015-04-07 13:44:53 -0600165
Mark Lobodzinskia910dc82015-05-14 14:30:48 -0500166 // Force layer output level to be >= WARNING so that we catch those messages but ignore others
167 setLayerOptionEnum("MemTrackerReportLevel", "VK_DBG_LAYER_LEVEL_WARNING");
168 setLayerOptionEnum("ObjectTrackerReportLevel", "VK_DBG_LAYER_LEVEL_WARNING");
169 setLayerOptionEnum("ThreadingReportLevel", "VK_DBG_LAYER_LEVEL_WARNING");
170
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600171 this->app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
Tony Barbour30486ea2015-04-07 13:44:53 -0600172 this->app_info.pNext = NULL;
173 this->app_info.pAppName = "layer_tests";
174 this->app_info.appVersion = 1;
175 this->app_info.pEngineName = "unittest";
176 this->app_info.engineVersion = 1;
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600177 this->app_info.apiVersion = VK_API_VERSION;
Tony Barbour30486ea2015-04-07 13:44:53 -0600178
Tony Barbour0c1bdc62015-04-29 17:34:29 -0600179 m_errorMonitor = new ErrorMonitor;
180 InitFramework(extensions, myDbgFunc, m_errorMonitor);
181
Tony Barbour30486ea2015-04-07 13:44:53 -0600182 }
183
184 virtual void TearDown() {
185 // Clean up resources before we reset
Tony Barbour30486ea2015-04-07 13:44:53 -0600186 ShutdownFramework();
Tony Barbour8508b8e2015-04-09 10:48:04 -0600187 delete m_errorMonitor;
Tony Barbour30486ea2015-04-07 13:44:53 -0600188 }
189};
Mark Lobodzinski5f25be42015-05-14 15:08:13 -0500190
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600191VkResult VkLayerTest::BeginCommandBuffer(VkCommandBufferObj &cmdBuffer)
Tony Barbour30486ea2015-04-07 13:44:53 -0600192{
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600193 VkResult result;
Tony Barbour30486ea2015-04-07 13:44:53 -0600194
195 result = cmdBuffer.BeginCommandBuffer();
196
197 /*
198 * For render test all drawing happens in a single render pass
199 * on a single command buffer.
200 */
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600201 if (VK_SUCCESS == result) {
Tony Barbour30486ea2015-04-07 13:44:53 -0600202 cmdBuffer.BeginRenderPass(renderPass(), framebuffer());
203 }
204
205 return result;
206}
207
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600208VkResult VkLayerTest::EndCommandBuffer(VkCommandBufferObj &cmdBuffer)
Tony Barbour30486ea2015-04-07 13:44:53 -0600209{
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600210 VkResult result;
Tony Barbour30486ea2015-04-07 13:44:53 -0600211
212 cmdBuffer.EndRenderPass(renderPass());
213
214 result = cmdBuffer.EndCommandBuffer();
215
216 return result;
217}
218
Mark Lobodzinski5f25be42015-05-14 15:08:13 -0500219void VkLayerTest::VKTriangleTest(const char *vertShaderText, const char *fragShaderText, BsoFailSelect failMask)
220{
221 // Create identity matrix
222 int i;
223 struct vktriangle_vs_uniform data;
224
225 glm::mat4 Projection = glm::mat4(1.0f);
226 glm::mat4 View = glm::mat4(1.0f);
227 glm::mat4 Model = glm::mat4(1.0f);
228 glm::mat4 MVP = Projection * View * Model;
229 const int matrixSize = sizeof(MVP);
230 const int bufSize = sizeof(vktriangle_vs_uniform) / sizeof(float);
231
232 memcpy(&data.mvp, &MVP[0][0], matrixSize);
233
234 static const Vertex tri_data[] =
235 {
236 { XYZ1( -1, -1, 0 ), XYZ1( 1.f, 0.f, 0.f ) },
237 { XYZ1( 1, -1, 0 ), XYZ1( 0.f, 1.f, 0.f ) },
238 { XYZ1( 0, 1, 0 ), XYZ1( 0.f, 0.f, 1.f ) },
239 };
240
241 for (i=0; i<3; i++) {
242 data.position[i][0] = tri_data[i].posX;
243 data.position[i][1] = tri_data[i].posY;
244 data.position[i][2] = tri_data[i].posZ;
245 data.position[i][3] = tri_data[i].posW;
246 data.color[i][0] = tri_data[i].r;
247 data.color[i][1] = tri_data[i].g;
248 data.color[i][2] = tri_data[i].b;
249 data.color[i][3] = tri_data[i].a;
250 }
251
252 ASSERT_NO_FATAL_FAILURE(InitState());
253 ASSERT_NO_FATAL_FAILURE(InitViewport());
254
255 VkConstantBufferObj constantBuffer(m_device, bufSize*2, sizeof(float), (const void*) &data);
256
257 VkShaderObj vs(m_device,vertShaderText,VK_SHADER_STAGE_VERTEX, this);
258 VkShaderObj ps(m_device,fragShaderText, VK_SHADER_STAGE_FRAGMENT, this);
259
260 VkPipelineObj pipelineobj(m_device);
261 pipelineobj.AddShader(&vs);
262 pipelineobj.AddShader(&ps);
263
264 VkDescriptorSetObj descriptorSet(m_device);
265 descriptorSet.AppendBuffer(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, constantBuffer);
266
267 ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
268 VkCommandBufferObj cmdBuffer(m_device);
269 cmdBuffer.AddRenderTarget(m_renderTargets[0]);
270
271 ASSERT_VK_SUCCESS(BeginCommandBuffer(cmdBuffer));
272
273 GenericDrawPreparation(&cmdBuffer, pipelineobj, descriptorSet, failMask);
274
275 // render triangle
276 cmdBuffer.Draw(0, 3, 0, 1);
277
278 // finalize recording of the command buffer
279 EndCommandBuffer(cmdBuffer);
280
281 cmdBuffer.QueueCommandBuffer();
282}
283
284void VkLayerTest::GenericDrawPreparation(VkCommandBufferObj *cmdBuffer, VkPipelineObj &pipelineobj, VkDescriptorSetObj &descriptorSet, BsoFailSelect failMask)
285{
286 if (m_depthStencil->Initialized()) {
287 cmdBuffer->ClearAllBuffers(m_clear_color, m_depth_clear_color, m_stencil_clear_color, m_depthStencil);
288 } else {
289 cmdBuffer->ClearAllBuffers(m_clear_color, m_depth_clear_color, m_stencil_clear_color, NULL);
290 }
291
292 cmdBuffer->PrepareAttachments();
293 if ((failMask & BsoFailRaster) != BsoFailRaster) {
294 cmdBuffer->BindStateObject(VK_STATE_BIND_POINT_RASTER, m_stateRaster);
295 }
296 if ((failMask & BsoFailViewport) != BsoFailViewport) {
297 cmdBuffer->BindStateObject(VK_STATE_BIND_POINT_VIEWPORT, m_stateViewport);
298 }
299 if ((failMask & BsoFailColorBlend) != BsoFailColorBlend) {
300 cmdBuffer->BindStateObject(VK_STATE_BIND_POINT_COLOR_BLEND, m_colorBlend);
301 }
302 if ((failMask & BsoFailDepthStencil) != BsoFailDepthStencil) {
303 cmdBuffer->BindStateObject(VK_STATE_BIND_POINT_DEPTH_STENCIL, m_stateDepthStencil);
304 }
305 descriptorSet.CreateVKDescriptorSet(cmdBuffer);
306 pipelineobj.CreateVKPipeline(descriptorSet);
307 cmdBuffer->BindPipeline(pipelineobj);
308 cmdBuffer->BindDescriptorSet(descriptorSet);
309}
310
311// ********************************************************************************************************************
312// ********************************************************************************************************************
313// ********************************************************************************************************************
314// ********************************************************************************************************************
315
316TEST_F(VkLayerTest, MapMemWithoutHostVisibleBit)
317{
318 VK_DBG_MSG_TYPE msgType;
319 std::string msgString;
320 VkResult err;
321
322 ASSERT_NO_FATAL_FAILURE(InitState());
323 m_errorMonitor->ClearState();
324
325 // Create an image, allocate memory, free it, and then try to bind it
326 VkImage image;
327 VkDeviceMemory *mem;
328 VkMemoryRequirements *mem_reqs;
329
330 const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
331 const int32_t tex_width = 32;
332 const int32_t tex_height = 32;
333 size_t mem_reqs_size = sizeof(VkMemoryRequirements);
334 uint32_t num_allocations = 0;
335 size_t num_alloc_size = sizeof(num_allocations);
336
337 const VkImageCreateInfo image_create_info = {
338 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
339 .pNext = NULL,
340 .imageType = VK_IMAGE_TYPE_2D,
341 .format = tex_format,
342 .extent = { tex_width, tex_height, 1 },
343 .mipLevels = 1,
344 .arraySize = 1,
345 .samples = 1,
346 .tiling = VK_IMAGE_TILING_LINEAR,
347 .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
348 .flags = 0,
349 };
350 VkMemoryAllocInfo mem_alloc = {
351 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
352 .pNext = NULL,
353 .allocationSize = 0,
354 // Introduce failure, do NOT set memProps to VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
355 .memProps = 0,
356 .memPriority = VK_MEMORY_PRIORITY_NORMAL,
357 };
358
359 err = vkCreateImage(m_device->device(), &image_create_info, &image);
360 ASSERT_VK_SUCCESS(err);
361
362 err = vkGetObjectInfo(m_device->device(),
363 VK_OBJECT_TYPE_IMAGE,
364 image,
365 VK_OBJECT_INFO_TYPE_MEMORY_ALLOCATION_COUNT,
366 &num_alloc_size,
367 &num_allocations);
368 ASSERT_VK_SUCCESS(err);
369
370 mem_reqs = new VkMemoryRequirements[num_allocations];
371 mem = new VkDeviceMemory[num_allocations];
372
373 err = vkGetObjectInfo(m_device->device(),
374 VK_OBJECT_TYPE_IMAGE,
375 image,
376 VK_OBJECT_INFO_TYPE_MEMORY_REQUIREMENTS,
377 &mem_reqs_size,
378 mem_reqs);
379 ASSERT_VK_SUCCESS(err);
380
381 mem_alloc.allocationSize = mem_reqs[0].size;
382
383 // allocate memory
384 err = vkAllocMemory(m_device->device(), &mem_alloc, &(mem[0]));
385 ASSERT_VK_SUCCESS(err);
386
387 // Try to bind free memory that has been freed
388 err = vkBindObjectMemory(m_device->device(), VK_OBJECT_TYPE_IMAGE, image, 0, mem[0], 0);
389 ASSERT_VK_SUCCESS(err);
390
391 // Map memory as if to initialize the image
392 void *mappedAddress = NULL;
393 err = vkMapMemory(m_device->device(), mem[0], 0, 0, 0, &mappedAddress);
394
395 msgType = m_errorMonitor->GetState(&msgString);
396 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error while tring to map memory not visible to CPU";
397 if (!strstr(msgString.c_str(),"Mapping Memory without VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT")) {
398 FAIL() << "Error received did not match expected error message from vkMapMemory in MemTracker";
399 }
400}
401
402TEST_F(VkLayerTest, BindInvalidMemory)
403{
404 VK_DBG_MSG_TYPE msgType;
405 std::string msgString;
406 VkResult err;
407
408 ASSERT_NO_FATAL_FAILURE(InitState());
409 m_errorMonitor->ClearState();
410
411 // Create an image, allocate memory, free it, and then try to bind it
412 VkImage image;
413 VkDeviceMemory *mem;
414 VkMemoryRequirements *mem_reqs;
415
416 const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
417 const int32_t tex_width = 32;
418 const int32_t tex_height = 32;
419 size_t mem_reqs_size = sizeof(VkMemoryRequirements);
420 uint32_t num_allocations = 0;
421 size_t num_alloc_size = sizeof(num_allocations);
422
423 const VkImageCreateInfo image_create_info = {
424 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
425 .pNext = NULL,
426 .imageType = VK_IMAGE_TYPE_2D,
427 .format = tex_format,
428 .extent = { tex_width, tex_height, 1 },
429 .mipLevels = 1,
430 .arraySize = 1,
431 .samples = 1,
432 .tiling = VK_IMAGE_TILING_LINEAR,
433 .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
434 .flags = 0,
435 };
436 VkMemoryAllocInfo mem_alloc = {
437 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
438 .pNext = NULL,
439 .allocationSize = 0,
440 .memProps = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
441 .memPriority = VK_MEMORY_PRIORITY_NORMAL,
442 };
443
444 err = vkCreateImage(m_device->device(), &image_create_info, &image);
445 ASSERT_VK_SUCCESS(err);
446
447 err = vkGetObjectInfo(m_device->device(),
448 VK_OBJECT_TYPE_IMAGE,
449 image,
450 VK_OBJECT_INFO_TYPE_MEMORY_ALLOCATION_COUNT,
451 &num_alloc_size,
452 &num_allocations);
453 ASSERT_VK_SUCCESS(err);
454
455 mem_reqs = new VkMemoryRequirements[num_allocations];
456 mem = new VkDeviceMemory[num_allocations];
457
458 err = vkGetObjectInfo(m_device->device(),
459 VK_OBJECT_TYPE_IMAGE,
460 image,
461 VK_OBJECT_INFO_TYPE_MEMORY_REQUIREMENTS,
462 &mem_reqs_size,
463 mem_reqs);
464 ASSERT_VK_SUCCESS(err);
465
466 mem_alloc.allocationSize = mem_reqs[0].size;
467
468 // allocate memory
469 err = vkAllocMemory(m_device->device(), &mem_alloc, &(mem[0]));
470 ASSERT_VK_SUCCESS(err);
471
472 // Introduce validation failure, free memory before binding
473 vkFreeMemory(m_device->device(), mem[0]);
474 ASSERT_VK_SUCCESS(err);
475
476 // Try to bind free memory that has been freed
477 err = vkBindObjectMemory(m_device->device(), VK_OBJECT_TYPE_IMAGE, image, 0, mem[0], 0);
478 ASSERT_VK_SUCCESS(err);
479
480 msgType = m_errorMonitor->GetState(&msgString);
481 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error while tring to bind a freed memory object";
482 if (!strstr(msgString.c_str(),"Unable to set object")) {
483 FAIL() << "Error received did not match expected error message from BindObjectMemory in MemTracker";
484 }
485}
486
487TEST_F(VkLayerTest, FreeBoundMemory)
488{
489 VK_DBG_MSG_TYPE msgType;
490 std::string msgString;
491 VkResult err;
492
493 ASSERT_NO_FATAL_FAILURE(InitState());
494 m_errorMonitor->ClearState();
495
496 // Create an image, allocate memory, free it, and then try to bind it
497 VkImage image;
498 VkDeviceMemory *mem;
499 VkMemoryRequirements *mem_reqs;
500
501 const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
502 const int32_t tex_width = 32;
503 const int32_t tex_height = 32;
504 size_t mem_reqs_size = sizeof(VkMemoryRequirements);
505 uint32_t num_allocations = 0;
506 size_t num_alloc_size = sizeof(num_allocations);
507
508 const VkImageCreateInfo image_create_info = {
509 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
510 .pNext = NULL,
511 .imageType = VK_IMAGE_TYPE_2D,
512 .format = tex_format,
513 .extent = { tex_width, tex_height, 1 },
514 .mipLevels = 1,
515 .arraySize = 1,
516 .samples = 1,
517 .tiling = VK_IMAGE_TILING_LINEAR,
518 .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
519 .flags = 0,
520 };
521 VkMemoryAllocInfo mem_alloc = {
522 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
523 .pNext = NULL,
524 .allocationSize = 0,
525 .memProps = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
526 .memPriority = VK_MEMORY_PRIORITY_NORMAL,
527 };
528
529 err = vkCreateImage(m_device->device(), &image_create_info, &image);
530 ASSERT_VK_SUCCESS(err);
531
532 err = vkGetObjectInfo(m_device->device(),
533 VK_OBJECT_TYPE_IMAGE,
534 image,
535 VK_OBJECT_INFO_TYPE_MEMORY_ALLOCATION_COUNT,
536 &num_alloc_size,
537 &num_allocations);
538 ASSERT_VK_SUCCESS(err);
539
540 mem_reqs = new VkMemoryRequirements[num_allocations];
541 mem = new VkDeviceMemory[num_allocations];
542
543 err = vkGetObjectInfo(m_device->device(),
544 VK_OBJECT_TYPE_IMAGE,
545 image,
546 VK_OBJECT_INFO_TYPE_MEMORY_REQUIREMENTS,
547 &mem_reqs_size,
548 mem_reqs);
549 ASSERT_VK_SUCCESS(err);
550
551 mem_alloc.allocationSize = mem_reqs[0].size;
552
553 // allocate memory
554 err = vkAllocMemory(m_device->device(), &mem_alloc, &(mem[0]));
555 ASSERT_VK_SUCCESS(err);
556
557 // Bind memory to Image object
558 err = vkBindObjectMemory(m_device->device(), VK_OBJECT_TYPE_IMAGE, image, 0, mem[0], 0);
559 ASSERT_VK_SUCCESS(err);
560
561 // Introduce validation failure, free memory while still bound to object
562 vkFreeMemory(m_device->device(), mem[0]);
563 ASSERT_VK_SUCCESS(err);
564
565 msgType = m_errorMonitor->GetState(&msgString);
566 ASSERT_EQ(msgType, VK_DBG_MSG_WARNING) << "Did not receive an warning while tring to free bound memory";
567 if (!strstr(msgString.c_str(),"Freeing memory object while it still has references")) {
568 FAIL() << "Warning received did not match expected message from freeMemObjInfo in MemTracker";
569 }
570}
571
572
573TEST_F(VkLayerTest, BindMemoryToDestroyedObject)
574{
575 VK_DBG_MSG_TYPE msgType;
576 std::string msgString;
577 VkResult err;
578
579 ASSERT_NO_FATAL_FAILURE(InitState());
580 m_errorMonitor->ClearState();
581
582 // Create an image object, allocate memory, destroy the object and then try to bind it
583 VkImage image;
584 VkDeviceMemory *mem;
585 VkMemoryRequirements *mem_reqs;
586
587 const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
588 const int32_t tex_width = 32;
589 const int32_t tex_height = 32;
590 size_t mem_reqs_size = sizeof(VkMemoryRequirements);
591 uint32_t num_allocations = 0;
592 size_t num_alloc_size = sizeof(num_allocations);
593
594 const VkImageCreateInfo image_create_info = {
595 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
596 .pNext = NULL,
597 .imageType = VK_IMAGE_TYPE_2D,
598 .format = tex_format,
599 .extent = { tex_width, tex_height, 1 },
600 .mipLevels = 1,
601 .arraySize = 1,
602 .samples = 1,
603 .tiling = VK_IMAGE_TILING_LINEAR,
604 .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
605 .flags = 0,
606 };
607 VkMemoryAllocInfo mem_alloc = {
608 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
609 .pNext = NULL,
610 .allocationSize = 0,
611 .memProps = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
612 .memPriority = VK_MEMORY_PRIORITY_NORMAL,
613 };
614
615 err = vkCreateImage(m_device->device(), &image_create_info, &image);
616 ASSERT_VK_SUCCESS(err);
617
618 err = vkGetObjectInfo(m_device->device(),
619 VK_OBJECT_TYPE_IMAGE,
620 image,
621 VK_OBJECT_INFO_TYPE_MEMORY_ALLOCATION_COUNT,
622 &num_alloc_size,
623 &num_allocations);
624 ASSERT_VK_SUCCESS(err);
625
626 mem_reqs = new VkMemoryRequirements[num_allocations];
627 mem = new VkDeviceMemory[num_allocations];
628
629 err = vkGetObjectInfo(m_device->device(),
630 VK_OBJECT_TYPE_IMAGE,
631 image,
632 VK_OBJECT_INFO_TYPE_MEMORY_REQUIREMENTS,
633 &mem_reqs_size,
634 mem_reqs);
635 ASSERT_VK_SUCCESS(err);
636
637 mem_alloc.allocationSize = mem_reqs[0].size;
638
639 // Allocate memory
640 err = vkAllocMemory(m_device->device(), &mem_alloc, &(mem[0]));
641 ASSERT_VK_SUCCESS(err);
642
643 // Introduce validation failure, destroy Image object before binding
644 vkDestroyObject(m_device->device(), VK_OBJECT_TYPE_IMAGE, image);
645 ASSERT_VK_SUCCESS(err);
646
647 // Now Try to bind memory to this destroyted object
648 err = vkBindObjectMemory(m_device->device(), VK_OBJECT_TYPE_IMAGE, image, 0, mem[0], 0);
649 ASSERT_VK_SUCCESS(err);
650
651 msgType = m_errorMonitor->GetState(&msgString);
652 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error while binding memory to a destroyed object";
653 if (!strstr(msgString.c_str(),"Unable to set object")) {
654 FAIL() << "Error received did not match expected error message from updateObjectBinding in MemTracker";
655 }
656}
657
Tony Barbour8508b8e2015-04-09 10:48:04 -0600658TEST_F(VkLayerTest, SubmitSignaledFence)
Tony Barbour30486ea2015-04-07 13:44:53 -0600659{
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600660 vk_testing::Fence testFence;
661 VK_DBG_MSG_TYPE msgType;
Tony Barbour30486ea2015-04-07 13:44:53 -0600662 std::string msgString;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600663
664 VkFenceCreateInfo fenceInfo = {};
Tony Barbour8508b8e2015-04-09 10:48:04 -0600665 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
666 fenceInfo.pNext = NULL;
667 fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
Tony Barbour30486ea2015-04-07 13:44:53 -0600668
Tony Barbour30486ea2015-04-07 13:44:53 -0600669 ASSERT_NO_FATAL_FAILURE(InitState());
670 ASSERT_NO_FATAL_FAILURE(InitViewport());
671 ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
672
Tony Barbour01999182015-04-09 12:58:51 -0600673 VkCommandBufferObj cmdBuffer(m_device);
Tony Barbour30486ea2015-04-07 13:44:53 -0600674 cmdBuffer.AddRenderTarget(m_renderTargets[0]);
675
Tony Barbour8508b8e2015-04-09 10:48:04 -0600676 BeginCommandBuffer(cmdBuffer);
Tony Barbour30486ea2015-04-07 13:44:53 -0600677 cmdBuffer.ClearAllBuffers(m_clear_color, m_depth_clear_color, m_stencil_clear_color, NULL);
Tony Barbour8508b8e2015-04-09 10:48:04 -0600678 EndCommandBuffer(cmdBuffer);
Tony Barbour30486ea2015-04-07 13:44:53 -0600679
680 testFence.init(*m_device, fenceInfo);
681 m_errorMonitor->ClearState();
Tony Barbour8508b8e2015-04-09 10:48:04 -0600682 cmdBuffer.QueueCommandBuffer(testFence.obj());
Tony Barbour30486ea2015-04-07 13:44:53 -0600683 msgType = m_errorMonitor->GetState(&msgString);
Tony Barbour8508b8e2015-04-09 10:48:04 -0600684 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an err from using a fence in SIGNALED state in call to vkQueueSubmit";
685 if (!strstr(msgString.c_str(),"submitted in SIGNALED state. Fences must be reset before being submitted")) {
Mark Lobodzinski5f25be42015-05-14 15:08:13 -0500686 FAIL() << "Error received was not 'VkQueueSubmit with fence in SIGNALED_STATE'";
Tony Barbour8508b8e2015-04-09 10:48:04 -0600687 }
688
689}
690
691TEST_F(VkLayerTest, ResetUnsignaledFence)
692{
693 vk_testing::Fence testFence;
694 VK_DBG_MSG_TYPE msgType;
695 std::string msgString;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600696 VkFenceCreateInfo fenceInfo = {};
Tony Barbour8508b8e2015-04-09 10:48:04 -0600697 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
698 fenceInfo.pNext = NULL;
699
Tony Barbour8508b8e2015-04-09 10:48:04 -0600700 ASSERT_NO_FATAL_FAILURE(InitState());
701 testFence.init(*m_device, fenceInfo);
702 m_errorMonitor->ClearState();
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600703 VkFence fences[1] = {testFence.obj()};
Tony Barbour8508b8e2015-04-09 10:48:04 -0600704 vkResetFences(m_device->device(), 1, fences);
705 msgType = m_errorMonitor->GetState(&msgString);
706 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error from submitting fence with UNSIGNALED state to vkResetFences";
Tony Barbour01999182015-04-09 12:58:51 -0600707 if (!strstr(msgString.c_str(),"submitted to VkResetFences in UNSIGNALED STATE")) {
Mark Lobodzinski5f25be42015-05-14 15:08:13 -0500708 FAIL() << "Error received was not 'VkResetFences with fence in UNSIGNALED_STATE'";
Tony Barbour8508b8e2015-04-09 10:48:04 -0600709 }
Tony Barbour30486ea2015-04-07 13:44:53 -0600710
711}
712
Tony Barbour54cdd192015-04-22 15:12:07 -0600713TEST_F(VkLayerTest, WaitForUnsubmittedFence)
714{
715 vk_testing::Fence testFence;
716 VK_DBG_MSG_TYPE msgType;
717 std::string msgString;
718 VkFenceCreateInfo fenceInfo = {};
719 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
720 fenceInfo.pNext = NULL;
721
Tony Barbour54cdd192015-04-22 15:12:07 -0600722 ASSERT_NO_FATAL_FAILURE(InitState());
723 testFence.init(*m_device, fenceInfo);
724 m_errorMonitor->ClearState();
725 vkGetFenceStatus(m_device->device(),testFence.obj());
726 msgType = m_errorMonitor->GetState(&msgString);
727 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error asking for status of unsubmitted fence";
728 if (!strstr(msgString.c_str(),"Status Requested for Unsubmitted Fence")) {
729 FAIL() << "Error received was not Status Requested for Unsubmitted Fence";
730 }
731
732 VkFence fences[1] = {testFence.obj()};
733 m_errorMonitor->ClearState();
734 vkWaitForFences(m_device->device(), 1, fences, VK_TRUE, 0);
735 msgType = m_errorMonitor->GetState(&msgString);
736 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error for waiting for unsubmitted fence";
737 if (!strstr(msgString.c_str(),"Waiting for Unsubmitted Fence")) {
Mark Lobodzinski5f25be42015-05-14 15:08:13 -0500738 FAIL() << "Error received was not 'Waiting for Unsubmitted Fence'";
Tony Barbour54cdd192015-04-22 15:12:07 -0600739 }
740}
741
Tony Barbourdb686622015-05-06 09:35:56 -0600742TEST_F(VkLayerTest, GetObjectInfoMismatchedType)
743{
744 VkEventCreateInfo event_info;
745 VkEvent event;
746 VkMemoryRequirements mem_req;
747 size_t data_size = sizeof(mem_req);
748 VK_DBG_MSG_TYPE msgType;
749 std::string msgString;
750 VkResult err;
751
752 ASSERT_NO_FATAL_FAILURE(InitState());
753 memset(&event_info, 0, sizeof(event_info));
754 event_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
755
756 err = vkCreateEvent(device(), &event_info, &event);
757 ASSERT_VK_SUCCESS(err);
758 m_errorMonitor->ClearState();
759 err = vkGetObjectInfo(device(), VK_OBJECT_TYPE_IMAGE, event, VK_OBJECT_INFO_TYPE_MEMORY_REQUIREMENTS,
760 &data_size, &mem_req);
761 msgType = m_errorMonitor->GetState(&msgString);
762 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error from mismatched types in vkGetObjectInfo";
763 if (!strstr(msgString.c_str(),"does not match designated type")) {
Mark Lobodzinski5f25be42015-05-14 15:08:13 -0500764 FAIL() << "Error received was not 'does not match designated type'";
Tony Barbourdb686622015-05-06 09:35:56 -0600765 }
Mark Lobodzinski5f25be42015-05-14 15:08:13 -0500766}
Tony Barbourdb686622015-05-06 09:35:56 -0600767
Mark Lobodzinski5f25be42015-05-14 15:08:13 -0500768TEST_F(VkLayerTest, RasterStateNotBound)
769{
770 VK_DBG_MSG_TYPE msgType;
771 std::string msgString;
772
773 TEST_DESCRIPTION("Simple Draw Call that validates failure when a raster state object is not bound beforehand");
774
775 VKTriangleTest(bindStateVertShaderText, bindStateFragShaderText, BsoFailRaster);
776
777 msgType = m_errorMonitor->GetState(&msgString);
778 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error from Not Binding a Raster State Object";
779 if (!strstr(msgString.c_str(),"Raster object not bound to this command buffer")) {
780 FAIL() << "Error received was not 'Raster object not bound to this command buffer'";
781 }
782}
783
784TEST_F(VkLayerTest, ViewportStateNotBound)
785{
786 VK_DBG_MSG_TYPE msgType;
787 std::string msgString;
788 TEST_DESCRIPTION("Simple Draw Call that validates failure when a viewport state object is not bound beforehand");
789
790 VKTriangleTest(bindStateVertShaderText, bindStateFragShaderText, BsoFailViewport);
791
792 msgType = m_errorMonitor->GetState(&msgString);
793 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error from Not Binding a Viewport State Object";
794 if (!strstr(msgString.c_str(),"Viewport object not bound to this command buffer")) {
795 FAIL() << "Error received was not 'Viewport object not bound to this command buffer'";
796 }
797}
798
799TEST_F(VkLayerTest, ColorBlendStateNotBound)
800{
801 VK_DBG_MSG_TYPE msgType;
802 std::string msgString;
803
804 TEST_DESCRIPTION("Simple Draw Call that validates failure when a color-blend state object is not bound beforehand");
805
806 VKTriangleTest(bindStateVertShaderText, bindStateFragShaderText, BsoFailColorBlend);
807
808 msgType = m_errorMonitor->GetState(&msgString);
809 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error from Not Binding a ColorBlend State Object";
810 if (!strstr(msgString.c_str(),"Color-blend object not bound to this command buffer")) {
811 FAIL() << "Error received was not 'Color-blend object not bound to this command buffer'";
812 }
813}
814
815TEST_F(VkLayerTest, DepthStencilStateNotBound)
816{
817 VK_DBG_MSG_TYPE msgType;
818 std::string msgString;
819
820 TEST_DESCRIPTION("Simple Draw Call that validates failure when a depth-stencil state object is not bound beforehand");
821
822 VKTriangleTest(bindStateVertShaderText, bindStateFragShaderText, BsoFailDepthStencil);
823
824 msgType = m_errorMonitor->GetState(&msgString);
825 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error from Not Binding a DepthStencil State Object";
826 if (!strstr(msgString.c_str(),"Depth-stencil object not bound to this command buffer")) {
827 FAIL() << "Error received was not 'Depth-stencil object not bound to this command buffer'";
828 }
Tony Barbourdb686622015-05-06 09:35:56 -0600829}
830
Mike Stroyan09aae812015-05-12 16:00:45 -0600831#if GTEST_IS_THREADSAFE
832struct thread_data_struct {
833 VkCmdBuffer cmdBuffer;
834 VkEvent event;
835 bool bailout;
836};
837
838extern "C" void *AddToCommandBuffer(void *arg)
839{
840 struct thread_data_struct *data = (struct thread_data_struct *) arg;
841 std::string msgString;
842
843 for (int i = 0; i<10000; i++) {
844 vkCmdSetEvent(data->cmdBuffer, data->event, VK_PIPE_EVENT_COMMANDS_COMPLETE);
845 if (data->bailout) {
846 break;
847 }
848 }
849 return NULL;
850}
851
852TEST_F(VkLayerTest, ThreadCmdBufferCollision)
853{
854 VK_DBG_MSG_TYPE msgType;
855 std::string msgString;
856 pthread_t thread;
857 pthread_attr_t thread_attr;
858
859 ASSERT_NO_FATAL_FAILURE(InitState());
860 ASSERT_NO_FATAL_FAILURE(InitViewport());
861 ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
862
863 VkCommandBufferObj cmdBuffer(m_device);
864
865 m_errorMonitor->ClearState();
866 pthread_attr_init(&thread_attr);
867 BeginCommandBuffer(cmdBuffer);
868
869 VkEventCreateInfo event_info;
870 VkEvent event;
871 VkMemoryRequirements mem_req;
872 size_t data_size = sizeof(mem_req);
873 VkResult err;
874
875 memset(&event_info, 0, sizeof(event_info));
876 event_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
877
878 err = vkCreateEvent(device(), &event_info, &event);
879 ASSERT_VK_SUCCESS(err);
880
881 err = vkGetObjectInfo(device(), VK_OBJECT_TYPE_EVENT, event, VK_OBJECT_INFO_TYPE_MEMORY_REQUIREMENTS,
882 &data_size, &mem_req);
883 ASSERT_VK_SUCCESS(err);
884
885 VkMemoryAllocInfo mem_info;
886 VkDeviceMemory event_mem;
887
888 ASSERT_NE(0, mem_req.size) << "vkGetObjectInfo (Event): Failed - expect events to require memory";
889
890 memset(&mem_info, 0, sizeof(mem_info));
891 mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
892 mem_info.allocationSize = mem_req.size;
893 mem_info.memProps = VK_MEMORY_PROPERTY_SHAREABLE_BIT;
894 mem_info.memPriority = VK_MEMORY_PRIORITY_NORMAL;
895 err = vkAllocMemory(device(), &mem_info, &event_mem);
896 ASSERT_VK_SUCCESS(err);
897
898 err = vkBindObjectMemory(device(), VK_OBJECT_TYPE_EVENT, event, 0, event_mem, 0);
899 ASSERT_VK_SUCCESS(err);
900
901 err = vkResetEvent(device(), event);
902 ASSERT_VK_SUCCESS(err);
903
904 struct thread_data_struct data;
905 data.cmdBuffer = cmdBuffer.obj();
906 data.event = event;
907 data.bailout = false;
908 m_errorMonitor->SetBailout(&data.bailout);
909 // Add many entries to command buffer from another thread.
910 pthread_create(&thread, &thread_attr, AddToCommandBuffer, (void *)&data);
911 // Add many entries to command buffer from this thread at the same time.
912 AddToCommandBuffer(&data);
913 pthread_join(thread, NULL);
914 EndCommandBuffer(cmdBuffer);
915
916 msgType = m_errorMonitor->GetState(&msgString);
917 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an err from using one VkCommandBufferObj in two threads";
918 if (!strstr(msgString.c_str(),"THREADING ERROR")) {
Mark Lobodzinski5f25be42015-05-14 15:08:13 -0500919 FAIL() << "Error received was not 'THREADING ERROR'";
Mike Stroyan09aae812015-05-12 16:00:45 -0600920 }
921
922}
923#endif
924
Tony Barbour30486ea2015-04-07 13:44:53 -0600925int main(int argc, char **argv) {
926 int result;
927
928 ::testing::InitGoogleTest(&argc, argv);
Tony Barbour01999182015-04-09 12:58:51 -0600929 VkTestFramework::InitArgs(&argc, argv);
Tony Barbour30486ea2015-04-07 13:44:53 -0600930
931 ::testing::AddGlobalTestEnvironment(new TestEnvironment);
932
933 result = RUN_ALL_TESTS();
934
Tony Barbour01999182015-04-09 12:58:51 -0600935 VkTestFramework::Finish();
Tony Barbour30486ea2015-04-07 13:44:53 -0600936 return result;
937}