summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorArielG-NV <159081215+ArielG-NV@users.noreply.github.com>2024-07-02 13:35:49 -0400
committerGitHub <noreply@github.com>2024-07-02 13:35:49 -0400
commitd5d03d1510f45f5ed7864031244713d87fc82b87 (patch)
treee0391686ca3b06406e497c4e7e7f90172355e4cf /source
parentbd01bd3f4b8eecbfb924b8eb4090694e44e8166c (diff)
Emit errors when invalid capabilities are used (#4510)
* Fix invalid capabilities being allowed fixes: #4506 fixes: #4508 1. As per #4506, no longer allow invalid `[require(...)]` 2. As per #4508, no longer allow mismatch between `case` and `require` of a calling function 3. Fixes incorrect hlsl.meta capabilities 4. Added a ref to the parent function/decl for when erroring with capabilities to help debug meta.slang files for when weird source locations are generated. * rename vars and copy lambdas by value * fix some more capabilities * incorrect capabilities on a texture test * push capabilities fix note: seperated capabilities for glsl,spirv,cuda,hlsl since not all functions support all targets (source of capability error) * fix cmd line arg by using `xslang` to passthrough to slangc * let auto-infer run for certain capabilities to reduce simple mistakes --------- Co-authored-by: Jay Kwak <82421531+jkwak-work@users.noreply.github.com>
Diffstat (limited to 'source')
-rw-r--r--source/slang/glsl.meta.slang30
-rw-r--r--source/slang/hlsl.meta.slang28
-rw-r--r--source/slang/slang-capabilities.capdef32
-rw-r--r--source/slang/slang-check-decl.cpp98
-rw-r--r--source/slang/slang-check-modifier.cpp2
-rw-r--r--source/slang/slang-diagnostic-defs.h1
-rw-r--r--source/slang/slang-stdlib-textures.cpp2
7 files changed, 116 insertions, 77 deletions
diff --git a/source/slang/glsl.meta.slang b/source/slang/glsl.meta.slang
index ae6fbd67c..0078d39cb 100644
--- a/source/slang/glsl.meta.slang
+++ b/source/slang/glsl.meta.slang
@@ -1870,7 +1870,7 @@ public ivec3 textureSize(Sampler2DMSArray<vector<T,N>,sampleCount> sampler)
__generic<T, let isArray:int, let sampleCount:int, let isShadow:int, let format:int>
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylod)]
+[require(glsl_hlsl_metal_spirv, texture_querylod)]
public vec2 textureQueryLod(__TextureImpl<
T,
__Shape1D,
@@ -1903,7 +1903,7 @@ public vec2 textureQueryLod(__TextureImpl<
__generic<T, Shape: __ITextureShape, let isArray:int, let sampleCount:int, let isShadow:int, let format:int>
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylod)]
+[require(glsl_hlsl_metal_spirv, texture_querylod)]
public vec2 textureQueryLod(__TextureImpl<
T,
Shape,
@@ -1940,7 +1940,7 @@ public vec2 textureQueryLod(__TextureImpl<
__generic<T:__BuiltinArithmeticType, let N:int>
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylevels)]
+[require(cpp_glsl_hlsl_metal_spirv, texture_querylevels)]
public int textureQueryLevels(Sampler1D<vector<T,N>> sampler)
{
int width;
@@ -1951,7 +1951,7 @@ public int textureQueryLevels(Sampler1D<vector<T,N>> sampler)
__generic<T:__BuiltinArithmeticType, let N:int>
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylevels)]
+[require(cpp_glsl_hlsl_metal_spirv, texture_querylevels)]
public int textureQueryLevels(Sampler2D<vector<T,N>> sampler)
{
vector<int,2> dim;
@@ -1962,7 +1962,7 @@ public int textureQueryLevels(Sampler2D<vector<T,N>> sampler)
__generic<T:__BuiltinArithmeticType, let N:int>
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylevels)]
+[require(cpp_glsl_hlsl_metal_spirv, texture_querylevels)]
public int textureQueryLevels(Sampler3D<vector<T,N>> sampler)
{
vector<int,3> dim;
@@ -1973,7 +1973,7 @@ public int textureQueryLevels(Sampler3D<vector<T,N>> sampler)
__generic<T:__BuiltinArithmeticType, let N:int>
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylevels)]
+[require(cpp_glsl_hlsl_metal_spirv, texture_querylevels)]
public int textureQueryLevels(SamplerCube<vector<T,N>> sampler)
{
vector<int,2> dim;
@@ -1984,7 +1984,7 @@ public int textureQueryLevels(SamplerCube<vector<T,N>> sampler)
__generic<T:__BuiltinArithmeticType, let N:int>
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylevels)]
+[require(cpp_glsl_hlsl_metal_spirv, texture_querylevels)]
public int textureQueryLevels(Sampler1DArray<vector<T,N>> sampler)
{
vector<int,2> dim;
@@ -1995,7 +1995,7 @@ public int textureQueryLevels(Sampler1DArray<vector<T,N>> sampler)
__generic<T:__BuiltinArithmeticType, let N:int>
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylevels)]
+[require(cpp_glsl_hlsl_metal_spirv, texture_querylevels)]
public int textureQueryLevels(Sampler2DArray<vector<T,N>> sampler)
{
vector<int,3> dim;
@@ -2006,7 +2006,7 @@ public int textureQueryLevels(Sampler2DArray<vector<T,N>> sampler)
__generic<T:__BuiltinArithmeticType, let N:int>
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylevels)]
+[require(cpp_glsl_hlsl_metal_spirv, texture_querylevels)]
public int textureQueryLevels(SamplerCubeArray<vector<T,N>> sampler)
{
vector<int,3> dim;
@@ -2016,7 +2016,7 @@ public int textureQueryLevels(SamplerCubeArray<vector<T,N>> sampler)
}
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylevels)]
+[require(cpp_glsl_hlsl_metal_spirv, texture_querylevels)]
public int textureQueryLevels(sampler1DShadow sampler)
{
int dim;
@@ -2026,7 +2026,7 @@ public int textureQueryLevels(sampler1DShadow sampler)
}
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylevels)]
+[require(cpp_glsl_hlsl_metal_spirv, texture_querylevels)]
public int textureQueryLevels(sampler2DShadow sampler)
{
vector<int,2> dim;
@@ -2036,7 +2036,7 @@ public int textureQueryLevels(sampler2DShadow sampler)
}
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylevels)]
+[require(cpp_glsl_hlsl_metal_spirv, texture_querylevels)]
public int textureQueryLevels(samplerCubeShadow sampler)
{
vector<int,2> dim;
@@ -2046,7 +2046,7 @@ public int textureQueryLevels(samplerCubeShadow sampler)
}
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylevels)]
+[require(cpp_glsl_hlsl_metal_spirv, texture_querylevels)]
public int textureQueryLevels(sampler1DArrayShadow sampler)
{
vector<int,2> dim;
@@ -2056,7 +2056,7 @@ public int textureQueryLevels(sampler1DArrayShadow sampler)
}
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylevels)]
+[require(cpp_glsl_hlsl_metal_spirv, texture_querylevels)]
public int textureQueryLevels(sampler2DArrayShadow sampler)
{
vector<int,3> dim;
@@ -2066,7 +2066,7 @@ public int textureQueryLevels(sampler2DArrayShadow sampler)
}
[ForceInline]
-[require(cpp_cuda_glsl_hlsl_spirv, texture_querylevels)]
+[require(cpp_glsl_hlsl_metal_spirv, texture_querylevels)]
public int textureQueryLevels(samplerCubeArrayShadow sampler)
{
vector<int,3> dim;
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang
index f50c63367..d83059b00 100644
--- a/source/slang/hlsl.meta.slang
+++ b/source/slang/hlsl.meta.slang
@@ -2901,7 +2901,6 @@ extension __TextureImpl<T,Shape,isArray,0,sampleCount,$(access),isShadow, 0,form
[__readNone]
[ForceInline]
- [require(hlsl, texture_sm_4_1)]
T Load(vector<int, Shape.dimensions+isArray> location, vector<int, Shape.dimensions+isArray> offset, out uint status)
{
__target_switch
@@ -3124,7 +3123,6 @@ extension __TextureImpl<T,Shape,isArray,1,sampleCount,$(access),isShadow, 0,form
[__readNone]
[ForceInline]
- [require(hlsl, texture_sm_4_1_compute_fragment)]
T Load(vector<int, Shape.dimensions+isArray> location, int sampleIndex, vector<int, Shape.dimensions+isArray> offset, out uint status)
{
__target_switch
@@ -3292,11 +3290,7 @@ ${{{{
if (shape == kStdlibShapeIndex3D && isArray == 1)
continue;
const char* textureTypeName = isCombined ? "Sampler" : "Texture";
-
- StringBuilder requireStringBuilder;
- auto requireString = requireStringBuilder.toString();
}}}}
-$(requireString)
typealias $(accessPrefix[access])$(textureTypeName)$(shapeTypeNames[shape])$(msPostFix[isMS])$(arrayPostFix[isArray])<T=float4, let sampleCount:int=0, let format:int=0> = __TextureImpl<T, __Shape$(shapeTypeNames[shape]), $(isArray), $(isMS), sampleCount, $(access), 0, $(isCombined), format>;
${{{{
}
@@ -14117,7 +14111,7 @@ vector<T, N> WaveActive$(opName.hlslName)(vector<T, N> expr)
}
__generic<T : __BuiltinIntegerType, let N : int, let M : int>
-[require(cuda_hlsl, subgroup_arithmetic)]
+[require(cuda_glsl_hlsl_spirv, subgroup_arithmetic)]
matrix<T, N, M> WaveActive$(opName.hlslName)(matrix<T, N, M> expr)
{
__target_switch
@@ -14189,7 +14183,7 @@ vector<T, N> WaveActive$(opName)(vector<T, N> expr)
}
__generic<T : __BuiltinArithmeticType, let N : int, let M : int>
-[require(cuda_hlsl, subgroup_arithmetic)]
+[require(cuda_glsl_hlsl_spirv, subgroup_arithmetic)]
matrix<T, N, M> WaveActive$(opName)(matrix<T, N, M> expr)
{
__target_switch
@@ -14283,7 +14277,7 @@ vector<T,N> WaveActive$(opName.hlslName)(vector<T,N> expr)
}
__generic<T : __BuiltinArithmeticType, let N : int, let M : int>
-[require(cuda_hlsl, subgroup_arithmetic)]
+[require(cuda_glsl_hlsl_spirv, subgroup_arithmetic)]
matrix<T, N, M> WaveActive$(opName.hlslName)(matrix<T, N, M> expr)
{
__target_switch
@@ -14600,7 +14594,7 @@ vector<T,N> WavePrefixProduct(vector<T,N> expr)
}
__generic<T : __BuiltinArithmeticType, let N : int, let M : int>
-[require(cuda_hlsl, subgroup_arithmetic)]
+[require(cuda_glsl_hlsl_spirv, subgroup_arithmetic)]
matrix<T, N, M> WavePrefixProduct(matrix<T, N, M> expr)
{
__target_switch
@@ -14676,7 +14670,7 @@ vector<T,N> WavePrefixSum(vector<T,N> expr)
}
__generic<T : __BuiltinArithmeticType, let N : int, let M : int>
-[require(cuda_hlsl, subgroup_arithmetic)]
+[require(cuda_glsl_hlsl_spirv, subgroup_arithmetic)]
matrix<T,N,M> WavePrefixSum(matrix<T,N,M> expr)
{
__target_switch
@@ -14732,7 +14726,7 @@ vector<T,N> WaveReadLaneFirst(vector<T,N> expr)
}
__generic<T : __BuiltinType, let N : int, let M : int>
-[require(cuda_hlsl, subgroup_ballot)]
+[require(cuda_glsl_hlsl_spirv, subgroup_ballot)]
matrix<T,N,M> WaveReadLaneFirst(matrix<T,N,M> expr)
{
__target_switch
@@ -14796,7 +14790,7 @@ vector<T,N> WaveBroadcastLaneAt(vector<T,N> value, constexpr int lane)
}
__generic<T : __BuiltinType, let N : int, let M : int>
-[require(cuda_hlsl, subgroup_ballot)]
+[require(cuda_glsl_hlsl_spirv, subgroup_ballot)]
matrix<T, N, M> WaveBroadcastLaneAt(matrix<T, N, M> value, constexpr int lane)
{
__target_switch
@@ -14857,7 +14851,7 @@ vector<T,N> WaveReadLaneAt(vector<T,N> value, int lane)
}
__generic<T : __BuiltinType, let N : int, let M : int>
-[require(cuda_hlsl, subgroup_shuffle)]
+[require(cuda_glsl_hlsl_spirv, subgroup_shuffle)]
matrix<T, N, M> WaveReadLaneAt(matrix<T, N, M> value, int lane)
{
__target_switch
@@ -15023,7 +15017,7 @@ uint4 WaveMatch(vector<T,N> value)
}
__generic<T : __BuiltinType, let N : int, let M : int>
-[require(cuda_glsl_hlsl, subgroup_partitioned)]
+[require(cuda_glsl_hlsl_spirv, subgroup_partitioned)]
uint4 WaveMatch(matrix<T,N,M> value)
{
__target_switch
@@ -16243,7 +16237,7 @@ void SetMeshOutputCounts(uint vertexCount, uint primitiveCount)
// This function cannot be inlined due to a legalization pass happening mid-way through processing
// and later more processing happening to the function which requires eventual inlining.
[KnownBuiltin("DispatchMesh")]
-[require(glsl_hlsl_spirv, meshshading)]
+[require(glsl_hlsl_metal_spirv, meshshading)]
[noRefInline]
void DispatchMesh<P>(uint threadGroupCountX, uint threadGroupCountY, uint threadGroupCountZ, __ref P meshPayload)
{
@@ -18533,7 +18527,7 @@ struct HitObject
/// Returns the attributes of a hit. Valid if the hit object represents a hit or a miss.
[ForceInline]
- [require(glsl_spirv, ser_raygen_closesthit_miss)]
+ [require(glsl_hlsl_spirv, ser_raygen_closesthit_miss)]
attr_t GetAttributes<attr_t>()
{
__target_switch
diff --git a/source/slang/slang-capabilities.capdef b/source/slang/slang-capabilities.capdef
index 1511c3a08..140346163 100644
--- a/source/slang/slang-capabilities.capdef
+++ b/source/slang/slang-capabilities.capdef
@@ -401,7 +401,7 @@ alias rayquery = GL_EXT_ray_query | _sm_6_3;
alias raytracing_motionblur = raytracing + motionblur | cuda;
alias ser_motion = ser + motionblur;
alias shaderclock = GL_EXT_shader_realtime_clock | hlsl_nvapi | cpp | cuda;
-alias meshshading_internal = GL_EXT_mesh_shader | _sm_6_5;
+alias meshshading_internal = GL_EXT_mesh_shader | _sm_6_5 | metal;
alias meshshading = amplification_mesh + meshshading_internal;
alias fragmentshaderinterlock = _GL_ARB_fragment_shader_interlock | hlsl_nvapi | spvFragmentShaderPixelInterlockEXT;
alias atomic64 = GL_EXT_shader_atomic_int64 | _sm_6_6 | cpp | cuda;
@@ -447,7 +447,7 @@ alias sm_4_0_version = _sm_4_0
;
alias sm_4_0 = sm_4_0_version
| SPV_GOOGLE_user_type + spvMinLod
- | GL_ARB_sparse_texture_clamp + GL_EXT_samplerless_texture_functions + GL_EXT_texture_query_lod + GL_EXT_texture_shadow_lod + GL_EXT_debug_printf
+ | GL_ARB_sparse_texture_clamp + GL_EXT_samplerless_texture_functions + GL_EXT_texture_query_lod + GL_EXT_texture_shadow_lod + GL_EXT_debug_printf + GL_ARB_shader_image_size
;
alias sm_4_1_version = _sm_4_1
@@ -458,6 +458,7 @@ alias sm_4_1_version = _sm_4_1
| cpp
;
alias sm_4_1 = sm_4_1_version
+ | GL_ARB_texture_gather + GL_ARB_texture_query_levels + GL_ARB_shader_texture_image_samples
// previous
| sm_4_0
;
@@ -737,6 +738,9 @@ alias consumestructuredbuffer = sm_5_0_version;
alias fragmentprocessing = fragment + _sm_5_0
| fragment + glsl_spirv
| raytracingstages_compute_amplification_mesh + GL_NV_compute_shader_derivatives
+ | fragment + metal
+ | fragment + cpp
+ | fragment + cuda
;
alias fragmentprocessing_derivativecontrol = fragment + _sm_5_0
| fragment + GL_ARB_derivative_control
@@ -758,15 +762,15 @@ alias texture_sm_4_1_samplerless = texture_sm_4_1
// supposedly works on only limited stages, support all stages for now
alias texture_sm_4_1_compute_fragment = texture_sm_4_1;
alias texture_sm_4_0_fragment = texture_sm_4_0;
-alias texture_sm_4_1_clamp_fragment = texture_sm_4_0_fragment + GL_ARB_sparse_texture_clamp;
+alias texture_sm_4_1_clamp_fragment = texture_sm_4_0_fragment | GL_ARB_sparse_texture_clamp;
alias texture_sm_4_1_vertex_fragment_geometry = texture_sm_4_1;
-alias texture_gather = texture_sm_4_1_vertex_fragment_geometry + GL_ARB_texture_gather;
-alias image_samples = texture_sm_4_1_compute_fragment + GL_ARB_shader_texture_image_samples;
-alias image_size = texture_sm_4_1_compute_fragment + GL_ARB_shader_image_size;
-alias texture_size = texture_sm_4_1 + GL_ARB_shader_image_size;
-alias texture_querylod = texture_sm_4_1 + GL_EXT_texture_query_lod;
-alias texture_querylevels = texture_sm_4_1 + GL_ARB_texture_query_levels;
-alias texture_shadowlod = texture_sm_4_1 + GL_EXT_texture_shadow_lod
+alias texture_gather = texture_sm_4_1_vertex_fragment_geometry | GL_ARB_texture_gather;
+alias image_samples = texture_sm_4_1_compute_fragment | GL_ARB_shader_texture_image_samples;
+alias image_size = texture_sm_4_1_compute_fragment | GL_ARB_shader_image_size;
+alias texture_size = texture_sm_4_1 | GL_ARB_shader_image_size;
+alias texture_querylod = texture_sm_4_1 | GL_EXT_texture_query_lod;
+alias texture_querylevels = texture_sm_4_1 | GL_ARB_texture_query_levels;
+alias texture_shadowlod = texture_sm_4_1 | GL_EXT_texture_shadow_lod
| texture_sm_4_1;
alias atomic_glsl_float1 = GL_EXT_shader_atomic_float;
@@ -803,19 +807,19 @@ alias subgroup_basic_ballot = glsl + GL_KHR_shader_subgroup_basic + subgroup_bal
alias subgroup_vote = GL_KHR_shader_subgroup_vote | _sm_6_0 | _cuda_sm_7_0;
alias shaderinvocationgroup = subgroup_vote;
alias subgroup_arithmetic = GL_KHR_shader_subgroup_arithmetic | _sm_6_0 | _cuda_sm_7_0;
-alias subgroup_shuffle = glsl + GL_KHR_shader_subgroup_shuffle | _sm_6_0 | _cuda_sm_7_0;
+alias subgroup_shuffle = GL_KHR_shader_subgroup_shuffle | _sm_6_0 | _cuda_sm_7_0;
alias subgroup_shufflerelative = GL_KHR_shader_subgroup_shuffle_relative | _sm_6_0 | _cuda_sm_7_0;
alias subgroup_clustered = GL_KHR_shader_subgroup_clustered | _sm_6_0 | _cuda_sm_7_0;
alias subgroup_quad = GL_KHR_shader_subgroup_quad | _sm_6_0 | _cuda_sm_7_0;
-alias subgroup_partitioned = GL_NV_shader_subgroup_partitioned + subgroup_ballot_activemask | _sm_6_5;
+alias subgroup_partitioned = GL_NV_shader_subgroup_partitioned + subgroup_ballot_activemask | _sm_6_5 | _cuda_sm_7_0;
alias atomic_glsl_hlsl_nvapi_cuda_float1 = atomic_glsl_float1 | hlsl_nvapi + _sm_4_0 | _cuda_sm_2_0;
alias atomic_glsl_hlsl_nvapi_cuda5_int64 = atomic_glsl_int64 | hlsl_nvapi + _sm_4_0 | _cuda_sm_6_0;
alias atomic_glsl_hlsl_nvapi_cuda6_int64 = atomic_glsl_int64 | hlsl_nvapi + _sm_4_0 | _cuda_sm_6_0;
alias atomic_glsl_hlsl_nvapi_cuda9_int64 = atomic_glsl_int64 | hlsl_nvapi + _sm_4_0 | _cuda_sm_9_0;
-alias atomic_glsl_hlsl_cuda = atomic_glsl | _sm_5_0 | _cuda_sm_2_0;
-alias atomic_glsl_hlsl_cuda9_int64 = atomic_glsl_int64 | _sm_6_6 | _cuda_sm_9_0;
+alias atomic_glsl_hlsl_cuda = atomic_glsl | _sm_5_0 | _cuda_sm_2_0 | metal;
+alias atomic_glsl_hlsl_cuda9_int64 = atomic_glsl_int64 | _sm_6_6 | _cuda_sm_9_0 | metal;
alias helper_lane = _sm_6_0 + fragment
| GL_EXT_demote_to_helper_invocation + fragment
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 74d08f8e5..c3074bc55 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -10095,6 +10095,11 @@ namespace Slang
}
}
+ static void _propagateSeeDefinitionOf(SemanticsVisitor* visitor, Decl* funcDecl, DiagnosticCategory diagnosticCategory)
+ {
+ maybeDiagnose(visitor->getSink(), visitor->getOptionSet(), diagnosticCategory, funcDecl, Diagnostics::seeDefinitionOf, funcDecl);
+ }
+
static void _propagateRequirement(SemanticsVisitor* visitor, CapabilitySet& resultCaps, SyntaxNode* userNode, SyntaxNode* referencedNode, const CapabilitySet& nodeCaps, SourceLoc referenceLoc)
{
auto referencedDecl = as<Decl>(referencedNode);
@@ -10178,20 +10183,22 @@ namespace Slang
CapabilitySet getStatementCapabilityUsage(SemanticsVisitor* visitor, Stmt* stmt);
- template<typename ProcessFunc>
+ template<typename ProcessFunc, typename ParentDiagnosticFunc>
struct CapabilityDeclReferenceVisitor
- : public SemanticsDeclReferenceVisitor<CapabilityDeclReferenceVisitor<ProcessFunc>>
+ : public SemanticsDeclReferenceVisitor<CapabilityDeclReferenceVisitor<ProcessFunc, ParentDiagnosticFunc>>
{
- typedef SemanticsDeclReferenceVisitor<CapabilityDeclReferenceVisitor<ProcessFunc>> Base;
+ typedef SemanticsDeclReferenceVisitor<CapabilityDeclReferenceVisitor<ProcessFunc, ParentDiagnosticFunc>> Base;
- const ProcessFunc& handleReferenceFunc;
+ const ProcessFunc handleProcessFunc;
+ const ParentDiagnosticFunc handleParentDiagnosticFunc;
RequireCapabilityAttribute* maybeRequireCapability;
SemanticsContext& outerContext;
- CapabilityDeclReferenceVisitor(const ProcessFunc& processFunc, RequireCapabilityAttribute* maybeRequireCapability, SemanticsContext& outer)
- : handleReferenceFunc(processFunc)
+ CapabilityDeclReferenceVisitor(const ProcessFunc& processFunc, const ParentDiagnosticFunc& parentDiagnosticFunc, RequireCapabilityAttribute* maybeRequireCapability, SemanticsContext& outer)
+ : handleProcessFunc(processFunc)
+ , handleParentDiagnosticFunc(parentDiagnosticFunc)
, maybeRequireCapability(maybeRequireCapability)
, outerContext(outer)
- , SemanticsDeclReferenceVisitor<CapabilityDeclReferenceVisitor<ProcessFunc>>(outer)
+ , SemanticsDeclReferenceVisitor<CapabilityDeclReferenceVisitor<ProcessFunc, ParentDiagnosticFunc>>(outer)
{
}
virtual void processReferencedDecl(Decl* decl) override
@@ -10199,16 +10206,16 @@ namespace Slang
SourceLoc loc = SourceLoc();
if (Base::sourceLocStack.getCount())
loc = Base::sourceLocStack.getLast();
- handleReferenceFunc(decl, decl->inferredCapabilityRequirements, loc);
+ handleProcessFunc(decl, decl->inferredCapabilityRequirements, loc);
}
virtual void processDeclModifiers(Decl* decl) override
{
if (decl)
- handleReferenceFunc(decl, decl->inferredCapabilityRequirements, decl->loc);
+ handleProcessFunc(decl, decl->inferredCapabilityRequirements, decl->loc);
}
void visitDiscardStmt(DiscardStmt* stmt)
{
- handleReferenceFunc(stmt, CapabilitySet(CapabilityName::fragment), stmt->loc);
+ handleProcessFunc(stmt, CapabilitySet(CapabilityName::fragment), stmt->loc);
}
void visitTargetSwitchStmt(TargetSwitchStmt* stmt)
{
@@ -10247,6 +10254,19 @@ namespace Slang
else
{
targetCap = CapabilitySet(CapabilityName(stmt->targetCases[targetCaseIndex]->capability));
+
+ if (maybeRequireCapability)
+ {
+ CapabilitySet testingForInvalid = maybeRequireCapability->capabilitySet;
+ // Ensure case statement is valid with parent `[require(...)]`
+ testingForInvalid.join(targetCap);
+ if (testingForInvalid.isInvalid())
+ {
+ maybeDiagnose(Base::getSink(), outerContext.getOptionSet(), DiagnosticCategory::Capability, stmt->targetCases[targetCaseIndex]->loc,
+ Diagnostics::conflictingCapabilityDueToStatement, targetCap, maybeRequireCapability, maybeRequireCapability->capabilitySet);
+ handleParentDiagnosticFunc(DiagnosticCategory::Capability);
+ }
+ }
}
auto targetCase = stmt->targetCases[targetCaseIndex];
auto oldCap = targetCap;
@@ -10255,22 +10275,23 @@ namespace Slang
if (targetCap.isInvalid())
{
maybeDiagnose(Base::getSink(), outerContext.getOptionSet(), DiagnosticCategory::Capability, targetCase->body->loc, Diagnostics::conflictingCapabilityDueToStatement, bodyCap, "target_switch", oldCap);
+ handleParentDiagnosticFunc(DiagnosticCategory::Capability);
}
set.unionWith(targetCap);
}
- handleReferenceFunc(stmt, set, stmt->loc);
+ handleProcessFunc(stmt, set, stmt->loc);
}
void visitRequireCapabilityDecl(RequireCapabilityDecl* decl)
{
- handleReferenceFunc(decl, decl->inferredCapabilityRequirements, decl->loc);
+ handleProcessFunc(decl, decl->inferredCapabilityRequirements, decl->loc);
}
};
- template<typename ProcessFunc>
- void visitReferencedDecls(SemanticsContext& context, NodeBase* node, SourceLoc initialLoc, RequireCapabilityAttribute* maybeRequireCapability, const ProcessFunc& func)
+ template<typename ProcessFunc, typename ParentDiagnosticFunc>
+ void visitReferencedDecls(SemanticsContext& context, NodeBase* node, SourceLoc initialLoc, RequireCapabilityAttribute* maybeRequireCapability, const ProcessFunc& processFunc, const ParentDiagnosticFunc& parentDiagnosticFunc)
{
- CapabilityDeclReferenceVisitor<ProcessFunc> visitor(func, maybeRequireCapability, context);
+ CapabilityDeclReferenceVisitor<ProcessFunc, ParentDiagnosticFunc> visitor(processFunc, parentDiagnosticFunc, maybeRequireCapability, context);
visitor.sourceLocStack.add(initialLoc);
if (auto val = as<Val>(node))
@@ -10289,19 +10310,31 @@ namespace Slang
return CapabilitySet();
CapabilitySet inferredRequirements;
- visitReferencedDecls(*visitor, stmt, stmt->loc, nullptr, [&](SyntaxNode* node, const CapabilitySet& nodeCaps, SourceLoc refLoc)
- {
- _propagateRequirement(visitor, inferredRequirements, stmt, node, nodeCaps, refLoc);
- });
+ visitReferencedDecls(*visitor, stmt, stmt->loc, nullptr,
+ [&](SyntaxNode* node, const CapabilitySet& nodeCaps, SourceLoc refLoc)
+ {
+ _propagateRequirement(visitor, inferredRequirements, stmt, node, nodeCaps, refLoc);
+ },
+ [](DiagnosticCategory category)
+ {
+ SLANG_UNUSED(category);
+ }
+ );
return inferredRequirements;
}
void SemanticsDeclCapabilityVisitor::checkVarDeclCommon(VarDeclBase* varDecl)
{
- visitReferencedDecls(*this, varDecl->type.type, varDecl->loc, varDecl->findModifier<RequireCapabilityAttribute>(), [this, varDecl](SyntaxNode* node, const CapabilitySet& nodeCaps, SourceLoc refLoc)
- {
- _propagateRequirement(this, varDecl->inferredCapabilityRequirements, varDecl, node, nodeCaps, refLoc);
- });
+ visitReferencedDecls(*this, varDecl->type.type, varDecl->loc, varDecl->findModifier<RequireCapabilityAttribute>(),
+ [this, varDecl](SyntaxNode* node, const CapabilitySet& nodeCaps, SourceLoc refLoc)
+ {
+ _propagateRequirement(this, varDecl->inferredCapabilityRequirements, varDecl, node, nodeCaps, refLoc);
+ },
+ [this, varDecl](DiagnosticCategory category)
+ {
+ _propagateSeeDefinitionOf(this, varDecl, category);
+ }
+ );
}
CapabilitySet SemanticsDeclCapabilityVisitor::getDeclaredCapabilitySet(Decl* decl)
@@ -10351,8 +10384,8 @@ namespace Slang
decl->inferredCapabilityRequirements = getDeclaredCapabilitySet(decl);
}
- template<typename ProcessFunc>
- static inline void _dispatchCapabilitiesVisitorOfFunctionDecl(SemanticsVisitor* visitor, FunctionDeclBase* funcDecl, ProcessFunc propegateFuncForReferences)
+ template<typename ProcessFunc, typename ParentDiagnosticFunc>
+ static inline void _dispatchCapabilitiesVisitorOfFunctionDecl(SemanticsVisitor* visitor, FunctionDeclBase* funcDecl, const ProcessFunc& processFunc, const ParentDiagnosticFunc& parentDiagnosticFunc)
{
visitor->setParentFuncOfVisitor(funcDecl);
@@ -10362,7 +10395,7 @@ namespace Slang
_propagateRequirement(visitor, funcDecl->inferredCapabilityRequirements, funcDecl, member, member->inferredCapabilityRequirements, member->loc);
}
- visitReferencedDecls(*visitor, funcDecl->body, funcDecl->loc, funcDecl->findModifier<RequireCapabilityAttribute>(), propegateFuncForReferences);
+ visitReferencedDecls(*visitor, funcDecl->body, funcDecl->loc, funcDecl->findModifier<RequireCapabilityAttribute>(), processFunc, parentDiagnosticFunc);
if (!isEffectivelyStatic(funcDecl))
{
@@ -10378,10 +10411,15 @@ namespace Slang
void SemanticsDeclCapabilityVisitor::visitFunctionDeclBase(FunctionDeclBase* funcDecl)
{
_dispatchCapabilitiesVisitorOfFunctionDecl(this, funcDecl,
- [this, funcDecl](SyntaxNode* node, const CapabilitySet& nodeCaps, SourceLoc refLoc)
- {
- _propagateRequirement(this, funcDecl->inferredCapabilityRequirements, funcDecl, node, nodeCaps, refLoc);
- });
+ [this, funcDecl](SyntaxNode* node, const CapabilitySet& nodeCaps, SourceLoc refLoc)
+ {
+ _propagateRequirement(this, funcDecl->inferredCapabilityRequirements, funcDecl, node, nodeCaps, refLoc);
+ },
+ [this, funcDecl](DiagnosticCategory category)
+ {
+ _propagateSeeDefinitionOf(this, funcDecl, category);
+ }
+ );
auto declaredCaps = getDeclaredCapabilitySet(funcDecl);
diff --git a/source/slang/slang-check-modifier.cpp b/source/slang/slang-check-modifier.cpp
index 7721fedbf..e91d2e45b 100644
--- a/source/slang/slang-check-modifier.cpp
+++ b/source/slang/slang-check-modifier.cpp
@@ -932,6 +932,8 @@ namespace Slang
}
}
requireCapAttr->capabilitySet = CapabilitySet(capabilityNames);
+ if (requireCapAttr->capabilitySet.isInvalid())
+ maybeDiagnose(getSink(), this->getOptionSet(), DiagnosticCategory::Capability, attr, Diagnostics::unexpectedCapability, attr, CapabilityName::Invalid);
}
else if (auto requirePreludeAttr = as<RequirePreludeAttribute>(attr))
{
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index cb994b904..496fb7e32 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -391,6 +391,7 @@ DIAGNOSTIC(36107, Error, entryPointUsesUnavailableCapability, "entrypoint '$0' r
DIAGNOSTIC(36108, Error, declHasDependenciesNotCompatibleOnTarget, "'$0' has dependencies that are not compatible on the required target '$1'.")
DIAGNOSTIC(36109, Error, invalidTargetSwitchCase, "'$0' cannot be used as a target_switch case.")
DIAGNOSTIC(36110, Error, stageIsInCompatibleWithCapabilityDefinition, "'$0' is defined for stage '$1', which is incompatible with the declared capability set '$2'.")
+DIAGNOSTIC(36111, Error, unexpectedCapability, "'$0' resolves into a disallowed `$1` Capability.")
// Attributes
DIAGNOSTIC(31000, Warning, unknownAttributeName, "unknown attribute '$0'")
diff --git a/source/slang/slang-stdlib-textures.cpp b/source/slang/slang-stdlib-textures.cpp
index 380ed1677..dd4df7d9c 100644
--- a/source/slang/slang-stdlib-textures.cpp
+++ b/source/slang/slang-stdlib-textures.cpp
@@ -453,7 +453,7 @@ void TextureTypeInfo::writeGetDimensionFunctions()
sb << " __glsl_version(450)\n";
sb << " __glsl_extension(GL_EXT_samplerless_texture_functions)\n";
- sb << " [require(glsl_hlsl_metal_spirv, texture_sm_4_1)]\n";
+ sb << " [require(cpp_glsl_hlsl_metal_spirv, texture_sm_4_1)]\n";
writeFunc(
"void",
"GetDimensions",