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 717732823f9c21bdba9cc51ffaceb545ce3857a8cGeoff Lang#include "compiler/translator/InfoSink.h" 86b9cb25980022d0c792d858bc6f6500c00a6c29dJamie Madill#include "compiler/translator/ParseContext.h" 917732823f9c21bdba9cc51ffaceb545ce3857a8cGeoff Lang#include "compiler/translator/depgraph/DependencyGraphOutput.h" 1017732823f9c21bdba9cc51ffaceb545ce3857a8cGeoff Lang#include "compiler/translator/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;"); 34464850868307005a1287d79f7a640f05372358bbNicolas Capens // Sampling ops provided by EXT_shader_texture_lod. 35464850868307005a1287d79f7a640f05372358bbNicolas Capens mSamplingOps.insert("texture2DLodEXT(1;vf2;f1;"); 36464850868307005a1287d79f7a640f05372358bbNicolas Capens mSamplingOps.insert("texture2DProjLodEXT(1;vf3;f1;"); 37464850868307005a1287d79f7a640f05372358bbNicolas Capens mSamplingOps.insert("texture2DProjLodEXT(1;vf4;f1;"); 38464850868307005a1287d79f7a640f05372358bbNicolas Capens mSamplingOps.insert("textureCubeLodEXT(1;vf4;f1;"); 39464850868307005a1287d79f7a640f05372358bbNicolas Capens mSamplingOps.insert("texture2DGradEXT(1;vf2;vf2;vf2;"); 40464850868307005a1287d79f7a640f05372358bbNicolas Capens mSamplingOps.insert("texture2DProjGradEXT(1;vf3;vf2;vf2;"); 41464850868307005a1287d79f7a640f05372358bbNicolas Capens mSamplingOps.insert("texture2DProjGradEXT(1;vf4;vf2;vf2;"); 42464850868307005a1287d79f7a640f05372358bbNicolas Capens mSamplingOps.insert("textureCubeGradEXT(1;vf3;vf3;vf3;"); 438b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com} 448b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com 4566ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com// FIXME(mvujovic): We do not know if the execution time of built-in operations like sin, pow, etc. 4666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com// can vary based on the value of the input arguments. If so, we should restrict those as well. 4766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.comvoid RestrictFragmentShaderTiming::enforceRestrictions(const TDependencyGraph& graph) 4866ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 4966ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com mNumErrors = 0; 5066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 5166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com // FIXME(mvujovic): The dependency graph does not support user defined function calls right now, 5266ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com // so we generate errors for them. 5366ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com validateUserDefinedFunctionCallUsage(graph); 5466ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 5577222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com // Starting from each sampler, traverse the dependency graph and generate an error each time we 5677222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com // hit a node where sampler dependent values are not allowed. 5777222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com for (TGraphSymbolVector::const_iterator iter = graph.beginSamplerSymbols(); 5877222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com iter != graph.endSamplerSymbols(); 5977222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com ++iter) 6077222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com { 6177222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com TGraphSymbol* samplerSymbol = *iter; 6277222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com clearVisited(); 6377222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com samplerSymbol->traverse(this); 6477222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com } 6566ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 6666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 6766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.comvoid RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph) 6866ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 6966ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls(); 7066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com iter != graph.endUserDefinedFunctionCalls(); 7166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com ++iter) 7266ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com { 7366ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com TGraphFunctionCall* functionCall = *iter; 7466ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com beginError(functionCall->getIntermFunctionCall()); 7566ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com mSink << "A call to a user defined function is not permitted.\n"; 7666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com } 7766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 7866ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 7966ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.comvoid RestrictFragmentShaderTiming::beginError(const TIntermNode* node) 8066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 8166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com ++mNumErrors; 8266ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com mSink.prefix(EPrefixError); 8366ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com mSink.location(node->getLine()); 8466ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 8566ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 868b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.combool RestrictFragmentShaderTiming::isSamplingOp(const TIntermAggregate* intermFunctionCall) const 8766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 888b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com return !intermFunctionCall->isUserDefined() && 898b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSamplingOps.find(intermFunctionCall->getName()) != mSamplingOps.end(); 908b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com} 9166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 928b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.comvoid RestrictFragmentShaderTiming::visitArgument(TGraphArgument* parameter) 938b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com{ 948b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // Texture cache access time might leak sensitive information. 958b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // Thus, we restrict sampler dependent values from affecting the coordinate or LOD bias of a 968b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // sampling operation. 978b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com if (isSamplingOp(parameter->getIntermFunctionCall())) { 988b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com switch (parameter->getArgumentNumber()) { 998b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com case 1: 1008b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // Second argument (coord) 1018b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com beginError(parameter->getIntermFunctionCall()); 1028b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSink << "An expression dependent on a sampler is not permitted to be the" 1038b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com << " coordinate argument of a sampling operation.\n"; 1048b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com break; 1058b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com case 2: 1068b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // Third argument (bias) 1078b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com beginError(parameter->getIntermFunctionCall()); 1088b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com mSink << "An expression dependent on a sampler is not permitted to be the" 1098b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com << " bias argument of a sampling operation.\n"; 1108b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com break; 1118b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com default: 1128b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com // First argument (sampler) 1138b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com break; 1148b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com } 1158b8f02dcd343c52f90f4e5d1937d3cc496812405maxvujovic@gmail.com } 11666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 11766ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 11866ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.comvoid RestrictFragmentShaderTiming::visitSelection(TGraphSelection* selection) 11966ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 12066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com beginError(selection->getIntermSelection()); 12177222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com mSink << "An expression dependent on a sampler is not permitted in a conditional statement.\n"; 12266ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 12366ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 12466ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.comvoid RestrictFragmentShaderTiming::visitLoop(TGraphLoop* loop) 12566ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 12666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com beginError(loop->getIntermLoop()); 12777222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com mSink << "An expression dependent on a sampler is not permitted in a loop condition.\n"; 12866ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 12966ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com 13066ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.comvoid RestrictFragmentShaderTiming::visitLogicalOp(TGraphLogicalOp* logicalOp) 13166ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com{ 13266ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com beginError(logicalOp->getIntermLogicalOp()); 13377222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com mSink << "An expression dependent on a sampler is not permitted on the left hand side of a logical " 13477222c9715408518c21a7f359b8f0f9af8c4bfddmaxvujovic@gmail.com << logicalOp->getOpString() 13566ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com << " operator.\n"; 13666ebd0143ea40a9beb83eab5d86e24f52825b3famaxvujovic@gmail.com} 137