1 #include <array> 2 3 #include "TaskProcessor.h" 4 5 /** 6 * Sets all entries of the buffer to a value that depends on its coordinate and a delta. 7 */ 8 class SimpleTask : public android::renderscript::Task { 9 uint8_t* mBuffer; 10 uint8_t mDelta; 11 virtual void processData(int threadIndex, size_t startX, size_t startY, size_t endX, 12 size_t endY); 13 14 public: SimpleTask(uint8_t * buffer,size_t vectorSize,size_t sizeX,size_t sizeY,uint8_t delta)15 SimpleTask(uint8_t* buffer, size_t vectorSize, size_t sizeX, size_t sizeY, uint8_t delta) 16 : Task{sizeX, sizeY, vectorSize, false, nullptr}, mBuffer{buffer}, mDelta{delta} {} 17 }; 18 19 /** 20 * Create a new value that's a function of the x, y coordinates and a delta. 21 */ newValue(size_t x,size_t y,uint8_t delta)22 static uint8_t newValue(size_t x, size_t y, uint8_t delta) { 23 return (((x & 0xff) << 4) | (y & 0xff)) + delta; 24 } 25 processData(int,size_t startX,size_t startY,size_t endX,size_t endY)26 void SimpleTask::processData(int /*threadIndex*/, size_t startX, size_t startY, size_t endX, 27 size_t endY) { 28 for (size_t y = startY; y < endY; y++) { 29 for (size_t x = startX; x < endX; x++) { 30 size_t index = (y * mSizeX + x) * mVectorSize; 31 for (size_t i = 0; i < mVectorSize; i++) { 32 // Use add to make sure the opertion is only done once. This assumes 33 // the buffer starts set at 0. 34 mBuffer[index + i] += newValue(x, y, mDelta + i); 35 } 36 } 37 } 38 } 39 40 /** 41 * Returns true if all the entries of the vector are the expected value. 42 * Prints an error if not. 43 */ verifyAllTheSame(const std::vector<uint8_t> & buffer,size_t vectorSize,size_t sizeX,size_t sizeY,uint8_t delta)44 bool verifyAllTheSame(const std::vector<uint8_t>& buffer, size_t vectorSize, size_t sizeX, 45 size_t sizeY, uint8_t delta) { 46 for (size_t y = 0; y < sizeY; y++) { 47 for (size_t x = 0; x < sizeX; x++) { 48 size_t index = (y * sizeX + x) * vectorSize; 49 for (size_t i = 0; i < vectorSize; i++) { 50 uint8_t expectedValue = newValue(x, y, delta + i); 51 if (buffer[index + i] != expectedValue) { 52 printf("Test Error at %zu, %zu. Expected %u found %u instead\n", x, y, 53 expectedValue, buffer[index + i]); 54 return false; 55 } 56 } 57 } 58 } 59 return true; 60 } 61 62 /** 63 * Create a buffer of the specified size, set each entry of that buffer 64 * to the specified value using TaskProcessor, and verify the results. 65 */ testOne(android::renderscript::TaskProcessor * processor,uint8_t delta,size_t vectorSize,size_t sizeX,size_t sizeY)66 void testOne(android::renderscript::TaskProcessor* processor, uint8_t delta, size_t vectorSize, 67 size_t sizeX, size_t sizeY) { 68 std::vector<uint8_t> buffer(sizeX * sizeY * vectorSize); 69 70 SimpleTask task{buffer.data(), vectorSize, sizeX, sizeY, delta}; 71 processor->doTask(&task); 72 73 if (verifyAllTheSame(buffer, vectorSize, sizeX, sizeY, delta)) { 74 printf("Test %u: All good!\n", delta); 75 } 76 } 77 main()78 int main() { 79 std::vector<std::thread> testThreads; 80 81 // Test with multiple threads, to help find synchronization errors. 82 android::renderscript::TaskProcessor processorA(1); 83 android::renderscript::TaskProcessor processorB(4); 84 testThreads.emplace_back(testOne, &processorA, 1, 4, 30, 40); 85 testThreads.emplace_back(testOne, &processorB, 1, 4, 30, 40); 86 testThreads.emplace_back(testOne, &processorA, 2, 4, 800, 600); 87 testThreads.emplace_back(testOne, &processorB, 2, 4, 800, 600); 88 testThreads.emplace_back(testOne, &processorA, 3, 1, 123, 47); 89 testThreads.emplace_back(testOne, &processorB, 3, 1, 123, 47); 90 testThreads.emplace_back(testOne, &processorA, 5, 2, 5000, 8000); 91 testThreads.emplace_back(testOne, &processorB, 5, 2, 5000, 8000); 92 testThreads.emplace_back(testOne, &processorA, 6, 3, 26000, 1); 93 testThreads.emplace_back(testOne, &processorB, 6, 3, 26000, 1); 94 testThreads.emplace_back(testOne, &processorA, 7, 4, 1, 26000); 95 testThreads.emplace_back(testOne, &processorB, 7, 4, 1, 26000); 96 testThreads.emplace_back(testOne, &processorA, 8, 4, 1000, 1000); 97 testThreads.emplace_back(testOne, &processorB, 8, 4, 1000, 1000); 98 testThreads.emplace_back(testOne, &processorA, 9, 1, 1, 1); 99 testThreads.emplace_back(testOne, &processorB, 9, 1, 1, 1); 100 101 for (auto& thread : testThreads) { 102 thread.join(); 103 } 104 return 0; 105 } 106