blob: d12531b49af14e064d4029b4f691c13b2da972fd [file] [log] [blame]
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001// XGL tests
Chia-I Wucb67c652014-10-21 11:06:26 +08002//
Chia-I Wu6170c9e2014-12-08 14:30:10 +08003// Copyright (C) 2014 LunarG, Inc.
Chia-I Wucb67c652014-10-21 11:06:26 +08004//
Chia-I Wu6170c9e2014-12-08 14:30:10 +08005// Permission is hereby granted, free of charge, to any person obtaining a
6// copy of this software and associated documentation files (the "Software"),
7// to deal in the Software without restriction, including without limitation
8// the rights to use, copy, modify, merge, publish, distribute, sublicense,
9// and/or sell copies of the Software, and to permit persons to whom the
10// Software is furnished to do so, subject to the following conditions:
Chia-I Wucb67c652014-10-21 11:06:26 +080011//
Chia-I Wu6170c9e2014-12-08 14:30:10 +080012// The above copyright notice and this permission notice shall be included
13// in all copies or substantial portions of the Software.
Chia-I Wucb67c652014-10-21 11:06:26 +080014//
Chia-I Wu6170c9e2014-12-08 14:30:10 +080015// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21// DEALINGS IN THE SOFTWARE.
Chia-I Wucb67c652014-10-21 11:06:26 +080022
23// Blit (copy, clear, and resolve) tests
24
Chia-I Wu6170c9e2014-12-08 14:30:10 +080025#include <set>
26#include <utility>
27#include <vector>
28
29#include "gtest/gtest.h"
30#include "xgl.h"
Chia-I Wucb67c652014-10-21 11:06:26 +080031
32#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
33
Chia-I Wu6170c9e2014-12-08 14:30:10 +080034namespace xgl_testing {
Chia-I Wucb67c652014-10-21 11:06:26 +080035
Chia-I Wu6170c9e2014-12-08 14:30:10 +080036class Buffer;
37class CmdBuffer;
38class Device;
39class Image;
Chia-I Wucb67c652014-10-21 11:06:26 +080040
Chia-I Wu6170c9e2014-12-08 14:30:10 +080041XGL_SIZE get_format_size(XGL_FORMAT format);
42XGL_EXTENT3D get_mip_level_extent(const XGL_EXTENT3D &extent, XGL_UINT mip_level);
43
44class Environment : public ::testing::Environment {
45public:
46 Environment();
47
48 bool parse_args(int argc, char **argv);
Chia-I Wucb67c652014-10-21 11:06:26 +080049
50 virtual void SetUp();
51 virtual void TearDown();
52
Chia-I Wu6170c9e2014-12-08 14:30:10 +080053 const std::vector<Device *> &devices() { return devs_; }
54 Device &default_device() { return *(devs_[default_dev_]); }
Chia-I Wucb67c652014-10-21 11:06:26 +080055
Chia-I Wu6170c9e2014-12-08 14:30:10 +080056private:
57 XGL_APPLICATION_INFO app_;
58 int default_dev_;
Chia-I Wucb67c652014-10-21 11:06:26 +080059
Chia-I Wu6170c9e2014-12-08 14:30:10 +080060 std::vector<Device *> devs_;
Chia-I Wucb67c652014-10-21 11:06:26 +080061};
62
Chia-I Wu6170c9e2014-12-08 14:30:10 +080063class Gpu {
64public:
65 explicit Gpu(XGL_PHYSICAL_GPU gpu) : gpu_(gpu) {}
66 bool init();
67
68 XGL_PHYSICAL_GPU obj() const { return gpu_; }
69 const XGL_PHYSICAL_GPU_PROPERTIES &properties() const { return props_; };
70 const XGL_PHYSICAL_GPU_PERFORMANCE &performance() const { return perf_; };
71 const XGL_PHYSICAL_GPU_MEMORY_PROPERTIES &memory_properties() const { return mem_props_; };
72 const std::vector<XGL_PHYSICAL_GPU_QUEUE_PROPERTIES> &queue_properties() const { return queue_props_; }
73 const std::vector<const XGL_CHAR *> &extensions() const { return exts_; }
74
75private:
76 void init_exts();
77
78 XGL_PHYSICAL_GPU gpu_;
79 XGL_PHYSICAL_GPU_PROPERTIES props_;
80 XGL_PHYSICAL_GPU_PERFORMANCE perf_;
81 XGL_PHYSICAL_GPU_MEMORY_PROPERTIES mem_props_;
82 std::vector<XGL_PHYSICAL_GPU_QUEUE_PROPERTIES> queue_props_;
83 std::vector<const XGL_CHAR *> exts_;
84};
85
86class Device {
87public:
88 explicit Device(XGL_PHYSICAL_GPU gpu) : gpu_(gpu), dev_(XGL_NULL_HANDLE) {}
89 ~Device();
90 bool init();
91
92 XGL_DEVICE obj() const { return dev_; }
93 XGL_PHYSICAL_GPU gpu() const { return gpu_.obj(); }
94
95 XGL_QUEUE queue(XGL_QUEUE_TYPE type, XGL_UINT idx) const;
96
97 const std::vector<XGL_MEMORY_HEAP_PROPERTIES> &heap_properties() const { return heap_props_; }
98
99 struct Format {
100 XGL_FORMAT format;
101 XGL_IMAGE_TILING tiling;
102 XGL_FLAGS features;
103 };
104 const std::vector<Format> &formats() const { return formats_; }
105
106 bool submit(XGL_QUEUE queue, const CmdBuffer &cmd, XGL_FENCE fence);
107 bool wait(XGL_QUEUE queue) { return (xglQueueWaitIdle(queue) == XGL_SUCCESS); }
108 bool wait() { return (xglDeviceWaitIdle(dev_) == XGL_SUCCESS); }
109
110private:
111 Device(const Device &);
112 Device &operator=(const Device &);
113
114 void init_queues();
115 void init_heap_props();
116 void init_formats();
117
118 Gpu gpu_;
119 XGL_DEVICE dev_;
120 std::vector<XGL_QUEUE> graphics_queues_;
121 std::vector<XGL_QUEUE> compute_queues_;
122 std::vector<XGL_QUEUE> dma_queues_;
123 std::vector<XGL_MEMORY_HEAP_PROPERTIES> heap_props_;
124 std::vector<Format> formats_;
125};
126
127class Object {
128public:
129 const XGL_MEMORY_REQUIREMENTS &memory_requirements() const { return mem_reqs_; }
130 bool bind_memory(XGL_GPU_MEMORY mem, XGL_GPU_SIZE offset);
131 XGL_GPU_MEMORY alloc_memory(const Device &dev);
132
133 XGL_GPU_MEMORY bound_memory() const { return bound_mem_; }
134
135protected:
136 Object() : obj_(XGL_NULL_HANDLE), bound_mem_(XGL_NULL_HANDLE) {}
137 ~Object();
138 bool init(XGL_OBJECT obj);
139
140private:
141 Object(const Object &);
142 Object &operator=(const Object &);
143
144 XGL_OBJECT obj_;
145 XGL_MEMORY_REQUIREMENTS mem_reqs_;
146
147protected:
148 // not private because of Buffer, which is not an XGL_OBJECT yet
149 XGL_GPU_MEMORY bound_mem_;
150
151};
152
153class CmdBuffer : public Object {
154public:
155 CmdBuffer() : cmd_(XGL_NULL_HANDLE) {}
156 bool init(const Device &dev, const XGL_CMD_BUFFER_CREATE_INFO &info);
157 bool init(const Device &dev);
158
159 XGL_CMD_BUFFER obj() const { return cmd_; }
160
161 void add_memory_ref(const Object &obj, XGL_FLAGS flags);
162 void clear_memory_refs() { mem_refs_.clear(); }
163
164 std::vector<XGL_MEMORY_REF> memory_refs() const
165 {
166 return std::vector<XGL_MEMORY_REF>(mem_refs_.begin(), mem_refs_.end());
167 }
168
169 bool begin(XGL_FLAGS flags);
170 bool begin();
171 bool end();
172
173private:
174 class mem_ref_compare {
175 public:
176 bool operator()(const XGL_MEMORY_REF &a, const XGL_MEMORY_REF &b) const
177 {
178 return (a.mem < b.mem);
179 }
180 };
181
182 XGL_CMD_BUFFER_CREATE_INFO info_;
183 XGL_CMD_BUFFER cmd_;
184 std::set<XGL_MEMORY_REF, mem_ref_compare> mem_refs_;
185};
186
187class Buffer : public Object {
188public:
189 Buffer() : mem_(XGL_NULL_HANDLE) {}
190 ~Buffer();
191 bool init(const Device &dev, const XGL_MEMORY_ALLOC_INFO &info);
192 bool init(const Device &dev, XGL_GPU_SIZE size);
193
194 XGL_GPU_MEMORY obj() const { return mem_; }
195 XGL_GPU_SIZE size() const { return info_.allocationSize; }
196
197 XGL_MEMORY_STATE_TRANSITION prepare(XGL_MEMORY_STATE old_state, XGL_MEMORY_STATE new_state,
198 XGL_GPU_SIZE offset, XGL_GPU_SIZE size)
199 {
200 XGL_MEMORY_STATE_TRANSITION transition = {};
201 transition.sType = XGL_STRUCTURE_TYPE_MEMORY_STATE_TRANSITION;
202 transition.mem = mem_;
203 transition.oldState = old_state;
204 transition.newState = new_state;
205 transition.offset = offset;
206 transition.regionSize = size;
207 return transition;
208 }
209
210 void *map();
211 void unmap();
212
213private:
214 XGL_MEMORY_ALLOC_INFO info_;
215 XGL_GPU_MEMORY mem_;
216};
217
218class Image : public Object {
219public:
220 Image() : features_(0), img_(XGL_NULL_HANDLE), mem_(XGL_NULL_HANDLE) {}
221 ~Image();
222 bool init(const Device &dev, const XGL_IMAGE_CREATE_INFO &info);
223
224 static XGL_IMAGE_CREATE_INFO create_info()
225 {
226 XGL_IMAGE_CREATE_INFO info = {};
227
228 info.sType = XGL_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
229 info.extent.width = 1;
230 info.extent.height = 1;
231 info.extent.depth = 1;
232 info.mipLevels = 1;
233 info.arraySize = 1;
234 info.samples = 1;
235
236 return info;
237 }
238
239 static XGL_IMAGE_SUBRESOURCE subresource(XGL_IMAGE_ASPECT aspect, XGL_UINT mip_level, XGL_UINT array_slice)
240 {
241 XGL_IMAGE_SUBRESOURCE subres = {};
242 subres.aspect = aspect;
243 subres.mipLevel = mip_level;
244 subres.arraySlice = array_slice;
245 return subres;
246 }
247
248 static XGL_IMAGE_SUBRESOURCE subresource(const XGL_IMAGE_SUBRESOURCE_RANGE &range,
249 XGL_UINT mip_level, XGL_UINT array_slice)
250 {
251 return subresource(range.aspect, range.baseMipLevel + mip_level, range.baseArraySlice + array_slice);
252 }
253
254 static XGL_IMAGE_SUBRESOURCE_RANGE subresource_range(XGL_IMAGE_ASPECT aspect,
255 XGL_UINT base_mip_level, XGL_UINT mip_levels,
256 XGL_UINT base_array_slice, XGL_UINT array_size)
257 {
258 XGL_IMAGE_SUBRESOURCE_RANGE range = {};
259 range.aspect = aspect;
260 range.baseMipLevel = base_mip_level;
261 range.mipLevels = mip_levels;
262 range.baseArraySlice = base_array_slice;
263 range.arraySize = array_size;
264 return range;
265 }
266
267 static XGL_IMAGE_SUBRESOURCE_RANGE subresource_range(XGL_IMAGE_ASPECT aspect,
268 const XGL_IMAGE_CREATE_INFO &info)
269 {
270 return subresource_range(aspect, 0, info.mipLevels, 0, info.arraySize);
271 }
272
273 static XGL_IMAGE_SUBRESOURCE_RANGE subresource_range(const XGL_IMAGE_SUBRESOURCE &subres)
274 {
275 return subresource_range(subres.aspect, subres.mipLevel, 1, subres.arraySlice, 1);
276 }
277
278 XGL_IMAGE obj() const { return img_; }
279
280 bool copyable() const { return (features_ & XGL_FORMAT_IMAGE_COPY_BIT); }
281 bool transparent() const;
282 XGL_EXTENT3D extent(XGL_UINT mip_level) const { return get_mip_level_extent(info_.extent, mip_level); }
283 XGL_EXTENT3D extent() const { return info_.extent; }
284
285 XGL_IMAGE_SUBRESOURCE_RANGE subresource_range(XGL_IMAGE_ASPECT aspect) const
286 {
287 return subresource_range(aspect, info_);
288 }
289
290 XGL_SUBRESOURCE_LAYOUT subresource_layout(const XGL_IMAGE_SUBRESOURCE &subres) const;
291
292 XGL_IMAGE_STATE_TRANSITION prepare(XGL_IMAGE_STATE old_state, XGL_IMAGE_STATE new_state,
293 const XGL_IMAGE_SUBRESOURCE_RANGE &range) const
294 {
295 XGL_IMAGE_STATE_TRANSITION transition = {};
296 transition.image = img_;
297 transition.oldState = old_state;
298 transition.newState = new_state;
299 transition.subresourceRange = range;
300 return transition;
301 }
302
303 void *map() const;
304 void unmap() const;
305
306private:
307 XGL_IMAGE_CREATE_INFO info_;
308 XGL_FLAGS features_;
309 XGL_IMAGE img_;
310 XGL_GPU_MEMORY mem_;
311};
312
313class ImageChecker {
314public:
315 explicit ImageChecker(const XGL_IMAGE_CREATE_INFO &info, const std::vector<XGL_MEMORY_IMAGE_COPY> &regions)
316 : info_(info), regions_(regions), pattern_(HASH) {}
317 explicit ImageChecker(const XGL_IMAGE_CREATE_INFO &info, const std::vector<XGL_IMAGE_SUBRESOURCE_RANGE> &ranges);
318 explicit ImageChecker(const XGL_IMAGE_CREATE_INFO &info);
319
320 void set_solid_pattern(const std::vector<uint8_t> &solid);
321
322 XGL_GPU_SIZE buffer_size() const;
323 bool fill(Buffer &buf) const { return walk(FILL, buf); }
324 bool fill(Image &img) const { return walk(FILL, img); }
325 bool check(Buffer &buf) const { return walk(CHECK, buf); }
326 bool check(Image &img) const { return walk(CHECK, img); }
327
328 const std::vector<XGL_MEMORY_IMAGE_COPY> &regions() const { return regions_; }
329
330 static void hash_salt_generate() { hash_salt_++; }
331
332private:
333 enum Action {
334 FILL,
335 CHECK,
336 };
337
338 enum Pattern {
339 HASH,
340 SOLID,
341 };
342
343 XGL_SIZE buffer_cpp() const;
344 XGL_SUBRESOURCE_LAYOUT buffer_layout(const XGL_MEMORY_IMAGE_COPY &region) const;
345
346 bool walk(Action action, Buffer &buf) const;
347 bool walk(Action action, Image &img) const;
348 bool walk_region(Action action, const XGL_MEMORY_IMAGE_COPY &region, const XGL_SUBRESOURCE_LAYOUT &layout, void *data) const;
349
350 std::vector<uint8_t> pattern_hash(const XGL_IMAGE_SUBRESOURCE &subres, const XGL_OFFSET3D &offset) const;
351
352 static uint32_t hash_salt_;
353
354 XGL_IMAGE_CREATE_INFO info_;
355 std::vector<XGL_MEMORY_IMAGE_COPY> regions_;
356
357 Pattern pattern_;
358 std::vector<uint8_t> pattern_solid_;
359};
360
361Environment::Environment() :
362 default_dev_(0)
Chia-I Wucb67c652014-10-21 11:06:26 +0800363{
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800364 app_.sType = XGL_STRUCTURE_TYPE_APPLICATION_INFO;
365 app_.pAppName = (const XGL_CHAR *) "xgl_testing";
366 app_.appVersion = 1;
367 app_.pEngineName = (const XGL_CHAR *) "xgl_testing";
368 app_.engineVersion = 1;
369 app_.apiVersion = XGL_MAKE_VERSION(0, 22, 0);
370}
371
372bool Environment::parse_args(int argc, char **argv)
373{
374 int i;
375
376 for (i = 1; i < argc; i++) {
377#define ARG(name) (strcmp(argv[i], name) == 0)
378#define ARG_P(name) (i < argc - 1 && ARG(name))
379 if (ARG_P("--gpu")) {
380 default_dev_ = atoi(argv[++i]);
381 } else {
382 break;
383 }
384#undef ARG
385#undef ARG_P
386 }
387
388 if (i < argc) {
389 std::cout <<
390 "invalid argument: " << argv[i] << "\n\n" <<
391 "Usage: " << argv[0] << " <options>\n\n" <<
392 "Options:\n"
393 " --gpu <n> Use GPU<n> as the default GPU\n";
394
395 return false;
396 }
397
398 return true;
399}
400
401void Environment::SetUp()
402{
403 XGL_PHYSICAL_GPU gpus[XGL_MAX_PHYSICAL_GPUS];
Chia-I Wucb67c652014-10-21 11:06:26 +0800404 XGL_UINT count;
405 XGL_RESULT err;
406
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800407 err = xglInitAndEnumerateGpus(&app_, NULL, ARRAY_SIZE(gpus), &count, gpus);
408 ASSERT_EQ(XGL_SUCCESS, err);
409 ASSERT_GT(count, default_dev_);
Chia-I Wucb67c652014-10-21 11:06:26 +0800410
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800411 devs_.reserve(count);
412 for (XGL_UINT i = 0; i < count; i++) {
413 devs_.push_back(new Device(gpus[i]));
414 if (i == default_dev_) {
415 const bool created = devs_[i]->init();
416 ASSERT_EQ(true, created);
417 }
418 }
Chia-I Wucb67c652014-10-21 11:06:26 +0800419}
420
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800421void Environment::TearDown()
Chia-I Wucb67c652014-10-21 11:06:26 +0800422{
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800423 // destroy devices first
424 for (std::vector<Device *>::iterator it = devs_.begin(); it != devs_.end(); it++)
425 delete *it;
426 devs_.clear();
Chia-I Wucb67c652014-10-21 11:06:26 +0800427
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800428 XGL_UINT dummy_count;
429 xglInitAndEnumerateGpus(&app_, NULL, 0, &dummy_count, NULL);
Chia-I Wucb67c652014-10-21 11:06:26 +0800430}
431
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800432bool Gpu::init()
433{
434 XGL_SIZE size;
435 XGL_RESULT err;
436
437 size = sizeof(props_);
438 err = xglGetGpuInfo(gpu_, XGL_INFO_TYPE_PHYSICAL_GPU_PROPERTIES, &size, &props_);
439 if (err != XGL_SUCCESS || size != sizeof(props_))
440 return false;
441
442 size = sizeof(perf_);
443 err = xglGetGpuInfo(gpu_, XGL_INFO_TYPE_PHYSICAL_GPU_PERFORMANCE, &size, &perf_);
444 if (err != XGL_SUCCESS || size != sizeof(perf_))
445 return false;
446
447 size = sizeof(mem_props_);
448 err = xglGetGpuInfo(gpu_, XGL_INFO_TYPE_PHYSICAL_GPU_MEMORY_PROPERTIES, &size, &mem_props_);
449 if (err != XGL_SUCCESS || size != sizeof(mem_props_))
450 return false;
451
452 err = xglGetGpuInfo(gpu_, XGL_INFO_TYPE_PHYSICAL_GPU_QUEUE_PROPERTIES, &size, NULL);
453 if (err != XGL_SUCCESS || size % sizeof(queue_props_[0]))
454 return false;
455
456 queue_props_.resize(size / sizeof(queue_props_[0]));
457 err = xglGetGpuInfo(gpu_, XGL_INFO_TYPE_PHYSICAL_GPU_QUEUE_PROPERTIES, &size, &queue_props_[0]);
458 if (err != XGL_SUCCESS || size != queue_props_.size() * sizeof(queue_props_[0]))
459 return false;
460
461 init_exts();
462
463 return true;
464}
465
466void Gpu::init_exts()
467{
468 static const XGL_CHAR *known_exts[] = {
469 (const XGL_CHAR *) "XGL_WSI_X11",
470 };
471 XGL_RESULT err;
472
473 for (int i; i < ARRAY_SIZE(known_exts); i++) {
474 err = xglGetExtensionSupport(gpu_, known_exts[i]);
475 if (err == XGL_SUCCESS)
476 exts_.push_back(known_exts[i]);
477 }
478}
479
480Device::~Device()
481{
482 if (dev_ != XGL_NULL_HANDLE)
483 xglDestroyDevice(dev_);
484}
485
486bool Device::init()
487{
488 XGL_RESULT err;
489
490 if (dev_ != XGL_NULL_HANDLE)
491 return true;
492
493 if (!gpu_.init())
494 return false;
495
496 // request all queues
497 std::vector<XGL_DEVICE_QUEUE_CREATE_INFO> queue_info;
498 queue_info.reserve(gpu_.queue_properties().size());
499 for (XGL_UINT i = 0; i < gpu_.queue_properties().size(); i++) {
500 XGL_DEVICE_QUEUE_CREATE_INFO qi = {};
501 qi.queueNodeIndex = i;
502 qi.queueCount = gpu_.queue_properties()[i].queueCount;
503 queue_info.push_back(qi);
504 }
505
506 XGL_DEVICE_CREATE_INFO dev_info = {};
507 dev_info.sType = XGL_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
508 dev_info.queueRecordCount = queue_info.size();
509 dev_info.pRequestedQueues = &queue_info[0];
510 dev_info.extensionCount = gpu_.extensions().size();
511 dev_info.ppEnabledExtensionNames = &gpu_.extensions()[0];
512 dev_info.maxValidationLevel = XGL_VALIDATION_LEVEL_END_RANGE;
513 dev_info.flags = XGL_DEVICE_CREATE_VALIDATION_BIT;
514
515 err = xglCreateDevice(gpu_.obj(), &dev_info, &dev_);
516 if (err != XGL_SUCCESS)
517 return false;
518
519 init_queues();
520 init_heap_props();
521 init_formats();
522
523 if (graphics_queues_.empty() || heap_props_.empty() || formats_.empty()) {
524 xglDestroyDevice(dev_);
525 dev_ = XGL_NULL_HANDLE;
526 return false;
527 }
528
529 return true;
530}
531
532void Device::init_queues()
Chia-I Wucb67c652014-10-21 11:06:26 +0800533{
534 const struct {
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800535 XGL_QUEUE_TYPE type;
536 std::vector<XGL_QUEUE> &queues;
537 } known_queues[] = {
538 { XGL_QUEUE_TYPE_GRAPHICS, graphics_queues_ },
539 { XGL_QUEUE_TYPE_COMPUTE, compute_queues_ },
540 { XGL_QUEUE_TYPE_DMA, dma_queues_ },
Chia-I Wucb67c652014-10-21 11:06:26 +0800541 };
Chia-I Wucb67c652014-10-21 11:06:26 +0800542 XGL_RESULT err;
Chia-I Wucb67c652014-10-21 11:06:26 +0800543
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800544 for (int i = 0; i < ARRAY_SIZE(known_queues); i++) {
545 XGL_UINT idx = 0;
Chia-I Wucb67c652014-10-21 11:06:26 +0800546
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800547 while (true) {
548 XGL_QUEUE queue;
549 err = xglGetDeviceQueue(dev_, known_queues[i].type, idx++, &queue);
550 if (err != XGL_SUCCESS)
551 break;
552 known_queues[i].queues.push_back(queue);
Chia-I Wucb67c652014-10-21 11:06:26 +0800553 }
Chia-I Wucb67c652014-10-21 11:06:26 +0800554 }
Chia-I Wucb67c652014-10-21 11:06:26 +0800555}
556
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800557void Device::init_heap_props()
Chia-I Wuea9367f2014-11-23 02:16:45 +0800558{
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800559 XGL_UINT count;
560 XGL_RESULT err;
561
562 err = xglGetMemoryHeapCount(dev_, &count);
563 if (err != XGL_SUCCESS || !count)
564 return;
565
566 heap_props_.reserve(count);
567 for (XGL_UINT i = 0; i < count; i++) {
568 XGL_MEMORY_HEAP_PROPERTIES props;
569 XGL_SIZE size = sizeof(props);
570
571 err = xglGetMemoryHeapInfo(dev_, i, XGL_INFO_TYPE_MEMORY_HEAP_PROPERTIES, &size, &props);
572 if (err == XGL_SUCCESS && size == sizeof(props))
573 heap_props_.push_back(props);
574 }
575}
576
577void Device::init_formats()
578{
579 XGL_RESULT err;
580
581 for (int ch = XGL_CH_FMT_UNDEFINED; ch <= XGL_MAX_CH_FMT; ch++) {
582 for (int num = XGL_NUM_FMT_UNDEFINED; num <= XGL_MAX_NUM_FMT; num++) {
583 const XGL_FORMAT fmt = { static_cast<XGL_CHANNEL_FORMAT>(ch),
584 static_cast<XGL_NUM_FORMAT>(num) };
585
586 XGL_FORMAT_PROPERTIES props;
587 XGL_SIZE size = sizeof(props);
588 err = xglGetFormatInfo(dev_, fmt, XGL_INFO_TYPE_FORMAT_PROPERTIES, &size, &props);
589 if (err != XGL_SUCCESS || size != sizeof(props))
590 continue;
591
592 if (props.linearTilingFeatures) {
593 const Format tmp = { fmt, XGL_LINEAR_TILING, props.linearTilingFeatures };
594 formats_.push_back(tmp);
595 }
596
597 if (props.optimalTilingFeatures) {
598 const Format tmp = { fmt, XGL_OPTIMAL_TILING, props.optimalTilingFeatures };
599 formats_.push_back(tmp);
600 }
601 }
602 }
603}
604
605XGL_QUEUE Device::queue(XGL_QUEUE_TYPE type, XGL_UINT idx) const
606{
607 switch (type) {
608 case XGL_QUEUE_TYPE_GRAPHICS: return graphics_queues_[idx];
609 case XGL_QUEUE_TYPE_COMPUTE: return compute_queues_[idx];
610 case XGL_QUEUE_TYPE_DMA: return dma_queues_[idx];
611 default: return XGL_NULL_HANDLE;
612 }
613}
614
615bool Device::submit(XGL_QUEUE queue, const CmdBuffer &cmd, XGL_FENCE fence)
616{
617 XGL_CMD_BUFFER obj = cmd.obj();
618 const std::vector<XGL_MEMORY_REF> refs = cmd.memory_refs();
619
620 return (xglQueueSubmit(queue, 1, &obj, refs.size(), &refs[0], fence) == XGL_SUCCESS);
621}
622
623Object::~Object()
624{
625 if (obj_ != XGL_NULL_HANDLE) {
626 xglBindObjectMemory(obj_, XGL_NULL_HANDLE, 0);
627 xglDestroyObject(obj_);
628 }
629}
630
631bool Object::init(XGL_OBJECT obj)
632{
633 XGL_RESULT err;
634
635 XGL_SIZE size = sizeof(mem_reqs_);
636 err = xglGetObjectInfo(obj, XGL_INFO_TYPE_MEMORY_REQUIREMENTS, &size, &mem_reqs_);
637 if (err != XGL_SUCCESS || size != sizeof(mem_reqs_))
638 return false;
639
640 obj_ = obj;
641
642 return true;
643}
644
645bool Object::bind_memory(XGL_GPU_MEMORY mem, XGL_GPU_SIZE offset)
646{
647 if (xglBindObjectMemory(obj_, mem, offset) == XGL_SUCCESS) {
648 bound_mem_ = mem;
649 return true;
650 } else {
651 return false;
652 }
653}
654
655XGL_GPU_MEMORY Object::alloc_memory(const Device &dev)
656{
657 if (!mem_reqs_.size)
658 return XGL_NULL_HANDLE;
659
660 XGL_MEMORY_ALLOC_INFO mem_alloc = {};
661 mem_alloc.sType = XGL_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
662 mem_alloc.allocationSize = mem_reqs_.size;
663 mem_alloc.alignment = mem_reqs_.alignment;
664 mem_alloc.heapCount = mem_reqs_.heapCount;
665 memcpy(mem_alloc.heaps, mem_reqs_.heaps,
666 sizeof(mem_reqs_.heaps[0]) * mem_reqs_.heapCount);
667 mem_alloc.memPriority = XGL_MEMORY_PRIORITY_NORMAL;
668
Chia-I Wuea9367f2014-11-23 02:16:45 +0800669 XGL_GPU_MEMORY mem;
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800670 XGL_RESULT err = xglAllocMemory(dev.obj(), &mem_alloc, &mem);
671 if (err != XGL_SUCCESS)
672 mem = XGL_NULL_HANDLE;
Chia-I Wuea9367f2014-11-23 02:16:45 +0800673
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800674 return mem;
Chia-I Wuea9367f2014-11-23 02:16:45 +0800675}
676
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800677bool CmdBuffer::init(const Device &dev, const XGL_CMD_BUFFER_CREATE_INFO &info)
Chia-I Wucb67c652014-10-21 11:06:26 +0800678{
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800679 info_ = info;
680
681 XGL_RESULT err = xglCreateCommandBuffer(dev.obj(), &info_, &cmd_);
682 if (err != XGL_SUCCESS)
683 return false;
684
685 return Object::init(cmd_);
686}
687
688bool CmdBuffer::init(const Device &dev)
689{
690 XGL_CMD_BUFFER_CREATE_INFO info = {};
691
692 info.sType = XGL_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO;
693 info.queueType = XGL_QUEUE_TYPE_GRAPHICS;
694
695 return init(dev, info);
696}
697
698void CmdBuffer::add_memory_ref(const Object &obj, XGL_FLAGS flags)
699{
700 XGL_MEMORY_REF ref = {};
701 ref.mem = obj.bound_memory();
702 ref.flags = flags;
703
704 std::pair<std::set<XGL_MEMORY_REF>::iterator, bool> inserted = mem_refs_.insert(ref);
705 if (!inserted.second) {
706 const XGL_FLAGS prev_flags = (*inserted.first).flags;
707
708 if ((prev_flags & flags) != prev_flags) {
709 mem_refs_.erase(inserted.first);
710 mem_refs_.insert(ref);
711 }
712 }
713}
714
715bool CmdBuffer::begin(XGL_FLAGS flags)
716{
717 return (xglBeginCommandBuffer(cmd_, flags) == XGL_SUCCESS);
718}
719
720bool CmdBuffer::begin()
721{
722 return begin(XGL_CMD_BUFFER_OPTIMIZE_GPU_SMALL_BATCH_BIT |
723 XGL_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT);
724}
725
726bool CmdBuffer::end()
727{
728 return (xglEndCommandBuffer(cmd_) == XGL_SUCCESS);
729}
730
731Buffer::~Buffer()
732{
733 if (mem_ != XGL_NULL_HANDLE)
734 xglFreeMemory(mem_);
735}
736
737bool Buffer::init(const Device &dev, const XGL_MEMORY_ALLOC_INFO &info)
738{
739 info_ = info;
740
741 // cannot call Object::init()
742 if (xglAllocMemory(dev.obj(), &info_, &mem_) == XGL_SUCCESS) {
743 bound_mem_ = mem_;
744 return true;
745 } else {
746 return false;
747 }
748}
749
750bool Buffer::init(const Device &dev, XGL_GPU_SIZE size)
751{
752 XGL_MEMORY_ALLOC_INFO info = {};
753 info.sType = XGL_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
754 info.allocationSize = size;
755 info.memPriority = XGL_MEMORY_PRIORITY_NORMAL;
756
757 // find a CPU visible heap
758 for (XGL_UINT id = 0; id < dev.heap_properties().size(); id++) {
759 const XGL_MEMORY_HEAP_PROPERTIES &heap = dev.heap_properties()[id];
760
761 if (heap.flags & XGL_MEMORY_HEAP_CPU_VISIBLE_BIT) {
762 info.heapCount = 1;
763 info.heaps[0] = id;
764 }
765 }
766
767 return (info.heapCount) ? init(dev, info) : false;
768}
769
770void *Buffer::map()
771{
Chia-I Wucb67c652014-10-21 11:06:26 +0800772 void *data;
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800773 return (xglMapMemory(mem_, 0, &data) == XGL_SUCCESS) ? data : NULL;
774}
Chia-I Wucb67c652014-10-21 11:06:26 +0800775
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800776void Buffer::unmap()
777{
778 xglUnmapMemory(mem_);
779}
Chia-I Wucb67c652014-10-21 11:06:26 +0800780
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800781Image::~Image()
782{
783 if (mem_ != XGL_NULL_HANDLE) {
784 xglBindObjectMemory(img_, XGL_NULL_HANDLE, 0);
785 xglFreeMemory(mem_);
786 }
787}
Chia-I Wucb67c652014-10-21 11:06:26 +0800788
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800789bool Image::init(const Device &dev, const XGL_IMAGE_CREATE_INFO &info)
790{
791 info_ = info;
Chia-I Wucb67c652014-10-21 11:06:26 +0800792
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800793 for (std::vector<xgl_testing::Device::Format>::const_iterator it = dev.formats().begin();
794 it != dev.formats().end(); it++) {
795 if (!memcmp(&it->format, &info_.format, sizeof(info_.format)) && it->tiling == info_.tiling) {
796 features_ = it->features;
797 break;
798 }
799 }
Chia-I Wucb67c652014-10-21 11:06:26 +0800800
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800801 XGL_RESULT err = xglCreateImage(dev.obj(), &info_, &img_);
802 if (err != XGL_SUCCESS)
803 return false;
Chia-I Wucb67c652014-10-21 11:06:26 +0800804
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800805 if (!Object::init(img_))
806 return false;
807
808 mem_ = alloc_memory(dev);
809 if (mem_ == XGL_NULL_HANDLE || !bind_memory(mem_, 0))
810 return false;
811
812 return true;
813}
814
815bool Image::transparent() const
816{
817 return (info_.tiling == XGL_LINEAR_TILING &&
818 info_.samples == 1 &&
819 !(info_.usage & (XGL_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
820 XGL_IMAGE_USAGE_DEPTH_STENCIL_BIT)));
821}
822
823XGL_SUBRESOURCE_LAYOUT Image::subresource_layout(const XGL_IMAGE_SUBRESOURCE &subres) const
824{
825 XGL_SUBRESOURCE_LAYOUT layout;
826 XGL_SIZE size = sizeof(layout);
827
828 XGL_RESULT err = xglGetImageSubresourceInfo(img_, &subres,
829 XGL_INFO_TYPE_SUBRESOURCE_LAYOUT, &size, &layout);
830 if (err != XGL_SUCCESS || size != sizeof(layout))
831 memset(&layout, 0, sizeof(layout));
832
833 return layout;
834}
835
836void *Image::map() const
837{
838 void *data;
839 return (transparent() && xglMapMemory(mem_, 0, &data) == XGL_SUCCESS) ? data : NULL;
840}
841
842void Image::unmap() const
843{
844 xglUnmapMemory(mem_);
845}
846
847uint32_t ImageChecker::hash_salt_;
848
849ImageChecker::ImageChecker(const XGL_IMAGE_CREATE_INFO &info)
850 : info_(info), regions_(), pattern_(HASH)
851{
852 // create a region for every mip level in array slice 0
853 XGL_GPU_SIZE offset = 0;
854 for (XGL_UINT lv = 0; lv < info_.mipLevels; lv++) {
855 XGL_MEMORY_IMAGE_COPY region = {};
856
857 region.memOffset = offset;
858 region.imageSubresource.mipLevel = lv;
859 region.imageSubresource.arraySlice = 0;
860 region.imageExtent = get_mip_level_extent(info_.extent, lv);
861
862 if (info_.usage & XGL_IMAGE_USAGE_DEPTH_STENCIL_BIT) {
863 if (info_.format.channelFormat != XGL_CH_FMT_R8) {
864 region.imageSubresource.aspect = XGL_IMAGE_ASPECT_DEPTH;
865 regions_.push_back(region);
866 }
867
868 if (info_.format.channelFormat == XGL_CH_FMT_R16G8 ||
869 info_.format.channelFormat == XGL_CH_FMT_R32G8 ||
870 info_.format.channelFormat == XGL_CH_FMT_R8) {
871 region.imageSubresource.aspect = XGL_IMAGE_ASPECT_STENCIL;
872 regions_.push_back(region);
873 }
Chia-I Wucb67c652014-10-21 11:06:26 +0800874 } else {
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800875 region.imageSubresource.aspect = XGL_IMAGE_ASPECT_COLOR;
876 regions_.push_back(region);
877 }
878
879 offset += buffer_layout(region).size;
880 }
881
882 // arraySize should be limited in our tests. If this proves to be an
883 // issue, we can store only the regions for array slice 0 and be smart.
884 if (info_.arraySize > 1) {
885 const XGL_GPU_SIZE slice_pitch = offset;
886 const XGL_UINT slice_region_count = regions_.size();
887
888 regions_.reserve(slice_region_count * info_.arraySize);
889
890 for (XGL_UINT slice = 1; slice < info_.arraySize; slice++) {
891 for (XGL_UINT i = 0; i < slice_region_count; i++) {
892 XGL_MEMORY_IMAGE_COPY region = regions_[i];
893
894 region.memOffset += slice_pitch * slice;
895 region.imageSubresource.arraySlice = slice;
896 regions_.push_back(region);
897 }
898 }
899 }
900}
901
902ImageChecker::ImageChecker(const XGL_IMAGE_CREATE_INFO &info, const std::vector<XGL_IMAGE_SUBRESOURCE_RANGE> &ranges)
903 : info_(info), regions_(), pattern_(HASH)
904{
905 XGL_GPU_SIZE offset = 0;
906 for (std::vector<XGL_IMAGE_SUBRESOURCE_RANGE>::const_iterator it = ranges.begin();
907 it != ranges.end(); it++) {
908 for (XGL_UINT lv = 0; lv < it->mipLevels; lv++) {
909 for (XGL_UINT slice = 0; slice < it->arraySize; slice++) {
910 XGL_MEMORY_IMAGE_COPY region = {};
911 region.memOffset = offset;
912 region.imageSubresource = Image::subresource(*it, lv, slice);
913 region.imageExtent = get_mip_level_extent(info_.extent, lv);
914
915 regions_.push_back(region);
916
917 offset += buffer_layout(region).size;
918 }
919 }
920 }
921}
922
923void ImageChecker::set_solid_pattern(const std::vector<uint8_t> &solid)
924{
925 pattern_ = SOLID;
Chia-I Wu4dce6af2014-12-21 14:59:04 +0800926 pattern_solid_.clear();
927 pattern_solid_.reserve(buffer_cpp());
928 for (int i = 0; i < buffer_cpp(); i++)
929 pattern_solid_.push_back(solid[i % solid.size()]);
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800930}
931
932XGL_SIZE ImageChecker::buffer_cpp() const
933{
934 return get_format_size(info_.format);
935}
936
937XGL_SUBRESOURCE_LAYOUT ImageChecker::buffer_layout(const XGL_MEMORY_IMAGE_COPY &region) const
938{
939 XGL_SUBRESOURCE_LAYOUT layout = {};
940 layout.offset = region.memOffset;
941 layout.rowPitch = buffer_cpp() * region.imageExtent.width;
942 layout.depthPitch = layout.rowPitch * region.imageExtent.height;
943 layout.size = layout.depthPitch * region.imageExtent.depth;
944
945 return layout;
946}
947
948XGL_GPU_SIZE ImageChecker::buffer_size() const
949{
950 XGL_GPU_SIZE size = 0;
951
952 for (std::vector<XGL_MEMORY_IMAGE_COPY>::const_iterator it = regions_.begin();
953 it != regions_.end(); it++) {
954 const XGL_SUBRESOURCE_LAYOUT layout = buffer_layout(*it);
955 if (size < layout.offset + layout.size)
956 size = layout.offset + layout.size;
957 }
958
959 return size;
960}
961
962bool ImageChecker::walk_region(Action action, const XGL_MEMORY_IMAGE_COPY &region,
963 const XGL_SUBRESOURCE_LAYOUT &layout, void *data) const
964{
965 for (XGL_INT z = 0; z < region.imageExtent.depth; z++) {
966 for (XGL_INT y = 0; y < region.imageExtent.height; y++) {
967 for (XGL_INT x = 0; x < region.imageExtent.width; x++) {
968 uint8_t *dst = static_cast<uint8_t *>(data);
969 dst += layout.offset + layout.depthPitch * z +
970 layout.rowPitch * y + buffer_cpp() * x;
971
972 XGL_OFFSET3D offset = region.imageOffset;
973 offset.x += x;
974 offset.y += y;
975 offset.z += z;
976
977 const std::vector<uint8_t> &val = (pattern_ == HASH) ?
978 pattern_hash(region.imageSubresource, offset) :
979 pattern_solid_;
980 assert(val.size() == buffer_cpp());
981
982 if (action == FILL) {
983 memcpy(dst, &val[0], val.size());
984 } else {
985 for (int i = 0; i < val.size(); i++) {
986 EXPECT_EQ(val[i], dst[i]) <<
987 "Offset is: (" << x << ", " << y << ", " << z << ")";
988 if (val[i] != dst[i])
989 return false;
990 }
991 }
992 }
Chia-I Wucb67c652014-10-21 11:06:26 +0800993 }
994 }
995
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800996 return true;
Chia-I Wucb67c652014-10-21 11:06:26 +0800997}
998
Chia-I Wu6170c9e2014-12-08 14:30:10 +0800999bool ImageChecker::walk(Action action, Buffer &buf) const
Chia-I Wu3c3fd122014-11-22 02:51:25 +08001000{
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001001 void *data = buf.map();
1002 if (!data)
1003 return false;
Chia-I Wu3c3fd122014-11-22 02:51:25 +08001004
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001005 std::vector<XGL_MEMORY_IMAGE_COPY>::const_iterator it;
1006 for (it = regions_.begin(); it != regions_.end(); it++) {
1007 if (!walk_region(action, *it, buffer_layout(*it), data))
1008 break;
Chia-I Wu3c3fd122014-11-22 02:51:25 +08001009 }
1010
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001011 buf.unmap();
Chia-I Wu3c3fd122014-11-22 02:51:25 +08001012
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001013 return (it == regions_.end());
Chia-I Wu3c3fd122014-11-22 02:51:25 +08001014}
1015
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001016bool ImageChecker::walk(Action action, Image &img) const
1017{
1018 void *data = img.map();
1019 if (!data)
1020 return false;
1021
1022 std::vector<XGL_MEMORY_IMAGE_COPY>::const_iterator it;
1023 for (it = regions_.begin(); it != regions_.end(); it++) {
1024 if (!walk_region(action, *it, img.subresource_layout(it->imageSubresource), data))
1025 break;
1026 }
1027
1028 img.unmap();
1029
1030 return (it == regions_.end());
1031}
1032
1033std::vector<uint8_t> ImageChecker::pattern_hash(const XGL_IMAGE_SUBRESOURCE &subres, const XGL_OFFSET3D &offset) const
1034{
1035#define HASH_BYTE(val, b) static_cast<uint8_t>((static_cast<uint32_t>(val) >> (b * 8)) & 0xff)
1036#define HASH_BYTES(val) HASH_BYTE(val, 0), HASH_BYTE(val, 1), HASH_BYTE(val, 2), HASH_BYTE(val, 3)
1037 const unsigned char input[] = {
1038 HASH_BYTES(hash_salt_),
1039 HASH_BYTES(subres.mipLevel),
1040 HASH_BYTES(subres.arraySlice),
1041 HASH_BYTES(offset.x),
1042 HASH_BYTES(offset.y),
1043 HASH_BYTES(offset.z),
1044 };
1045 unsigned long hash = 5381;
1046
1047 for (XGL_INT i = 0; i < ARRAY_SIZE(input); i++)
1048 hash = ((hash << 5) + hash) + input[i];
1049
1050 const uint8_t output[4] = { HASH_BYTES(hash) };
1051#undef HASH_BYTES
1052#undef HASH_BYTE
1053
Chia-I Wu4dce6af2014-12-21 14:59:04 +08001054 std::vector<uint8_t> val;
1055 val.reserve(buffer_cpp());
1056 for (int i = 0; i < buffer_cpp(); i++)
1057 val.push_back(output[i % 4]);
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001058
1059 return val;
1060}
1061
1062XGL_SIZE get_format_size(XGL_FORMAT format)
1063{
1064 static const struct format_info {
1065 XGL_SIZE size;
1066 XGL_UINT channel_count;
1067 } format_table[XGL_MAX_CH_FMT + 1] = {
1068 [XGL_CH_FMT_UNDEFINED] = { 0, 0 },
1069 [XGL_CH_FMT_R4G4] = { 1, 2 },
1070 [XGL_CH_FMT_R4G4B4A4] = { 2, 4 },
1071 [XGL_CH_FMT_R5G6B5] = { 2, 3 },
1072 [XGL_CH_FMT_B5G6R5] = { 2, 3 },
1073 [XGL_CH_FMT_R5G5B5A1] = { 2, 4 },
1074 [XGL_CH_FMT_R8] = { 1, 1 },
1075 [XGL_CH_FMT_R8G8] = { 2, 2 },
1076 [XGL_CH_FMT_R8G8B8A8] = { 4, 4 },
1077 [XGL_CH_FMT_B8G8R8A8] = { 4, 4 },
1078 [XGL_CH_FMT_R10G11B11] = { 4, 3 },
1079 [XGL_CH_FMT_R11G11B10] = { 4, 3 },
1080 [XGL_CH_FMT_R10G10B10A2] = { 4, 4 },
1081 [XGL_CH_FMT_R16] = { 2, 1 },
1082 [XGL_CH_FMT_R16G16] = { 4, 2 },
1083 [XGL_CH_FMT_R16G16B16A16] = { 8, 4 },
1084 [XGL_CH_FMT_R32] = { 4, 1 },
1085 [XGL_CH_FMT_R32G32] = { 8, 2 },
1086 [XGL_CH_FMT_R32G32B32] = { 12, 3 },
1087 [XGL_CH_FMT_R32G32B32A32] = { 16, 4 },
1088 [XGL_CH_FMT_R16G8] = { 3, 2 },
1089 [XGL_CH_FMT_R32G8] = { 5, 2 },
1090 [XGL_CH_FMT_R9G9B9E5] = { 4, 3 },
1091 [XGL_CH_FMT_BC1] = { 8, 4 },
1092 [XGL_CH_FMT_BC2] = { 16, 4 },
1093 [XGL_CH_FMT_BC3] = { 16, 4 },
1094 [XGL_CH_FMT_BC4] = { 8, 4 },
1095 [XGL_CH_FMT_BC5] = { 16, 4 },
1096 [XGL_CH_FMT_BC6U] = { 16, 4 },
1097 [XGL_CH_FMT_BC6S] = { 16, 4 },
1098 [XGL_CH_FMT_BC7] = { 16, 4 },
1099 };
1100
1101 return format_table[format.channelFormat].size;
1102}
1103
1104XGL_EXTENT3D get_mip_level_extent(const XGL_EXTENT3D &extent, XGL_UINT mip_level)
1105{
1106 const XGL_EXTENT3D ext = {
1107 (extent.width >> mip_level) ? extent.width >> mip_level : 1,
1108 (extent.height >> mip_level) ? extent.height >> mip_level : 1,
1109 (extent.depth >> mip_level) ? extent.depth >> mip_level : 1,
1110 };
1111
1112 return ext;
1113}
1114
1115}; // namespace xgl_testing
1116
1117namespace {
1118
1119#define DO(action) ASSERT_EQ(true, action);
1120
1121xgl_testing::Environment *environment;
1122
1123class XglCmdBlitTest : public ::testing::Test {
1124protected:
1125 XglCmdBlitTest() :
1126 dev_(environment->default_device()),
1127 queue_(dev_.queue(XGL_QUEUE_TYPE_GRAPHICS, 0)),
1128 cmd_()
1129 {
1130 // make sure every test uses a different pattern
1131 xgl_testing::ImageChecker::hash_salt_generate();
1132 }
1133
1134 virtual void SetUp()
1135 {
1136 DO(cmd_.init(dev_));
1137 }
1138
1139 virtual void TearDown()
1140 {
1141 }
1142
1143 bool submit_and_done()
1144 {
1145 const bool ret = (dev_.submit(queue_, cmd_, XGL_NULL_HANDLE) && dev_.wait(queue_));
1146 cmd_.clear_memory_refs();
1147 return ret;
1148 }
1149
1150 xgl_testing::Device &dev_;
1151 XGL_QUEUE queue_;
1152 xgl_testing::CmdBuffer cmd_;
1153};
1154
1155typedef XglCmdBlitTest XglCmdFillMemoryTest;
1156
1157TEST_F(XglCmdFillMemoryTest, Basic)
1158{
1159 xgl_testing::Buffer buf;
1160
1161 buf.init(dev_, 20);
1162 cmd_.add_memory_ref(buf, 0);
1163
1164 cmd_.begin();
1165 xglCmdFillMemory(cmd_.obj(), buf.obj(), 0, 4, 0x11111111);
1166 xglCmdFillMemory(cmd_.obj(), buf.obj(), 4, 16, 0x22222222);
1167 cmd_.end();
1168
1169 submit_and_done();
1170
1171 const uint32_t *data = static_cast<const uint32_t *>(buf.map());
1172 EXPECT_EQ(0x11111111, data[0]);
1173 EXPECT_EQ(0x22222222, data[1]);
1174 EXPECT_EQ(0x22222222, data[2]);
1175 EXPECT_EQ(0x22222222, data[3]);
1176 EXPECT_EQ(0x22222222, data[4]);
1177 buf.unmap();
1178}
1179
1180TEST_F(XglCmdFillMemoryTest, Large)
Chia-I Wuea9367f2014-11-23 02:16:45 +08001181{
1182 const XGL_GPU_SIZE size = 32 * 1024 * 1024;
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001183 xgl_testing::Buffer buf;
Chia-I Wuea9367f2014-11-23 02:16:45 +08001184
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001185 buf.init(dev_, size);
1186 cmd_.add_memory_ref(buf, 0);
Chia-I Wuea9367f2014-11-23 02:16:45 +08001187
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001188 cmd_.begin();
1189 xglCmdFillMemory(cmd_.obj(), buf.obj(), 0, size / 2, 0x11111111);
1190 xglCmdFillMemory(cmd_.obj(), buf.obj(), size / 2, size / 2, 0x22222222);
1191 cmd_.end();
Chia-I Wuea9367f2014-11-23 02:16:45 +08001192
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001193 submit_and_done();
Chia-I Wuea9367f2014-11-23 02:16:45 +08001194
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001195 const uint32_t *data = static_cast<const uint32_t *>(buf.map());
1196 XGL_GPU_SIZE offset;
1197 for (offset = 0; offset < size / 2; offset += 4)
1198 EXPECT_EQ(0x11111111, data[offset / 4]) << "Offset is: " << offset;
1199 for (; offset < size; offset += 4)
1200 EXPECT_EQ(0x22222222, data[offset / 4]) << "Offset is: " << offset;
1201 buf.unmap();
1202}
Chia-I Wuea9367f2014-11-23 02:16:45 +08001203
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001204TEST_F(XglCmdFillMemoryTest, Overlap)
1205{
1206 xgl_testing::Buffer buf;
1207
1208 buf.init(dev_, 64);
1209 cmd_.add_memory_ref(buf, 0);
1210
1211 cmd_.begin();
1212 xglCmdFillMemory(cmd_.obj(), buf.obj(), 0, 48, 0x11111111);
1213 xglCmdFillMemory(cmd_.obj(), buf.obj(), 32, 32, 0x22222222);
1214 cmd_.end();
1215
1216 submit_and_done();
1217
1218 const uint32_t *data = static_cast<const uint32_t *>(buf.map());
1219 XGL_GPU_SIZE offset;
1220 for (offset = 0; offset < 32; offset += 4)
1221 EXPECT_EQ(0x11111111, data[offset / 4]) << "Offset is: " << offset;
1222 for (; offset < 64; offset += 4)
1223 EXPECT_EQ(0x22222222, data[offset / 4]) << "Offset is: " << offset;
1224 buf.unmap();
1225}
1226
1227TEST_F(XglCmdFillMemoryTest, MultiAlignments)
1228{
1229 xgl_testing::Buffer bufs[9];
1230 XGL_GPU_SIZE size = 4;
1231
1232 cmd_.begin();
1233 for (int i = 0; i < ARRAY_SIZE(bufs); i++) {
1234 bufs[i].init(dev_, size);
1235 cmd_.add_memory_ref(bufs[i], 0);
1236 xglCmdFillMemory(cmd_.obj(), bufs[i].obj(), 0, size, 0x11111111);
1237 size <<= 1;
1238 }
1239 cmd_.end();
1240
1241 submit_and_done();
1242
1243 size = 4;
1244 for (int i = 0; i < ARRAY_SIZE(bufs); i++) {
1245 const uint32_t *data = static_cast<const uint32_t *>(bufs[i].map());
1246 XGL_GPU_SIZE offset;
1247 for (offset = 0; offset < size; offset += 4)
1248 EXPECT_EQ(0x11111111, data[offset / 4]) << "Buffser is: " << i << "\n" <<
1249 "Offset is: " << offset;
1250 bufs[i].unmap();
1251
1252 size <<= 1;
1253 }
1254}
1255
1256typedef XglCmdBlitTest XglCmdCopyMemoryTest;
1257
1258TEST_F(XglCmdCopyMemoryTest, Basic)
1259{
1260 xgl_testing::Buffer src, dst;
1261
1262 src.init(dev_, 4);
1263 uint32_t *data = static_cast<uint32_t *>(src.map());
1264 data[0] = 0x11111111;
1265 src.unmap();
1266 cmd_.add_memory_ref(src, XGL_MEMORY_REF_READ_ONLY_BIT);
1267
1268 dst.init(dev_, 4);
1269 cmd_.add_memory_ref(dst, 0);
1270
1271 cmd_.begin();
1272 XGL_MEMORY_COPY region = {};
1273 region.copySize = 4;
1274 xglCmdCopyMemory(cmd_.obj(), src.obj(), dst.obj(), 1, &region);
1275 cmd_.end();
1276
1277 submit_and_done();
1278
1279 data = static_cast<uint32_t *>(dst.map());
1280 EXPECT_EQ(0x11111111, data[0]);
1281 dst.unmap();
1282}
1283
1284TEST_F(XglCmdCopyMemoryTest, Large)
1285{
1286 const XGL_GPU_SIZE size = 32 * 1024 * 1024;
1287 xgl_testing::Buffer src, dst;
1288
1289 src.init(dev_, size);
1290 uint32_t *data = static_cast<uint32_t *>(src.map());
1291 XGL_GPU_SIZE offset;
1292 for (offset = 0; offset < size; offset += 4)
1293 data[offset / 4] = offset;
1294 src.unmap();
1295 cmd_.add_memory_ref(src, XGL_MEMORY_REF_READ_ONLY_BIT);
1296
1297 dst.init(dev_, size);
1298 cmd_.add_memory_ref(dst, 0);
1299
1300 cmd_.begin();
1301 XGL_MEMORY_COPY region = {};
Chia-I Wuea9367f2014-11-23 02:16:45 +08001302 region.copySize = size;
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001303 xglCmdCopyMemory(cmd_.obj(), src.obj(), dst.obj(), 1, &region);
1304 cmd_.end();
Chia-I Wuea9367f2014-11-23 02:16:45 +08001305
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001306 submit_and_done();
Chia-I Wuea9367f2014-11-23 02:16:45 +08001307
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001308 data = static_cast<uint32_t *>(dst.map());
1309 for (offset = 0; offset < size; offset += 4)
1310 EXPECT_EQ(offset, data[offset / 4]);
1311 dst.unmap();
Chia-I Wuea9367f2014-11-23 02:16:45 +08001312}
1313
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001314TEST_F(XglCmdCopyMemoryTest, MultiAlignments)
Chia-I Wucb67c652014-10-21 11:06:26 +08001315{
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001316 const XGL_MEMORY_COPY regions[] = {
1317 /* well aligned */
1318 { 0, 0, 256 },
1319 { 0, 256, 128 },
1320 { 0, 384, 64 },
1321 { 0, 448, 32 },
1322 { 0, 480, 16 },
1323 { 0, 496, 8 },
Chia-I Wucb67c652014-10-21 11:06:26 +08001324
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001325 /* ill aligned */
1326 { 7, 510, 16 },
1327 { 16, 530, 13 },
1328 { 32, 551, 16 },
1329 { 45, 570, 15 },
1330 { 50, 590, 1 },
1331 };
1332 xgl_testing::Buffer src, dst;
Chia-I Wucb67c652014-10-21 11:06:26 +08001333
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001334 src.init(dev_, 256);
1335 uint8_t *data = static_cast<uint8_t *>(src.map());
1336 for (int i = 0; i < 256; i++)
1337 data[i] = i;
1338 src.unmap();
1339 cmd_.add_memory_ref(src, XGL_MEMORY_REF_READ_ONLY_BIT);
Chia-I Wucb67c652014-10-21 11:06:26 +08001340
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001341 dst.init(dev_, 1024);
1342 cmd_.add_memory_ref(dst, 0);
Chia-I Wucb67c652014-10-21 11:06:26 +08001343
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001344 cmd_.begin();
1345 xglCmdCopyMemory(cmd_.obj(), src.obj(), dst.obj(), ARRAY_SIZE(regions), regions);
1346 cmd_.end();
Chia-I Wucb67c652014-10-21 11:06:26 +08001347
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001348 submit_and_done();
Chia-I Wucb67c652014-10-21 11:06:26 +08001349
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001350 data = static_cast<uint8_t *>(dst.map());
1351 for (int i = 0; i < ARRAY_SIZE(regions); i++) {
1352 const XGL_MEMORY_COPY &r = regions[i];
Chia-I Wucb67c652014-10-21 11:06:26 +08001353
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001354 for (int j = 0; j < r.copySize; j++) {
1355 EXPECT_EQ(r.srcOffset + j, data[r.destOffset + j]) <<
1356 "Region is: " << i << "\n" <<
1357 "Offset is: " << r.destOffset + j;
1358 }
1359 }
1360 dst.unmap();
1361}
Chia-I Wucb67c652014-10-21 11:06:26 +08001362
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001363TEST_F(XglCmdCopyMemoryTest, RAWHazard)
1364{
1365 xgl_testing::Buffer bufs[3];
Chia-I Wucb67c652014-10-21 11:06:26 +08001366
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001367 for (int i = 0; i < ARRAY_SIZE(bufs); i++) {
1368 bufs[i].init(dev_, 4);
1369 cmd_.add_memory_ref(bufs[i], 0);
Chia-I Wucb67c652014-10-21 11:06:26 +08001370
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001371 uint32_t *data = static_cast<uint32_t *>(bufs[i].map());
1372 data[0] = 0x22222222 * (i + 1);
1373 bufs[i].unmap();
1374 }
1375
1376 cmd_.begin();
1377
1378 xglCmdFillMemory(cmd_.obj(), bufs[0].obj(), 0, 4, 0x11111111);
1379 // is this necessary?
1380 XGL_MEMORY_STATE_TRANSITION transition = bufs[0].prepare(
1381 XGL_MEMORY_STATE_DATA_TRANSFER, XGL_MEMORY_STATE_DATA_TRANSFER, 0, 4);
1382 xglCmdPrepareMemoryRegions(cmd_.obj(), 1, &transition);
1383
1384 XGL_MEMORY_COPY region = {};
1385 region.copySize = 4;
1386 xglCmdCopyMemory(cmd_.obj(), bufs[0].obj(), bufs[1].obj(), 1, &region);
1387 // is this necessary?
1388 transition = bufs[1].prepare(
1389 XGL_MEMORY_STATE_DATA_TRANSFER, XGL_MEMORY_STATE_DATA_TRANSFER, 0, 4);
1390 xglCmdPrepareMemoryRegions(cmd_.obj(), 1, &transition);
1391
1392 xglCmdCopyMemory(cmd_.obj(), bufs[1].obj(), bufs[2].obj(), 1, &region);
1393 cmd_.end();
1394
1395 submit_and_done();
1396
1397 const uint32_t *data = static_cast<const uint32_t *>(bufs[2].map());
1398 EXPECT_EQ(0x11111111, data[0]);
1399 bufs[2].unmap();
1400}
1401
1402class XglCmdBlitImageTest : public XglCmdBlitTest {
1403protected:
1404 void init_test_formats(XGL_FLAGS features)
Chia-I Wucb67c652014-10-21 11:06:26 +08001405 {
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001406 first_linear_format_.channelFormat = XGL_CH_FMT_UNDEFINED;
1407 first_linear_format_.numericFormat = XGL_NUM_FMT_UNDEFINED;
1408 first_optimal_format_.channelFormat = XGL_CH_FMT_UNDEFINED;
1409 first_optimal_format_.numericFormat = XGL_NUM_FMT_UNDEFINED;
Chia-I Wucb67c652014-10-21 11:06:26 +08001410
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001411 for (std::vector<xgl_testing::Device::Format>::const_iterator it = dev_.formats().begin();
1412 it != dev_.formats().end(); it++) {
1413 if (it->features & features) {
1414 test_formats_.push_back(*it);
Chia-I Wucb67c652014-10-21 11:06:26 +08001415
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001416 if (it->tiling == XGL_LINEAR_TILING &&
1417 first_linear_format_.channelFormat == XGL_CH_FMT_UNDEFINED)
1418 first_linear_format_ = it->format;
1419 if (it->tiling == XGL_OPTIMAL_TILING &&
1420 first_optimal_format_.channelFormat == XGL_CH_FMT_UNDEFINED)
1421 first_optimal_format_ = it->format;
1422 }
1423 }
1424 }
Chia-I Wucb67c652014-10-21 11:06:26 +08001425
Chia-I Wu9feab842014-12-22 13:19:08 +08001426 void init_test_formats()
1427 {
1428 init_test_formats(static_cast<XGL_FLAGS>(-1));
1429 }
1430
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001431 void fill_src(xgl_testing::Image &img, const xgl_testing::ImageChecker &checker)
1432 {
1433 if (img.transparent()) {
1434 checker.fill(img);
1435 return;
Chia-I Wucb67c652014-10-21 11:06:26 +08001436 }
1437
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001438 ASSERT_EQ(true, img.copyable());
1439
1440 xgl_testing::Buffer in_buf;
1441 in_buf.init(dev_, checker.buffer_size());
1442 checker.fill(in_buf);
1443
1444 cmd_.add_memory_ref(in_buf, XGL_MEMORY_REF_READ_ONLY_BIT);
1445 cmd_.add_memory_ref(img, 0);
1446
1447 // copy in and tile
1448 cmd_.begin();
1449 xglCmdCopyMemoryToImage(cmd_.obj(), in_buf.obj(), img.obj(),
1450 checker.regions().size(), &checker.regions()[0]);
1451 cmd_.end();
1452
1453 submit_and_done();
Chia-I Wucb67c652014-10-21 11:06:26 +08001454 }
1455
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001456 void check_dst(xgl_testing::Image &img, const xgl_testing::ImageChecker &checker)
Chia-I Wu86822632014-11-22 15:09:42 +08001457 {
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001458 if (img.transparent()) {
1459 DO(checker.check(img));
1460 return;
Chia-I Wu86822632014-11-22 15:09:42 +08001461 }
1462
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001463 ASSERT_EQ(true, img.copyable());
1464
1465 xgl_testing::Buffer out_buf;
1466 out_buf.init(dev_, checker.buffer_size());
1467
1468 cmd_.add_memory_ref(img, XGL_MEMORY_REF_READ_ONLY_BIT);
1469 cmd_.add_memory_ref(out_buf, 0);
1470
1471 // copy out and linearize
1472 cmd_.begin();
1473 xglCmdCopyImageToMemory(cmd_.obj(), img.obj(), out_buf.obj(),
1474 checker.regions().size(), &checker.regions()[0]);
1475 cmd_.end();
1476
1477 submit_and_done();
1478
1479 DO(checker.check(out_buf));
Chia-I Wu86822632014-11-22 15:09:42 +08001480 }
1481
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001482 std::vector<xgl_testing::Device::Format> test_formats_;
1483 XGL_FORMAT first_linear_format_;
1484 XGL_FORMAT first_optimal_format_;
1485};
1486
1487class XglCmdCopyMemoryToImageTest : public XglCmdBlitImageTest {
1488protected:
1489 virtual void SetUp()
1490 {
1491 XglCmdBlitTest::SetUp();
1492 init_test_formats(XGL_FORMAT_IMAGE_COPY_BIT);
1493 ASSERT_NE(true, test_formats_.empty());
1494 }
1495
1496 void test_copy_memory_to_image(const XGL_IMAGE_CREATE_INFO &img_info, const xgl_testing::ImageChecker &checker)
1497 {
1498 xgl_testing::Buffer buf;
1499 xgl_testing::Image img;
1500
1501 buf.init(dev_, checker.buffer_size());
1502 checker.fill(buf);
1503 cmd_.add_memory_ref(buf, XGL_MEMORY_REF_READ_ONLY_BIT);
1504
1505 img.init(dev_, img_info);
1506 cmd_.add_memory_ref(img, 0);
1507
1508 cmd_.begin();
1509 xglCmdCopyMemoryToImage(cmd_.obj(), buf.obj(), img.obj(),
1510 checker.regions().size(), &checker.regions()[0]);
1511 cmd_.end();
1512
1513 submit_and_done();
1514
1515 check_dst(img, checker);
1516 }
1517
1518 void test_copy_memory_to_image(const XGL_IMAGE_CREATE_INFO &img_info, const std::vector<XGL_MEMORY_IMAGE_COPY> &regions)
1519 {
1520 xgl_testing::ImageChecker checker(img_info, regions);
1521 test_copy_memory_to_image(img_info, checker);
1522 }
1523
1524 void test_copy_memory_to_image(const XGL_IMAGE_CREATE_INFO &img_info)
1525 {
1526 xgl_testing::ImageChecker checker(img_info);
1527 test_copy_memory_to_image(img_info, checker);
1528 }
1529};
1530
1531TEST_F(XglCmdCopyMemoryToImageTest, Basic)
1532{
1533 for (std::vector<xgl_testing::Device::Format>::const_iterator it = test_formats_.begin();
1534 it != test_formats_.end(); it++) {
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001535 XGL_IMAGE_CREATE_INFO img_info = xgl_testing::Image::create_info();
1536 img_info.imageType = XGL_IMAGE_2D;
1537 img_info.format = it->format;
1538 img_info.extent.width = 64;
1539 img_info.extent.height = 64;
1540 img_info.tiling = it->tiling;
1541
1542 test_copy_memory_to_image(img_info);
1543 }
Chia-I Wu86822632014-11-22 15:09:42 +08001544}
1545
Chia-I Wu830fb332014-12-13 15:28:20 +08001546class XglCmdCopyImageToMemoryTest : public XglCmdBlitImageTest {
1547protected:
1548 virtual void SetUp()
1549 {
1550 XglCmdBlitTest::SetUp();
1551 init_test_formats(XGL_FORMAT_IMAGE_COPY_BIT);
1552 ASSERT_NE(true, test_formats_.empty());
1553 }
1554
1555 void test_copy_image_to_memory(const XGL_IMAGE_CREATE_INFO &img_info, const xgl_testing::ImageChecker &checker)
1556 {
1557 xgl_testing::Image img;
1558 xgl_testing::Buffer buf;
1559
1560 img.init(dev_, img_info);
1561 fill_src(img, checker);
1562 cmd_.add_memory_ref(img, XGL_MEMORY_REF_READ_ONLY_BIT);
1563
1564 buf.init(dev_, checker.buffer_size());
1565 cmd_.add_memory_ref(buf, 0);
1566
1567 cmd_.begin();
1568 xglCmdCopyImageToMemory(cmd_.obj(), img.obj(), buf.obj(),
1569 checker.regions().size(), &checker.regions()[0]);
1570 cmd_.end();
1571
1572 submit_and_done();
1573
1574 checker.check(buf);
1575 }
1576
1577 void test_copy_image_to_memory(const XGL_IMAGE_CREATE_INFO &img_info, const std::vector<XGL_MEMORY_IMAGE_COPY> &regions)
1578 {
1579 xgl_testing::ImageChecker checker(img_info, regions);
1580 test_copy_image_to_memory(img_info, checker);
1581 }
1582
1583 void test_copy_image_to_memory(const XGL_IMAGE_CREATE_INFO &img_info)
1584 {
1585 xgl_testing::ImageChecker checker(img_info);
1586 test_copy_image_to_memory(img_info, checker);
1587 }
1588};
1589
1590TEST_F(XglCmdCopyImageToMemoryTest, Basic)
1591{
1592 for (std::vector<xgl_testing::Device::Format>::const_iterator it = test_formats_.begin();
1593 it != test_formats_.end(); it++) {
1594 XGL_IMAGE_CREATE_INFO img_info = xgl_testing::Image::create_info();
1595 img_info.imageType = XGL_IMAGE_2D;
1596 img_info.format = it->format;
1597 img_info.extent.width = 64;
1598 img_info.extent.height = 64;
1599 img_info.tiling = it->tiling;
1600
1601 test_copy_image_to_memory(img_info);
1602 }
1603}
1604
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001605class XglCmdCopyImageTest : public XglCmdBlitImageTest {
1606protected:
1607 virtual void SetUp()
1608 {
1609 XglCmdBlitTest::SetUp();
1610 init_test_formats(XGL_FORMAT_IMAGE_COPY_BIT);
1611 ASSERT_NE(true, test_formats_.empty());
Chia-I Wuf7ff6b42014-11-22 16:24:41 +08001612 }
1613
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001614 void test_copy_image(const XGL_IMAGE_CREATE_INFO &src_info, const XGL_IMAGE_CREATE_INFO &dst_info,
1615 const std::vector<XGL_IMAGE_COPY> &copies)
Chia-I Wuf7ff6b42014-11-22 16:24:41 +08001616 {
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001617 // convert XGL_IMAGE_COPY to two sets of XGL_MEMORY_IMAGE_COPY
1618 std::vector<XGL_MEMORY_IMAGE_COPY> src_regions, dst_regions;
1619 XGL_GPU_SIZE src_offset = 0, dst_offset = 0;
1620 for (std::vector<XGL_IMAGE_COPY>::const_iterator it = copies.begin(); it != copies.end(); it++) {
1621 XGL_MEMORY_IMAGE_COPY src_region = {}, dst_region = {};
Chia-I Wuf7ff6b42014-11-22 16:24:41 +08001622
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001623 src_region.memOffset = src_offset;
1624 src_region.imageSubresource = it->srcSubresource;
1625 src_region.imageOffset = it->srcOffset;
1626 src_region.imageExtent = it->extent;
1627 src_regions.push_back(src_region);
Chia-I Wuf7ff6b42014-11-22 16:24:41 +08001628
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001629 dst_region.memOffset = src_offset;
1630 dst_region.imageSubresource = it->destSubresource;
1631 dst_region.imageOffset = it->destOffset;
1632 dst_region.imageExtent = it->extent;
1633 dst_regions.push_back(dst_region);
Chia-I Wuf7ff6b42014-11-22 16:24:41 +08001634
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001635 const XGL_GPU_SIZE size = it->extent.width * it->extent.height * it->extent.depth;
1636 src_offset += xgl_testing::get_format_size(src_info.format) * size;
1637 dst_offset += xgl_testing::get_format_size(dst_info.format) * size;
1638 }
Chia-I Wuf7ff6b42014-11-22 16:24:41 +08001639
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001640 xgl_testing::ImageChecker src_checker(src_info, src_regions);
1641 xgl_testing::ImageChecker dst_checker(dst_info, dst_regions);
1642
1643 xgl_testing::Image src;
1644 src.init(dev_, src_info);
1645 fill_src(src, src_checker);
1646 cmd_.add_memory_ref(src, XGL_MEMORY_REF_READ_ONLY_BIT);
1647
1648 xgl_testing::Image dst;
1649 dst.init(dev_, dst_info);
1650 cmd_.add_memory_ref(dst, 0);
1651
1652 cmd_.begin();
1653 xglCmdCopyImage(cmd_.obj(), src.obj(), dst.obj(), copies.size(), &copies[0]);
1654 cmd_.end();
1655
1656 submit_and_done();
1657
1658 check_dst(dst, dst_checker);
1659 }
1660};
1661
1662TEST_F(XglCmdCopyImageTest, Basic)
1663{
1664 for (std::vector<xgl_testing::Device::Format>::const_iterator it = test_formats_.begin();
1665 it != test_formats_.end(); it++) {
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001666 XGL_IMAGE_CREATE_INFO img_info = xgl_testing::Image::create_info();
1667 img_info.imageType = XGL_IMAGE_2D;
1668 img_info.format = it->format;
1669 img_info.extent.width = 64;
1670 img_info.extent.height = 64;
1671 img_info.tiling = it->tiling;
1672
1673 XGL_IMAGE_COPY copy = {};
1674 copy.srcSubresource = xgl_testing::Image::subresource(XGL_IMAGE_ASPECT_COLOR, 0, 0);
1675 copy.destSubresource = copy.srcSubresource;
1676 copy.extent = img_info.extent;
1677
1678 test_copy_image(img_info, img_info, std::vector<XGL_IMAGE_COPY>(&copy, &copy + 1));
1679 }
1680}
1681
1682class XglCmdClearColorImageTest : public XglCmdBlitImageTest {
1683protected:
Chia-I Wu9feab842014-12-22 13:19:08 +08001684 XglCmdClearColorImageTest() : test_raw_(false) {}
1685 XglCmdClearColorImageTest(bool test_raw) : test_raw_(test_raw) {}
1686
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001687 virtual void SetUp()
1688 {
1689 XglCmdBlitTest::SetUp();
Chia-I Wu9feab842014-12-22 13:19:08 +08001690
1691 if (test_raw_)
1692 init_test_formats();
1693 else
1694 init_test_formats(XGL_FORMAT_CONVERSION_BIT);
1695
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001696 ASSERT_NE(true, test_formats_.empty());
1697 }
1698
Chia-I Wu9feab842014-12-22 13:19:08 +08001699 union Color {
1700 XGL_FLOAT color[4];
1701 XGL_UINT32 raw[4];
1702 };
1703
1704 bool test_raw_;
1705
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001706 std::vector<uint8_t> color_to_raw(XGL_FORMAT format, const XGL_FLOAT color[4])
1707 {
1708 std::vector<uint8_t> raw;
1709
1710 // TODO support all formats
1711 if (format.numericFormat == XGL_NUM_FMT_UNORM) {
1712 switch (format.channelFormat) {
1713 case XGL_CH_FMT_R8G8B8A8:
1714 raw.push_back(color[0] * 255.0f);
1715 raw.push_back(color[1] * 255.0f);
1716 raw.push_back(color[2] * 255.0f);
1717 raw.push_back(color[3] * 255.0f);
1718 break;
1719 case XGL_CH_FMT_B8G8R8A8:
1720 raw.push_back(color[2] * 255.0f);
1721 raw.push_back(color[1] * 255.0f);
1722 raw.push_back(color[0] * 255.0f);
1723 raw.push_back(color[3] * 255.0f);
1724 break;
1725 default:
1726 break;
Chia-I Wuf7ff6b42014-11-22 16:24:41 +08001727 }
1728 }
1729
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001730 return raw;
Chia-I Wuf7ff6b42014-11-22 16:24:41 +08001731 }
Chia-I Wuf7ff6b42014-11-22 16:24:41 +08001732
Chia-I Wu9feab842014-12-22 13:19:08 +08001733 std::vector<uint8_t> color_to_raw(XGL_FORMAT format, const XGL_UINT32 color[4])
1734 {
1735 std::vector<uint8_t> raw;
1736
1737 // TODO support all formats
1738 if (format.numericFormat == XGL_NUM_FMT_UNORM) {
1739 switch (format.channelFormat) {
1740 case XGL_CH_FMT_R8G8B8A8:
1741 raw.push_back(static_cast<uint8_t>(color[0]));
1742 raw.push_back(static_cast<uint8_t>(color[1]));
1743 raw.push_back(static_cast<uint8_t>(color[2]));
1744 raw.push_back(static_cast<uint8_t>(color[3]));
1745 break;
1746 case XGL_CH_FMT_B8G8R8A8:
1747 raw.push_back(static_cast<uint8_t>(color[2]));
1748 raw.push_back(static_cast<uint8_t>(color[1]));
1749 raw.push_back(static_cast<uint8_t>(color[0]));
1750 raw.push_back(static_cast<uint8_t>(color[3]));
1751 break;
1752 default:
1753 break;
1754 }
1755 }
1756
1757 return raw;
1758 }
1759
1760 std::vector<uint8_t> color_to_raw(XGL_FORMAT format, const Color &color)
1761 {
1762 if (test_raw_)
1763 return color_to_raw(format, color.raw);
1764 else
1765 return color_to_raw(format, color.color);
1766 }
1767
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001768 void test_clear_color_image(const XGL_IMAGE_CREATE_INFO &img_info,
Chia-I Wu9feab842014-12-22 13:19:08 +08001769 const Color &color,
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001770 const std::vector<XGL_IMAGE_SUBRESOURCE_RANGE> &ranges)
Chia-I Wucb67c652014-10-21 11:06:26 +08001771 {
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001772 xgl_testing::Image img;
1773 img.init(dev_, img_info);
1774 cmd_.add_memory_ref(img, 0);
Chia-I Wucb67c652014-10-21 11:06:26 +08001775
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001776 std::vector<XGL_IMAGE_STATE_TRANSITION> to_clear;
1777 std::vector<XGL_IMAGE_STATE_TRANSITION> to_xfer;
Chia-I Wucb67c652014-10-21 11:06:26 +08001778
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001779 const XGL_IMAGE_STATE initial_state =
1780 (img_info.usage & XGL_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) ?
1781 XGL_IMAGE_STATE_UNINITIALIZED_TARGET : XGL_IMAGE_STATE_DATA_TRANSFER;
1782 for (std::vector<XGL_IMAGE_SUBRESOURCE_RANGE>::const_iterator it = ranges.begin();
1783 it != ranges.end(); it++) {
1784 to_clear.push_back(img.prepare(initial_state, XGL_IMAGE_STATE_CLEAR, *it));
1785 to_xfer.push_back(img.prepare(XGL_IMAGE_STATE_CLEAR, XGL_IMAGE_STATE_DATA_TRANSFER, *it));
Chia-I Wucb67c652014-10-21 11:06:26 +08001786 }
1787
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001788 cmd_.begin();
Chia-I Wu9feab842014-12-22 13:19:08 +08001789
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001790 xglCmdPrepareImages(cmd_.obj(), to_clear.size(), &to_clear[0]);
Chia-I Wu9feab842014-12-22 13:19:08 +08001791 if (test_raw_)
1792 xglCmdClearColorImageRaw(cmd_.obj(), img.obj(), color.raw, ranges.size(), &ranges[0]);
1793 else
1794 xglCmdClearColorImage(cmd_.obj(), img.obj(), color.color, ranges.size(), &ranges[0]);
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001795 xglCmdPrepareImages(cmd_.obj(), to_xfer.size(), &to_xfer[0]);
Chia-I Wu9feab842014-12-22 13:19:08 +08001796
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001797 cmd_.end();
1798
1799 submit_and_done();
1800
1801 // cannot verify
1802 if (!img.transparent() && !img.copyable())
1803 return;
1804
1805 xgl_testing::ImageChecker checker(img_info, ranges);
1806
1807 const std::vector<uint8_t> solid_pattern = color_to_raw(img_info.format, color);
1808 if (solid_pattern.empty())
1809 return;
1810
1811 checker.set_solid_pattern(solid_pattern);
1812 check_dst(img, checker);
1813 }
Chia-I Wu9feab842014-12-22 13:19:08 +08001814
1815 void test_clear_color_image(const XGL_IMAGE_CREATE_INFO &img_info,
1816 const XGL_FLOAT color[4],
1817 const std::vector<XGL_IMAGE_SUBRESOURCE_RANGE> &ranges)
1818 {
1819 Color c;
1820 memcpy(c.color, color, sizeof(c.color));
1821 test_clear_color_image(img_info, c, ranges);
1822 }
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001823};
1824
1825TEST_F(XglCmdClearColorImageTest, Basic)
1826{
1827 for (std::vector<xgl_testing::Device::Format>::const_iterator it = test_formats_.begin();
1828 it != test_formats_.end(); it++) {
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001829 const XGL_FLOAT color[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
1830
1831 XGL_IMAGE_CREATE_INFO img_info = xgl_testing::Image::create_info();
1832 img_info.imageType = XGL_IMAGE_2D;
1833 img_info.format = it->format;
1834 img_info.extent.width = 64;
1835 img_info.extent.height = 64;
1836 img_info.tiling = it->tiling;
1837
1838 const XGL_IMAGE_SUBRESOURCE_RANGE range =
1839 xgl_testing::Image::subresource_range(XGL_IMAGE_ASPECT_COLOR, img_info);
1840 std::vector<XGL_IMAGE_SUBRESOURCE_RANGE> ranges(&range, &range + 1);
1841
1842 test_clear_color_image(img_info, color, ranges);
Chia-I Wucb67c652014-10-21 11:06:26 +08001843 }
1844}
1845
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001846class XglCmdClearDepthStencilTest : public XglCmdBlitImageTest {
1847protected:
1848 virtual void SetUp()
1849 {
1850 XglCmdBlitTest::SetUp();
1851 init_test_formats(XGL_FORMAT_DEPTH_ATTACHMENT_BIT |
1852 XGL_FORMAT_STENCIL_ATTACHMENT_BIT);
1853 ASSERT_NE(true, test_formats_.empty());
1854 }
1855
1856 std::vector<uint8_t> ds_to_raw(XGL_FORMAT format, XGL_FLOAT depth, XGL_UINT32 stencil)
1857 {
1858 std::vector<uint8_t> raw;
1859
1860 // depth
1861 switch (format.channelFormat) {
1862 case XGL_CH_FMT_R16:
1863 case XGL_CH_FMT_R16G8:
1864 {
1865 const uint16_t unorm = depth * 65535.0f;
1866 raw.push_back(unorm & 0xff);
1867 raw.push_back(unorm >> 8);
1868 }
1869 break;
1870 case XGL_CH_FMT_R32:
1871 case XGL_CH_FMT_R32G8:
1872 {
1873 const union {
1874 XGL_FLOAT depth;
1875 uint32_t u32;
1876 } u = { depth };
1877
1878 raw.push_back((u.u32 ) & 0xff);
1879 raw.push_back((u.u32 >> 8) & 0xff);
1880 raw.push_back((u.u32 >> 16) & 0xff);
1881 raw.push_back((u.u32 >> 24) & 0xff);
1882 }
1883 break;
1884 default:
1885 break;
1886 }
1887
1888 // stencil
1889 switch (format.channelFormat) {
1890 case XGL_CH_FMT_R8:
1891 raw.push_back(stencil);
1892 break;
1893 case XGL_CH_FMT_R16G8:
1894 raw.push_back(stencil);
1895 raw.push_back(0);
1896 break;
1897 case XGL_CH_FMT_R32G8:
1898 raw.push_back(stencil);
1899 raw.push_back(0);
1900 raw.push_back(0);
1901 raw.push_back(0);
1902 break;
1903 default:
1904 break;
1905 }
1906
1907 return raw;
1908 }
1909
1910 void test_clear_depth_stencil(const XGL_IMAGE_CREATE_INFO &img_info,
1911 XGL_FLOAT depth, XGL_UINT32 stencil,
1912 const std::vector<XGL_IMAGE_SUBRESOURCE_RANGE> &ranges)
1913 {
1914 xgl_testing::Image img;
1915 img.init(dev_, img_info);
1916 cmd_.add_memory_ref(img, 0);
1917
1918 std::vector<XGL_IMAGE_STATE_TRANSITION> to_clear;
1919 std::vector<XGL_IMAGE_STATE_TRANSITION> to_xfer;
1920
1921 for (std::vector<XGL_IMAGE_SUBRESOURCE_RANGE>::const_iterator it = ranges.begin();
1922 it != ranges.end(); it++) {
1923 to_clear.push_back(img.prepare(XGL_IMAGE_STATE_UNINITIALIZED_TARGET, XGL_IMAGE_STATE_CLEAR, *it));
1924 to_xfer.push_back(img.prepare(XGL_IMAGE_STATE_CLEAR, XGL_IMAGE_STATE_DATA_TRANSFER, *it));
1925 }
1926
1927 cmd_.begin();
1928 xglCmdPrepareImages(cmd_.obj(), to_clear.size(), &to_clear[0]);
1929 xglCmdClearDepthStencil(cmd_.obj(), img.obj(), depth, stencil, ranges.size(), &ranges[0]);
1930 xglCmdPrepareImages(cmd_.obj(), to_xfer.size(), &to_xfer[0]);
1931 cmd_.end();
1932
1933 submit_and_done();
1934
1935 // cannot verify
1936 if (!img.transparent() && !img.copyable())
1937 return;
1938
1939 xgl_testing::ImageChecker checker(img_info, ranges);
1940
1941 checker.set_solid_pattern(ds_to_raw(img_info.format, depth, stencil));
1942 check_dst(img, checker);
1943 }
1944};
1945
1946TEST_F(XglCmdClearDepthStencilTest, Basic)
1947{
1948 for (std::vector<xgl_testing::Device::Format>::const_iterator it = test_formats_.begin();
1949 it != test_formats_.end(); it++) {
1950 // known driver issues
1951 if (it->format.channelFormat == XGL_CH_FMT_R8)
1952 continue;
1953
1954 XGL_IMAGE_CREATE_INFO img_info = xgl_testing::Image::create_info();
1955 img_info.imageType = XGL_IMAGE_2D;
1956 img_info.format = it->format;
1957 img_info.extent.width = 64;
1958 img_info.extent.height = 64;
1959 img_info.tiling = it->tiling;
1960 img_info.usage = XGL_IMAGE_USAGE_DEPTH_STENCIL_BIT;
1961
1962 const XGL_IMAGE_SUBRESOURCE_RANGE range =
1963 xgl_testing::Image::subresource_range(XGL_IMAGE_ASPECT_DEPTH, img_info);
1964 std::vector<XGL_IMAGE_SUBRESOURCE_RANGE> ranges(&range, &range + 1);
1965
1966 test_clear_depth_stencil(img_info, 0.25f, 63, ranges);
1967 }
1968}
1969
1970}; // namespace
1971
Chia-I Wucb67c652014-10-21 11:06:26 +08001972int main(int argc, char **argv)
1973{
Chia-I Wucb67c652014-10-21 11:06:26 +08001974 ::testing::InitGoogleTest(&argc, argv);
Chia-I Wucb67c652014-10-21 11:06:26 +08001975
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001976 environment = new xgl_testing::Environment();
Chia-I Wucb67c652014-10-21 11:06:26 +08001977
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001978 if (!environment->parse_args(argc, argv))
1979 return -1;
Chia-I Wucb67c652014-10-21 11:06:26 +08001980
Chia-I Wu6170c9e2014-12-08 14:30:10 +08001981 ::testing::AddGlobalTestEnvironment(environment);
1982
1983 return RUN_ALL_TESTS();
Chia-I Wucb67c652014-10-21 11:06:26 +08001984}