def dtype(self): '''The numpy datatype used to represent this block member in a buffer. :rtype: :py:class:`numpy.dtype` :raises TypeError: If the block layout is not a standard layout. ''' # Rule 1, 2 & 3 if isinstance(self.datatype, (Scalar, Vector)): return self.datatype.machine_type # Rule 10 could be defined separately to be consisted with packed/shared layout dtypes. # However, all members are guaranteed to be preserved in standard formats, and this produces # dtypes that are easier to work with # Rule 4, 6, 8 & 10 if isinstance(self.datatype, Array): element = self[0] item_dtype = element.dtype if isinstance(element.datatype, BasicType): item_dtype = dtype({'names': [element.datatype.name], 'formats': [item_dtype], 'itemsize': self.array_stride}) return dtype((item_dtype, len(self))) # Rules 5 & 7 if isinstance(self.datatype, Matrix): if self.matrix_layout == MatrixLayout.column_major: item_dim = 'column' items, components = self.datatype.shape elif self.matrix_layout == MatrixLayout.row_major: item_dim = 'row' components, items = self.datatype.shape item_dtype = Vector.fromType(self.datatype.scalar_type, components).machine_type item_dtype = dtype({'names': ['-'.join((self.datatype.name, item_dim))], 'formats': [item_dtype], 'itemsize': self.matrix_stride}) return dtype((item_dtype, items)) # Rule 9 if isinstance(self.datatype, Struct): names = [c.name for c in self] dtypes = [c.dtype for c in self] offsets = [] offset = 0 for c in self: offset = roundUp(offset, c.alignment) offsets.append(offset) offset += c.dtype.itemsize struct_size = roundUp(offset, self.alignment) return dtype({'names': names, 'formats': dtypes, 'offsets': offsets, 'itemsize': struct_size})
def alignment(self): '''How the block member is to be aligned. Returns :py:obj:`None` if the layout of the block containing this object is not a standardized layout. :rtype: :py:obj:`int` or :py:obj:`None` ''' if self.layout not in (BlockLayout.std140, BlockLayout.std430): return None if self.layout == BlockLayout.std140: alignment_rounding = Vector.vec4.machine_type.itemsize else: alignment_rounding = 1 # Rule 1 if isinstance(self.datatype, Scalar): return self.datatype.machine_type.itemsize # Rule 2 & 3 elif isinstance(self.datatype, Vector): item_type, (components,) = self.datatype.machine_type.subdtype if components == 3: components = 4 return item_type.itemsize * components # Rule 4, 6, 7 & 10 if isinstance(self.datatype, Array): return roundUp(self[0].alignment, alignment_rounding) # Rules 5 & 7 if isinstance(self.datatype, Matrix): if self.matrix_layout == MatrixLayout.column_major: items, components = self.datatype.shape elif self.matrix_layout == MatrixLayout.row_major: components, items = self.datatype.shape align_type = Array(Vector.fromType(self.datatype.scalar_type, components), items) return InterfaceBlockMember(self.block, self.name, align_type).alignment # Rule 9 if isinstance(self.datatype, Struct): alignment = max(c.alignment for c in self) return roundUp(alignment, alignment_rounding)
def dtype(self): '''The memory layout of the uniform block. :rtype: :py:class:`numpy.dtype` :raises TypeError: If the block layout is not a standard layout. ''' if self.layout.standardized: offsets = [] offset = 0 for m in self: offset = roundUp(offset, m.alignment) offsets.append(offset) offset += m.dtype.itemsize names, formats = zip(*((m.name, m.dtype) for m in self)) return dtype({'names': list(names), 'formats': list(formats), 'offsets': offsets}) else: raise TypeError("The layout for this interface block is not defined.")
def array_stride(self): if not (isinstance(self.datatype, Array) and self.layout.standardized): raise TypeError("Not an array with standardized layout.") return roundUp(self[0].dtype.itemsize, self.alignment)