blob: f00a465ae0e254d41d3ce5c3b6087021c7d90c8b [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"
Tony Barbour30486ea2015-04-07 13:44:53 -06005
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06006void VKAPI myDbgFunc(
7 VK_DBG_MSG_TYPE msgType,
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -06008 VkValidationLevel validationLevel,
Mike Stroyan230e6252015-04-17 12:36:38 -06009 VkObject srcObject,
Tony Barbour30486ea2015-04-07 13:44:53 -060010 size_t location,
11 int32_t msgCode,
12 const char* pMsg,
13 void* pUserData);
14
15class ErrorMonitor {
16public:
Tony Barbour0c1bdc62015-04-29 17:34:29 -060017 ErrorMonitor()
Tony Barbour30486ea2015-04-07 13:44:53 -060018 {
Mike Stroyan09aae812015-05-12 16:00:45 -060019 pthread_mutexattr_t attr;
20 pthread_mutexattr_init(&attr);
21 pthread_mutex_init(&m_mutex, &attr);
22 pthread_mutex_lock(&m_mutex);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060023 m_msgType = VK_DBG_MSG_UNKNOWN;
Mike Stroyan09aae812015-05-12 16:00:45 -060024 m_bailout = NULL;
25 pthread_mutex_unlock(&m_mutex);
Tony Barbour30486ea2015-04-07 13:44:53 -060026 }
27 void ClearState()
28 {
Mike Stroyan09aae812015-05-12 16:00:45 -060029 pthread_mutex_lock(&m_mutex);
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060030 m_msgType = VK_DBG_MSG_UNKNOWN;
Tony Barbour30486ea2015-04-07 13:44:53 -060031 m_msgString.clear();
Mike Stroyan09aae812015-05-12 16:00:45 -060032 pthread_mutex_unlock(&m_mutex);
Tony Barbour30486ea2015-04-07 13:44:53 -060033 }
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060034 VK_DBG_MSG_TYPE GetState(std::string *msgString)
Tony Barbour30486ea2015-04-07 13:44:53 -060035 {
Mike Stroyan09aae812015-05-12 16:00:45 -060036 pthread_mutex_lock(&m_mutex);
Tony Barbour30486ea2015-04-07 13:44:53 -060037 *msgString = m_msgString;
Mike Stroyan09aae812015-05-12 16:00:45 -060038 pthread_mutex_unlock(&m_mutex);
Tony Barbour30486ea2015-04-07 13:44:53 -060039 return m_msgType;
40 }
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060041 void SetState(VK_DBG_MSG_TYPE msgType, const char *msgString)
Tony Barbour30486ea2015-04-07 13:44:53 -060042 {
Mike Stroyan09aae812015-05-12 16:00:45 -060043 pthread_mutex_lock(&m_mutex);
44 if (m_bailout != NULL) {
45 *m_bailout = true;
46 }
Tony Barbour30486ea2015-04-07 13:44:53 -060047 m_msgType = msgType;
Tony Barbour8508b8e2015-04-09 10:48:04 -060048 m_msgString.reserve(strlen(msgString));
49 m_msgString = msgString;
Mike Stroyan09aae812015-05-12 16:00:45 -060050 pthread_mutex_unlock(&m_mutex);
51 }
52 void SetBailout(bool *bailout)
53 {
54 m_bailout = bailout;
Tony Barbour30486ea2015-04-07 13:44:53 -060055 }
56
57private:
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060058 VK_DBG_MSG_TYPE m_msgType;
Mike Stroyan09aae812015-05-12 16:00:45 -060059 std::string m_msgString;
60 pthread_mutex_t m_mutex;
61 bool* m_bailout;
Tony Barbour30486ea2015-04-07 13:44:53 -060062};
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060063void VKAPI myDbgFunc(
Mike Stroyan230e6252015-04-17 12:36:38 -060064 VK_DBG_MSG_TYPE msgType,
65 VkValidationLevel validationLevel,
66 VkObject srcObject,
Tony Barbour30486ea2015-04-07 13:44:53 -060067 size_t location,
68 int32_t msgCode,
69 const char* pMsg,
70 void* pUserData)
71{
Tony Barbour8508b8e2015-04-09 10:48:04 -060072 if (msgType == VK_DBG_MSG_WARNING || msgType == VK_DBG_MSG_ERROR) {
73 ErrorMonitor *errMonitor = (ErrorMonitor *)pUserData;
74 errMonitor->SetState(msgType, pMsg);
75 }
Tony Barbour30486ea2015-04-07 13:44:53 -060076}
Tony Barbour01999182015-04-09 12:58:51 -060077class VkLayerTest : public VkRenderFramework
Tony Barbour30486ea2015-04-07 13:44:53 -060078{
79public:
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -060080 VkResult BeginCommandBuffer(VkCommandBufferObj &cmdBuffer);
81 VkResult EndCommandBuffer(VkCommandBufferObj &cmdBuffer);
Tony Barbour30486ea2015-04-07 13:44:53 -060082
83protected:
Tony Barbour01999182015-04-09 12:58:51 -060084 VkMemoryRefManager m_memoryRefManager;
85 ErrorMonitor *m_errorMonitor;
Tony Barbour30486ea2015-04-07 13:44:53 -060086
87 virtual void SetUp() {
Mike Stroyan09aae812015-05-12 16:00:45 -060088 const char *extension_names[] = {"MemTracker", "ObjectTracker", "Threading"};
89 const std::vector<const char *> extensions(extension_names,
90 extension_names + sizeof(extension_names)/sizeof(extension_names[0]));
Tony Barbour950ebc02015-04-23 12:55:36 -060091
92 size_t extSize = sizeof(uint32_t);
93 uint32_t extCount = 0;
Tony Barbour04ada4a2015-04-23 15:28:27 -060094 VkResult U_ASSERT_ONLY err;
Tony Barbour950ebc02015-04-23 12:55:36 -060095 err = vkGetGlobalExtensionInfo(VK_EXTENSION_INFO_TYPE_COUNT, 0, &extSize, &extCount);
96 assert(!err);
97
98 VkExtensionProperties extProp;
99 extSize = sizeof(VkExtensionProperties);
100 bool32_t extFound;
101
Tony Barbour04ada4a2015-04-23 15:28:27 -0600102 for (uint32_t i = 0; i < extensions.size(); i++) {
Tony Barbour950ebc02015-04-23 12:55:36 -0600103 extFound = 0;
104 for (uint32_t j = 0; j < extCount; j++) {
105 err = vkGetGlobalExtensionInfo(VK_EXTENSION_INFO_TYPE_PROPERTIES, j, &extSize, &extProp);
Tony Barbour04ada4a2015-04-23 15:28:27 -0600106 assert(!err);
107 if (!strcmp(extensions[i], extProp.extName)) {
Tony Barbour950ebc02015-04-23 12:55:36 -0600108 extFound = 1;
109 break;
110 }
111 }
Tony Barbour04ada4a2015-04-23 15:28:27 -0600112 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 -0600113 }
Tony Barbour30486ea2015-04-07 13:44:53 -0600114
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600115 this->app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
Tony Barbour30486ea2015-04-07 13:44:53 -0600116 this->app_info.pNext = NULL;
117 this->app_info.pAppName = "layer_tests";
118 this->app_info.appVersion = 1;
119 this->app_info.pEngineName = "unittest";
120 this->app_info.engineVersion = 1;
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600121 this->app_info.apiVersion = VK_API_VERSION;
Tony Barbour30486ea2015-04-07 13:44:53 -0600122
Tony Barbour0c1bdc62015-04-29 17:34:29 -0600123 m_errorMonitor = new ErrorMonitor;
124 InitFramework(extensions, myDbgFunc, m_errorMonitor);
125
Tony Barbour30486ea2015-04-07 13:44:53 -0600126 }
127
128 virtual void TearDown() {
129 // Clean up resources before we reset
Tony Barbour30486ea2015-04-07 13:44:53 -0600130 ShutdownFramework();
Tony Barbour8508b8e2015-04-09 10:48:04 -0600131 delete m_errorMonitor;
Tony Barbour30486ea2015-04-07 13:44:53 -0600132 }
133};
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600134VkResult VkLayerTest::BeginCommandBuffer(VkCommandBufferObj &cmdBuffer)
Tony Barbour30486ea2015-04-07 13:44:53 -0600135{
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600136 VkResult result;
Tony Barbour30486ea2015-04-07 13:44:53 -0600137
138 result = cmdBuffer.BeginCommandBuffer();
139
140 /*
141 * For render test all drawing happens in a single render pass
142 * on a single command buffer.
143 */
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600144 if (VK_SUCCESS == result) {
Tony Barbour30486ea2015-04-07 13:44:53 -0600145 cmdBuffer.BeginRenderPass(renderPass(), framebuffer());
146 }
147
148 return result;
149}
150
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600151VkResult VkLayerTest::EndCommandBuffer(VkCommandBufferObj &cmdBuffer)
Tony Barbour30486ea2015-04-07 13:44:53 -0600152{
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600153 VkResult result;
Tony Barbour30486ea2015-04-07 13:44:53 -0600154
155 cmdBuffer.EndRenderPass(renderPass());
156
157 result = cmdBuffer.EndCommandBuffer();
158
159 return result;
160}
161
Tony Barbour8508b8e2015-04-09 10:48:04 -0600162TEST_F(VkLayerTest, SubmitSignaledFence)
Tony Barbour30486ea2015-04-07 13:44:53 -0600163{
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600164 vk_testing::Fence testFence;
165 VK_DBG_MSG_TYPE msgType;
Tony Barbour30486ea2015-04-07 13:44:53 -0600166 std::string msgString;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600167
168 VkFenceCreateInfo fenceInfo = {};
Tony Barbour8508b8e2015-04-09 10:48:04 -0600169 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
170 fenceInfo.pNext = NULL;
171 fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
Tony Barbour30486ea2015-04-07 13:44:53 -0600172
Tony Barbour30486ea2015-04-07 13:44:53 -0600173 ASSERT_NO_FATAL_FAILURE(InitState());
174 ASSERT_NO_FATAL_FAILURE(InitViewport());
175 ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
176
Tony Barbour01999182015-04-09 12:58:51 -0600177 VkCommandBufferObj cmdBuffer(m_device);
Tony Barbour30486ea2015-04-07 13:44:53 -0600178 cmdBuffer.AddRenderTarget(m_renderTargets[0]);
179
Tony Barbour8508b8e2015-04-09 10:48:04 -0600180 BeginCommandBuffer(cmdBuffer);
Tony Barbour30486ea2015-04-07 13:44:53 -0600181 cmdBuffer.ClearAllBuffers(m_clear_color, m_depth_clear_color, m_stencil_clear_color, NULL);
Tony Barbour8508b8e2015-04-09 10:48:04 -0600182 EndCommandBuffer(cmdBuffer);
Tony Barbour30486ea2015-04-07 13:44:53 -0600183
184 testFence.init(*m_device, fenceInfo);
185 m_errorMonitor->ClearState();
Tony Barbour8508b8e2015-04-09 10:48:04 -0600186 cmdBuffer.QueueCommandBuffer(testFence.obj());
Tony Barbour30486ea2015-04-07 13:44:53 -0600187 msgType = m_errorMonitor->GetState(&msgString);
Tony Barbour8508b8e2015-04-09 10:48:04 -0600188 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an err from using a fence in SIGNALED state in call to vkQueueSubmit";
189 if (!strstr(msgString.c_str(),"submitted in SIGNALED state. Fences must be reset before being submitted")) {
Tony Barbour9c238c42015-04-09 16:00:51 -0600190 FAIL() << "Error received was not VkQueueSubmit with fence in SIGNALED_STATE";
Tony Barbour8508b8e2015-04-09 10:48:04 -0600191 }
192
193}
194
195TEST_F(VkLayerTest, ResetUnsignaledFence)
196{
197 vk_testing::Fence testFence;
198 VK_DBG_MSG_TYPE msgType;
199 std::string msgString;
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600200 VkFenceCreateInfo fenceInfo = {};
Tony Barbour8508b8e2015-04-09 10:48:04 -0600201 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
202 fenceInfo.pNext = NULL;
203
Tony Barbour8508b8e2015-04-09 10:48:04 -0600204 ASSERT_NO_FATAL_FAILURE(InitState());
205 testFence.init(*m_device, fenceInfo);
206 m_errorMonitor->ClearState();
Courtney Goeltzenleuchter382489d2015-04-10 08:34:15 -0600207 VkFence fences[1] = {testFence.obj()};
Tony Barbour8508b8e2015-04-09 10:48:04 -0600208 vkResetFences(m_device->device(), 1, fences);
209 msgType = m_errorMonitor->GetState(&msgString);
210 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 -0600211 if (!strstr(msgString.c_str(),"submitted to VkResetFences in UNSIGNALED STATE")) {
Tony Barbour9c238c42015-04-09 16:00:51 -0600212 FAIL() << "Error received was not VkResetFences with fence in UNSIGNALED_STATE";
Tony Barbour8508b8e2015-04-09 10:48:04 -0600213 }
Tony Barbour30486ea2015-04-07 13:44:53 -0600214
215}
216
Tony Barbour54cdd192015-04-22 15:12:07 -0600217TEST_F(VkLayerTest, WaitForUnsubmittedFence)
218{
219 vk_testing::Fence testFence;
220 VK_DBG_MSG_TYPE msgType;
221 std::string msgString;
222 VkFenceCreateInfo fenceInfo = {};
223 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
224 fenceInfo.pNext = NULL;
225
Tony Barbour54cdd192015-04-22 15:12:07 -0600226 ASSERT_NO_FATAL_FAILURE(InitState());
227 testFence.init(*m_device, fenceInfo);
228 m_errorMonitor->ClearState();
229 vkGetFenceStatus(m_device->device(),testFence.obj());
230 msgType = m_errorMonitor->GetState(&msgString);
231 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error asking for status of unsubmitted fence";
232 if (!strstr(msgString.c_str(),"Status Requested for Unsubmitted Fence")) {
233 FAIL() << "Error received was not Status Requested for Unsubmitted Fence";
234 }
235
236 VkFence fences[1] = {testFence.obj()};
237 m_errorMonitor->ClearState();
238 vkWaitForFences(m_device->device(), 1, fences, VK_TRUE, 0);
239 msgType = m_errorMonitor->GetState(&msgString);
240 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error for waiting for unsubmitted fence";
241 if (!strstr(msgString.c_str(),"Waiting for Unsubmitted Fence")) {
242 FAIL() << "Error received was not Waiting for Unsubmitted Fence";
243 }
244}
245
Tony Barbourdb686622015-05-06 09:35:56 -0600246TEST_F(VkLayerTest, GetObjectInfoMismatchedType)
247{
248 VkEventCreateInfo event_info;
249 VkEvent event;
250 VkMemoryRequirements mem_req;
251 size_t data_size = sizeof(mem_req);
252 VK_DBG_MSG_TYPE msgType;
253 std::string msgString;
254 VkResult err;
255
256 ASSERT_NO_FATAL_FAILURE(InitState());
257 memset(&event_info, 0, sizeof(event_info));
258 event_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
259
260 err = vkCreateEvent(device(), &event_info, &event);
261 ASSERT_VK_SUCCESS(err);
262 m_errorMonitor->ClearState();
263 err = vkGetObjectInfo(device(), VK_OBJECT_TYPE_IMAGE, event, VK_OBJECT_INFO_TYPE_MEMORY_REQUIREMENTS,
264 &data_size, &mem_req);
265 msgType = m_errorMonitor->GetState(&msgString);
266 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an error from mismatched types in vkGetObjectInfo";
267 if (!strstr(msgString.c_str(),"does not match designated type")) {
268 FAIL() << "Error received was not event does not match designated type image";
269 }
270
271}
272
Mike Stroyan09aae812015-05-12 16:00:45 -0600273#if GTEST_IS_THREADSAFE
274struct thread_data_struct {
275 VkCmdBuffer cmdBuffer;
276 VkEvent event;
277 bool bailout;
278};
279
280extern "C" void *AddToCommandBuffer(void *arg)
281{
282 struct thread_data_struct *data = (struct thread_data_struct *) arg;
283 std::string msgString;
284
285 for (int i = 0; i<10000; i++) {
286 vkCmdSetEvent(data->cmdBuffer, data->event, VK_PIPE_EVENT_COMMANDS_COMPLETE);
287 if (data->bailout) {
288 break;
289 }
290 }
291 return NULL;
292}
293
294TEST_F(VkLayerTest, ThreadCmdBufferCollision)
295{
296 VK_DBG_MSG_TYPE msgType;
297 std::string msgString;
298 pthread_t thread;
299 pthread_attr_t thread_attr;
300
301 ASSERT_NO_FATAL_FAILURE(InitState());
302 ASSERT_NO_FATAL_FAILURE(InitViewport());
303 ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
304
305 VkCommandBufferObj cmdBuffer(m_device);
306
307 m_errorMonitor->ClearState();
308 pthread_attr_init(&thread_attr);
309 BeginCommandBuffer(cmdBuffer);
310
311 VkEventCreateInfo event_info;
312 VkEvent event;
313 VkMemoryRequirements mem_req;
314 size_t data_size = sizeof(mem_req);
315 VkResult err;
316
317 memset(&event_info, 0, sizeof(event_info));
318 event_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
319
320 err = vkCreateEvent(device(), &event_info, &event);
321 ASSERT_VK_SUCCESS(err);
322
323 err = vkGetObjectInfo(device(), VK_OBJECT_TYPE_EVENT, event, VK_OBJECT_INFO_TYPE_MEMORY_REQUIREMENTS,
324 &data_size, &mem_req);
325 ASSERT_VK_SUCCESS(err);
326
327 VkMemoryAllocInfo mem_info;
328 VkDeviceMemory event_mem;
329
330 ASSERT_NE(0, mem_req.size) << "vkGetObjectInfo (Event): Failed - expect events to require memory";
331
332 memset(&mem_info, 0, sizeof(mem_info));
333 mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
334 mem_info.allocationSize = mem_req.size;
335 mem_info.memProps = VK_MEMORY_PROPERTY_SHAREABLE_BIT;
336 mem_info.memPriority = VK_MEMORY_PRIORITY_NORMAL;
337 err = vkAllocMemory(device(), &mem_info, &event_mem);
338 ASSERT_VK_SUCCESS(err);
339
340 err = vkBindObjectMemory(device(), VK_OBJECT_TYPE_EVENT, event, 0, event_mem, 0);
341 ASSERT_VK_SUCCESS(err);
342
343 err = vkResetEvent(device(), event);
344 ASSERT_VK_SUCCESS(err);
345
346 struct thread_data_struct data;
347 data.cmdBuffer = cmdBuffer.obj();
348 data.event = event;
349 data.bailout = false;
350 m_errorMonitor->SetBailout(&data.bailout);
351 // Add many entries to command buffer from another thread.
352 pthread_create(&thread, &thread_attr, AddToCommandBuffer, (void *)&data);
353 // Add many entries to command buffer from this thread at the same time.
354 AddToCommandBuffer(&data);
355 pthread_join(thread, NULL);
356 EndCommandBuffer(cmdBuffer);
357
358 msgType = m_errorMonitor->GetState(&msgString);
359 ASSERT_EQ(msgType, VK_DBG_MSG_ERROR) << "Did not receive an err from using one VkCommandBufferObj in two threads";
360 if (!strstr(msgString.c_str(),"THREADING ERROR")) {
361 FAIL() << "Error received was not THREADING ERROR";
362 }
363
364}
365#endif
366
Tony Barbour30486ea2015-04-07 13:44:53 -0600367int main(int argc, char **argv) {
368 int result;
369
370 ::testing::InitGoogleTest(&argc, argv);
Tony Barbour01999182015-04-09 12:58:51 -0600371 VkTestFramework::InitArgs(&argc, argv);
Tony Barbour30486ea2015-04-07 13:44:53 -0600372
373 ::testing::AddGlobalTestEnvironment(new TestEnvironment);
374
375 result = RUN_ALL_TESTS();
376
Tony Barbour01999182015-04-09 12:58:51 -0600377 VkTestFramework::Finish();
Tony Barbour30486ea2015-04-07 13:44:53 -0600378 return result;
379}