ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Slang 成员访问表达式(Member Access Expression)完整指南:语法、隐式解引用与 Swizzle 机制

Slang 成员访问表达式(Member Access Expression)完整指南:语法、隐式解引用与 Swizzle 机制 Slang 成员访问表达式Member Access Expression完整指南语法、隐式解引用与 Swizzle 机制【免费下载链接】slangMaking it easier to work with shaders项目地址: https://gitcode.com/GitHub_Trending/sl/slang本指南基于 docs/language-reference/expressions-member-access.md 展开系统讲解 Slang 着色语言中通过.、::、-访问命名空间、类型与值成员的全部规则。你将掌握成员访问表达式的文法与四种求值分支、指针类类型如ConstantBufferT的隐式解引用行为、向量与矩阵 swizzle 的构成约束与左值规则以及静态成员表达式的用法并深入看到这些规则在source/slang编译器源码中的解析parser与语义检查semantic check实现。一、成员访问表达式的语法与语义总览成员访问表达式member access expression用于从命名空间namespace、类型type或值表达式value expression中选取一个成员。其核心语法由四种形态构成namespace-identifier (. | ::) member-identifier type-expr (. | ::) member-identifier value-expr . member-identifier pointer-value-expr - member-identifier第一行左操作数是命名空间标识符表达式构成在该命名空间内的限定查找qualified lookup被选中的成员可以是任意命名空间成员——包括值、类型甚至是嵌套的命名空间。详见 basics-name-lookup.md。第二行左操作数是类型表达式表达式构成该类型内的静态成员查找static member lookup具体规则可参考 types-enum.md、types-struct.md 与 basics-name-lookup.md。第三行左操作数是值行为取决于该值的具体类型见下一节。第四行左操作数是指针值通过-完成解引用后取成员见“隐式解引用”一节。从编译器实现看成员访问相关节点在 source/slang/slang-ast-expr.h 中有明确的 AST 对应MemberExprL335-L340通用成员访问x.m继承自DeclRefExpr携带baseExpression与memberOperatorLocDerefMemberExprL343-L347被解引用的成员表达式即a-bStaticMemberExprL350-L356作用于类型而非值的成员查找即T::m。在解析阶段source/slang/slang-parser.cpp 的parsePostfixExprL9226 起在循环中依次处理后缀运算符[]生成IndexExprL9251-L9275、(x)生成InvokeExprL9278-L9302、::生成StaticMemberExprL9305-L9323、.与-分别生成MemberExpr与DerefMemberExprL9325-L9340从而支持a.b.c、a[i].m等任意深度的链式访问。二、左操作数为值时的成员访问规则当左操作数是一个值时成员访问的表达含义按值类型分情况处理标量、向量、矩阵或元组tuple值成员访问表达式是swizzle 表达式即按分量名直接选取、重组元素。详见下文“向量 Swizzle”与“矩阵 Swizzle”两节。结构体struct值若member-identifier命名的是成员字段或函数则表达式是该成员的值表达式且保持与基表达式一致的值类别value category——即基表达式是左值l-value时字段访问也是左值有关值类别的背景可参考 expressions-value-categories.md。若member-identifier命名的是属性property则根据表达式是“读取”还是“赋值”该属性分别翻译为属性的get或set访问器调用。结构体字段/方法与属性访问的具体类型布局与成员声明规则见 types-struct.md。三、隐式解引用Implicit Dereference当成员引用的基表达式是一个指针类类型pointer-like type例如ConstantBufferT时成员引用表达式会对基表达式执行隐式解引用从而访问被指向的值。以ConstantBufferT为例解引用后访问的就是该缓冲区内类型为T的内容。因此在 Slang 中你可以直接写出ConstantBufferLight lightBuffer; float3 color lightBuffer.diffuseColor; // 无需显式解引用这背后的实现事实是指针类类型通过标准库中的__implicit_conversion声明了对底层元素的隐式转换。例如 source/slang/core.meta.slangL852、L1924 附近以及 source/slang/hlsl.meta.slangL27731 起多处都使用了__implicit_conversion($(kConversionCost_ImplicitDereference))而转换代价常量kConversionCost_ImplicitDereference 10定义于 source/slang/slang-ast-support-types.hL107。语义检查阶段通过getPointedToTypeIfCanImplicitDeref声明于 source/slang/slang-check-impl.h L69实现于 source/slang/slang-check-expr.cpp L714、L8282 等处判断基表达式是否可隐式解引用再据此解析成员访问相关的转换代价累加逻辑位于 source/slang/slang-check-conversion.cppL2436-L2498。对于显式指针则使用箭头运算符-x-m与(*x).m完全等价。由于它作用于指针-与指针解引用运算符*一样处于相同的实验性experimental状态使用前需要留意对应的能力开关或目标支持情况。指针类型的完整介绍见 types-pointer.md。四、向量 SwizzleVector Swizzles当成员表达式的基表达式是向量类型vectorT,N时成员表达式就是向量 swizzle 表达式。成员名必须满足以下约束名称长度必须为1 到 4 个 ASCII 字符字符只能来自集合(x, y, z, w)或(r, g, b, a)它们分别对应元素下标(0, 1, 2, 3)每个字符对应的元素下标必须小于N即不能越界访问向量中不存在的分量。结果的类型规则若 swizzle 名称由单个字符构成则表达式类型为T等价于对基向量使用相应下标的下标表达式subscript expression若 swizzle 名称由M 个字符构成则结果是vectorT,M由基向量中对应下标的元素按书写顺序构造而成。左值规则当且仅当基表达式是左值且名称中各字符对应的下标无重复时向量 swizzle 表达式是左值。换言之v.xy可以出现在赋值左侧而v.xx这类含重复分量的 swizzle 只能作为右值读取。源码中的校验实现语义检查阶段的CheckSwizzleExprsource/slang/slang-check-expr.cpp L8537-L8645完整实现了上述规则逐字符读取 swizzle 文本将x/r映射为 0、y/g映射为 1、z/b映射为 2、w/a映射为 3L8555-L8572非法字符、越界下标elementIndex limitElement以及超过 4 个分量都会设置错误标志并返回nullptrL8573-L8611检测重复下标并记录L8597-L8602单分量时结果类型为标量baseElementTypeL8619-L8627多分量时构造vectorT,ML8628-L8637左值判定为!anyDuplicates base 是左值L8641-L8642。实际测试位于 tests/language-feature/swizzles/vector-swizzle-write-swizzle.slang例如float4 a float4(0); a.zw.y 9.0; // 嵌套 swizzle 写入 a.xyzw.yx float2(1.0, 2.0); // 最终 a (2.0, 1.0, 0.0, 9.0)该测试同时覆盖了COMPARE_COMPUTE在 CPU、Vulkan-vk、Metal-mtl等多个后端上的行为一致性可见 swizzle 语义在代码生成层是被统一保证的。五、矩阵 SwizzleMatrix Swizzles当基表达式是矩阵类型时采用 HLSL 风格矩阵 swizzle 语法的成员表达式即为矩阵 swizzle 表达式。支持的书写形式包括零基zero-based_mij形式如_m00、_m12一基one-based简写如_41表示第 4 行第 1 列对应零基下标_m30多分量组合例如m._41_32同时选取两个元素组成新向量。示例来自 tests/language-feature/swizzles/matrix-swizzles.slangfloat2x2 worldMatrix float2x2(1, 2, 3, 4); float2 tempVector1 worldMatrix._m00_m11; // 取 (0,0) 与 (1,1) float2 tempVector2 worldMatrix._12_21; // 一基写法等价于 _m01 与 _m20左值规则当基表达式是左值且 swizzle不选取重复矩阵元素时矩阵 swizzle 表达式是左值。此外对矩阵 swizzle 左值进行常量下标索引constant-indexed subscript的结果也是左值这使m._12_21[0]这类写法可用于赋值。源码中的表示与下降AST 层面对应MatrixSwizzleExprsource/slang/slang-ast-expr.h L371-L379其中MatrixCoordL358-L369以零基的行、列row、col记录每个被选元素elementCoords[4]最多容纳 4 个分量elementCount记录实际分量数。IR 阶段还存在专门的slang-ir-lower-matrix-swizzle-store模块source/slang/slang-ir-lower-matrix-swizzle-store.cpp负责把矩阵 swizzle 的存储写入操作下降为逐元素写入相关测试见 tests/language-feature/swizzles 目录下的matrix-swizzle-write-single.slang、matrix-swizzle-write-swizzle.slang、matrix-swizzle-write-array.slang等。六、静态成员表达式Static Member Expressions当成员表达式的基表达式是类型而非值时结果是静态成员表达式static member expression。它可以引用结构体类型的静态字段static field或静态方法static method枚举类型的枚举成员case。静态成员表达式区别于一般成员表达式允许使用::代替.来分隔基类型与成员名// 以下两种写法完全等价 Color.Red Color::Red需要强调::只能用于静态成员表达式以及命名空间限定查找普通值成员访问不能使用::。枚举与结构体的静态成员声明方式见 types-enum.md 与 types-struct.md。实现层面StaticMemberExpr在 source/slang/slang-ast-expr.h L350-L356 定义解析时由parsePostfixExpr在遇到TokenType::Scope即::时构造source/slang/slang-parser.cpp L9305-L9323。七、下标运算符与成员访问运算符原文档为这两个运算符保留了独立小节但内容仍标记为 TODO下标运算符[]TODO。成员访问运算符.TODO。尽管文档尚未展开从编译器现状看这两者都已具备完整实现[]在解析层生成IndexExprsource/slang/slang-ast-expr.h L323-L332支持多下标、记录括号与逗号位置供语言服务使用解析见 source/slang/slang-parser.cpp L9251-L9275语义检查与代码生成中由CheckIndexExpr等路径处理.即本文通篇讨论的MemberExpr。需要了解运算符优先级与结合性的读者可参考 expressions-operator-precedence.md后缀.、::、-、[]属于最高优先级的一类。八、小结与速查基表达式运算符表达式含义左值条件命名空间标识符./::命名空间限定查找值/类型/嵌套命名空间依成员而定类型表达式./::静态成员查找静态字段/方法、枚举 case依成员而定标量/向量/矩阵/元组值.swizzle 表达式基表达式为左值且无重复分量结构体值.字段/函数成员或属性get/set保持基表达式值类别指针类类型如ConstantBufferT.隐式解引用后访问成员保持基表达式值类别显式指针-(*x).m与指针解引用同处实验状态保持基表达式值类别成员访问表达式是 Slang 语言中连接命名空间、类型系统与值语义的关键枢纽它的四种语法形态分别对应限定查找、静态查找、swizzle 重组与解引用访问其完整规则既反映在 expressions-member-access.md 的规范描述中也精确落实于 source/slang/slang-ast-expr.h、source/slang/slang-parser.cpp 与 source/slang/slang-check-expr.cpp 的编译器实现里并有tests/language-feature/swizzles下的多后端测试作为行为保证。【免费下载链接】slangMaking it easier to work with shaders项目地址: https://gitcode.com/GitHub_Trending/sl/slang创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表