blocklayoutHLSL.cpp (5304B)
1 // 2 // Copyright 2013 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // blocklayout.cpp: 7 // Implementation for block layout classes and methods. 8 // 9 10 #include "compiler/translator/blocklayoutHLSL.h" 11 12 #include "common/mathutil.h" 13 #include "common/utilities.h" 14 15 namespace sh 16 { 17 18 HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices) 19 : mEncoderStrategy(strategy), mTransposeMatrices(transposeMatrices) 20 {} 21 22 void HLSLBlockEncoder::enterAggregateType(const ShaderVariable &structVar) 23 { 24 align(kComponentsPerRegister); 25 } 26 27 void HLSLBlockEncoder::exitAggregateType(const ShaderVariable &structVar) {} 28 29 void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, 30 const std::vector<unsigned int> &arraySizes, 31 bool isRowMajorMatrix, 32 int *arrayStrideOut, 33 int *matrixStrideOut) 34 { 35 GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn); 36 37 // We assume we are only dealing with 4 byte components (no doubles or half-words currently) 38 ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == kBytesPerComponent); 39 40 int matrixStride = 0; 41 int arrayStride = 0; 42 43 // if variables are not to be packed, or we're about to 44 // pack a matrix or array, skip to the start of the next 45 // register 46 if (!isPacked() || gl::IsMatrixType(type) || !arraySizes.empty()) 47 { 48 align(kComponentsPerRegister); 49 } 50 51 if (gl::IsMatrixType(type)) 52 { 53 matrixStride = kComponentsPerRegister; 54 55 if (!arraySizes.empty()) 56 { 57 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); 58 arrayStride = kComponentsPerRegister * numRegisters; 59 } 60 } 61 else if (!arraySizes.empty()) 62 { 63 arrayStride = kComponentsPerRegister; 64 } 65 else if (isPacked()) 66 { 67 int numComponents = gl::VariableComponentCount(type); 68 if ((numComponents + (mCurrentOffset % kComponentsPerRegister)) > kComponentsPerRegister) 69 { 70 align(kComponentsPerRegister); 71 } 72 } 73 74 *matrixStrideOut = matrixStride; 75 *arrayStrideOut = arrayStride; 76 } 77 78 void HLSLBlockEncoder::advanceOffset(GLenum typeIn, 79 const std::vector<unsigned int> &arraySizes, 80 bool isRowMajorMatrix, 81 int arrayStride, 82 int matrixStride) 83 { 84 GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn); 85 86 if (!arraySizes.empty()) 87 { 88 unsigned int arraySize = gl::ArraySizeProduct(arraySizes); 89 if (arraySize > 0) 90 { 91 mCurrentOffset += arrayStride * (arraySize - 1); 92 } 93 } 94 95 if (gl::IsMatrixType(type)) 96 { 97 ASSERT(matrixStride == kComponentsPerRegister); 98 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); 99 const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix); 100 mCurrentOffset += kComponentsPerRegister * (numRegisters - 1); 101 mCurrentOffset += numComponents; 102 } 103 else if (isPacked()) 104 { 105 mCurrentOffset += gl::VariableComponentCount(type); 106 } 107 else 108 { 109 mCurrentOffset += kComponentsPerRegister; 110 } 111 } 112 113 void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters) 114 { 115 mCurrentOffset += (numRegisters * kComponentsPerRegister); 116 } 117 118 HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor( 119 ShShaderOutput outputType) 120 { 121 switch (outputType) 122 { 123 case SH_HLSL_3_0_OUTPUT: 124 return ENCODE_LOOSE; 125 case SH_HLSL_4_1_OUTPUT: 126 case SH_HLSL_4_0_FL9_3_OUTPUT: 127 return ENCODE_PACKED; 128 default: 129 UNREACHABLE(); 130 return ENCODE_PACKED; 131 } 132 } 133 134 template <class ShaderVarType> 135 void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder) 136 { 137 if (variable.isStruct()) 138 { 139 for (size_t arrayElement = 0; arrayElement < variable.getArraySizeProduct(); arrayElement++) 140 { 141 encoder->enterAggregateType(variable); 142 143 for (const ShaderVariable &field : variable.fields) 144 { 145 HLSLVariableRegisterCount(field, encoder); 146 } 147 148 encoder->exitAggregateType(variable); 149 } 150 } 151 else 152 { 153 // We operate only on varyings and uniforms, which do not have matrix layout qualifiers 154 encoder->encodeType(variable.type, variable.arraySizes, false); 155 } 156 } 157 158 unsigned int HLSLVariableRegisterCount(const ShaderVariable &variable, ShShaderOutput outputType) 159 { 160 HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType), true); 161 HLSLVariableRegisterCount(variable, &encoder); 162 163 const size_t registerBytes = (encoder.kBytesPerComponent * encoder.kComponentsPerRegister); 164 return static_cast<unsigned int>( 165 rx::roundUp<size_t>(encoder.getCurrentOffset(), registerBytes) / registerBytes); 166 } 167 } // namespace sh