1e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com// 2e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. 3e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com// Use of this source code is governed by a BSD-style license that can be 4e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com// found in the LICENSE file. 5e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com// 6e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com// Contains analysis utilities for dealing with HLSL's lack of support for 7e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com// the use of intrinsic functions which (implicitly or explicitly) compute 8e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com// gradients of functions with discontinuities. 9e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com// 10e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com 11dcefb75e81f3eec28fb1d2d3b3847682659e7378Geoff Lang#include "compiler/translator/DetectDiscontinuity.h" 12e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com 13dcefb75e81f3eec28fb1d2d3b3847682659e7378Geoff Lang#include "compiler/translator/ParseContext.h" 1479744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com 15e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.comnamespace sh 16e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com{ 1779744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.combool DetectLoopDiscontinuity::traverse(TIntermNode *node) 18e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com{ 19e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com mLoopDepth = 0; 2079744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com mLoopDiscontinuity = false; 21e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com node->traverse(this); 2279744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com return mLoopDiscontinuity; 23e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com} 24e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com 25e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.combool DetectLoopDiscontinuity::visitLoop(Visit visit, TIntermLoop *loop) 26e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com{ 27e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com if (visit == PreVisit) 28e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com { 29e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com ++mLoopDepth; 30e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com } 31e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com else if (visit == PostVisit) 32e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com { 33e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com --mLoopDepth; 34e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com } 35e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com 36e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com return true; 37e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com} 38e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com 3979744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.combool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node) 40e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com{ 4179744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com if (mLoopDiscontinuity) 4279744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com { 4379744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com return false; 4479744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com } 4579744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com 46e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com if (!mLoopDepth) 47e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com { 48e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com return true; 49e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com } 50e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com 51e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com switch (node->getFlowOp()) 52e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com { 53e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com case EOpKill: 54e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com break; 55e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com case EOpBreak: 56e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com case EOpContinue: 57e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com case EOpReturn: 58e91615cb0765069a6317c84787e10d9ecd7b2359shannon.woods@transgaming.com mLoopDiscontinuity = true; 59e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com break; 60e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com default: UNREACHABLE(); 61e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com } 62e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com 6379744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com return !mLoopDiscontinuity; 6479744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com} 6579744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com 6679744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.combool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node) 6779744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com{ 6879744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com return !mLoopDiscontinuity; 6979744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com} 7079744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com 7179744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.combool containsLoopDiscontinuity(TIntermNode *node) 7279744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com{ 7379744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com DetectLoopDiscontinuity detectLoopDiscontinuity; 7479744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com return detectLoopDiscontinuity.traverse(node); 7579744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com} 7679744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com 7779744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.combool DetectGradientOperation::traverse(TIntermNode *node) 7879744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com{ 7979744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com mGradientOperation = false; 8079744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com node->traverse(this); 8179744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com return mGradientOperation; 8279744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com} 8379744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com 8479744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.combool DetectGradientOperation::visitUnary(Visit visit, TIntermUnary *node) 8579744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com{ 8679744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com if (mGradientOperation) 8779744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com { 8879744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com return false; 8979744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com } 9079744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com 9179744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com switch (node->getOp()) 9279744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com { 9379744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com case EOpDFdx: 9479744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com case EOpDFdy: 9579744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com mGradientOperation = true; 9679744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com default: 9779744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com break; 9879744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com } 9979744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com 10079744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com return !mGradientOperation; 10179744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com} 10279744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com 10379744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.combool DetectGradientOperation::visitAggregate(Visit visit, TIntermAggregate *node) 10479744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com{ 10579744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com if (mGradientOperation) 10679744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com { 10779744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com return false; 10879744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com } 10979744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com 11079744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com if (node->getOp() == EOpFunctionCall) 11179744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com { 11279744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com if (!node->isUserDefined()) 11379744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com { 11479744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com TString name = TFunction::unmangleName(node->getName()); 11579744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com 11679744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com if (name == "texture2D" || 11779744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com name == "texture2DProj" || 11879744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com name == "textureCube") 11979744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com { 12079744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com mGradientOperation = true; 12179744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com } 12279744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com } 12379744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com else 12479744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com { 12579744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com // When a user defined function is called, we have to 12679744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com // conservatively assume it to contain gradient operations 12779744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com mGradientOperation = true; 12879744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com } 12979744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com } 13079744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com 13179744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com return !mGradientOperation; 13279744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com} 13379744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com 13479744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.combool containsGradientOperation(TIntermNode *node) 13579744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com{ 13679744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com DetectGradientOperation detectGradientOperation; 13779744f226551bae5dfa69bc5588311d7100ef991daniel@transgaming.com return detectGradientOperation.traverse(node); 138e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com} 139e209564280f9733853b2b0a9c8e8467af20ce05bdaniel@transgaming.com} 140