ShaderD3D.cpp (14188B)
1 // 2 // Copyright 2014 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 7 // ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl. 8 9 #include "libANGLE/renderer/d3d/ShaderD3D.h" 10 11 #include "common/system_utils.h" 12 #include "common/utilities.h" 13 #include "libANGLE/Caps.h" 14 #include "libANGLE/Compiler.h" 15 #include "libANGLE/Context.h" 16 #include "libANGLE/Shader.h" 17 #include "libANGLE/features.h" 18 #include "libANGLE/renderer/ContextImpl.h" 19 #include "libANGLE/renderer/d3d/ProgramD3D.h" 20 #include "libANGLE/renderer/d3d/RendererD3D.h" 21 #include "libANGLE/trace.h" 22 23 namespace rx 24 { 25 26 class TranslateTaskD3D : public angle::Closure 27 { 28 public: 29 TranslateTaskD3D(ShHandle handle, 30 const ShCompileOptions &options, 31 const std::string &source, 32 const std::string &sourcePath) 33 : mHandle(handle), 34 mOptions(options), 35 mSource(source), 36 mSourcePath(sourcePath), 37 mResult(false) 38 {} 39 40 void operator()() override 41 { 42 ANGLE_TRACE_EVENT1("gpu.angle", "TranslateTask::run", "source", mSource); 43 std::vector<const char *> srcStrings; 44 if (!mSourcePath.empty()) 45 { 46 srcStrings.push_back(mSourcePath.c_str()); 47 } 48 srcStrings.push_back(mSource.c_str()); 49 50 mResult = sh::Compile(mHandle, &srcStrings[0], srcStrings.size(), mOptions); 51 } 52 53 bool getResult() { return mResult; } 54 55 private: 56 ShHandle mHandle; 57 ShCompileOptions mOptions; 58 std::string mSource; 59 std::string mSourcePath; 60 bool mResult; 61 }; 62 63 using PostTranslateFunctor = 64 std::function<bool(gl::ShCompilerInstance *compiler, std::string *infoLog)>; 65 66 class WaitableCompileEventD3D final : public WaitableCompileEvent 67 { 68 public: 69 WaitableCompileEventD3D(std::shared_ptr<angle::WaitableEvent> waitableEvent, 70 gl::ShCompilerInstance *compilerInstance, 71 PostTranslateFunctor &&postTranslateFunctor, 72 std::shared_ptr<TranslateTaskD3D> translateTask) 73 : WaitableCompileEvent(waitableEvent), 74 mCompilerInstance(compilerInstance), 75 mPostTranslateFunctor(std::move(postTranslateFunctor)), 76 mTranslateTask(translateTask) 77 {} 78 79 bool getResult() override { return mTranslateTask->getResult(); } 80 81 bool postTranslate(std::string *infoLog) override 82 { 83 return mPostTranslateFunctor(mCompilerInstance, infoLog); 84 } 85 86 private: 87 gl::ShCompilerInstance *mCompilerInstance; 88 PostTranslateFunctor mPostTranslateFunctor; 89 std::shared_ptr<TranslateTaskD3D> mTranslateTask; 90 }; 91 92 ShaderD3D::ShaderD3D(const gl::ShaderState &state, RendererD3D *renderer) 93 : ShaderImpl(state), mRenderer(renderer) 94 { 95 uncompile(); 96 } 97 98 ShaderD3D::~ShaderD3D() {} 99 100 std::string ShaderD3D::getDebugInfo() const 101 { 102 if (mDebugInfo.empty()) 103 { 104 return ""; 105 } 106 107 return mDebugInfo + std::string("\n// ") + gl::GetShaderTypeString(mState.getShaderType()) + 108 " SHADER END\n"; 109 } 110 111 // initialize/clean up previous state 112 void ShaderD3D::uncompile() 113 { 114 // set by compileToHLSL 115 mCompilerOutputType = SH_ESSL_OUTPUT; 116 117 mUsesMultipleRenderTargets = false; 118 mUsesFragColor = false; 119 mUsesFragData = false; 120 mUsesSecondaryColor = false; 121 mUsesFragCoord = false; 122 mUsesFrontFacing = false; 123 mUsesHelperInvocation = false; 124 mUsesPointSize = false; 125 mUsesPointCoord = false; 126 mUsesDepthRange = false; 127 mUsesFragDepth = false; 128 mHasANGLEMultiviewEnabled = false; 129 mUsesVertexID = false; 130 mUsesViewID = false; 131 mUsesDiscardRewriting = false; 132 mUsesNestedBreak = false; 133 mRequiresIEEEStrictCompiling = false; 134 135 mDebugInfo.clear(); 136 } 137 138 void ShaderD3D::generateWorkarounds(CompilerWorkaroundsD3D *workarounds) const 139 { 140 if (mUsesDiscardRewriting) 141 { 142 // ANGLE issue 486: 143 // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by 144 // disabling optimization 145 workarounds->skipOptimization = true; 146 } 147 else if (mUsesNestedBreak) 148 { 149 // ANGLE issue 603: 150 // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, 151 // by maximizing optimization We want to keep the use of 152 // ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes 153 // precedence 154 workarounds->useMaxOptimization = true; 155 } 156 157 if (mRequiresIEEEStrictCompiling) 158 { 159 // IEEE Strictness for D3D compiler needs to be enabled for NaNs to work. 160 workarounds->enableIEEEStrictness = true; 161 } 162 } 163 164 unsigned int ShaderD3D::getUniformRegister(const std::string &uniformName) const 165 { 166 ASSERT(mUniformRegisterMap.count(uniformName) > 0); 167 return mUniformRegisterMap.find(uniformName)->second; 168 } 169 170 unsigned int ShaderD3D::getUniformBlockRegister(const std::string &blockName) const 171 { 172 ASSERT(mUniformBlockRegisterMap.count(blockName) > 0); 173 return mUniformBlockRegisterMap.find(blockName)->second; 174 } 175 176 bool ShaderD3D::shouldUniformBlockUseStructuredBuffer(const std::string &blockName) const 177 { 178 ASSERT(mUniformBlockUseStructuredBufferMap.count(blockName) > 0); 179 return mUniformBlockUseStructuredBufferMap.find(blockName)->second; 180 } 181 182 unsigned int ShaderD3D::getShaderStorageBlockRegister(const std::string &blockName) const 183 { 184 ASSERT(mShaderStorageBlockRegisterMap.count(blockName) > 0); 185 return mShaderStorageBlockRegisterMap.find(blockName)->second; 186 } 187 188 ShShaderOutput ShaderD3D::getCompilerOutputType() const 189 { 190 return mCompilerOutputType; 191 } 192 193 bool ShaderD3D::useImage2DFunction(const std::string &functionName) const 194 { 195 if (mUsedImage2DFunctionNames.empty()) 196 { 197 return false; 198 } 199 200 return mUsedImage2DFunctionNames.find(functionName) != mUsedImage2DFunctionNames.end(); 201 } 202 203 const std::set<std::string> &ShaderD3D::getSlowCompilingUniformBlockSet() const 204 { 205 return mSlowCompilingUniformBlockSet; 206 } 207 208 const std::map<std::string, unsigned int> &GetUniformRegisterMap( 209 const std::map<std::string, unsigned int> *uniformRegisterMap) 210 { 211 ASSERT(uniformRegisterMap); 212 return *uniformRegisterMap; 213 } 214 215 const std::set<std::string> &GetSlowCompilingUniformBlockSet( 216 const std::set<std::string> *slowCompilingUniformBlockSet) 217 { 218 ASSERT(slowCompilingUniformBlockSet); 219 return *slowCompilingUniformBlockSet; 220 } 221 222 const std::set<std::string> &GetUsedImage2DFunctionNames( 223 const std::set<std::string> *usedImage2DFunctionNames) 224 { 225 ASSERT(usedImage2DFunctionNames); 226 return *usedImage2DFunctionNames; 227 } 228 229 std::shared_ptr<WaitableCompileEvent> ShaderD3D::compile(const gl::Context *context, 230 gl::ShCompilerInstance *compilerInstance, 231 ShCompileOptions *options) 232 { 233 std::string sourcePath; 234 uncompile(); 235 236 const angle::FeaturesD3D &features = mRenderer->getFeatures(); 237 const gl::Extensions &extensions = mRenderer->getNativeExtensions(); 238 239 const std::string &source = mState.getSource(); 240 241 #if !defined(ANGLE_ENABLE_WINDOWS_UWP) 242 if (gl::DebugAnnotationsActive(context)) 243 { 244 sourcePath = angle::CreateTemporaryFile().value(); 245 writeFile(sourcePath.c_str(), source.c_str(), source.length()); 246 options->lineDirectives = true; 247 options->sourcePath = true; 248 } 249 #endif 250 251 if (features.expandIntegerPowExpressions.enabled) 252 { 253 options->expandSelectHLSLIntegerPowExpressions = true; 254 } 255 256 if (features.getDimensionsIgnoresBaseLevel.enabled) 257 { 258 options->HLSLGetDimensionsIgnoresBaseLevel = true; 259 } 260 261 if (features.preAddTexelFetchOffsets.enabled) 262 { 263 options->rewriteTexelFetchOffsetToTexelFetch = true; 264 } 265 if (features.rewriteUnaryMinusOperator.enabled) 266 { 267 options->rewriteIntegerUnaryMinusOperator = true; 268 } 269 if (features.emulateIsnanFloat.enabled) 270 { 271 options->emulateIsnanFloatFunction = true; 272 } 273 if (features.skipVSConstantRegisterZero.enabled && 274 mState.getShaderType() == gl::ShaderType::Vertex) 275 { 276 options->skipD3DConstantRegisterZero = true; 277 } 278 if (features.forceAtomicValueResolution.enabled) 279 { 280 options->forceAtomicValueResolution = true; 281 } 282 if (features.allowTranslateUniformBlockToStructuredBuffer.enabled) 283 { 284 options->allowTranslateUniformBlockToStructuredBuffer = true; 285 } 286 if (extensions.multiviewOVR || extensions.multiview2OVR) 287 { 288 options->initializeBuiltinsForInstancedMultiview = true; 289 } 290 if (extensions.shaderPixelLocalStorageANGLE) 291 { 292 options->pls.type = mRenderer->getNativePixelLocalStorageType(); 293 if (extensions.shaderPixelLocalStorageCoherentANGLE) 294 { 295 options->pls.fragmentSynchronizationType = 296 ShFragmentSynchronizationType::RasterizerOrderViews_D3D; 297 } 298 } 299 300 auto postTranslateFunctor = [this](gl::ShCompilerInstance *compiler, std::string *infoLog) { 301 // TODO(jmadill): We shouldn't need to cache this. 302 mCompilerOutputType = compiler->getShaderOutputType(); 303 304 const std::string &translatedSource = mState.getTranslatedSource(); 305 306 mUsesMultipleRenderTargets = translatedSource.find("GL_USES_MRT") != std::string::npos; 307 mUsesFragColor = translatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos; 308 mUsesFragData = translatedSource.find("GL_USES_FRAG_DATA") != std::string::npos; 309 mUsesSecondaryColor = translatedSource.find("GL_USES_SECONDARY_COLOR") != std::string::npos; 310 mUsesFragCoord = translatedSource.find("GL_USES_FRAG_COORD") != std::string::npos; 311 mUsesFrontFacing = translatedSource.find("GL_USES_FRONT_FACING") != std::string::npos; 312 mUsesHelperInvocation = 313 translatedSource.find("GL_USES_HELPER_INVOCATION") != std::string::npos; 314 mUsesPointSize = translatedSource.find("GL_USES_POINT_SIZE") != std::string::npos; 315 mUsesPointCoord = translatedSource.find("GL_USES_POINT_COORD") != std::string::npos; 316 mUsesDepthRange = translatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos; 317 mUsesFragDepth = translatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos; 318 mHasANGLEMultiviewEnabled = 319 translatedSource.find("GL_ANGLE_MULTIVIEW_ENABLED") != std::string::npos; 320 mUsesVertexID = translatedSource.find("GL_USES_VERTEX_ID") != std::string::npos; 321 mUsesViewID = translatedSource.find("GL_USES_VIEW_ID") != std::string::npos; 322 mUsesDiscardRewriting = 323 translatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos; 324 mUsesNestedBreak = translatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos; 325 mRequiresIEEEStrictCompiling = 326 translatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos; 327 328 ShHandle compilerHandle = compiler->getHandle(); 329 330 mUniformRegisterMap = GetUniformRegisterMap(sh::GetUniformRegisterMap(compilerHandle)); 331 mReadonlyImage2DRegisterIndex = sh::GetReadonlyImage2DRegisterIndex(compilerHandle); 332 mImage2DRegisterIndex = sh::GetImage2DRegisterIndex(compilerHandle); 333 mUsedImage2DFunctionNames = 334 GetUsedImage2DFunctionNames(sh::GetUsedImage2DFunctionNames(compilerHandle)); 335 336 for (const sh::InterfaceBlock &interfaceBlock : mState.getUniformBlocks()) 337 { 338 if (interfaceBlock.active) 339 { 340 unsigned int index = static_cast<unsigned int>(-1); 341 bool blockRegisterResult = 342 sh::GetUniformBlockRegister(compilerHandle, interfaceBlock.name, &index); 343 ASSERT(blockRegisterResult); 344 bool useStructuredBuffer = 345 sh::ShouldUniformBlockUseStructuredBuffer(compilerHandle, interfaceBlock.name); 346 347 mUniformBlockRegisterMap[interfaceBlock.name] = index; 348 mUniformBlockUseStructuredBufferMap[interfaceBlock.name] = useStructuredBuffer; 349 } 350 } 351 352 mSlowCompilingUniformBlockSet = 353 GetSlowCompilingUniformBlockSet(sh::GetSlowCompilingUniformBlockSet(compilerHandle)); 354 355 for (const sh::InterfaceBlock &interfaceBlock : mState.getShaderStorageBlocks()) 356 { 357 if (interfaceBlock.active) 358 { 359 unsigned int index = static_cast<unsigned int>(-1); 360 bool blockRegisterResult = 361 sh::GetShaderStorageBlockRegister(compilerHandle, interfaceBlock.name, &index); 362 ASSERT(blockRegisterResult); 363 364 mShaderStorageBlockRegisterMap[interfaceBlock.name] = index; 365 } 366 } 367 368 mDebugInfo += std::string("// ") + gl::GetShaderTypeString(mState.getShaderType()) + 369 " SHADER BEGIN\n"; 370 mDebugInfo += "\n// GLSL BEGIN\n\n" + mState.getSource() + "\n\n// GLSL END\n\n\n"; 371 mDebugInfo += 372 "// INITIAL HLSL BEGIN\n\n" + translatedSource + "\n// INITIAL HLSL END\n\n\n"; 373 // Successive steps will append more info 374 return true; 375 }; 376 377 auto workerThreadPool = context->getWorkerThreadPool(); 378 auto translateTask = std::make_shared<TranslateTaskD3D>(compilerInstance->getHandle(), *options, 379 source, sourcePath); 380 381 return std::make_shared<WaitableCompileEventD3D>( 382 angle::WorkerThreadPool::PostWorkerTask(workerThreadPool, translateTask), compilerInstance, 383 std::move(postTranslateFunctor), translateTask); 384 } 385 386 bool ShaderD3D::hasUniform(const std::string &name) const 387 { 388 return mUniformRegisterMap.find(name) != mUniformRegisterMap.end(); 389 } 390 391 } // namespace rx