Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit b36e46a

Browse files
ShabbyXCommit Bot
authored andcommitted
Vulkan: Line raster emulation through specialization constant
In preparation for compiling shaders early at link time, this change reworks line raster emulation such that it uses specialization constants instead of a preprocessor condition. This means drawing both triangles and lines with this program will still result in a one-time shader compilation. The compilation is still done at draw time in this change. Bug: angleproject:3394 Change-Id: I0bf91398868d7f7147456533b728906b505192b2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1992365 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Tim Van Patten <timvp@google.com>
1 parent 6d6b91a commit b36e46a

19 files changed

+282
-145
lines changed

include/GLSLANG/ShaderLang.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
// Version number for shader translation API.
2828
// It is incremented every time the API changes.
29-
#define ANGLE_SH_VERSION 222
29+
#define ANGLE_SH_VERSION 223
3030

3131
enum ShShaderSpec
3232
{
@@ -732,6 +732,20 @@ inline bool IsDesktopGLSpec(ShShaderSpec spec)
732732
{
733733
return spec == SH_GL_CORE_SPEC || spec == SH_GL_COMPATIBILITY_SPEC;
734734
}
735+
736+
namespace vk
737+
{
738+
739+
// Specialization constant ids
740+
enum class SpecializationConstantId : uint32_t
741+
{
742+
LineRasterEmulation = 0,
743+
744+
InvalidEnum = 1,
745+
EnumCount = 1,
746+
};
747+
748+
} // namespace vk
735749
} // namespace sh
736750

737751
#endif // GLSLANG_SHADERLANG_H_

src/compiler/translator/TranslatorVulkan.cpp

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ constexpr ImmutableString kEmulatedDepthRangeParams = ImmutableString("ANGLEDept
161161
constexpr ImmutableString kUniformsBlockName = ImmutableString("ANGLEUniformBlock");
162162
constexpr ImmutableString kUniformsVarName = ImmutableString("ANGLEUniforms");
163163

164+
// Specialization constant names
165+
constexpr ImmutableString kLineRasterEmulationSpecConstVarName =
166+
ImmutableString("ANGLELineRasterEmulation");
167+
164168
constexpr const char kViewport[] = "viewport";
165169
constexpr const char kHalfRenderAreaHeight[] = "halfRenderAreaHeight";
166170
constexpr 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

435436
TVariable *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

src/libANGLE/renderer/glslang_wrapper_utils.cpp

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,6 @@ constexpr char kParamsEnd = ')';
5656
constexpr char kUniformQualifier[] = "uniform";
5757
constexpr char kSSBOQualifier[] = "buffer";
5858
constexpr char kUnusedUniformSubstitution[] = "// ";
59-
constexpr char kVersionDefine[] = "#version 450 core\n";
60-
constexpr char kLineRasterDefine[] = R"(#version 450 core
61-
62-
#define ANGLE_ENABLE_LINE_SEGMENT_RASTERIZATION
63-
)";
6459
constexpr uint32_t kANGLEPositionLocationOffset = 1;
6560
constexpr uint32_t kXfbANGLEPositionLocationOffset = 2;
6661

@@ -1082,7 +1077,7 @@ constexpr gl::ShaderMap<EShLanguage> kShLanguageMap = {
10821077
angle::Result GetShaderSpirvCode(GlslangErrorCallback callback,
10831078
const gl::Caps &glCaps,
10841079
const gl::ShaderMap<std::string> &shaderSources,
1085-
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut)
1080+
gl::ShaderMap<SpirvBlob> *spirvBlobsOut)
10861081
{
10871082
// Enable SPIR-V and Vulkan rules when parsing GLSL
10881083
EShMessages messages = static_cast<EShMessages>(EShMsgSpvRules | EShMsgVulkanRules);
@@ -1144,7 +1139,7 @@ angle::Result GetShaderSpirvCode(GlslangErrorCallback callback,
11441139
}
11451140

11461141
glslang::TIntermediate *intermediate = program.getIntermediate(kShLanguageMap[shaderType]);
1147-
glslang::GlslangToSpv(*intermediate, (*shaderCodeOut)[shaderType]);
1142+
glslang::GlslangToSpv(*intermediate, (*spirvBlobsOut)[shaderType]);
11481143
}
11491144

11501145
return angle::Result::Continue;
@@ -1270,33 +1265,9 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options,
12701265

12711266
angle::Result GlslangGetShaderSpirvCode(GlslangErrorCallback callback,
12721267
const gl::Caps &glCaps,
1273-
bool enableLineRasterEmulation,
12741268
const gl::ShaderMap<std::string> &shaderSources,
1275-
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut)
1269+
gl::ShaderMap<SpirvBlob> *spirvBlobsOut)
12761270
{
1277-
if (enableLineRasterEmulation)
1278-
{
1279-
ASSERT(shaderSources[gl::ShaderType::Compute].empty());
1280-
1281-
gl::ShaderMap<std::string> patchedSources = shaderSources;
1282-
1283-
for (const gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
1284-
{
1285-
if (!shaderSources[shaderType].empty())
1286-
{
1287-
// #defines must come after the #version directive.
1288-
ANGLE_GLSLANG_CHECK(callback,
1289-
angle::ReplaceSubstring(&patchedSources[shaderType],
1290-
kVersionDefine, kLineRasterDefine),
1291-
GlslangError::InvalidShader);
1292-
}
1293-
}
1294-
1295-
return GetShaderSpirvCode(callback, glCaps, patchedSources, shaderCodeOut);
1296-
}
1297-
else
1298-
{
1299-
return GetShaderSpirvCode(callback, glCaps, shaderSources, shaderCodeOut);
1300-
}
1271+
return GetShaderSpirvCode(callback, glCaps, shaderSources, spirvBlobsOut);
13011272
}
13021273
} // namespace rx

src/libANGLE/renderer/glslang_wrapper_utils.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ struct GlslangSourceOptions
3939
bool emulateTransformFeedback = false;
4040
};
4141

42+
using SpirvBlob = std::vector<uint32_t>;
43+
4244
using GlslangErrorCallback = std::function<angle::Result(GlslangError)>;
4345

4446
void GlslangInitialize();
@@ -56,9 +58,8 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options,
5658

5759
angle::Result GlslangGetShaderSpirvCode(GlslangErrorCallback callback,
5860
const gl::Caps &glCaps,
59-
bool enableLineRasterEmulation,
6061
const gl::ShaderMap<std::string> &shaderSources,
61-
gl::ShaderMap<std::vector<uint32_t>> *shaderCodesOut);
62+
gl::ShaderMap<SpirvBlob> *spirvBlobsOut);
6263

6364
} // namespace rx
6465

src/libANGLE/renderer/metal/ProgramMtl.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,8 @@ void ReadFromDefaultUniformBlock(int componentCount,
312312

313313
// Convert GLSL to spirv code
314314
gl::ShaderMap<std::vector<uint32_t>> shaderCodes;
315-
ANGLE_TRY(mtl::GlslangGetShaderSpirvCode(contextMtl, contextMtl->getCaps(), false,
316-
mShaderSource, &shaderCodes));
315+
ANGLE_TRY(mtl::GlslangGetShaderSpirvCode(contextMtl, contextMtl->getCaps(), mShaderSource,
316+
&shaderCodes));
317317

318318
// Convert spirv code to MSL
319319
ANGLE_TRY(convertToMsl(glContext, gl::ShaderType::Vertex, infoLog,

src/libANGLE/renderer/metal/mtl_glslang_utils.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ void GlslangGetShaderSource(const gl::ProgramState &programState,
2424

2525
angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
2626
const gl::Caps &glCaps,
27-
bool enableLineRasterEmulation,
2827
const gl::ShaderMap<std::string> &shaderSources,
2928
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut);
3029
} // namespace mtl

src/libANGLE/renderer/metal/mtl_glslang_utils.mm

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,12 @@ void GlslangGetShaderSource(const gl::ProgramState &programState,
5050

5151
angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
5252
const gl::Caps &glCaps,
53-
bool enableLineRasterEmulation,
5453
const gl::ShaderMap<std::string> &shaderSources,
5554
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut)
5655
{
5756
return rx::GlslangGetShaderSpirvCode(
5857
[context](GlslangError error) { return HandleError(context, error); }, glCaps,
59-
enableLineRasterEmulation, shaderSources, shaderCodeOut);
58+
shaderSources, shaderCodeOut);
6059
}
6160
} // namespace mtl
6261
} // namespace rx

src/libANGLE/renderer/vulkan/GlslangWrapperVk.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,11 @@ void GlslangWrapperVk::GetShaderSource(const angle::FeaturesVk &features,
5151
// static
5252
angle::Result GlslangWrapperVk::GetShaderCode(vk::Context *context,
5353
const gl::Caps &glCaps,
54-
bool enableLineRasterEmulation,
5554
const gl::ShaderMap<std::string> &shaderSources,
5655
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut)
5756
{
5857
return GlslangGetShaderSpirvCode(
5958
[context](GlslangError error) { return ErrorHandler(context, error); }, glCaps,
60-
enableLineRasterEmulation, shaderSources, shaderCodeOut);
59+
shaderSources, shaderCodeOut);
6160
}
6261
} // namespace rx

src/libANGLE/renderer/vulkan/GlslangWrapperVk.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ class GlslangWrapperVk
3131

3232
static angle::Result GetShaderCode(vk::Context *context,
3333
const gl::Caps &glCaps,
34-
bool enableLineRasterEmulation,
3534
const gl::ShaderMap<std::string> &shaderSources,
3635
gl::ShaderMap<std::vector<uint32_t>> *shaderCodesOut);
3736
};

0 commit comments

Comments
 (0)