blob: 7a59c8e8a7701e187f1240063cf859d6affda2de [file] [log] [blame]
Chia-I Wucb67c652014-10-21 11:06:26 +08001// Copyright 2005, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14// * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30
31// XGL tests
32//
33// Copyright (C) 2014 LunarG, Inc.
34//
35// Permission is hereby granted, free of charge, to any person obtaining a
36// copy of this software and associated documentation files (the "Software"),
37// to deal in the Software without restriction, including without limitation
38// the rights to use, copy, modify, merge, publish, distribute, sublicense,
39// and/or sell copies of the Software, and to permit persons to whom the
40// Software is furnished to do so, subject to the following conditions:
41//
42// The above copyright notice and this permission notice shall be included
43// in all copies or substantial portions of the Software.
44//
45// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
47// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
48// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
49// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
50// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
51// DEALINGS IN THE SOFTWARE.
52
53// Blit (copy, clear, and resolve) tests
54
55#include <string.h>
56#include <xgl.h>
57#include "gtest-1.7.0/include/gtest/gtest.h"
58#include "xgldevice.h"
59#include "xglimage.h"
60#include "xgltestframework.h"
61
62#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
63
64class XglBlitTest : public XglTestFramework
65{
66protected:
67 XGL_APPLICATION_INFO app_info;
68 XglDevice *m_device;
69
70 XGL_CMD_BUFFER m_cmd;
71
72 XGL_MEMORY_REF m_mem_refs[8];
73 XGL_UINT m_mem_ref_count;
74
75 virtual void SetUp();
76 virtual void TearDown();
77
78 XGL_DEVICE device() { return m_device->device(); }
79
80 void ClearMemoryRefs()
81 {
82 m_mem_ref_count = 0;
83 }
84
85 void AddMemoryRef(XGL_GPU_MEMORY mem, bool readonly)
86 {
87 ASSERT_LE(m_mem_ref_count, ARRAY_SIZE(m_mem_refs));
88
89 m_mem_refs[m_mem_ref_count].mem = mem;
90 m_mem_refs[m_mem_ref_count].flags =
91 (readonly) ? XGL_MEMORY_REF_READ_ONLY_BIT : 0;
92 m_mem_ref_count++;
93 }
94
95 XGL_GPU_MEMORY AllocMemory(XGL_GPU_SIZE size)
96 {
97 XGL_MEMORY_ALLOC_INFO info;
98 XGL_GPU_MEMORY mem;
99 XGL_RESULT err;
100
101 memset(&info, 0, sizeof(info));
102 info.sType = XGL_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
103 info.allocationSize = size;
104 info.alignment = 1;
105 info.heapCount = 1;
106 info.memPriority = XGL_MEMORY_PRIORITY_NORMAL;
107
108 err = xglAllocMemory(device(), &info, &mem);
109 if (err)
110 mem = XGL_NULL_HANDLE;
111
112 return mem;
113 }
114
115 XGL_GPU_MEMORY AddMemory(XGL_GPU_SIZE size, bool readonly)
116 {
117 XGL_GPU_MEMORY mem;
118
119 mem = AllocMemory(size);
120 if (mem)
121 AddMemoryRef(mem, readonly);
122
123 return mem;
124 }
125
126 void BeginCmd()
127 {
128 XGL_RESULT err;
129
130 err = xglBeginCommandBuffer(m_cmd,
131 XGL_CMD_BUFFER_OPTIMIZE_GPU_SMALL_BATCH_BIT |
132 XGL_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT);
133 ASSERT_XGL_SUCCESS(err);
134 }
135
136 void EndAndSubmitCmd()
137 {
138 XGL_RESULT err;
139
140 err = xglEndCommandBuffer(m_cmd);
141 ASSERT_XGL_SUCCESS(err);
142
143 err = xglQueueSubmit(m_device->m_queue, 1, &m_cmd, m_mem_ref_count, m_mem_refs, NULL );
144 ASSERT_XGL_SUCCESS(err);
145
146 err = xglQueueWaitIdle(m_device->m_queue);
147 ASSERT_XGL_SUCCESS(err);
148 }
149};
150
151void XglBlitTest::SetUp()
152{
153 XGL_CMD_BUFFER_CREATE_INFO cmd_info;
154 XGL_PHYSICAL_GPU gpu;
155 XGL_UINT count;
156 XGL_RESULT err;
157
158 memset(&app_info, 0, sizeof(app_info));
159 app_info.sType = XGL_STRUCTURE_TYPE_APPLICATION_INFO;
160 app_info.pNext = NULL;
161 app_info.pAppName = (const XGL_CHAR *) "blit tests";
162 app_info.appVersion = 1;
163 app_info.pEngineName = (const XGL_CHAR *) "unittest";
164 app_info.engineVersion = 1;
165 app_info.apiVersion = XGL_MAKE_VERSION(0, 22, 0);
166
167 err = xglInitAndEnumerateGpus(&app_info, NULL, 1, &count, &gpu);
168 ASSERT_XGL_SUCCESS(err);
169 ASSERT_GE(1, count) << "No GPU available";
170
171 m_device = new XglDevice(0, gpu);
172 m_device->get_device_queue();
173
174 memset(&cmd_info, 0, sizeof(cmd_info));
175 cmd_info.sType = XGL_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO;
176 cmd_info.queueType = XGL_QUEUE_TYPE_GRAPHICS;
177
178 err = xglCreateCommandBuffer(device(), &cmd_info, &m_cmd);
179 ASSERT_XGL_SUCCESS(err) << "xglCreateCommandBuffer failed";
180}
181
182void XglBlitTest::TearDown()
183{
184 XGL_UINT dummy_count;
185
186 xglDestroyObject(m_cmd);
187 xglInitAndEnumerateGpus(&app_info, NULL, 0, &dummy_count, NULL);
188}
189
190TEST_F(XglBlitTest, FillMemory)
191{
192 const struct {
193 XGL_GPU_SIZE offset;
194 XGL_GPU_SIZE size;
195 XGL_UINT value;
196 } ranges[] = {
197 { 0, 64, 0x11111111 }, // 16-byte aligned
198 { 64, 12, 0x22222222 }, // 4-byte aligned
199 { 76, 4, 0x33333333 }, // min. fill size
200 { 80, 20, 0x44444444 },
201 { 92, 8, 0x55555555 }, // overlapped
202 };
203 XGL_GPU_MEMORY mem;
204 XGL_RESULT err;
205 void *data;
206 XGL_UINT i;
207
208 ClearMemoryRefs();
209
210 mem = AddMemory(256, false);
211 ASSERT_NE((XGL_GPU_MEMORY) XGL_NULL_HANDLE, mem);
212
213 BeginCmd();
214 for (i = 0; i < ARRAY_SIZE(ranges); i++) {
215 xglCmdFillMemory(m_cmd, mem, ranges[i].offset,
216 ranges[i].size, ranges[i].value);
217 }
218 EndAndSubmitCmd();
219
220 err = xglMapMemory(mem, 0, &data);
221 ASSERT_XGL_SUCCESS(err);
222
223 for (i = 0; i < ARRAY_SIZE(ranges); i++) {
224 const XGL_UINT expected = ranges[i].value;
225 const XGL_UINT *real = (const XGL_UINT *)
226 ((char *) data + ranges[i].offset);
227 XGL_UINT count, j;
228
229 count = ranges[i].size / 4;
230
231 /* check if the next range overlaps */
232 if (i + 1 < ARRAY_SIZE(ranges)) {
233 if (ranges[i].offset + ranges[i].size > ranges[i + 1].offset)
234 count = (ranges[i + 1].offset - ranges[i].offset) / 4;
235 }
236
237 for (j = 0; j < count; j++)
238 ASSERT_EQ(expected, real[j]);
239 }
240
241 xglUnmapMemory(mem);
242 xglFreeMemory(mem);
243}
244
245TEST_F(XglBlitTest, CopyMemory)
246{
247 XGL_GPU_MEMORY src, dst;
248 XGL_MEMORY_COPY regions[17];
249 XGL_RESULT err;
250 void *data;
251 XGL_UINT i;
252
253 ClearMemoryRefs();
254
255 src = AddMemory(256, false);
256 ASSERT_NE((XGL_GPU_MEMORY) XGL_NULL_HANDLE, src);
257
258 err = xglMapMemory(src, 0, &data);
259 ASSERT_XGL_SUCCESS(err);
260 for (i = 0; i < 256; i++)
261 ((char *) data)[i] = i;
262 xglUnmapMemory(src);
263
264 dst = AddMemory(256, false);
265 ASSERT_NE((XGL_GPU_MEMORY) XGL_NULL_HANDLE, dst);
266
267 /* copy with various alignments */
268 for (i = 0; i < 16; i++) {
269 regions[i].copySize = i + 1;
270 regions[i].srcOffset = i * 8;
271
272 if (i > 0) {
273 regions[i].destOffset = regions[i - 1].destOffset +
274 regions[i - 1].copySize;
275 } else {
276 regions[i].destOffset = 0;
277 }
278 }
279
280 regions[i].srcOffset = 192;
281 regions[i].destOffset = 192;
282 regions[i].copySize = 64;
283
284 BeginCmd();
285
286 xglCmdCopyMemory(m_cmd, src, dst, 16, regions);
287 xglCmdCopyMemory(m_cmd, src, dst, 1, &regions[16]);
288
289 EndAndSubmitCmd();
290
291 err = xglMapMemory(dst, 0, &data);
292 ASSERT_XGL_SUCCESS(err);
293
294 for (i = 0; i < ARRAY_SIZE(regions); i++) {
295 const unsigned char *real = (const unsigned char *) data +
296 regions[i].destOffset;
297 XGL_UINT j;
298
299 for (j = 0; j < regions[i].copySize; j++)
300 ASSERT_EQ(regions[i].srcOffset + j, real[j]);
301 }
302
303 xglUnmapMemory(dst);
304 xglFreeMemory(src);
305 xglFreeMemory(dst);
306}
307
308TEST_F(XglBlitTest, ClearColorImageBasic)
309{
310 const XGL_FLOAT color[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
311 const XGL_UINT width = 64;
312 const XGL_UINT height = 64;
313 XglImage *img;
314 XGL_FORMAT format;
315 XGL_IMAGE_SUBRESOURCE subres;
316 XGL_IMAGE_SUBRESOURCE_RANGE subres_range;
317 XGL_IMAGE_STATE_TRANSITION transition;
318 XGL_RESULT err;
319
320 format.channelFormat = XGL_CH_FMT_R8G8B8A8;
321 format.numericFormat = XGL_NUM_FMT_UNORM;
322
323 subres.aspect = XGL_IMAGE_ASPECT_COLOR;
324 subres.mipLevel = 0;
325 subres.arraySlice = 0;
326
327 subres_range.aspect = XGL_IMAGE_ASPECT_COLOR;
328 subres_range.baseMipLevel = 0;
329 subres_range.mipLevels = 1;
330 subres_range.baseArraySlice = 0;
331 subres_range.arraySize = 1;
332
333 img = new XglImage(m_device);
334 img->init(width, height, format, XGL_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
335
336 ClearMemoryRefs();
337 AddMemoryRef(img->memory(), false);
338
339 BeginCmd();
340
341 transition.image = img->image();
342 transition.oldState = XGL_IMAGE_STATE_UNINITIALIZED_TARGET;
343 transition.newState = XGL_IMAGE_STATE_CLEAR;
344 transition.subresourceRange = subres_range;
345 xglCmdPrepareImages(m_cmd, 1, &transition);
346
347 xglCmdClearColorImage(m_cmd, img->image(), color, 1, &subres_range);
348
349 EndAndSubmitCmd();
350
351 {
352 XGL_SUBRESOURCE_LAYOUT layout;
353 XGL_SIZE layout_size;
354 XGL_UINT x, y;
355 void *data;
356
357 err = img->MapMemory(&data);
358 ASSERT_XGL_SUCCESS(err);
359
360 err = xglGetImageSubresourceInfo(img->image(), &subres,
361 XGL_INFO_TYPE_SUBRESOURCE_LAYOUT, &layout_size, &layout);
362 ASSERT_XGL_SUCCESS(err);
363 ASSERT_EQ(sizeof(layout), layout_size);
364
365 for (y = 0; y < height; y++) {
366 const XGL_UINT *real = (const XGL_UINT *)
367 ((char *) data + layout.offset + layout.rowPitch * y);
368
369 for (x = 0; x < width; x++)
370 ASSERT_EQ(0xff00ff00, real[x]);
371 }
372
373 img->UnmapMemory();
374 }
375
376 delete img;
377}
378
379TEST_F(XglBlitTest, CopyImageBasic)
380{
381 const XGL_FLOAT color[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
382 const XGL_UINT width = 64;
383 const XGL_UINT height = 64;
384 XglImage *src, *dst;
385 XGL_FORMAT format;
386 XGL_IMAGE_SUBRESOURCE subres;
387 XGL_IMAGE_SUBRESOURCE_RANGE subres_range;
388 XGL_IMAGE_STATE_TRANSITION transition;
389 XGL_RESULT err;
390
391 format.channelFormat = XGL_CH_FMT_R8G8B8A8;
392 format.numericFormat = XGL_NUM_FMT_UNORM;
393
394 subres.aspect = XGL_IMAGE_ASPECT_COLOR;
395 subres.mipLevel = 0;
396 subres.arraySlice = 0;
397
398 subres_range.aspect = XGL_IMAGE_ASPECT_COLOR;
399 subres_range.baseMipLevel = 0;
400 subres_range.mipLevels = 1;
401 subres_range.baseArraySlice = 0;
402 subres_range.arraySize = 1;
403
404 src = new XglImage(m_device);
405 src->init(width, height, format, XGL_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
406 dst = new XglImage(m_device);
407 dst->init(width, height, format, XGL_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
408
409 ClearMemoryRefs();
410 AddMemoryRef(src->memory(), false);
411 AddMemoryRef(dst->memory(), false);
412
413 BeginCmd();
414
415 transition.image = src->image();
416 transition.oldState = XGL_IMAGE_STATE_UNINITIALIZED_TARGET;
417 transition.newState = XGL_IMAGE_STATE_CLEAR;
418 transition.subresourceRange = subres_range;
419 xglCmdPrepareImages(m_cmd, 1, &transition);
420
421 xglCmdClearColorImage(m_cmd, src->image(), color, 1, &subres_range);
422
423 transition.oldState = XGL_IMAGE_STATE_CLEAR;
424 transition.newState = XGL_IMAGE_STATE_DATA_TRANSFER;
425 xglCmdPrepareImages(m_cmd, 1, &transition);
426
427 transition.image = dst->image();
428 transition.oldState = XGL_IMAGE_STATE_UNINITIALIZED_TARGET;
429 transition.newState = XGL_IMAGE_STATE_DATA_TRANSFER;
430 xglCmdPrepareImages(m_cmd, 1, &transition);
431
432 XGL_IMAGE_COPY copy;
433 memset(&copy, 0, sizeof(copy));
434 copy.srcSubresource = subres;
435 copy.destSubresource = subres;
436 copy.extent.width = width;
437 copy.extent.height = height;
438 copy.extent.depth = 1;
439 xglCmdCopyImage(m_cmd, src->image(), dst->image(), 1, &copy);
440
441 EndAndSubmitCmd();
442
443 {
444 XGL_SUBRESOURCE_LAYOUT layout;
445 XGL_SIZE layout_size;
446 void *data;
447 XGL_UINT x, y;
448
449 err = dst->MapMemory(&data);
450 ASSERT_XGL_SUCCESS(err);
451
452 err = xglGetImageSubresourceInfo(dst->image(), &subres,
453 XGL_INFO_TYPE_SUBRESOURCE_LAYOUT, &layout_size, &layout);
454 ASSERT_XGL_SUCCESS(err);
455 ASSERT_EQ(sizeof(layout), layout_size);
456
457 for (y = 0; y < height; y++) {
458 const XGL_UINT *real = (const XGL_UINT *)
459 ((char *) data + layout.offset + layout.rowPitch * y);
460
461 for (x = 0; x < width; x++)
462 ASSERT_EQ(0xff00ff00, real[x]);
463 }
464
465 dst->UnmapMemory();
466 }
467
468 delete src;
469 delete dst;
470}
471
472TEST_F(XglBlitTest, ClearDepthStencilBasic)
473{
474 const XGL_FLOAT clear_depth = 0.4f;
475 const XGL_UINT width = 64;
476 const XGL_UINT height = 64;
477 XglImage *img;
478 XGL_FORMAT format;
479 XGL_IMAGE_SUBRESOURCE subres;
480 XGL_IMAGE_SUBRESOURCE_RANGE subres_range;
481 XGL_IMAGE_STATE_TRANSITION transition;
482 XGL_RESULT err;
483
484 format.channelFormat = XGL_CH_FMT_R32;
485 format.numericFormat = XGL_NUM_FMT_DS;
486
487 subres.aspect = XGL_IMAGE_ASPECT_DEPTH;
488 subres.mipLevel = 0;
489 subres.arraySlice = 0;
490
491 subres_range.aspect = XGL_IMAGE_ASPECT_DEPTH;
492 subres_range.baseMipLevel = 0;
493 subres_range.mipLevels = 1;
494 subres_range.baseArraySlice = 0;
495 subres_range.arraySize = 1;
496
497 img = new XglImage(m_device);
498 img->init(width, height, format, XGL_IMAGE_USAGE_DEPTH_STENCIL_BIT,
499 XGL_OPTIMAL_TILING);
500
501 ClearMemoryRefs();
502 AddMemoryRef(img->memory(), false);
503
504 BeginCmd();
505
506 transition.image = img->image();
507 transition.oldState = XGL_IMAGE_STATE_UNINITIALIZED_TARGET;
508 transition.newState = XGL_IMAGE_STATE_CLEAR;
509 transition.subresourceRange = subres_range;
510 xglCmdPrepareImages(m_cmd, 1, &transition);
511
512 xglCmdClearDepthStencil(m_cmd, img->image(), clear_depth,
513 0, 1, &subres_range);
514
515 EndAndSubmitCmd();
516
517 /*
518 * TODO xglCmdCopyImageToMemory to linearize
519 *
520 * This works only because xglMapMemory calls intel_bo_map_gtt_async.
521 */
522 {
523 XGL_SUBRESOURCE_LAYOUT layout;
524 XGL_SIZE layout_size;
525 XGL_UINT x, y;
526 void *data;
527
528 err = img->MapMemory(&data);
529 ASSERT_XGL_SUCCESS(err);
530
531 err = xglGetImageSubresourceInfo(img->image(), &subres,
532 XGL_INFO_TYPE_SUBRESOURCE_LAYOUT, &layout_size, &layout);
533 ASSERT_XGL_SUCCESS(err);
534 ASSERT_EQ(sizeof(layout), layout_size);
535
536 for (y = 0; y < height; y++) {
537 const float *real = (const float *)
538 ((char *) data + layout.offset + layout.rowPitch * y);
539
540 for (x = 0; x < width; x++)
541 ASSERT_EQ(clear_depth, real[x]);
542 }
543
544 img->UnmapMemory();
545 }
546}
547
548int main(int argc, char **argv)
549{
550 int result;
551
552 ::testing::InitGoogleTest(&argc, argv);
553 XglTestFramework::InitArgs(&argc, argv);
554
555 ::testing::Environment* const xgl_test_env = ::testing::AddGlobalTestEnvironment(new TestEnvironment);
556
557 result = RUN_ALL_TESTS();
558
559 XglTestFramework::Finish();
560 return result;
561}