@@ -161,6 +161,10 @@ constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDept
161161constexpr ImmutableString kUniformsBlockName = ImmutableString(" ANGLEUniformBlock" );
162162constexpr ImmutableString kUniformsVarName = ImmutableString(" ANGLEUniforms" );
163163
164+ // Specialization constant names
165+ constexpr ImmutableString kLineRasterEmulationSpecConstVarName =
166+ ImmutableString (" ANGLELineRasterEmulation" );
167+
164168constexpr const char kViewport [] = " viewport" ;
165169constexpr const char kHalfRenderAreaHeight [] = " halfRenderAreaHeight" ;
166170constexpr const char kViewportYScale [] = " viewportYScale" ;
@@ -421,35 +425,28 @@ const TVariable *AddComputeDriverUniformsToShader(TIntermBlock *root, TSymbolTab
421425 kUniformsVarName );
422426}
423427
424- TIntermPreprocessorDirective * GenerateLineRasterIfDef ( )
428+ TIntermSymbol * GenerateLineRasterSpecConstRef (TSymbolTable *symbolTable )
425429{
426- return new TIntermPreprocessorDirective (
427- PreprocessorDirective::Ifdef, ImmutableString (" ANGLE_ENABLE_LINE_SEGMENT_RASTERIZATION" ));
428- }
429-
430- TIntermPreprocessorDirective *GenerateEndIf ()
431- {
432- return new TIntermPreprocessorDirective (PreprocessorDirective::Endif, kEmptyImmutableString );
430+ TVariable *specConstVar =
431+ new TVariable (symbolTable, kLineRasterEmulationSpecConstVarName ,
432+ StaticType::GetBasic<EbtBool>(), SymbolType::AngleInternal);
433+ return new TIntermSymbol (specConstVar);
433434}
434435
435436TVariable *AddANGLEPositionVaryingDeclaration (TIntermBlock *root,
436437 TSymbolTable *symbolTable,
437438 TQualifier qualifier)
438439{
439- TIntermSequence *insertSequence = new TIntermSequence;
440-
441- insertSequence->push_back (GenerateLineRasterIfDef ());
442-
443440 // Define a driver varying vec2 "ANGLEPosition".
444441 TType *varyingType = new TType (EbtFloat, EbpMedium, qualifier, 2 );
445442 TVariable *varyingVar = new TVariable (symbolTable, ImmutableString (" ANGLEPosition" ),
446443 varyingType, SymbolType::AngleInternal);
447444 TIntermSymbol *varyingDeclarator = new TIntermSymbol (varyingVar);
448445 TIntermDeclaration *varyingDecl = new TIntermDeclaration;
449446 varyingDecl->appendDeclarator (varyingDeclarator);
450- insertSequence->push_back (varyingDecl);
451447
452- insertSequence->push_back (GenerateEndIf ());
448+ TIntermSequence *insertSequence = new TIntermSequence;
449+ insertSequence->push_back (varyingDecl);
453450
454451 // Insert the declarations before Main.
455452 size_t mainIndex = FindMainIndex (root);
@@ -514,15 +511,18 @@ ANGLE_NO_DISCARD bool AddBresenhamEmulationVS(TCompiler *compiler,
514511 TIntermSymbol *varyingRef = new TIntermSymbol (anglePosition);
515512 TIntermBinary *varyingAssign = new TIntermBinary (EOpAssign, varyingRef, clampedNDC);
516513
514+ TIntermBlock *emulationBlock = new TIntermBlock;
515+ emulationBlock->appendStatement (ndcDecl);
516+ emulationBlock->appendStatement (windowDecl);
517+ emulationBlock->appendStatement (clampedDecl);
518+ emulationBlock->appendStatement (varyingAssign);
519+ TIntermIfElse *ifEmulation =
520+ new TIntermIfElse (GenerateLineRasterSpecConstRef (symbolTable), emulationBlock, nullptr );
521+
517522 // Ensure the statements run at the end of the main() function.
518523 TIntermFunctionDefinition *main = FindMain (root);
519524 TIntermBlock *mainBody = main->getBody ();
520- mainBody->appendStatement (GenerateLineRasterIfDef ());
521- mainBody->appendStatement (ndcDecl);
522- mainBody->appendStatement (windowDecl);
523- mainBody->appendStatement (clampedDecl);
524- mainBody->appendStatement (varyingAssign);
525- mainBody->appendStatement (GenerateEndIf ());
525+ mainBody->appendStatement (ifEmulation);
526526 return compiler->validateAST (root);
527527}
528528
@@ -538,9 +538,9 @@ ANGLE_NO_DISCARD bool InsertFragCoordCorrection(TCompiler *compiler,
538538 BuiltInVariable::gl_FragCoord (), kFlippedFragCoordName , pivot);
539539}
540540
541- // This block adds OpenGL line segment rasterization emulation behind #ifdef guards.
542- // OpenGL's simple rasterization algorithm is a strict subset of the pixels generated by the Vulkan
543- // algorithm. Thus we can implement a shader patch that rejects pixels if they would not be
541+ // This block adds OpenGL line segment rasterization emulation behind a specialization constant
542+ // guard. OpenGL's simple rasterization algorithm is a strict subset of the pixels generated by the
543+ // Vulkan algorithm. Thus we can implement a shader patch that rejects pixels if they would not be
544544// generated by the OpenGL algorithm. OpenGL's algorithm is similar to Bresenham's line algorithm.
545545// It is implemented for each pixel by testing if the line segment crosses a small diamond inside
546546// the pixel. See the OpenGL ES 2.0 spec section "3.4.1 Basic Line Segment Rasterization". Also
@@ -652,25 +652,33 @@ ANGLE_NO_DISCARD bool AddBresenhamEmulationFS(TCompiler *compiler,
652652 discardBlock->appendStatement (discard);
653653 TIntermIfElse *ifStatement = new TIntermIfElse (checkXY, discardBlock, nullptr );
654654
655+ TIntermBlock *emulationBlock = new TIntermBlock;
656+ TIntermSequence *emulationSequence = emulationBlock->getSequence ();
657+
658+ std::array<TIntermNode *, 8 > nodes = {
659+ {pDecl, dDecl, fDecl , p_decl, d_decl, f_decl, iDecl, ifStatement}};
660+ emulationSequence->insert (emulationSequence->begin (), nodes.begin (), nodes.end ());
661+
662+ TIntermIfElse *ifEmulation =
663+ new TIntermIfElse (GenerateLineRasterSpecConstRef (symbolTable), emulationBlock, nullptr );
664+
655665 // Ensure the line raster code runs at the beginning of main().
656666 TIntermFunctionDefinition *main = FindMain (root);
657667 TIntermSequence *mainSequence = main->getBody ()->getSequence ();
658668 ASSERT (mainSequence);
659669
660- std::array<TIntermNode *, 9 > nodes = {
661- {pDecl, dDecl, fDecl , p_decl, d_decl, f_decl, iDecl, ifStatement, GenerateEndIf ()}};
662- mainSequence->insert (mainSequence->begin (), nodes.begin (), nodes.end ());
670+ mainSequence->insert (mainSequence->begin (), ifEmulation);
663671
664- // If the shader does not use frag coord, we should insert it inside the ifdef .
672+ // If the shader does not use frag coord, we should insert it inside the emulation if .
665673 if (!usesFragCoord)
666674 {
667- if (!InsertFragCoordCorrection (compiler, root, mainSequence, symbolTable, driverUniforms))
675+ if (!InsertFragCoordCorrection (compiler, root, emulationSequence, symbolTable,
676+ driverUniforms))
668677 {
669678 return false ;
670679 }
671680 }
672681
673- mainSequence->insert (mainSequence->begin (), GenerateLineRasterIfDef ());
674682 return compiler->validateAST (root);
675683}
676684
@@ -819,6 +827,15 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
819827 {
820828 return false ;
821829 }
830+
831+ // Add specialization constant declarations. The default value of the specialization
832+ // constant is irrelevant, as it will be set when creating the pipeline.
833+ if (compileOptions & SH_ADD_BRESENHAM_LINE_RASTER_EMULATION)
834+ {
835+ sink << " layout(constant_id="
836+ << static_cast <uint32_t >(vk::SpecializationConstantId::LineRasterEmulation)
837+ << " ) const bool " << kLineRasterEmulationSpecConstVarName << " = false;\n\n " ;
838+ }
822839 }
823840
824841 // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData
0 commit comments