// // Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // blocklayout.cpp: // Implementation for block layout classes and methods. // #include "compiler/translator/blocklayout.h" #include "common/mathutil.h" #include "common/utilities.h" namespace sh { BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0) { } BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix) { int arrayStride; int matrixStride; getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride); const BlockMemberInfo memberInfo(static_cast(mCurrentOffset * BytesPerComponent), static_cast(arrayStride * BytesPerComponent), static_cast(matrixStride * BytesPerComponent), isRowMajorMatrix); advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride); return memberInfo; } // static size_t BlockLayoutEncoder::getBlockRegister(const BlockMemberInfo &info) { return (info.offset / BytesPerComponent) / ComponentsPerRegister; } // static size_t BlockLayoutEncoder::getBlockRegisterElement(const BlockMemberInfo &info) { return (info.offset / BytesPerComponent) % ComponentsPerRegister; } void BlockLayoutEncoder::nextRegister() { mCurrentOffset = rx::roundUp(mCurrentOffset, ComponentsPerRegister); } Std140BlockEncoder::Std140BlockEncoder() { } void Std140BlockEncoder::enterAggregateType() { nextRegister(); } void Std140BlockEncoder::exitAggregateType() { nextRegister(); } void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) { // We assume we are only dealing with 4 byte components (no doubles or half-words currently) ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); size_t baseAlignment = 0; int matrixStride = 0; int arrayStride = 0; if (gl::IsMatrixType(type)) { baseAlignment = ComponentsPerRegister; matrixStride = ComponentsPerRegister; if (arraySize > 0) { const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); arrayStride = ComponentsPerRegister * numRegisters; } } else if (arraySize > 0) { baseAlignment = ComponentsPerRegister; arrayStride = ComponentsPerRegister; } else { const int numComponents = gl::VariableComponentCount(type); baseAlignment = (numComponents == 3 ? 4u : static_cast(numComponents)); } mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment); *matrixStrideOut = matrixStride; *arrayStrideOut = arrayStride; } void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) { if (arraySize > 0) { mCurrentOffset += arrayStride * arraySize; } else if (gl::IsMatrixType(type)) { ASSERT(matrixStride == ComponentsPerRegister); const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); mCurrentOffset += ComponentsPerRegister * numRegisters; } else { mCurrentOffset += gl::VariableComponentCount(type); } } }