166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com// 266ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. 366ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com// Use of this source code is governed by a BSD-style license that can be 466ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com// found in the LICENSE file. 566ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com// 666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com#include "compiler/InfoSink.h" 866ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com#include "compiler/ParseHelper.h" 966ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com#include "compiler/depgraph/DependencyGraphOutput.h" 1066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com#include "compiler/timing/RestrictFragmentShaderTiming.h" 1166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 128b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.comRestrictFragmentShaderTiming::RestrictFragmentShaderTiming(TInfoSinkBase& sink) 138b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com : mSink(sink) 148b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com , mNumErrors(0) 158b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com{ 168b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // Sampling ops found only in fragment shaders. 178b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("texture2D(s21;vf2;f1;"); 188b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("texture2DProj(s21;vf3;f1;"); 198b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("texture2DProj(s21;vf4;f1;"); 208b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("textureCube(sC1;vf3;f1;"); 218b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // Sampling ops found in both vertex and fragment shaders. 228b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("texture2D(s21;vf2;"); 238b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("texture2DProj(s21;vf3;"); 248b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("texture2DProj(s21;vf4;"); 258b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("textureCube(sC1;vf3;"); 268b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // Sampling ops provided by OES_EGL_image_external. 278b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("texture2D(1;vf2;"); 288b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("texture2DProj(1;vf3;"); 298b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("texture2DProj(1;vf4;"); 308b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // Sampling ops provided by ARB_texture_rectangle. 318b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("texture2DRect(1;vf2;"); 328b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("texture2DRectProj(1;vf3;"); 338b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.insert("texture2DRectProj(1;vf4;"); 348b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com} 358b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com 3666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com// FIXME(mvujovic): We do not know if the execution time of built-in operations like sin, pow, etc. 3766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com// can vary based on the value of the input arguments. If so, we should restrict those as well. 3866ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.comvoid RestrictFragmentShaderTiming::enforceRestrictions(const TDependencyGraph& graph) 3966ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 4066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com mNumErrors = 0; 4166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 4266ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com // FIXME(mvujovic): The dependency graph does not support user defined function calls right now, 4366ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com // so we generate errors for them. 4466ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com validateUserDefinedFunctionCallUsage(graph); 4566ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 4677222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com // Starting from each sampler, traverse the dependency graph and generate an error each time we 4777222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com // hit a node where sampler dependent values are not allowed. 4877222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com for (TGraphSymbolVector::const_iterator iter = graph.beginSamplerSymbols(); 4977222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com iter != graph.endSamplerSymbols(); 5077222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com ++iter) 5177222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com { 5277222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com TGraphSymbol* samplerSymbol = *iter; 5377222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com clearVisited(); 5477222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com samplerSymbol->traverse(this); 5577222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com } 5666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 5766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 5866ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.comvoid RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph) 5966ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 6066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls(); 6166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com iter != graph.endUserDefinedFunctionCalls(); 6266ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com ++iter) 6366ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com { 6466ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com TGraphFunctionCall* functionCall = *iter; 6566ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com beginError(functionCall->getIntermFunctionCall()); 6666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com mSink << "A call to a user defined function is not permitted.\n"; 6766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com } 6866ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 6966ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 7066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.comvoid RestrictFragmentShaderTiming::beginError(const TIntermNode* node) 7166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 7266ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com ++mNumErrors; 7366ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com mSink.prefix(EPrefixError); 7466ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com mSink.location(node->getLine()); 7566ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 7666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 778b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.combool RestrictFragmentShaderTiming::isSamplingOp(const TIntermAggregate* intermFunctionCall) const 7866ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 798b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com return !intermFunctionCall->isUserDefined() && 808b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.find(intermFunctionCall->getName()) != mSamplingOps.end(); 818b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com} 8266ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 838b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.comvoid RestrictFragmentShaderTiming::visitArgument(TGraphArgument* parameter) 848b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com{ 858b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // Texture cache access time might leak sensitive information. 868b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // Thus, we restrict sampler dependent values from affecting the coordinate or LOD bias of a 878b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // sampling operation. 888b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com if (isSamplingOp(parameter->getIntermFunctionCall())) { 898b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com switch (parameter->getArgumentNumber()) { 908b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com case 1: 918b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // Second argument (coord) 928b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com beginError(parameter->getIntermFunctionCall()); 938b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSink << "An expression dependent on a sampler is not permitted to be the" 948b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com << " coordinate argument of a sampling operation.\n"; 958b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com break; 968b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com case 2: 978b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // Third argument (bias) 988b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com beginError(parameter->getIntermFunctionCall()); 998b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSink << "An expression dependent on a sampler is not permitted to be the" 1008b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com << " bias argument of a sampling operation.\n"; 1018b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com break; 1028b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com default: 1038b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // First argument (sampler) 1048b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com break; 1058b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com } 1068b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com } 10766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 10866ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 10966ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.comvoid RestrictFragmentShaderTiming::visitSelection(TGraphSelection* selection) 11066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 11166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com beginError(selection->getIntermSelection()); 11277222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com mSink << "An expression dependent on a sampler is not permitted in a conditional statement.\n"; 11366ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 11466ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 11566ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.comvoid RestrictFragmentShaderTiming::visitLoop(TGraphLoop* loop) 11666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 11766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com beginError(loop->getIntermLoop()); 11877222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com mSink << "An expression dependent on a sampler is not permitted in a loop condition.\n"; 11966ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 12066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 12166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.comvoid RestrictFragmentShaderTiming::visitLogicalOp(TGraphLogicalOp* logicalOp) 12266ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 12366ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com beginError(logicalOp->getIntermLogicalOp()); 12477222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com mSink << "An expression dependent on a sampler is not permitted on the left hand side of a logical " 12577222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com << logicalOp->getOpString() 12666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com << " operator.\n"; 12766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 128