diff options
| -rw-r--r-- | source/slang/core.meta.slang | 34 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang | 70 | ||||
| -rw-r--r-- | source/slang/slang-ast-expr.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 72 | ||||
| -rw-r--r-- | source/slang/slang-ir-inst-defs.h | 4 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-ir-spirv-legalize.cpp | 134 | ||||
| -rw-r--r-- | source/slang/slang-ir-spirv-legalize.h | 3 | ||||
| -rw-r--r-- | source/slang/slang-ir.cpp | 12 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 4 | ||||
| -rw-r--r-- | source/slang/slang-parser.cpp | 5 | ||||
| -rw-r--r-- | tests/pipeline/rasterization/conservative-rasterization/inner-coverage.slang | 8 | ||||
| -rw-r--r-- | tests/pipeline/rasterization/conservative-rasterization/inner-coverage.slang.glsl | 14 | ||||
| -rw-r--r-- | tests/pipeline/rasterization/fragment-shader-interlock.slang | 12 | ||||
| -rw-r--r-- | tests/pipeline/rasterization/get-attribute-at-vertex.slang | 9 |
15 files changed, 340 insertions, 43 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index e989e4ffa..55cf5896f 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -1760,16 +1760,42 @@ __target_intrinsic(cpp, "int(((char*)&($1)) - ((char*)&($0))") int __offsetOf(in T t, in F field); /// Mark beginning of "interlocked" operations in a fragment shader. -__target_intrinsic(glsl, "beginInvocationInterlockARB") __glsl_extension(GL_ARB_fragment_shader_interlock) __glsl_version(420) -void beginInvocationInterlock() {} +void beginInvocationInterlock() +{ + __target_switch + { + case glsl: + __intrinsic_asm "beginInvocationInterlockARB"; + case spirv: + spirv_asm { + OpCapability FragmentShaderPixelInterlockEXT; + OpExtension "SPV_EXT_fragment_shader_interlock"; + OpExecutionMode __entryPoint PixelInterlockOrderedEXT; + OpBeginInvocationInterlockEXT; + }; + } +} /// Mark end of "interlocked" operations in a fragment shader. -__target_intrinsic(glsl, "endInvocationInterlockARB") __glsl_extension(GL_ARB_fragment_shader_interlock) __glsl_version(420) -void endInvocationInterlock() {} +void endInvocationInterlock() +{ + __target_switch + { + case glsl: + __intrinsic_asm "endInvocationInterlockARB"; + case spirv: + spirv_asm { + OpCapability FragmentShaderPixelInterlockEXT; + OpExtension "SPV_EXT_fragment_shader_interlock"; + OpExecutionMode __entryPoint PixelInterlockOrderedEXT; + OpEndInvocationInterlockEXT; + }; + } +} // Operators to apply to `enum` types diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 5829a5109..d95c1e4d6 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -2898,15 +2898,26 @@ matrix<T, N, M> fwidth(matrix<T, N, M> x) /// This function can be applied to scalars, vectors, and matrices of /// built-in scalar types. /// -/// Note: these functions are not curently implemented for Vulkan/SPIR-V output. -/// __generic<T : __BuiltinType> [__readNone] -__target_intrinsic(hlsl) -__target_intrinsic(GL_NV_fragment_shader_barycentric, "$0[$1]") -__target_intrinsic(GL_EXT_fragment_shader_barycentric, "$0[$1]") __glsl_version(450) -T GetAttributeAtVertex(T attribute, uint vertexIndex); +T GetAttributeAtVertex(T attribute, uint vertexIndex) +{ + __target_switch + { + case hlsl: + __intrinsic_asm "GetAttributeAtVertex"; + case GL_NV_fragment_shader_barycentric: + case GL_EXT_fragment_shader_barycentric: + __intrinsic_asm "$0[$1]"; + case spirv: + return spirv_asm { + %_ptr_Input_T = OpTypePointer Input $$T; + %addr = OpAccessChain %_ptr_Input_T $attribute $vertexIndex; + result:$$T = OpLoad %addr; + }; + } +} /// Get the value of a vertex attribute at a specific vertex. /// @@ -2920,15 +2931,26 @@ T GetAttributeAtVertex(T attribute, uint vertexIndex); /// This function can be applied to scalars, vectors, and matrices of /// built-in scalar types. /// -/// Note: these functions are not curently implemented for Vulkan/SPIR-V output. -/// __generic<T : __BuiltinType, let N : int> [__readNone] -__target_intrinsic(hlsl) -__target_intrinsic(GL_NV_fragment_shader_barycentric, "$0[$1]") -__target_intrinsic(GL_EXT_fragment_shader_barycentric, "$0[$1]") __glsl_version(450) -vector<T,N> GetAttributeAtVertex(vector<T,N> attribute, uint vertexIndex); +vector<T,N> GetAttributeAtVertex(vector<T,N> attribute, uint vertexIndex) +{ + __target_switch + { + case hlsl: + __intrinsic_asm "GetAttributeAtVertex"; + case GL_NV_fragment_shader_barycentric: + case GL_EXT_fragment_shader_barycentric: + __intrinsic_asm "$0[$1]"; + case spirv: + return spirv_asm { + %_ptr_Input_vectorT = OpTypePointer Input $$vector<T,N>; + %addr = OpAccessChain %_ptr_Input_vectorT $attribute $vertexIndex; + result:$$vector<T,N> = OpLoad %addr; + }; + } +} /// Get the value of a vertex attribute at a specific vertex. /// @@ -2942,16 +2964,26 @@ vector<T,N> GetAttributeAtVertex(vector<T,N> attribute, uint vertexIndex); /// This function can be applied to scalars, vectors, and matrices of /// built-in scalar types. /// -/// Note: these functions are not curently implemented for Vulkan/SPIR-V output. -/// __generic<T : __BuiltinType, let N : int, let M : int> [__readNone] -__target_intrinsic(hlsl) -__target_intrinsic(GL_NV_fragment_shader_barycentric, "$0[$1]") -__target_intrinsic(GL_EXT_fragment_shader_barycentric, "$0[$1]") __glsl_version(450) -matrix<T,N,M> GetAttributeAtVertex(matrix<T,N,M> attribute, uint vertexIndex); - +matrix<T,N,M> GetAttributeAtVertex(matrix<T,N,M> attribute, uint vertexIndex) +{ + __target_switch + { + case hlsl: + __intrinsic_asm "GetAttributeAtVertex"; + case GL_NV_fragment_shader_barycentric: + case GL_EXT_fragment_shader_barycentric: + __intrinsic_asm "$0[$1]"; + case spirv: + return spirv_asm { + %_ptr_Input_matrixT = OpTypePointer Input $$matrix<T,N,M>; + %addr = OpAccessChain %_ptr_Input_matrixT $attribute $vertexIndex; + result:$$matrix<T,N,M> = OpLoad %addr; + }; + } +} // Get number of samples in render target [__readNone] diff --git a/source/slang/slang-ast-expr.h b/source/slang/slang-ast-expr.h index 9c604f6a0..5238cd4e2 100644 --- a/source/slang/slang-ast-expr.h +++ b/source/slang/slang-ast-expr.h @@ -659,6 +659,7 @@ public: SlangType, SampledType, // __sampledType(T), this becomes a 4 vector of the component type of T TruncateMarker, // __truncate, an invented instruction which coerces to the result type by truncating the element count + EntryPoint, // __entryPoint, a placeholder for the id of a referencing entryPoint. BuiltinVar, GLSL450Set, }; diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 2be86cdfe..0aa4d4c60 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -1061,6 +1061,42 @@ struct SPIRVEmitContext return spvInst; } + template<typename OperandEmitFunc> + SpvInst* emitInstMemoizedNoResultIDCustomOperandFunc( + SpvInstParent* parent, + IRInst* irInst, + SpvOp opcode, + const OperandEmitFunc& f + ) + { + List<SpvWord> ourOperands; + { + auto scopePeek = OperandMemoizeScope(this); + f(); + // Steal our operands back, so we don't have to calculate them + // again + ourOperands = std::move(m_operandStack); + } + + // Hash the whole global stack and opcode + SpvTypeInstKey key; + key.words.add(opcode); + key.words.addRange(ourOperands); + + // If we have seen this before, return the memoized instruction + if (SpvInst** memoized = m_spvTypeInsts.tryGetValue(key)) + return *memoized; + + // Otherwise, we can construct our instruction and record the result + InstConstructScope scopeInst(this, opcode, irInst); + SpvInst* spvInst = scopeInst; + m_spvTypeInsts[key] = spvInst; + + m_operandStack.addRange(ourOperands); + + parent->addInst(spvInst); + return spvInst; + } // // Specific emit funcs // @@ -2313,12 +2349,12 @@ struct SPIRVEmitContext // to the new globals, which would be used in the SPIR-V emit case. auto entryPointDecor = cast<IREntryPointDecoration>(decoration); + auto entryPoint = as<IRFunc>(decoration->getParent()); auto spvStage = mapStageToExecutionModel(entryPointDecor->getProfile().getStage()); auto name = entryPointDecor->getName()->getStringSlice(); List<SpvInst*> params; HashSet<SpvInst*> paramsSet; // `interface` part: reference all global variables that are used by this entrypoint. - // TODO: we may want to perform more accurate tracking. for (auto globalInst : m_irModule->getModuleInst()->getChildren()) { switch (globalInst->getOp()) @@ -2329,8 +2365,13 @@ struct SPIRVEmitContext SpvInst* spvGlobalInst; if (m_mapIRInstToSpvInst.tryGetValue(globalInst, spvGlobalInst)) { - paramsSet.add(spvGlobalInst); - params.add(spvGlobalInst); + // Is this globalInst referenced by this entry point? + auto refSet = m_referencingEntryPoints.tryGetValue(globalInst); + if (refSet && refSet->contains(entryPoint)) + { + paramsSet.add(spvGlobalInst); + params.add(spvGlobalInst); + } } break; } @@ -2622,6 +2663,7 @@ struct SPIRVEmitContext else if (semanticName == "sv_innercoverage") { requireSPIRVCapability(SpvCapabilityFragmentFullyCoveredEXT); + ensureExtensionDeclaration(UnownedStringSlice("SPV_EXT_fragment_fully_covered")); return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInFullyCoveredEXT); } else if (semanticName == "sv_depth") @@ -2694,6 +2736,7 @@ struct SPIRVEmitContext else if (semanticName == "sv_stencilref") { requireSPIRVCapability(SpvCapabilityStencilExportEXT); + ensureExtensionDeclaration(UnownedStringSlice("SPV_EXT_shader_stencil_export")); return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInFragStencilRefEXT); } else if (semanticName == "sv_tessfactor") @@ -2722,6 +2765,7 @@ struct SPIRVEmitContext else if (semanticName == "nv_viewport_mask") { requireSPIRVCapability(SpvCapabilityPerViewAttributesNV); + ensureExtensionDeclaration(UnownedStringSlice("SPV_NV_mesh_shader")); return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInViewportMaskPerViewNV); } else if (semanticName == "sv_barycentrics") @@ -2729,11 +2773,13 @@ struct SPIRVEmitContext if (m_targetRequest->getTargetCaps().implies(CapabilityAtom::GL_NV_fragment_shader_barycentric)) { requireSPIRVCapability(SpvCapabilityFragmentBarycentricNV); + ensureExtensionDeclaration(UnownedStringSlice("SPV_NV_fragment_shader_barycentric")); return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInBaryCoordNV); } else { requireSPIRVCapability(SpvCapabilityFragmentBarycentricKHR); + ensureExtensionDeclaration(UnownedStringSlice("SPV_KHR_fragment_shader_barycentric")); return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInBaryCoordKHR); } @@ -2744,11 +2790,13 @@ struct SPIRVEmitContext else if (semanticName == "sv_cullprimitive") { requireSPIRVCapability(SpvCapabilityMeshShadingEXT); + ensureExtensionDeclaration(UnownedStringSlice("SPV_NV_mesh_shader")); return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInCullPrimitiveEXT); } else if (semanticName == "sv_shadingrate") { requireSPIRVCapability(SpvCapabilityFragmentShadingRateKHR); + ensureExtensionDeclaration(UnownedStringSlice("SPV_KHR_fragment_shading_rate")); return getBuiltinGlobalVar(inst->getFullType(), SpvBuiltInPrimitiveShadingRateKHR); } SLANG_UNREACHABLE("Unimplemented system value in spirv emit."); @@ -3988,6 +4036,8 @@ struct SPIRVEmitContext return getSection(SpvLogicalSectionID::Capabilities); case SpvOpExtension: return getSection(SpvLogicalSectionID::Extensions); + case SpvOpExecutionMode: + return getSection(SpvLogicalSectionID::ExecutionModes); default: return defaultParent; @@ -4212,6 +4262,22 @@ struct SPIRVEmitContext case SpvOpExtension: ensureExtensionDeclaration(as<IRStringLit>(spvInst->getOperand(1)->getOperand(0))->getStringSlice()); continue; + case SpvOpExecutionMode: + { + if (auto refEntryPointSet = m_referencingEntryPoints.tryGetValue(getParentFunc(inst))) + { + for (auto entryPoint : *refEntryPointSet) + { + emitInstMemoizedNoResultIDCustomOperandFunc(getSection(SpvLogicalSectionID::ExecutionModes), nullptr, SpvOpExecutionMode, + [&]() { + emitOperand(entryPoint); + for (UInt s = 2; s < spvInst->getOperandCount(); s++) + emitSpvAsmOperand(as<IRSPIRVAsmOperand>(spvInst->getOperand(s))); + }); + } + } + continue; + } default: break; } diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index b44b7b5d9..6b5d8e59a 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -1103,6 +1103,10 @@ INST(SPIRVAsmInst, SPIRVAsmInst, 1, 0) // A special instruction which represents a type directed truncation // operation where extra components are dropped INST(SPIRVAsmOperandTruncate, __truncate, 0, HOISTABLE) + + // A special instruction which represents an ID of an entry point that references the current function. + INST(SPIRVAsmOperandEntryPoint, __entryPoint, 0, HOISTABLE) + // A type function which returns the result type of sampling an image of // this component type INST(SPIRVAsmOperandSampledType, __sampledType, 1, HOISTABLE) diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index 63555c08d..0fd48f546 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -4021,6 +4021,7 @@ public: IRSPIRVAsmOperand* emitSPIRVAsmOperandGLSL450Set(); IRSPIRVAsmOperand* emitSPIRVAsmOperandSampledType(IRType* elementType); IRSPIRVAsmOperand* emitSPIRVAsmOperandTruncate(); + IRSPIRVAsmOperand* emitSPIRVAsmOperandEntryPoint(); IRSPIRVAsmInst* emitSPIRVAsmInst(IRInst* opcode, List<IRInst*> operands); IRSPIRVAsm* emitSPIRVAsm(IRType* type); IRInst* emitGenericAsm(UnownedStringSlice asmText); diff --git a/source/slang/slang-ir-spirv-legalize.cpp b/source/slang/slang-ir-spirv-legalize.cpp index 69abaa108..393b907f7 100644 --- a/source/slang/slang-ir-spirv-legalize.cpp +++ b/source/slang/slang-ir-spirv-legalize.cpp @@ -220,12 +220,50 @@ struct SPIRVLegalizationContext : public SourceEmitterBase } } + Stage getReferencingEntryPointStage(IRInst* inst) + { + for (auto use = inst->firstUse; use; use = use->nextUse) + { + if (auto f = getParentFunc(use->getUser())) + { + if (auto d = f->findDecoration<IREntryPointDecoration>()) + return d->getProfile().getStage(); + } + } + return Stage::Unknown; + } + + bool translatePerVertexInputType(IRInst* param) + { + if (auto interpolationModeDecor = param->findDecoration<IRInterpolationModeDecoration>()) + { + if (interpolationModeDecor->getMode() == IRInterpolationMode::PerVertex) + { + if (getReferencingEntryPointStage(param) == Stage::Fragment) + { + auto originalType = param->getFullType(); + IRBuilder builder(param); + builder.setInsertBefore(param); + auto arrayType = builder.getArrayType(originalType, builder.getIntValue(builder.getIntType(), 3)); + param->setFullType(arrayType); + return true; + } + } + } + return false; + } + void processGlobalParam(IRGlobalParam* inst) { // If the global param is not a pointer type, make it so and insert explicit load insts. auto ptrType = as<IRPtrTypeBase>(inst->getDataType()); if (!ptrType) { + bool needLoad = true; + + if (translatePerVertexInputType(inst)) + needLoad = false; + auto innerType = inst->getFullType(); auto arrayType = as<IRArrayType>(inst->getDataType()); @@ -261,7 +299,6 @@ struct SPIRVLegalizationContext : public SourceEmitterBase // Strip any HLSL wrappers IRBuilder builder(m_sharedContext->m_irModule); - bool needLoad = true; auto cbufferType = as<IRConstantBufferType>(innerType); auto paramBlockType = as<IRParameterBlockType>(innerType); if (cbufferType || paramBlockType) @@ -1055,6 +1092,100 @@ void legalizeSPIRV(SPIRVEmitSharedContext* sharedContext, IRModule* module) context.processModule(); } +void buildEntryPointReferenceGraph(SPIRVEmitSharedContext* context, IRModule* module) +{ + struct WorkItem + { + IRFunc* entryPoint; IRInst* inst; + + HashCode getHashCode() const + { + return combineHash(Slang::getHashCode(entryPoint), Slang::getHashCode(inst)); + } + bool operator == (const WorkItem& other) const + { + return entryPoint == other.entryPoint && inst == other.inst; + } + }; + HashSet<WorkItem> workListSet; + List<WorkItem> workList; + auto addToWorkList = [&](WorkItem item) + { + if (workListSet.add(item)) + workList.add(item); + }; + + auto registerEntryPointReference = [&](IRFunc* entryPoint, IRInst* inst) + { + if (auto set = context->m_referencingEntryPoints.tryGetValue(inst)) + set->add(entryPoint); + else + { + HashSet<IRFunc*> newSet; + newSet.add(entryPoint); + context->m_referencingEntryPoints.add(inst, _Move(newSet)); + } + }; + auto visit = [&](IRFunc* entryPoint, IRInst* inst) + { + if (auto code = as<IRGlobalValueWithCode>(inst)) + { + registerEntryPointReference(entryPoint, inst); + for (auto child : code->getChildren()) + { + addToWorkList({ entryPoint, child }); + } + return; + } + switch (inst->getOp()) + { + case kIROp_GlobalParam: + registerEntryPointReference(entryPoint, inst); + break; + case kIROp_Block: + case kIROp_SPIRVAsm: + for (auto child : inst->getChildren()) + { + addToWorkList({ entryPoint, child }); + } + break; + case kIROp_Call: + { + auto call = as<IRCall>(inst); + addToWorkList({ entryPoint, call->getCallee() }); + } + break; + case kIROp_SPIRVAsmOperandInst: + { + auto operand = as<IRSPIRVAsmOperandInst>(inst); + addToWorkList({ entryPoint, operand->getValue() }); + } + break; + } + for (UInt i = 0; i < inst->getOperandCount(); i++) + { + auto operand = inst->getOperand(i); + switch (operand->getOp()) + { + case kIROp_GlobalParam: + case kIROp_GlobalVar: + addToWorkList({ entryPoint, operand }); + break; + } + } + }; + + for (auto globalInst : module->getGlobalInsts()) + { + if (globalInst->getOp() == kIROp_Func && globalInst->findDecoration<IREntryPointDecoration>()) + { + visit(as<IRFunc>(globalInst), globalInst); + } + } + for (Index i = 0; i < workList.getCount(); i++) + visit(workList[i].entryPoint, workList[i].inst); +} + void legalizeIRForSPIRV( SPIRVEmitSharedContext* context, IRModule* module, @@ -1064,6 +1195,7 @@ void legalizeIRForSPIRV( GLSLExtensionTracker extensionTracker; legalizeEntryPointsForGLSL(module->getSession(), module, entryPoints, codeGenContext, &extensionTracker); legalizeSPIRV(context, module); + buildEntryPointReferenceGraph(context, module); } } // namespace Slang diff --git a/source/slang/slang-ir-spirv-legalize.h b/source/slang/slang-ir-spirv-legalize.h index b11cde72f..c9b75c07f 100644 --- a/source/slang/slang-ir-spirv-legalize.h +++ b/source/slang/slang-ir-spirv-legalize.h @@ -18,6 +18,9 @@ struct SPIRVEmitSharedContext IRModule* m_irModule; TargetRequest* m_targetRequest; Dictionary<IRTargetIntrinsicDecoration*, RefPtr<SpvSnippet>> m_parsedSpvSnippets; + + Dictionary<IRInst*, HashSet<IRFunc*>> m_referencingEntryPoints; // The entry-points that directly or transitively reference this global inst. + DiagnosticSink* m_sink; const SPIRVCoreGrammarInfo* m_grammarInfo; SPIRVEmitSharedContext(IRModule* module, TargetRequest* target, DiagnosticSink* sink) diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index 6777c0b3a..a54bc1f2e 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -5797,6 +5797,18 @@ namespace Slang return i; } + IRSPIRVAsmOperand* IRBuilder::emitSPIRVAsmOperandEntryPoint() + { + SLANG_ASSERT(as<IRSPIRVAsm>(m_insertLoc.getParent())); + const auto i = createInst<IRSPIRVAsmOperand>( + this, + kIROp_SPIRVAsmOperandEntryPoint, + getVoidType() + ); + addInst(i); + return i; + } + IRSPIRVAsmInst* IRBuilder::emitSPIRVAsmInst(IRInst* opcode, List<IRInst*> operands) { SLANG_ASSERT(as<IRSPIRVAsm>(m_insertLoc.getParent())); diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 4f64087d8..640482f12 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -3906,6 +3906,10 @@ struct ExprLoweringVisitorBase : public ExprVisitor<Derived, LoweredValInfo> { return builder->emitSPIRVAsmOperandTruncate(); } + case SPIRVAsmOperand::EntryPoint: + { + return builder->emitSPIRVAsmOperandEntryPoint(); + } } SLANG_UNREACHABLE("Unhandled case in visitSPIRVAsmExpr"); }; diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index 892edd328..0191b1e0c 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -6322,6 +6322,11 @@ namespace Slang { return SPIRVAsmOperand{SPIRVAsmOperand::TruncateMarker, parser->ReadToken()}; } + // The pseudo-operand for referencing entryPoint id. + else if (parser->LookAheadToken("__entryPoint")) + { + return SPIRVAsmOperand{ SPIRVAsmOperand::EntryPoint, parser->ReadToken() }; + } else if (AdvanceIf(parser, "builtin")) { // reference to a builtin var. diff --git a/tests/pipeline/rasterization/conservative-rasterization/inner-coverage.slang b/tests/pipeline/rasterization/conservative-rasterization/inner-coverage.slang index fe77095df..bfa7eb633 100644 --- a/tests/pipeline/rasterization/conservative-rasterization/inner-coverage.slang +++ b/tests/pipeline/rasterization/conservative-rasterization/inner-coverage.slang @@ -1,6 +1,12 @@ // inner-coverage.slang -//TEST:CROSS_COMPILE:-target spirv -entry main -stage fragment +//TEST:SIMPLE(filecheck=CHECK):-target spirv -entry main -stage fragment +//TEST:SIMPLE(filecheck=CHECK):-emit-spirv-directly -target spirv -entry main -stage fragment + +// CHECK: OpCapability FragmentFullyCoveredEXT +// CHECK: OpExtension "SPV_EXT_fragment_fully_covered" +// CHECK: OpEntryPoint Fragment %main "main" +// CHECK: OpDecorate %{{.*}} BuiltIn FullyCoveredEXT [shader("fragment")] void main( diff --git a/tests/pipeline/rasterization/conservative-rasterization/inner-coverage.slang.glsl b/tests/pipeline/rasterization/conservative-rasterization/inner-coverage.slang.glsl deleted file mode 100644 index 59fecd544..000000000 --- a/tests/pipeline/rasterization/conservative-rasterization/inner-coverage.slang.glsl +++ /dev/null @@ -1,14 +0,0 @@ -//TEST_IGNORE_FILE: -#version 450 -#extension GL_NV_conservative_raster_underestimation : require -layout(row_major) uniform; -layout(row_major) buffer; - -layout(location = 0) -out vec4 _S1; - -void main() -{ - _S1 = vec4(uint(gl_FragFullyCoveredNV)); - return; -} diff --git a/tests/pipeline/rasterization/fragment-shader-interlock.slang b/tests/pipeline/rasterization/fragment-shader-interlock.slang index 7215629a2..0e438c456 100644 --- a/tests/pipeline/rasterization/fragment-shader-interlock.slang +++ b/tests/pipeline/rasterization/fragment-shader-interlock.slang @@ -3,7 +3,17 @@ // Test that explicit use of fragment-shader interlock (FSI) // operations is supported by Slang -//TEST:CROSS_COMPILE:-target spirv -entry main -stage fragment +//TEST:SIMPLE(filecheck=CHECK):-target spirv -entry main -stage fragment +//TEST:SIMPLE(filecheck=CHECK):-emit-spirv-directly -target spirv -entry main -stage fragment + + +// CHECK: OpCapability FragmentShaderPixelInterlockEXT +// CHECK: OpExtension "SPV_EXT_fragment_shader_interlock" +// CHECK: OpEntryPoint Fragment %main "main" + +// CHECK-DAG: OpExecutionMode %main OriginUpperLeft + +// CHECK-DAG: OpExecutionMode %main PixelInterlockOrderedEXT [shader("fragment")] void main( diff --git a/tests/pipeline/rasterization/get-attribute-at-vertex.slang b/tests/pipeline/rasterization/get-attribute-at-vertex.slang index 87d39c806..a88cf8d24 100644 --- a/tests/pipeline/rasterization/get-attribute-at-vertex.slang +++ b/tests/pipeline/rasterization/get-attribute-at-vertex.slang @@ -4,6 +4,15 @@ //TEST:CROSS_COMPILE:-target dxil -entry main -stage fragment -profile sm_6_1 //TEST:CROSS_COMPILE:-target spirv -entry main -stage fragment -profile glsl_450 +//TEST:SIMPLE(filecheck=CHECK):-emit-spirv-directly -target spirv -entry main -stage fragment -profile glsl_450 + +// CHECK: OpCapability FragmentBarycentricKHR +// CHECK: OpExtension "SPV_KHR_fragment_shader_barycentric" + +// CHECK: OpEntryPoint Fragment %main "main" +// CHECK: %{{.*}} = OpAccessChain %_ptr_Input_{{.*}} %{{.*}} %uint_0 +// CHECK: %{{.*}} = OpAccessChain %_ptr_Input_{{.*}} %{{.*}} %uint_1 +// CHECK: %{{.*}} = OpAccessChain %_ptr_Input_{{.*}} %{{.*}} %uint_2 [shader("fragment")] void main( |
