Home | History | Annotate | Download | only in compiler
      1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #ifndef COMPILER_OUTPUTASM_H_
     16 #define COMPILER_OUTPUTASM_H_
     17 
     18 #include "intermediate.h"
     19 #include "ParseHelper.h"
     20 #include "Shader/PixelShader.hpp"
     21 #include "Shader/VertexShader.hpp"
     22 
     23 #include <list>
     24 #include <set>
     25 #include <map>
     26 
     27 namespace es2
     28 {
     29 	class Shader;
     30 }
     31 
     32 typedef unsigned int GLenum;
     33 
     34 namespace glsl
     35 {
     36 	struct BlockMemberInfo
     37 	{
     38 		BlockMemberInfo() : offset(-1), arrayStride(-1), matrixStride(-1), isRowMajorMatrix(false) {}
     39 
     40 		BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
     41 			: offset(offset),
     42 			arrayStride(arrayStride),
     43 			matrixStride(matrixStride),
     44 			isRowMajorMatrix(isRowMajorMatrix)
     45 		{}
     46 
     47 		static BlockMemberInfo getDefaultBlockInfo()
     48 		{
     49 			return BlockMemberInfo(-1, -1, -1, false);
     50 		}
     51 
     52 		int offset;
     53 		int arrayStride;
     54 		int matrixStride;
     55 		bool isRowMajorMatrix;
     56 	};
     57 
     58 	struct ShaderVariable
     59 	{
     60 		ShaderVariable(const TType& type, const std::string& name, int registerIndex);
     61 
     62 		GLenum type;
     63 		GLenum precision;
     64 		std::string name;
     65 		int arraySize;
     66 
     67 		int registerIndex;
     68 
     69 		std::vector<ShaderVariable> fields;
     70 	};
     71 
     72 	struct Uniform : public ShaderVariable
     73 	{
     74 		Uniform(const TType& type, const std::string &name, int registerIndex, int blockId, const BlockMemberInfo& blockMemberInfo);
     75 
     76 		int blockId;
     77 		BlockMemberInfo blockInfo;
     78 	};
     79 
     80 	typedef std::vector<Uniform> ActiveUniforms;
     81 
     82 	struct UniformBlock
     83 	{
     84 		UniformBlock(const std::string& name, unsigned int dataSize, unsigned int arraySize,
     85 		             TLayoutBlockStorage layout, bool isRowMajorLayout, int registerIndex, int blockId);
     86 
     87 		std::string name;
     88 		unsigned int dataSize;
     89 		unsigned int arraySize;
     90 		TLayoutBlockStorage layout;
     91 		bool isRowMajorLayout;
     92 		std::vector<int> fields;
     93 
     94 		int registerIndex;
     95 
     96 		int blockId;
     97 	};
     98 
     99 	class BlockLayoutEncoder
    100 	{
    101 	public:
    102 		BlockLayoutEncoder();
    103 		virtual ~BlockLayoutEncoder() {}
    104 
    105 		BlockMemberInfo encodeType(const TType &type);
    106 
    107 		size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
    108 
    109 		virtual void enterAggregateType() = 0;
    110 		virtual void exitAggregateType() = 0;
    111 
    112 		static const size_t BytesPerComponent = 4u;
    113 		static const unsigned int ComponentsPerRegister = 4u;
    114 
    115 		static size_t getBlockRegister(const BlockMemberInfo &info);
    116 		static size_t getBlockRegisterElement(const BlockMemberInfo &info);
    117 
    118 	protected:
    119 		size_t mCurrentOffset;
    120 
    121 		void nextRegister();
    122 
    123 		virtual void getBlockLayoutInfo(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0;
    124 		virtual void advanceOffset(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0;
    125 	};
    126 
    127 	// Block layout according to the std140 block layout
    128 	// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
    129 	class Std140BlockEncoder : public BlockLayoutEncoder
    130 	{
    131 	public:
    132 		Std140BlockEncoder();
    133 
    134 		void enterAggregateType() override;
    135 		void exitAggregateType() override;
    136 
    137 	protected:
    138 		void getBlockLayoutInfo(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) override;
    139 		void advanceOffset(const TType &type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) override;
    140 	};
    141 
    142 	typedef std::vector<UniformBlock> ActiveUniformBlocks;
    143 
    144 	struct Attribute
    145 	{
    146 		Attribute();
    147 		Attribute(GLenum type, const std::string &name, int arraySize, int location, int registerIndex);
    148 
    149 		GLenum type;
    150 		std::string name;
    151 		int arraySize;
    152 		int location;
    153 
    154 		int registerIndex;
    155 	};
    156 
    157 	typedef std::vector<Attribute> ActiveAttributes;
    158 
    159 	struct Varying : public ShaderVariable
    160 	{
    161 		Varying(const TType& type, const std::string &name, int reg = -1, int col = -1)
    162 			: ShaderVariable(type, name, reg), qualifier(type.getQualifier()), column(col)
    163 		{
    164 		}
    165 
    166 		bool isArray() const
    167 		{
    168 			return arraySize >= 1;
    169 		}
    170 
    171 		int size() const   // Unify with es2::Uniform?
    172 		{
    173 			return arraySize > 0 ? arraySize : 1;
    174 		}
    175 
    176 		TQualifier qualifier;
    177 		int column;    // First register element, assigned during link
    178 	};
    179 
    180 	typedef std::list<Varying> VaryingList;
    181 
    182 	class Shader
    183 	{
    184 		friend class OutputASM;
    185 	public:
    186 		virtual ~Shader() {};
    187 		virtual sw::Shader *getShader() const = 0;
    188 		virtual sw::PixelShader *getPixelShader() const;
    189 		virtual sw::VertexShader *getVertexShader() const;
    190 		int getShaderVersion() const { return shaderVersion; }
    191 
    192 	protected:
    193 		VaryingList varyings;
    194 		ActiveUniforms activeUniforms;
    195 		ActiveUniforms activeUniformStructs;
    196 		ActiveAttributes activeAttributes;
    197 		ActiveUniformBlocks activeUniformBlocks;
    198 		int shaderVersion;
    199 	};
    200 
    201 	struct Function
    202 	{
    203 		Function(int label, const char *name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret)
    204 		{
    205 		}
    206 
    207 		Function(int label, const TString &name, TIntermSequence *arg, TIntermTyped *ret) : label(label), name(name), arg(arg), ret(ret)
    208 		{
    209 		}
    210 
    211 		int label;
    212 		TString name;
    213 		TIntermSequence *arg;
    214 		TIntermTyped *ret;
    215 	};
    216 
    217 	typedef sw::Shader::Instruction Instruction;
    218 
    219 	class Temporary;
    220 
    221 	class OutputASM : public TIntermTraverser
    222 	{
    223 	public:
    224 		explicit OutputASM(TParseContext &context, Shader *shaderObject);
    225 		~OutputASM();
    226 
    227 		void output();
    228 
    229 		void freeTemporary(Temporary *temporary);
    230 
    231 	private:
    232 		enum Scope
    233 		{
    234 			GLOBAL,
    235 			FUNCTION
    236 		};
    237 
    238 		struct TextureFunction
    239 		{
    240 			TextureFunction(const TString& name);
    241 
    242 			enum Method
    243 			{
    244 				IMPLICIT,   // Mipmap LOD determined implicitly (standard lookup)
    245 				LOD,
    246 				SIZE,   // textureSize()
    247 				FETCH,
    248 				GRAD,
    249 			};
    250 
    251 			Method method;
    252 			bool proj;
    253 			bool offset;
    254 		};
    255 
    256 		void emitShader(Scope scope);
    257 
    258 		// Visit AST nodes and output their code to the body stream
    259 		void visitSymbol(TIntermSymbol*) override;
    260 		bool visitBinary(Visit visit, TIntermBinary*) override;
    261 		bool visitUnary(Visit visit, TIntermUnary*) override;
    262 		bool visitSelection(Visit visit, TIntermSelection*) override;
    263 		bool visitAggregate(Visit visit, TIntermAggregate*) override;
    264 		bool visitLoop(Visit visit, TIntermLoop*) override;
    265 		bool visitBranch(Visit visit, TIntermBranch*) override;
    266 		bool visitSwitch(Visit, TIntermSwitch*) override;
    267 
    268 		sw::Shader::Opcode getOpcode(sw::Shader::Opcode op, TIntermTyped *in) const;
    269 		Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0, TIntermNode *src3 = 0, TIntermNode *src4 = 0);
    270 		Instruction *emit(sw::Shader::Opcode op, TIntermTyped *dst, int dstIndex, TIntermNode *src0 = 0, int index0 = 0, TIntermNode *src1 = 0, int index1 = 0,
    271 		                  TIntermNode *src2 = 0, int index2 = 0, TIntermNode *src3 = 0, int index3 = 0, TIntermNode *src4 = 0, int index4 = 0);
    272 		Instruction *emitCast(TIntermTyped *dst, TIntermTyped *src);
    273 		Instruction *emitCast(TIntermTyped *dst, int dstIndex, TIntermTyped *src, int srcIndex);
    274 		void emitBinary(sw::Shader::Opcode op, TIntermTyped *dst = 0, TIntermNode *src0 = 0, TIntermNode *src1 = 0, TIntermNode *src2 = 0);
    275 		void emitAssign(sw::Shader::Opcode op, TIntermTyped *result, TIntermTyped *lhs, TIntermTyped *src0, TIntermTyped *src1 = 0);
    276 		void emitCmp(sw::Shader::Control cmpOp, TIntermTyped *dst, TIntermNode *left, TIntermNode *right, int index = 0);
    277 		void emitDeterminant(TIntermTyped *result, TIntermTyped *arg, int size, int col = -1, int row = -1, int outCol = 0, int outRow = 0);
    278 		void source(sw::Shader::SourceParameter &parameter, TIntermNode *argument, int index = 0);
    279 		void destination(sw::Shader::DestinationParameter &parameter, TIntermTyped *argument, int index = 0);
    280 		void copy(TIntermTyped *dst, TIntermNode *src, int offset = 0);
    281 		void assignLvalue(TIntermTyped *dst, TIntermTyped *src);
    282 		void evaluateRvalue(TIntermTyped *node);
    283 		int lvalue(sw::Shader::DestinationParameter &dst, TIntermTyped *node);
    284 		int lvalue(TIntermTyped *&root, unsigned int &offset, sw::Shader::Relative &rel, unsigned char &mask, Temporary &address, TIntermTyped *node);
    285 		sw::Shader::ParameterType registerType(TIntermTyped *operand);
    286 		bool hasFlatQualifier(TIntermTyped *operand);
    287 		unsigned int registerIndex(TIntermTyped *operand);
    288 		int writeMask(TIntermTyped *destination, int index = 0);
    289 		int readSwizzle(TIntermTyped *argument, int size);
    290 		bool trivial(TIntermTyped *expression, int budget);   // Fast to compute and no side effects
    291 		int cost(TIntermNode *expression, int budget);
    292 		const Function *findFunction(const TString &name);
    293 
    294 		int temporaryRegister(TIntermTyped *temporary);
    295 		int varyingRegister(TIntermTyped *varying);
    296 		void setPixelShaderInputs(const TType& type, int var, bool flat);
    297 		void declareVarying(TIntermTyped *varying, int reg);
    298 		void declareVarying(const TType &type, const TString &name, int registerIndex);
    299 		void declareFragmentOutput(TIntermTyped *fragmentOutput);
    300 		int uniformRegister(TIntermTyped *uniform);
    301 		int attributeRegister(TIntermTyped *attribute);
    302 		int fragmentOutputRegister(TIntermTyped *fragmentOutput);
    303 		int samplerRegister(TIntermTyped *sampler);
    304 		int samplerRegister(TIntermSymbol *sampler);
    305 		bool isSamplerRegister(TIntermTyped *operand);
    306 
    307 		typedef std::vector<TIntermTyped*> VariableArray;
    308 
    309 		int lookup(VariableArray &list, TIntermTyped *variable);
    310 		int lookup(VariableArray &list, TInterfaceBlock *block);
    311 		int blockMemberLookup(const TType &type, const TString &name, int registerIndex);
    312 		int allocate(VariableArray &list, TIntermTyped *variable, bool samplersOnly = false);
    313 		void free(VariableArray &list, TIntermTyped *variable);
    314 
    315 		void declareUniform(const TType &type, const TString &name, int registerIndex, bool samplersOnly, int blockId = -1, BlockLayoutEncoder* encoder = nullptr);
    316 
    317 		static int dim(TIntermNode *v);
    318 		static int dim2(TIntermNode *m);
    319 		static unsigned int loopCount(TIntermLoop *node);
    320 
    321 		Shader *const shaderObject;
    322 		sw::Shader *shader;
    323 		sw::PixelShader *pixelShader;
    324 		sw::VertexShader *vertexShader;
    325 
    326 		VariableArray temporaries;
    327 		VariableArray uniforms;
    328 		VariableArray varyings;
    329 		VariableArray attributes;
    330 		VariableArray samplers;
    331 		VariableArray fragmentOutputs;
    332 
    333 		struct TypedMemberInfo : public BlockMemberInfo
    334 		{
    335 			TypedMemberInfo(const BlockMemberInfo& b, const TType& t) : BlockMemberInfo(b), type(t) {}
    336 			TType type;
    337 		};
    338 		struct ArgumentInfo
    339 		{
    340 			ArgumentInfo(const BlockMemberInfo& b, const TType& t, int clampedIndex, int bufferIndex) :
    341 			    typedMemberInfo(b, t), clampedIndex(clampedIndex), bufferIndex(bufferIndex) {}
    342 			TypedMemberInfo typedMemberInfo;
    343 			int clampedIndex;
    344 			int bufferIndex;
    345 		};
    346 		int getBlockId(TIntermTyped *argument);
    347 		ArgumentInfo getArgumentInfo(TIntermTyped *argument, int index);
    348 
    349 		typedef std::map<int, TypedMemberInfo> BlockDefinitionIndexMap;
    350 		std::vector<BlockDefinitionIndexMap> blockDefinitions;
    351 
    352 		Scope emitScope;
    353 		Scope currentScope;
    354 
    355 		int currentFunction;
    356 		std::vector<Function> functionArray;
    357 
    358 		TQualifier outputQualifier;
    359 
    360 		TParseContext &mContext;
    361 	};
    362 
    363 	class LoopUnrollable : public TIntermTraverser
    364 	{
    365 	public:
    366 		bool traverse(TIntermNode *node);
    367 
    368 	private:
    369 		bool visitBranch(Visit visit, TIntermBranch *node);
    370 		bool visitLoop(Visit visit, TIntermLoop *loop);
    371 		bool visitAggregate(Visit visit, TIntermAggregate *node);
    372 
    373 		int loopDepth;
    374 		bool loopUnrollable;
    375 	};
    376 }
    377 
    378 #endif   // COMPILER_OUTPUTASM_H_
    379