import pickle
import random
import unittest
import struct
import sys
try:
import numpy
except:
numpy = None
import d3d11
from d3d11c import *
layout = [
("", 0, FORMAT_R32G32B32_FLOAT, 0, 0, INPUT_PER_VERTEX_DATA, 0),
("", 0, FORMAT_R32G32_FLOAT, 0, 12, INPUT_PER_VERTEX_DATA, 0),
]
layout2 = [
("", 0, FORMAT_R32G32B32A32_FLOAT, 0, 0, INPUT_PER_VERTEX_DATA, 0),
("", 0, FORMAT_R32G32B32A32_FLOAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0),
("", 0, FORMAT_R32G32_FLOAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0),
]
layout3 = [
("", 0, FORMAT_R32G32B32A32_UINT, 0, 0, INPUT_PER_VERTEX_DATA, 0),
]
ITEMCOUNT = 5
class Test(unittest.TestCase):
device = None
def setUp(self):
pass
def tearDown(self):
pass
def getRWBuffer(self, init, usage=USAGE_STAGING, cpu=CPU_ACCESS_READ | CPU_ACCESS_WRITE, bind=0):
b = d3d11.Buffer(layout, init, bind, usage, cpu, 0)
self.assert_(b.getItemSize() == 20)
self.assert_(b.getItemSize() == struct.calcsize(b.getItemFormat()))
self.assert_(b.getItemFormat() == "3f2f")
desc = b.getDesc() #b.getDesc()
self.assert_(desc.usage == usage)
self.assert_(desc.cpuAccess == cpu)
if not isinstance(init, int):
#Init is probably a sequence
self.assert_(len(b) == len(init))
self.assert_(len(b) == b.capacity())
return b
def getInitList(self, size):
init = []
for x in range(size):
init.append(self.vertex())
return init
def vertex(self):
return [random.random() * 100.235 for x in range(ITEMCOUNT)]
def assertFloatEq(self, a, b):
self.assert_(abs(a - b) < 0.00001)
def compareSeq(self, a, b):
self.assert_(len(a) == len(b))
for i, x in enumerate(a):
for i2, v in enumerate(x):
self.assertFloatEq(a[i][i2], b[i][i2])
def test_ctor(self):
SIZE = 63
b1 = self.getRWBuffer(SIZE)
self.assert_(len(b1) == 0)
b2 = self.getRWBuffer(self.getInitList(SIZE))
self.assert_(len(b2) == b2.capacity())
self.assert_(len(b2) == SIZE)
b1.copy(b2)
self.assert_(len(b1) == SIZE)
self.assert_(len(b1) == len(b2))
b1.map(MAP_READ_WRITE)
b2.map(MAP_READ_WRITE)
self.assertEqual(b1[:], b2[:])
self.assert_(list(b1)[:] == b1[:])
b2.unmap()
b1.unmap()
def test_pop(self):
SIZE = 222
s = self.getInitList(SIZE)
b = self.getRWBuffer(s)
b.map(MAP_READ_WRITE)
for x in range(SIZE):
v1 = s.pop()
v2 = b.pop()
self.assert_(len(v1) == len(v2))
self.assert_(len(s) == len(b))
for i, f in enumerate(v1):
self.assertFloatEq(f, v2[i])
self.failUnlessRaises(RuntimeError, b.pop) #Buffer is empty.
b.unmap()
self.assert_(len(b) == 0)
def test_append(self):
b = self.getRWBuffer(50)
pyList = []
b.map(MAP_READ_WRITE)
for x in range(50):
v = self.vertex()
b.append(v)
pyList.append(v)
bufList = b[:]
self.assertEqual(len(bufList), len(pyList))
for i, vertex in enumerate(pyList):
for i2, item in enumerate(vertex):
self.assertFloatEq(item, bufList[i][i2])
self.failUnlessRaises(RuntimeError, b.append, self.vertex()) #Buffer is full.
self.assert_(len(b) == 50)
b.unmap()
def test_extend(self):
b = self.getRWBuffer(100)
s = self.getInitList(25)
b.map(MAP_READ_WRITE)
for i in range(4):
b.extend(s)
self.assert_(len(b) == (i+1) * 25)
self.failUnlessRaises(RuntimeError, b.extend, [self.vertex()]) #Buffer is full.
self.assert_(len(b) == 100)
#Compare results with append()
tmp = b[:]
b.clear()
for i in range(4):
for x in s:
b.append(x)
self.assert_(tmp == b[:])
b.unmap()
def test_update(self):
a = self.getRWBuffer(100)
b = self.getRWBuffer(100, USAGE_DEFAULT, 0)
s = self.getInitList(20)
b.resize(20 * 3)
b.update(s, 0, 0)
b.update(s, 20, 0)
b.update(s, 40, 5)
a.copy(b)
a.map(MAP_READ_WRITE)
self.compareSeq(s * 2, a[:40])
self.compareSeq(s[5:], a[40:55])
a.unmap()
def test_updateRaw(self):
if numpy is None:
print("No numpy available")
return
initData = [(1,2000,3,40000,5)] * 50
numarray = numpy.array(initData, "5f")
#First with CPU map.
stager = self.getRWBuffer(100)
stager.resize(len(numarray))
self.assert_(len(stager) == len(numarray))
stager.map(MAP_READ_WRITE)
#Offset 0
stager.updateRaw(numarray)
self.compareSeq(initData, stager[:])
#Offset 50
stager.resize(100)
stager.updateRaw(numarray, 50)
self.compareSeq(initData, stager[50:])
stager.unmap()
#USAGE_DEFAULT-buffer.
default = self.getRWBuffer(100, USAGE_DEFAULT, 0)
default.resize(len(numarray))
default.updateRaw(numarray)
stager2 = self.getRWBuffer(100)
stager2.copy(default)
stager2.map(MAP_READ_WRITE)
self.compareSeq(initData, stager2[:])
stager2.unmap()
def test_sequence(self):
SIZE = 321
s = self.getInitList(SIZE)
b = self.getRWBuffer(s)
orginal = s[:]
b.map(MAP_READ_WRITE)
for x in range(1000):
index = random.randint(-SIZE, SIZE - 1)
start = random.randint(-10, SIZE + 10)
end = random.randint(-10, SIZE + 10)
step = random.randint(-5, 5)
if step == 0:
step = 1
#getitem
listItem = s[index]
bufItem = b[index]
self.assert_(len(listItem) == len(bufItem))
for i, item in enumerate(listItem):
self.assertFloatEq(item, bufItem[i])
#getitem slice
listSlice = s[start:end:step]
bufSlice = b[start:end:step]
self.assert_(len(listSlice) == len(bufSlice))
for i, vertex in enumerate(listSlice):
for i2, item in enumerate(vertex):
self.assertFloatEq(bufSlice[i][i2], item)
#setitem slice
s[start:end:step] = listSlice # bufSlice - hangs in difflib etc. wtf?
b[start:end:step] = bufSlice
#setitem
s[index] = listItem
b[index] = bufItem
self.assertEqual(s, orginal)
self.assert_(len(s) == len(b))
#Elements should not have changed.
for i1, vertex in enumerate(b[:]):
for i2, item in enumerate(vertex):
self.assertFloatEq(s[i1][i2], item)
#Consistency checks
self.assertEqual(b[:], b[:])
for x in range(SIZE):
self.assertEqual(b[x], b[x])
b.unmap()
def test_mapping(self):
b = self.getRWBuffer(self.getInitList(100))
b.map(MAP_READ_WRITE)
#Unfill the buffer a bit, so that next operations
#can safely add stuff to it.
for x in range(20):
b.pop()
self.failUnlessRaises(RuntimeError, b.map, MAP_READ_WRITE) #Double map()
b.unmap()
self.failUnlessRaises(RuntimeError, b.unmap) #Double unmap()
#These operations should fail because
#the buffer is not mapped.
preSize = len(b)
self.failUnlessRaises(RuntimeError, b.unmap)
self.failUnlessRaises(RuntimeError, b.__setitem__, 0, self.vertex())
self.failUnlessRaises(RuntimeError, b.__setitem__, slice(0, 5), [self.vertex()] * 5)
self.failUnlessRaises(RuntimeError, b.__getitem__, 0)
self.failUnlessRaises(RuntimeError, b.__getitem__, slice(0, 5))
self.failUnlessRaises(RuntimeError, b.pop)
self.failUnlessRaises(RuntimeError, b.append, self.vertex())
self.failUnlessRaises(RuntimeError, b.extend, [self.vertex()])
self.assert_(preSize == len(b))
#Test operations in read-only mode.
b.map(MAP_READ)
#Reads are OK
b[0]
b[0:5]
b.pop()
#Writes are invalid
preSize = len(b)
self.failUnlessRaises(RuntimeError, b.__setitem__, 0, self.vertex())
self.failUnlessRaises(RuntimeError, b.__setitem__, slice(0, 5), [self.vertex()] * 5)
self.failUnlessRaises(RuntimeError, b.append, self.vertex())
self.failUnlessRaises(RuntimeError, b.extend, [self.vertex()])
self.assert_(preSize == len(b))
b.unmap()
#Test operations in write-only mode.
b.map(MAP_WRITE)
#Writes are ok
b[0] = self.vertex()
b[0:5] = [self.vertex()] * 5
b.append(self.vertex())
b.extend([self.vertex()])
#Reads are invalid
preSize = len(b)
self.failUnlessRaises(RuntimeError, b.__getitem__, 0)
self.failUnlessRaises(RuntimeError, b.__getitem__, slice(0, 5))
self.failUnlessRaises(RuntimeError, b.pop)
self.assert_(preSize == len(b))
b.unmap()
def test_description(self):
b = self.getRWBuffer(5)
desc = b.getDesc()
self.assert_(desc[0] == layout)
self.assert_(desc[1] == b.capacity())
self.assert_(desc[2] == 0)
self.assert_(desc[3] == USAGE_STAGING)
self.assert_(desc[3] == desc.usage)
self.assert_(desc[4] == CPU_ACCESS_READ | CPU_ACCESS_WRITE)
self.assert_(desc[5] == 0)
b2 = d3d11.Buffer(*b.getDesc())
self.assert_(b.getDesc() == b2.getDesc())
def test_bufferprotocol(self):
if sys.version_info[0] < 3:
return #Skip
b = self.getRWBuffer(self.getInitList(100))
self.failUnlessRaises(BufferError, memoryview, b)
#Basic tests, read
b.map(MAP_READ)
readView = memoryview(b)
#self.assert_(readView.itemsize == b.itemSize())
self.assert_(len(readView) == len(b) * b.getItemSize())
self.assert_(readView.format == "3f2f")
self.assert_(readView.readonly == True)
b.unmap()
#Read-Write
b.map(MAP_READ_WRITE)
writeView = memoryview(b)
self.assert_(writeView.readonly == False)
itemSize = b.getItemSize()
#Reading
vRead = b[9]
binary = writeView[9*itemSize:9*itemSize+itemSize]
#binary = writeView[9]
self.assertEqual(tuple(vRead), struct.unpack("5f", binary))
#Writing
vOld = b[3]
writeView[3*itemSize:3*itemSize+itemSize] = b'\0' * itemSize
vNew = b[3]
self.assertNotEqual(vOld, vNew)
for x in vNew:
self.assert_(x == 0.0)
b.unmap()
def test_resize(self):
b = self.getRWBuffer(self.getInitList(123))
oldLen = len(b)
self.failUnlessRaises(RuntimeError, b.resize, oldLen + 1)
halfSize = oldLen // 2
b.resize(halfSize)
self.assert_(halfSize == len(b))
b.resize(oldLen)
self.assert_(oldLen == len(b))
b.clear()
self.assert_(len(b) == 0)
self.assert_(b.capacity() == 123)
def test_reformat(self):
b = self.getRWBuffer(self.getInitList(123))
oldMaxSize = b.capacity()
oldItemSize = b.getItemSize()
b.reformat(layout2)
self.assert_(b.getItemSize() == struct.calcsize(b.getItemFormat()))
self.assert_(len(b) == 0)
self.assert_(b.capacity() == oldMaxSize // 2)
self.assert_(b.getItemSize() == oldItemSize * 2)
def test_reformat2(self):
b = self.getRWBuffer(321)
b.reformat(layout3)
self.assert_(b.getItemSize() == struct.calcsize(b.getItemFormat()))
b.map(MAP_READ_WRITE)
for x in range(50):
b.append((42,) * 4)
while len(b):
v = b.pop()
for x in v:
self.assert_(x == 42)
self.assert_(type(x) == int)
b.unmap()
if __name__ == '__main__':
d3d11.enableDebug()
Test.device = d3d11.Device(None)
unittest.main()
Test.device.release()