1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 Google Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and/or associated documentation files (the
9 * "Materials"), to deal in the Materials without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Materials, and to
12 * permit persons to whom the Materials are furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice(s) and this permission notice shall be
16 * included in all copies or substantial portions of the Materials.
18 * The Materials are Confidential Information as defined by the
19 * Khronos Membership Agreement until designated non-confidential by
20 * Khronos, at which point this condition clause shall be removed.
22 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
32 * \brief Simple memory mapping tests.
33 *//*--------------------------------------------------------------------*/
35 #include "vktMemoryMappingTests.hpp"
37 #include "vktTestCaseUtil.hpp"
39 #include "tcuMaybe.hpp"
40 #include "tcuResultCollector.hpp"
41 #include "tcuTestLog.hpp"
43 #include "vkDeviceUtil.hpp"
44 #include "vkPlatform.hpp"
45 #include "vkQueryUtil.hpp"
47 #include "vkStrUtil.hpp"
49 #include "deRandom.hpp"
50 #include "deSharedPtr.hpp"
51 #include "deStringUtil.hpp"
52 #include "deUniquePtr.hpp"
73 Move<VkDeviceMemory> allocMemory (const DeviceInterface& vk, VkDevice device, VkDeviceSize pAllocInfo_allocationSize, deUint32 pAllocInfo_memoryTypeIndex)
75 VkDeviceMemory object = 0;
76 const VkMemoryAllocateInfo pAllocInfo =
78 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
80 pAllocInfo_allocationSize,
81 pAllocInfo_memoryTypeIndex,
83 VK_CHECK(vk.allocateMemory(device, &pAllocInfo, (const VkAllocationCallbacks*)DE_NULL, &object));
84 return Move<VkDeviceMemory>(check<VkDeviceMemory>(object), Deleter<VkDeviceMemory>(vk, device, (const VkAllocationCallbacks*)DE_NULL));
89 MemoryRange (VkDeviceSize offset_ = ~(VkDeviceSize)0, VkDeviceSize size_ = ~(VkDeviceSize)0)
102 : allocationSize (~(VkDeviceSize)0)
106 VkDeviceSize allocationSize;
110 vector<MemoryRange> flushMappings;
111 vector<MemoryRange> invalidateMappings;
115 bool compareAndLogBuffer (TestLog& log, size_t size, const deUint8* result, const deUint8* reference)
117 size_t failedBytes = 0;
118 size_t firstFailed = (size_t)-1;
120 for (size_t ndx = 0; ndx < size; ndx++)
122 if (result[ndx] != reference[ndx])
126 if (firstFailed == (size_t)-1)
133 log << TestLog::Message << "Comparison failed. Failed bytes " << failedBytes << ". First failed at offset " << firstFailed << "." << TestLog::EndMessage;
135 std::ostringstream expectedValues;
136 std::ostringstream resultValues;
138 for (size_t ndx = firstFailed; ndx < firstFailed + 10 && ndx < size; ndx++)
140 if (ndx != firstFailed)
142 expectedValues << ", ";
143 resultValues << ", ";
146 expectedValues << reference[ndx];
147 resultValues << result[ndx];
150 if (firstFailed + 10 < size)
152 expectedValues << "...";
153 resultValues << "...";
156 log << TestLog::Message << "Expected values at offset: " << firstFailed << ", " << expectedValues.str() << TestLog::EndMessage;
157 log << TestLog::Message << "Result values at offset: " << firstFailed << ", " << resultValues.str() << TestLog::EndMessage;
165 tcu::TestStatus testMemoryMapping (Context& context, const TestConfig config)
167 TestLog& log = context.getTestContext().getLog();
168 tcu::ResultCollector result (log);
169 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
170 const VkDevice device = context.getDevice();
171 const InstanceInterface& vki = context.getInstanceInterface();
172 const DeviceInterface& vkd = context.getDeviceInterface();
173 const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physicalDevice);
176 const tcu::ScopedLogSection section (log, "TestCaseInfo", "TestCaseInfo");
178 log << TestLog::Message << "Seed: " << config.seed << TestLog::EndMessage;
179 log << TestLog::Message << "Allocation size: " << config.allocationSize << TestLog::EndMessage;
180 log << TestLog::Message << "Mapping, offset: " << config.mapping.offset << ", size: " << config.mapping.size << TestLog::EndMessage;
182 if (!config.flushMappings.empty())
184 log << TestLog::Message << "Invalidating following ranges:" << TestLog::EndMessage;
186 for (size_t ndx = 0; ndx < config.flushMappings.size(); ndx++)
187 log << TestLog::Message << "\tOffset: " << config.flushMappings[ndx].offset << ", Size: " << config.flushMappings[ndx].size << TestLog::EndMessage;
191 log << TestLog::Message << "Remapping memory between flush and invalidation." << TestLog::EndMessage;
193 if (!config.invalidateMappings.empty())
195 log << TestLog::Message << "Flushing following ranges:" << TestLog::EndMessage;
197 for (size_t ndx = 0; ndx < config.invalidateMappings.size(); ndx++)
198 log << TestLog::Message << "\tOffset: " << config.invalidateMappings[ndx].offset << ", Size: " << config.invalidateMappings[ndx].size << TestLog::EndMessage;
202 for (deUint32 memoryTypeIndex = 0; memoryTypeIndex < memoryProperties.memoryTypeCount; memoryTypeIndex++)
206 const tcu::ScopedLogSection section (log, "MemoryType" + de::toString(memoryTypeIndex), "MemoryType" + de::toString(memoryTypeIndex));
207 const VkMemoryType& memoryType = memoryProperties.memoryTypes[memoryTypeIndex];
208 const VkMemoryHeap& memoryHeap = memoryProperties.memoryHeaps[memoryType.heapIndex];
210 log << TestLog::Message << "MemoryType: " << memoryType << TestLog::EndMessage;
211 log << TestLog::Message << "MemoryHeap: " << memoryHeap << TestLog::EndMessage;
213 if ((memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
215 log << TestLog::Message << "Memory type doesn't support mapping." << TestLog::EndMessage;
219 const Unique<VkDeviceMemory> memory (allocMemory(vkd, device, config.allocationSize, memoryTypeIndex));
220 de::Random rng (config.seed);
221 vector<deUint8> reference ((size_t)config.allocationSize);
222 deUint8* mapping = DE_NULL;
226 VK_CHECK(vkd.mapMemory(device, *memory, config.mapping.offset, config.mapping.size, 0u, &ptr));
229 mapping = (deUint8*)ptr;
232 for (VkDeviceSize ndx = 0; ndx < config.mapping.size; ndx++)
234 const deUint8 val = rng.getUint8();
237 reference[(size_t)(config.mapping.offset + ndx)] = val;
240 if (!config.flushMappings.empty())
242 vector<VkMappedMemoryRange> ranges;
244 for (size_t ndx = 0; ndx < config.flushMappings.size(); ndx++)
246 const VkMappedMemoryRange range =
248 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
252 config.flushMappings[ndx].offset,
253 config.flushMappings[ndx].size
256 ranges.push_back(range);
259 VK_CHECK(vkd.flushMappedMemoryRanges(device, (deUint32)ranges.size(), &ranges[0]));
265 vkd.unmapMemory(device, *memory);
266 VK_CHECK(vkd.mapMemory(device, *memory, config.mapping.offset, config.mapping.size, 0u, &ptr));
269 mapping = (deUint8*)ptr;
272 if (!config.invalidateMappings.empty())
274 vector<VkMappedMemoryRange> ranges;
276 for (size_t ndx = 0; ndx < config.invalidateMappings.size(); ndx++)
278 const VkMappedMemoryRange range =
280 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
284 config.invalidateMappings[ndx].offset,
285 config.invalidateMappings[ndx].size
288 ranges.push_back(range);
291 VK_CHECK(vkd.invalidateMappedMemoryRanges(device, (deUint32)ranges.size(), &ranges[0]));
294 if (!compareAndLogBuffer(log, (size_t)config.mapping.size, mapping, &reference[(size_t)config.mapping.offset]))
295 result.fail("Unexpected values read from mapped memory.");
297 vkd.unmapMemory(device, *memory);
300 catch (const tcu::TestError& error)
302 result.fail(error.getMessage());
306 return tcu::TestStatus(result.getResult(), result.getMessage());
312 MemoryMapping (const MemoryRange& range,
316 void randomRead (de::Random& rng);
317 void randomWrite (de::Random& rng);
318 void randomModify (de::Random& rng);
326 MemoryMapping::MemoryMapping (const MemoryRange& range,
333 DE_ASSERT(range.size > 0);
336 void MemoryMapping::randomRead (de::Random& rng)
338 const size_t count = (size_t)rng.getInt(0, 100);
340 for (size_t ndx = 0; ndx < count; ndx++)
342 const size_t pos = (size_t)(rng.getUint64() % (deUint64)m_range.size);
343 const deUint8 val = ((deUint8*) m_ptr)[pos];
345 if (m_refPtr[pos] < 256)
346 TCU_CHECK((deUint16)val == m_refPtr[pos]);
348 m_refPtr[pos] = (deUint16)val;
352 void MemoryMapping::randomWrite (de::Random& rng)
354 const size_t count = (size_t)rng.getInt(0, 100);
356 for (size_t ndx = 0; ndx < count; ndx++)
358 const size_t pos = (size_t)(rng.getUint64() % (deUint64)m_range.size);
359 const deUint8 val = rng.getUint8();
361 ((deUint8*)m_ptr)[pos] = val;
362 m_refPtr[pos] = (deUint16)val;
366 void MemoryMapping::randomModify (de::Random& rng)
368 const size_t count = (size_t)rng.getInt(0, 100);
370 for (size_t ndx = 0; ndx < count; ndx++)
372 const size_t pos = (size_t)(rng.getUint64() % (deUint64)m_range.size);
373 const deUint8 val = ((deUint8*)m_ptr)[pos];
374 const deUint8 mask = rng.getUint8();
376 if (m_refPtr[pos] < 256)
377 TCU_CHECK((deUint16)val == m_refPtr[pos]);
379 ((deUint8*)m_ptr)[pos] = val ^ mask;
380 m_refPtr[pos] = (deUint16)(val ^ mask);
384 void randomRanges (de::Random& rng, vector<VkMappedMemoryRange>& ranges, size_t count, VkDeviceMemory memory, VkDeviceSize maxSize)
386 ranges.resize(count);
388 for (size_t rangeNdx = 0; rangeNdx < count; rangeNdx++)
390 const VkDeviceSize size = (maxSize > 1 ? (VkDeviceSize)(1 + (rng.getUint64() % (deUint64)(maxSize - 1))) : 1);
391 const VkDeviceSize offset = (VkDeviceSize)(rng.getUint64() % (deUint64)(maxSize - size + 1));
393 const VkMappedMemoryRange range =
395 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
402 ranges[rangeNdx] = range;
409 MemoryObject (const DeviceInterface& vkd,
412 deUint32 memoryTypeIndex);
414 ~MemoryObject (void);
416 MemoryMapping* mapRandom (const DeviceInterface& vkd, VkDevice device, de::Random& rng);
419 void randomFlush (const DeviceInterface& vkd, VkDevice device, de::Random& rng);
420 void randomInvalidate (const DeviceInterface& vkd, VkDevice device, de::Random& rng);
422 VkDeviceSize getSize (void) const { return m_size; }
423 MemoryMapping* getMapping (void) { return m_mapping; }
426 const DeviceInterface& m_vkd;
429 deUint32 m_memoryTypeIndex;
432 Move<VkDeviceMemory> m_memory;
434 MemoryMapping* m_mapping;
435 vector<deUint16> m_reference;
438 MemoryObject::MemoryObject (const DeviceInterface& vkd,
441 deUint32 memoryTypeIndex)
444 , m_memoryTypeIndex (memoryTypeIndex)
446 , m_mapping (DE_NULL)
448 m_memory = allocMemory(m_vkd, m_device, m_size, m_memoryTypeIndex);
449 m_reference.resize((size_t)m_size, 0xFFFFu);
452 MemoryObject::~MemoryObject (void)
457 MemoryMapping* MemoryObject::mapRandom (const DeviceInterface& vkd, VkDevice device, de::Random& rng)
459 const VkDeviceSize size = (m_size > 1 ? (VkDeviceSize)(1 + (rng.getUint64() % (deUint64)(m_size - 1))) : 1);
460 const VkDeviceSize offset = (VkDeviceSize)(rng.getUint64() % (deUint64)(m_size - size + 1));
463 DE_ASSERT(!m_mapping);
465 VK_CHECK(vkd.mapMemory(device, *m_memory, offset, size, 0u, &ptr));
467 m_mapping = new MemoryMapping(MemoryRange(offset, size), ptr, &(m_reference[(size_t)offset]));
472 void MemoryObject::unmap (void)
474 m_vkd.unmapMemory(m_device, *m_memory);
480 void MemoryObject::randomFlush (const DeviceInterface& vkd, VkDevice device, de::Random& rng)
482 const size_t rangeCount = (size_t)rng.getInt(1, 10);
483 vector<VkMappedMemoryRange> ranges (rangeCount);
485 randomRanges(rng, ranges, rangeCount, *m_memory, m_size);
487 VK_CHECK(vkd.flushMappedMemoryRanges(device, (deUint32)ranges.size(), ranges.empty() ? DE_NULL : &ranges[0]));
490 void MemoryObject::randomInvalidate (const DeviceInterface& vkd, VkDevice device, de::Random& rng)
492 const size_t rangeCount = (size_t)rng.getInt(1, 10);
493 vector<VkMappedMemoryRange> ranges (rangeCount);
495 randomRanges(rng, ranges, rangeCount, *m_memory, m_size);
497 VK_CHECK(vkd.invalidateMappedMemoryRanges(device, (deUint32)ranges.size(), ranges.empty() ? DE_NULL : &ranges[0]));
502 // Use only 1/16 of each memory heap.
503 MAX_MEMORY_USAGE_DIV = 16
507 void removeFirstEqual (vector<T>& vec, const T& val)
509 for (size_t ndx = 0; ndx < vec.size(); ndx++)
513 vec[ndx] = vec.back();
523 MemoryHeap (const VkMemoryHeap& heap,
524 const vector<deUint32>& memoryTypes)
526 , m_memoryTypes (memoryTypes)
533 for (vector<MemoryObject*>::iterator iter = m_objects.begin(); iter != m_objects.end(); ++iter)
537 bool full (void) const { return m_usage * MAX_MEMORY_USAGE_DIV >= m_heap.size; }
538 bool empty (void) const { return m_usage == 0; }
540 MemoryObject* allocateRandom (const DeviceInterface& vkd, VkDevice device, de::Random& rng)
542 const VkDeviceSize size = 1 + (rng.getUint64() % (de::max((deInt64)((m_heap.size / MAX_MEMORY_USAGE_DIV) - m_usage - 1ull), (deInt64)1)));
543 const deUint32 type = rng.choose<deUint32>(m_memoryTypes.begin(), m_memoryTypes.end());
545 if ( (size > (VkDeviceSize)((m_heap.size / MAX_MEMORY_USAGE_DIV) - m_usage)) && (size != 1))
546 TCU_THROW(InternalError, "Test Error: trying to allocate memory more than the available heap size.");
548 MemoryObject* const object = new MemoryObject(vkd, device, size, type);
551 m_objects.push_back(object);
556 MemoryObject* getRandomObject (de::Random& rng) const
558 return rng.choose<MemoryObject*>(m_objects.begin(), m_objects.end());
561 void free (MemoryObject* object)
563 removeFirstEqual(m_objects, object);
564 m_usage -= object->getSize();
570 vector<deUint32> m_memoryTypes;
572 VkDeviceSize m_usage;
573 vector<MemoryObject*> m_objects;
576 class RandomMemoryMappingInstance : public TestInstance
579 RandomMemoryMappingInstance (Context& context, deUint32 seed)
580 : TestInstance (context)
584 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
585 const InstanceInterface& vki = context.getInstanceInterface();
586 const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physicalDevice);
590 vector<vector<deUint32> > memoryTypes (memoryProperties.memoryHeapCount);
592 for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < memoryProperties.memoryTypeCount; memoryTypeNdx++)
594 if (memoryProperties.memoryTypes[memoryTypeNdx].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
595 memoryTypes[memoryProperties.memoryTypes[memoryTypeNdx].heapIndex].push_back(memoryTypeNdx);
598 for (deUint32 heapIndex = 0; heapIndex < memoryProperties.memoryHeapCount; heapIndex++)
600 const VkMemoryHeap heapInfo = memoryProperties.memoryHeaps[heapIndex];
602 if (!memoryTypes[heapIndex].empty())
604 const de::SharedPtr<MemoryHeap> heap (new MemoryHeap(heapInfo, memoryTypes[heapIndex]));
607 m_nonFullHeaps.push_back(heap);
613 ~RandomMemoryMappingInstance (void)
617 tcu::TestStatus iterate (void)
619 const size_t opCount = 100;
620 const float memoryOpProbability = 0.5f; // 0.50
621 const float flushInvalidateProbability = 0.4f; // 0.20
622 const float mapProbability = 0.50f; // 0.15
623 const float unmapProbability = 0.25f; // 0.075
625 const float allocProbability = 0.75f; // Versun free
627 const VkDevice device = m_context.getDevice();
628 const DeviceInterface& vkd = m_context.getDeviceInterface();
630 if (m_opNdx < opCount)
632 if (!m_memoryMappings.empty() && m_rng.getFloat() < memoryOpProbability)
634 // Perform operations on mapped memory
635 MemoryMapping* const mapping = m_rng.choose<MemoryMapping*>(m_memoryMappings.begin(), m_memoryMappings.end());
645 const Op op = (Op)(m_rng.getUint32() % OP_LAST);
650 mapping->randomRead(m_rng);
654 mapping->randomWrite(m_rng);
658 mapping->randomModify(m_rng);
662 DE_FATAL("Invalid operation");
665 else if (!m_mappedMemoryObjects.empty() && m_rng.getFloat() < flushInvalidateProbability)
667 MemoryObject* const object = m_rng.choose<MemoryObject*>(m_mappedMemoryObjects.begin(), m_mappedMemoryObjects.end());
670 object->randomFlush(vkd, device, m_rng);
672 object->randomInvalidate(vkd, device, m_rng);
674 else if (!m_mappedMemoryObjects.empty() && m_rng.getFloat() < unmapProbability)
676 // Unmap memory object
677 MemoryObject* const object = m_rng.choose<MemoryObject*>(m_mappedMemoryObjects.begin(), m_mappedMemoryObjects.end());
680 removeFirstEqual(m_memoryMappings, object->getMapping());
683 removeFirstEqual(m_mappedMemoryObjects, object);
684 m_nonMappedMemoryObjects.push_back(object);
686 else if (!m_nonMappedMemoryObjects.empty() && m_rng.getFloat() < mapProbability)
689 MemoryObject* const object = m_rng.choose<MemoryObject*>(m_nonMappedMemoryObjects.begin(), m_nonMappedMemoryObjects.end());
690 MemoryMapping* mapping = object->mapRandom(vkd, device, m_rng);
692 m_memoryMappings.push_back(mapping);
693 m_mappedMemoryObjects.push_back(object);
694 removeFirstEqual(m_nonMappedMemoryObjects, object);
698 if (!m_nonFullHeaps.empty() && (m_nonEmptyHeaps.empty() || m_rng.getFloat() < allocProbability))
700 // Allocate more memory objects
701 de::SharedPtr<MemoryHeap> const heap = m_rng.choose<de::SharedPtr<MemoryHeap> >(m_nonFullHeaps.begin(), m_nonFullHeaps.end());
704 m_nonEmptyHeaps.push_back(heap);
707 MemoryObject* const object = heap->allocateRandom(vkd, device, m_rng);
710 removeFirstEqual(m_nonFullHeaps, heap);
712 m_nonMappedMemoryObjects.push_back(object);
717 // Free memory objects
718 de::SharedPtr<MemoryHeap> const heap = m_rng.choose<de::SharedPtr<MemoryHeap> >(m_nonEmptyHeaps.begin(), m_nonEmptyHeaps.end());
719 MemoryObject* const object = heap->getRandomObject(m_rng);
722 if (object->getMapping())
723 removeFirstEqual(m_memoryMappings, object->getMapping());
725 removeFirstEqual(m_mappedMemoryObjects, object);
726 removeFirstEqual(m_nonMappedMemoryObjects, object);
729 m_nonFullHeaps.push_back(heap);
734 removeFirstEqual(m_nonEmptyHeaps, heap);
739 return tcu::TestStatus::incomplete();
742 return tcu::TestStatus::pass("Pass");
749 vector<de::SharedPtr<MemoryHeap> > m_nonEmptyHeaps;
750 vector<de::SharedPtr<MemoryHeap> > m_nonFullHeaps;
752 vector<MemoryObject*> m_mappedMemoryObjects;
753 vector<MemoryObject*> m_nonMappedMemoryObjects;
754 vector<MemoryMapping*> m_memoryMappings;
763 OP_SUB_FLUSH_SEPARATE,
764 OP_SUB_FLUSH_OVERLAPPING,
768 OP_SUB_INVALIDATE_SEPARATE,
769 OP_SUB_INVALIDATE_OVERLAPPING,
776 TestConfig subMappedConfig (VkDeviceSize allocationSize,
777 const MemoryRange& mapping,
783 config.allocationSize = allocationSize;
785 config.mapping = mapping;
786 config.remap = false;
798 config.flushMappings = vector<MemoryRange>(1, MemoryRange(0, allocationSize));
802 DE_ASSERT(allocationSize / 4 > 0);
804 config.flushMappings = vector<MemoryRange>(1, MemoryRange(allocationSize / 4, allocationSize / 2));
807 case OP_SUB_FLUSH_SEPARATE:
808 DE_ASSERT(allocationSize / 2 > 0);
810 config.flushMappings.push_back(MemoryRange(allocationSize / 2, allocationSize - (allocationSize / 2)));
811 config.flushMappings.push_back(MemoryRange(0, allocationSize / 2));
815 case OP_SUB_FLUSH_OVERLAPPING:
816 DE_ASSERT((allocationSize / 3) > 0);
818 config.flushMappings.push_back(MemoryRange(allocationSize / 3, allocationSize - (allocationSize / 2)));
819 config.flushMappings.push_back(MemoryRange(0, (2 * allocationSize) / 3));
824 config.invalidateMappings = vector<MemoryRange>(1, MemoryRange(0, allocationSize));
827 case OP_SUB_INVALIDATE:
828 DE_ASSERT(allocationSize / 4 > 0);
830 config.invalidateMappings = vector<MemoryRange>(1, MemoryRange(allocationSize / 4, allocationSize / 2));
833 case OP_SUB_INVALIDATE_SEPARATE:
834 DE_ASSERT(allocationSize / 2 > 0);
836 config.invalidateMappings.push_back(MemoryRange(allocationSize / 2, allocationSize - (allocationSize / 2)));
837 config.invalidateMappings.push_back(MemoryRange(0, allocationSize / 2));
841 case OP_SUB_INVALIDATE_OVERLAPPING:
842 DE_ASSERT((allocationSize / 3) > 0);
844 config.invalidateMappings.push_back(MemoryRange(allocationSize / 3, allocationSize - (allocationSize / 2)));
845 config.invalidateMappings.push_back(MemoryRange(0, (2 * allocationSize) / 3));
850 DE_FATAL("Unknown Op");
855 TestConfig fullMappedConfig (VkDeviceSize allocationSize,
859 return subMappedConfig(allocationSize, MemoryRange(0, allocationSize), op, seed);
864 tcu::TestCaseGroup* createMappingTests (tcu::TestContext& testCtx)
866 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "mapping", "Memory mapping tests."));
868 const VkDeviceSize allocationSizes[] =
870 33, 257, 4087, 8095, 1*1024*1024 + 1
873 const VkDeviceSize offsets[] =
875 0, 17, 129, 255, 1025, 32*1024+1
878 const VkDeviceSize sizes[] =
880 31, 255, 1025, 4085, 1*1024*1024 - 1
886 const char* const name;
889 { OP_NONE, "simple" },
890 { OP_REMAP, "remap" },
891 { OP_FLUSH, "flush" },
892 { OP_SUB_FLUSH, "subflush" },
893 { OP_SUB_FLUSH_SEPARATE, "subflush_separate" },
894 { OP_SUB_FLUSH_SEPARATE, "subflush_overlapping" },
896 { OP_INVALIDATE, "invalidate" },
897 { OP_SUB_INVALIDATE, "subinvalidate" },
898 { OP_SUB_INVALIDATE_SEPARATE, "subinvalidate_separate" },
899 { OP_SUB_INVALIDATE_SEPARATE, "subinvalidate_overlapping" }
904 de::MovePtr<tcu::TestCaseGroup> fullGroup (new tcu::TestCaseGroup(testCtx, "full", "Map memory completely."));
906 for (size_t allocationSizeNdx = 0; allocationSizeNdx < DE_LENGTH_OF_ARRAY(allocationSizes); allocationSizeNdx++)
908 const VkDeviceSize allocationSize = allocationSizes[allocationSizeNdx];
909 de::MovePtr<tcu::TestCaseGroup> allocationSizeGroup (new tcu::TestCaseGroup(testCtx, de::toString(allocationSize).c_str(), ""));
911 for (size_t opNdx = 0; opNdx < DE_LENGTH_OF_ARRAY(ops); opNdx++)
913 const Op op = ops[opNdx].op;
914 const char* const name = ops[opNdx].name;
915 const deUint32 seed = (deUint32)(opNdx * allocationSizeNdx);
916 const TestConfig config = fullMappedConfig(allocationSize, op, seed);
918 addFunctionCase(allocationSizeGroup.get(), name, name, testMemoryMapping, config);
921 fullGroup->addChild(allocationSizeGroup.release());
924 group->addChild(fullGroup.release());
929 de::MovePtr<tcu::TestCaseGroup> subGroup (new tcu::TestCaseGroup(testCtx, "sub", "Map part of the memory."));
931 for (size_t allocationSizeNdx = 0; allocationSizeNdx < DE_LENGTH_OF_ARRAY(allocationSizes); allocationSizeNdx++)
933 const VkDeviceSize allocationSize = allocationSizes[allocationSizeNdx];
934 de::MovePtr<tcu::TestCaseGroup> allocationSizeGroup (new tcu::TestCaseGroup(testCtx, de::toString(allocationSize).c_str(), ""));
936 for (size_t offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
938 const VkDeviceSize offset = offsets[offsetNdx];
940 if (offset >= allocationSize)
943 de::MovePtr<tcu::TestCaseGroup> offsetGroup (new tcu::TestCaseGroup(testCtx, ("offset_" + de::toString(offset)).c_str(), ""));
945 for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
947 const VkDeviceSize size = sizes[sizeNdx];
949 if (offset + size > allocationSize)
952 if (offset == 0 && size == allocationSize)
955 de::MovePtr<tcu::TestCaseGroup> sizeGroup (new tcu::TestCaseGroup(testCtx, ("size_" + de::toString(size)).c_str(), ""));
957 for (size_t opNdx = 0; opNdx < DE_LENGTH_OF_ARRAY(ops); opNdx++)
959 const deUint32 seed = (deUint32)(opNdx * allocationSizeNdx);
960 const Op op = ops[opNdx].op;
961 const char* const name = ops[opNdx].name;
962 const TestConfig config = subMappedConfig(allocationSize, MemoryRange(offset, size), op, seed);
964 addFunctionCase(sizeGroup.get(), name, name, testMemoryMapping, config);
967 offsetGroup->addChild(sizeGroup.release());
970 allocationSizeGroup->addChild(offsetGroup.release());
973 subGroup->addChild(allocationSizeGroup.release());
976 group->addChild(subGroup.release());
981 de::MovePtr<tcu::TestCaseGroup> randomGroup (new tcu::TestCaseGroup(testCtx, "random", "Random memory mapping tests."));
982 de::Random rng (3927960301u);
984 for (size_t ndx = 0; ndx < 100; ndx++)
986 const deUint32 seed = rng.getUint32();
987 const std::string name = de::toString(ndx);
989 randomGroup->addChild(new InstanceFactory1<RandomMemoryMappingInstance, deUint32>(testCtx, tcu::NODETYPE_SELF_VALIDATE, de::toString(ndx), "Random case", seed));
992 group->addChild(randomGroup.release());
995 return group.release();