diff --git a/src/intrinsics.def b/src/intrinsics.def index 40a9d885b3..d63d72a173 100644 --- a/src/intrinsics.def +++ b/src/intrinsics.def @@ -281,18 +281,18 @@ fn determinant(mat) -> f32 fn distance(f32, f32) -> f32 fn distance(vec, vec) -> f32 fn dot(vec, vec) -> f32 -fn dpdx(f32) -> f32 -fn dpdx(vec) -> vec -fn dpdxCoarse(f32) -> f32 -fn dpdxCoarse(vec) -> vec -fn dpdxFine(f32) -> f32 -fn dpdxFine(vec) -> vec -fn dpdy(f32) -> f32 -fn dpdy(vec) -> vec -fn dpdyCoarse(f32) -> f32 -fn dpdyCoarse(vec) -> vec -fn dpdyFine(f32) -> f32 -fn dpdyFine(vec) -> vec +[[stage("fragment")]] fn dpdx(f32) -> f32 +[[stage("fragment")]] fn dpdx(vec) -> vec +[[stage("fragment")]] fn dpdxCoarse(f32) -> f32 +[[stage("fragment")]] fn dpdxCoarse(vec) -> vec +[[stage("fragment")]] fn dpdxFine(f32) -> f32 +[[stage("fragment")]] fn dpdxFine(vec) -> vec +[[stage("fragment")]] fn dpdy(f32) -> f32 +[[stage("fragment")]] fn dpdy(vec) -> vec +[[stage("fragment")]] fn dpdyCoarse(f32) -> f32 +[[stage("fragment")]] fn dpdyCoarse(vec) -> vec +[[stage("fragment")]] fn dpdyFine(f32) -> f32 +[[stage("fragment")]] fn dpdyFine(vec) -> vec fn exp(f32) -> f32 fn exp(vec) -> vec fn exp2(f32) -> f32 @@ -367,7 +367,7 @@ fn sqrt(f32) -> f32 fn sqrt(vec) -> vec fn step(f32, f32) -> f32 fn step(vec, vec) -> vec -fn storageBarrier() +[[stage("compute")]] fn storageBarrier() fn tan(f32) -> f32 fn tan(vec) -> vec fn tanh(f32) -> f32 @@ -379,7 +379,7 @@ fn unpack2x16snorm(u32) -> vec2 fn unpack2x16unorm(u32) -> vec2 fn unpack4x8snorm(u32) -> vec4 fn unpack4x8unorm(u32) -> vec4 -fn workgroupBarrier() +[[stage("compute")]] fn workgroupBarrier() fn textureDimensions(texture: texture_1d) -> i32 fn textureDimensions(texture: texture_2d) -> vec2 fn textureDimensions(texture: texture_2d, level: i32) -> vec2 @@ -420,36 +420,36 @@ fn textureNumLevels(texture: texture_depth_2d_array) -> i32 fn textureNumLevels(texture: texture_depth_cube) -> i32 fn textureNumLevels(texture: texture_depth_cube_array) -> i32 fn textureNumSamples(texture: texture_multisampled_2d) -> i32 -fn textureSample(texture: texture_1d, sampler: sampler, coords: f32) -> vec4 -fn textureSample(texture: texture_2d, sampler: sampler, coords: vec2) -> vec4 -fn textureSample(texture: texture_2d, sampler: sampler, coords: vec2, offset: vec2) -> vec4 -fn textureSample(texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: i32) -> vec4 -fn textureSample(texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: i32, offset: vec2) -> vec4 -fn textureSample(texture: texture_3d, sampler: sampler, coords: vec3) -> vec4 -fn textureSample(texture: texture_3d, sampler: sampler, coords: vec3, offset: vec3) -> vec4 -fn textureSample(texture: texture_cube, sampler: sampler, coords: vec3) -> vec4 -fn textureSample(texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: i32) -> vec4 -fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2) -> f32 -fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2, offset: vec2) -> f32 -fn textureSample(texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: i32) -> f32 -fn textureSample(texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: i32, offset: vec2) -> f32 -fn textureSample(texture: texture_depth_cube, sampler: sampler, coords: vec3) -> f32 -fn textureSample(texture: texture_depth_cube_array, sampler: sampler, coords: vec3, array_index: i32) -> f32 -fn textureSample(texture: texture_external, sampler: sampler, coords: vec2) -> vec4 -fn textureSampleBias(texture: texture_2d, sampler: sampler, coords: vec2, bias: f32) -> vec4 -fn textureSampleBias(texture: texture_2d, sampler: sampler, coords: vec2, bias: f32, offset: vec2) -> vec4 -fn textureSampleBias(texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: i32, bias: f32) -> vec4 -fn textureSampleBias(texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: i32, bias: f32, offset: vec2) -> vec4 -fn textureSampleBias(texture: texture_3d, sampler: sampler, coords: vec3, bias: f32) -> vec4 -fn textureSampleBias(texture: texture_3d, sampler: sampler, coords: vec3, bias: f32, offset: vec3) -> vec4 -fn textureSampleBias(texture: texture_cube, sampler: sampler, coords: vec3, bias: f32) -> vec4 -fn textureSampleBias(texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: i32, bias: f32) -> vec4 -fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32) -> f32 -fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32, offset: vec2) -> f32 -fn textureSampleCompare(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: i32, depth_ref: f32) -> f32 -fn textureSampleCompare(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: i32, depth_ref: f32, offset: vec2) -> f32 -fn textureSampleCompare(texture: texture_depth_cube, sampler: sampler_comparison, coords: vec3, depth_ref: f32) -> f32 -fn textureSampleCompare(texture: texture_depth_cube_array, sampler: sampler_comparison, coords: vec3, array_index: i32, depth_ref: f32) -> f32 +[[stage("fragment")]] fn textureSample(texture: texture_1d, sampler: sampler, coords: f32) -> vec4 +[[stage("fragment")]] fn textureSample(texture: texture_2d, sampler: sampler, coords: vec2) -> vec4 +[[stage("fragment")]] fn textureSample(texture: texture_2d, sampler: sampler, coords: vec2, offset: vec2) -> vec4 +[[stage("fragment")]] fn textureSample(texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: i32) -> vec4 +[[stage("fragment")]] fn textureSample(texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: i32, offset: vec2) -> vec4 +[[stage("fragment")]] fn textureSample(texture: texture_3d, sampler: sampler, coords: vec3) -> vec4 +[[stage("fragment")]] fn textureSample(texture: texture_3d, sampler: sampler, coords: vec3, offset: vec3) -> vec4 +[[stage("fragment")]] fn textureSample(texture: texture_cube, sampler: sampler, coords: vec3) -> vec4 +[[stage("fragment")]] fn textureSample(texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: i32) -> vec4 +[[stage("fragment")]] fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2) -> f32 +[[stage("fragment")]] fn textureSample(texture: texture_depth_2d, sampler: sampler, coords: vec2, offset: vec2) -> f32 +[[stage("fragment")]] fn textureSample(texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: i32) -> f32 +[[stage("fragment")]] fn textureSample(texture: texture_depth_2d_array, sampler: sampler, coords: vec2, array_index: i32, offset: vec2) -> f32 +[[stage("fragment")]] fn textureSample(texture: texture_depth_cube, sampler: sampler, coords: vec3) -> f32 +[[stage("fragment")]] fn textureSample(texture: texture_depth_cube_array, sampler: sampler, coords: vec3, array_index: i32) -> f32 +[[stage("fragment")]] fn textureSample(texture: texture_external, sampler: sampler, coords: vec2) -> vec4 +[[stage("fragment")]] fn textureSampleBias(texture: texture_2d, sampler: sampler, coords: vec2, bias: f32) -> vec4 +[[stage("fragment")]] fn textureSampleBias(texture: texture_2d, sampler: sampler, coords: vec2, bias: f32, offset: vec2) -> vec4 +[[stage("fragment")]] fn textureSampleBias(texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: i32, bias: f32) -> vec4 +[[stage("fragment")]] fn textureSampleBias(texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: i32, bias: f32, offset: vec2) -> vec4 +[[stage("fragment")]] fn textureSampleBias(texture: texture_3d, sampler: sampler, coords: vec3, bias: f32) -> vec4 +[[stage("fragment")]] fn textureSampleBias(texture: texture_3d, sampler: sampler, coords: vec3, bias: f32, offset: vec3) -> vec4 +[[stage("fragment")]] fn textureSampleBias(texture: texture_cube, sampler: sampler, coords: vec3, bias: f32) -> vec4 +[[stage("fragment")]] fn textureSampleBias(texture: texture_cube_array, sampler: sampler, coords: vec3, array_index: i32, bias: f32) -> vec4 +[[stage("fragment")]] fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32) -> f32 +[[stage("fragment")]] fn textureSampleCompare(texture: texture_depth_2d, sampler: sampler_comparison, coords: vec2, depth_ref: f32, offset: vec2) -> f32 +[[stage("fragment")]] fn textureSampleCompare(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: i32, depth_ref: f32) -> f32 +[[stage("fragment")]] fn textureSampleCompare(texture: texture_depth_2d_array, sampler: sampler_comparison, coords: vec2, array_index: i32, depth_ref: f32, offset: vec2) -> f32 +[[stage("fragment")]] fn textureSampleCompare(texture: texture_depth_cube, sampler: sampler_comparison, coords: vec3, depth_ref: f32) -> f32 +[[stage("fragment")]] fn textureSampleCompare(texture: texture_depth_cube_array, sampler: sampler_comparison, coords: vec3, array_index: i32, depth_ref: f32) -> f32 fn textureSampleGrad(texture: texture_2d, sampler: sampler, coords: vec2, ddx: vec2, ddy: vec2) -> vec4 fn textureSampleGrad(texture: texture_2d, sampler: sampler, coords: vec2, ddx: vec2, ddy: vec2, offset: vec2) -> vec4 fn textureSampleGrad(texture: texture_2d_array, sampler: sampler, coords: vec2, array_index: i32, ddx: vec2, ddy: vec2) -> vec4 diff --git a/tools/src/cmd/intrinsic-gen/ast/ast.go b/tools/src/cmd/intrinsic-gen/ast/ast.go index e7000f34ce..8d1da0e2bd 100644 --- a/tools/src/cmd/intrinsic-gen/ast/ast.go +++ b/tools/src/cmd/intrinsic-gen/ast/ast.go @@ -102,6 +102,7 @@ func (m MatcherDecl) Format(w fmt.State, verb rune) { type FunctionDecl struct { Source tok.Source Name string + Decorations Decorations TemplateParams TemplateParams Parameters Parameters ReturnType *TemplatedName diff --git a/tools/src/cmd/intrinsic-gen/parser/parser.go b/tools/src/cmd/intrinsic-gen/parser/parser.go index 84343059ad..4ab35167c1 100644 --- a/tools/src/cmd/intrinsic-gen/parser/parser.go +++ b/tools/src/cmd/intrinsic-gen/parser/parser.go @@ -43,20 +43,31 @@ type parser struct { func (p *parser) parse() (*ast.AST, error) { out := ast.AST{} + var decorations ast.Decorations for p.err == nil { t := p.peek(0) if t == nil { break } switch t.Kind { + case tok.Ldeco: + decorations = append(decorations, p.decorations()...) case tok.Enum: + if len(decorations) > 0 { + p.err = fmt.Errorf("%v unexpected decoration", decorations[0].Source) + } out.Enums = append(out.Enums, p.enumDecl()) case tok.Match: + if len(decorations) > 0 { + p.err = fmt.Errorf("%v unexpected decoration", decorations[0].Source) + } out.Matchers = append(out.Matchers, p.matcherDecl()) - case tok.Type, tok.Ldeco: - out.Types = append(out.Types, p.typeDecl()) + case tok.Type: + out.Types = append(out.Types, p.typeDecl(decorations)) + decorations = nil case tok.Function: - out.Functions = append(out.Functions, p.functionDecl()) + out.Functions = append(out.Functions, p.functionDecl(decorations)) + decorations = nil default: p.err = fmt.Errorf("%v unexpected token '%v'", t.Source, t.Kind) } @@ -98,8 +109,7 @@ func (p *parser) matcherDecl() ast.MatcherDecl { return m } -func (p *parser) typeDecl() ast.TypeDecl { - decos := p.decorations() +func (p *parser) typeDecl(decos ast.Decorations) ast.TypeDecl { p.expect(tok.Type, "type declaration") name := p.expect(tok.Identifier, "type name") m := ast.TypeDecl{ @@ -143,10 +153,14 @@ func (p *parser) decorations() ast.Decorations { return out } -func (p *parser) functionDecl() ast.FunctionDecl { +func (p *parser) functionDecl(decos ast.Decorations) ast.FunctionDecl { p.expect(tok.Function, "function declaration") name := p.expect(tok.Identifier, "function name") - f := ast.FunctionDecl{Source: name.Source, Name: string(name.Runes)} + f := ast.FunctionDecl{ + Source: name.Source, + Decorations: decos, + Name: string(name.Runes), + } if p.peekIs(0, tok.Lt) { f.TemplateParams = p.templateParams() } diff --git a/tools/src/cmd/intrinsic-gen/parser/parser_test.go b/tools/src/cmd/intrinsic-gen/parser/parser_test.go index 774dc0d629..fdc884bcf6 100644 --- a/tools/src/cmd/intrinsic-gen/parser/parser_test.go +++ b/tools/src/cmd/intrinsic-gen/parser/parser_test.go @@ -95,6 +95,14 @@ func TestParser(t *testing.T) { Name: "F", }}, }}, + {"[[deco]] fn F()", ast.AST{ + Functions: []ast.FunctionDecl{{ + Name: "F", + Decorations: ast.Decorations{ + {Name: "deco"}, + }, + }}, + }}, {"fn F(a)", ast.AST{ Functions: []ast.FunctionDecl{{ Name: "F", diff --git a/tools/src/cmd/intrinsic-gen/resolver/resolve.go b/tools/src/cmd/intrinsic-gen/resolver/resolve.go index 0f1a1e93e7..4f76f31fec 100644 --- a/tools/src/cmd/intrinsic-gen/resolver/resolve.go +++ b/tools/src/cmd/intrinsic-gen/resolver/resolve.go @@ -243,13 +243,43 @@ func (r *resolver) function(a ast.FunctionDecl) error { return err } - // Construct the semantic overload and append it to the function + // Construct the semantic overload overload := &sem.Overload{ Decl: a, Function: f, Parameters: make([]sem.Parameter, len(a.Parameters)), TemplateParams: templateParams, } + + // Process overload decorations + if stageDeco := a.Decorations.Take("stage"); stageDeco != nil { + for stageDeco != nil { + for _, stage := range stageDeco.Values { + switch stage { + case "vertex": + overload.CanBeUsedInStage.Vertex = true + case "fragment": + overload.CanBeUsedInStage.Fragment = true + case "compute": + overload.CanBeUsedInStage.Compute = true + default: + return fmt.Errorf("%v unknown stage '%v'", stageDeco.Source, stage) + } + } + stageDeco = a.Decorations.Take("stage") + } + } else { + overload.CanBeUsedInStage = sem.StageUses{ + Vertex: true, + Fragment: true, + Compute: true, + } + } + if len(a.Decorations) != 0 { + return fmt.Errorf("%v unknown decoration", a.Decorations[0].Source) + } + + // Append the overload to the function f.Overloads = append(f.Overloads, overload) // Sort the template parameters by resolved type. Append these to diff --git a/tools/src/cmd/intrinsic-gen/sem/sem.go b/tools/src/cmd/intrinsic-gen/sem/sem.go index b7b49c5930..36548ae528 100644 --- a/tools/src/cmd/intrinsic-gen/sem/sem.go +++ b/tools/src/cmd/intrinsic-gen/sem/sem.go @@ -129,13 +129,21 @@ type Function struct { // Overload describes a single overload of a function type Overload struct { - Decl ast.FunctionDecl - Function *Function - TemplateParams []TemplateParam - OpenTypes []*TemplateTypeParam - OpenNumbers []TemplateParam - ReturnType *FullyQualifiedName - Parameters []Parameter + Decl ast.FunctionDecl + Function *Function + TemplateParams []TemplateParam + OpenTypes []*TemplateTypeParam + OpenNumbers []TemplateParam + ReturnType *FullyQualifiedName + Parameters []Parameter + CanBeUsedInStage StageUses +} + +// StageUses describes the stages an overload can be used in +type StageUses struct { + Vertex bool + Fragment bool + Compute bool } // Format implements the fmt.Formatter interface