From 6f1371a7870a7c371a77cfdee1daa5c32f0c5377 Mon Sep 17 00:00:00 2001 From: ArielG-NV <159081215+ArielG-NV@users.noreply.github.com> Date: Thu, 18 Jul 2024 11:03:30 -0400 Subject: Adjust how `slang` and `slangc` uses a `profile` to manage the stage of an entry-point (#4670) * Fixes #4656 Changes: 1. Setting a profile via slangc no-longer sets an entry-point target-stage, this is to allow slangc to follow how the SLANG-API works (else `main` is assumed to be the default entry-point) 2. If the stage specified by a profile is not equal to the stage specified by a entry-point, we throw a capability error. 3. Resolving the stage of an entry point was changed to function (mostly) equally for when 0 entry-points are specified versus to when there are 1 or more. 4. changed capabilitySet Iterator so it is invalid if backing data is nullptr (although this should never happen, it would stop crashes in the worst case). * remove the breaking change since it likely is going to be a lot more than just a simple change due to the implicit `main` and stage through `profile` code. * print out profile name with errors * use target's profile for printing * change logic to print warning in a different method (account for more cases) * set unknown stages --- source/slang/slang-check-shader.cpp | 50 ++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 20 deletions(-) (limited to 'source/slang/slang-check-shader.cpp') diff --git a/source/slang/slang-check-shader.cpp b/source/slang/slang-check-shader.cpp index 14495dd6e..3d086b189 100644 --- a/source/slang/slang-check-shader.cpp +++ b/source/slang/slang-check-shader.cpp @@ -577,6 +577,30 @@ namespace Slang } } + bool resolveStageOfProfileWithEntryPoint(Profile& entryPointProfile, CompilerOptionSet& optionSet, const List>& targets, FuncDecl* entryPointFuncDecl, DiagnosticSink* sink) + { + if (auto entryPointAttr = entryPointFuncDecl->findModifier()) + { + auto entryPointProfileStage = entryPointProfile.getStage(); + // Ensure every target is specifying the same stage as an entry` point + // if a profile+stage was set, else user will not be aware that their + // code is requiring `fragment` on a `vertex` shader + for (auto target : targets) + { + auto targetProfile = target->getOptionSet().getProfile(); + auto profileStage = targetProfile.getStage(); + if (profileStage != Stage::Unknown && profileStage != entryPointAttr->stage) + maybeDiagnose(sink, optionSet, DiagnosticCategory::Capability, entryPointAttr, Diagnostics::entryPointAndProfileAreIncompatible, entryPointFuncDecl, entryPointAttr->stage, targetProfile.getName()); + } + if (entryPointProfileStage == Stage::Unknown) + entryPointProfile.setStage(entryPointAttr->stage); + else if (entryPointProfileStage != Stage::Unknown && entryPointProfileStage != entryPointAttr->stage) + maybeDiagnose(sink, optionSet, DiagnosticCategory::Capability, entryPointFuncDecl, Diagnostics::specifiedStageDoesntMatchAttribute, entryPointFuncDecl->getName(), entryPointProfileStage, entryPointAttr->stage); + return true; + } + return false; + } + // Given an entry point specified via API or command line options, // attempt to find a matching AST declaration that implements the specified // entry point. If such a function is found, then validate that it actually @@ -618,27 +642,13 @@ namespace Slang // // If the entry point specifies a stage via a `[shader("...")]` attribute, // then we might be able to infer a stage for the entry point request if - // it didn't have one, *or* issue a diagnostic if there is a mismatch. - // + // it didn't have one, *or* issue a diagnostic if there is a mismatch with the profile. + auto entryPointProfile = entryPointReq->getProfile(); - if( auto entryPointAttribute = entryPointFuncDecl->findModifier() ) - { - auto entryPointStage = entryPointProfile.getStage(); - if( entryPointStage == Stage::Unknown ) - { - entryPointProfile.setStage(entryPointAttribute->stage); - } - else if( entryPointAttribute->stage != entryPointStage ) - { - sink->diagnose(entryPointFuncDecl, Diagnostics::specifiedStageDoesntMatchAttribute, entryPointName, entryPointStage, entryPointAttribute->stage); - } - } - else - { - // TODO: Should we attach a `[shader(...)]` attribute to an - // entry point that didn't have one, so that we can have - // a more uniform representation in the AST? - } + resolveStageOfProfileWithEntryPoint(entryPointProfile, linkage->m_optionSet, linkage->targets, entryPointFuncDecl, sink); + // TODO: Should we attach a `[shader(...)]` attribute to an + // entry point that didn't have one, so that we can have + // a more uniform representation in the AST? RefPtr entryPoint = EntryPoint::create( linkage, -- cgit v1.2.3