完整指南:語法、隱式解引用與 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 展開系統(tǒng)講解 Slang 著色語言中通過.、::、-訪問命名空間、類型與值成員的全部規(guī)則。你將掌握成員訪問表達式的文法與四種求值分支、指針類類型如ConstantBufferT的隱式解引用行為、向量與矩陣 swizzle 的構(gòu)成約束與左值規(guī)則以及靜態(tài)成員表達式的用法并深入看到這些規(guī)則在source/slang編譯器源碼中的解析parser與語義檢查semantic check實現(xiàn)。一、成員訪問表達式的語法與語義總覽成員訪問表達式member access expression用于從命名空間namespace、類型type或值表達式value expression中選取一個成員。其核心語法由四種形態(tài)構(gòu)成namespace-identifier (. | ::) member-identifier type-expr (. | ::) member-identifier value-expr . member-identifier pointer-value-expr - member-identifier第一行左操作數(shù)是命名空間標識符表達式構(gòu)成在該命名空間內(nèi)的限定查找qualified lookup被選中的成員可以是任意命名空間成員——包括值、類型甚至是嵌套的命名空間。詳見 basics-name-lookup.md。第二行左操作數(shù)是類型表達式表達式構(gòu)成該類型內(nèi)的靜態(tài)成員查找static member lookup具體規(guī)則可參考 types-enum.md、types-struct.md 與 basics-name-lookup.md。第三行左操作數(shù)是值行為取決于該值的具體類型見下一節(jié)。第四行左操作數(shù)是指針值通過-完成解引用后取成員見“隱式解引用”一節(jié)。從編譯器實現(xiàn)看成員訪問相關節(jié)點在 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 起在循環(huán)中依次處理后綴運算符[]生成IndexExprL9251-L9275、(x)生成InvokeExprL9278-L9302、::生成StaticMemberExprL9305-L9323、.與-分別生成MemberExpr與DerefMemberExprL9325-L9340從而支持a.b.c、a[i].m等任意深度的鏈式訪問。二、左操作數(shù)為值時的成員訪問規(guī)則當左操作數(shù)是一個值時成員訪問的表達含義按值類型分情況處理標量、向量、矩陣或元組tuple值成員訪問表達式是swizzle 表達式即按分量名直接選取、重組元素。詳見下文“向量 Swizzle”與“矩陣 Swizzle”兩節(jié)。結(jié)構(gòu)體struct值若member-identifier命名的是成員字段或函數(shù)則表達式是該成員的值表達式且保持與基表達式一致的值類別value category——即基表達式是左值l-value時字段訪問也是左值有關值類別的背景可參考 expressions-value-categories.md。若member-identifier命名的是屬性property則根據(jù)表達式是“讀取”還是“賦值”該屬性分別翻譯為屬性的get或set訪問器調(diào)用。結(jié)構(gòu)體字段/方法與屬性訪問的具體類型布局與成員聲明規(guī)則見 types-struct.md。三、隱式解引用Implicit Dereference當成員引用的基表達式是一個指針類類型pointer-like type例如ConstantBufferT時成員引用表達式會對基表達式執(zhí)行隱式解引用從而訪問被指向的值。以ConstantBufferT為例解引用后訪問的就是該緩沖區(qū)內(nèi)類型為T的內(nèi)容。因此在 Slang 中你可以直接寫出ConstantBufferLight lightBuffer; float3 color lightBuffer.diffuseColor; // 無需顯式解引用這背后的實現(xiàn)事實是指針類類型通過標準庫中的__implicit_conversion聲明了對底層元素的隱式轉(zhuǎn)換。例如 source/slang/core.meta.slangL852、L1924 附近以及 source/slang/hlsl.meta.slangL27731 起多處都使用了__implicit_conversion($(kConversionCost_ImplicitDereference))而轉(zhuǎn)換代價常量kConversionCost_ImplicitDereference 10定義于 source/slang/slang-ast-support-types.hL107。語義檢查階段通過getPointedToTypeIfCanImplicitDeref聲明于 source/slang/slang-check-impl.h L69實現(xiàn)于 source/slang/slang-check-expr.cpp L714、L8282 等處判斷基表達式是否可隱式解引用再據(jù)此解析成員訪問相關的轉(zhuǎn)換代價累加邏輯位于 source/slang/slang-check-conversion.cppL2436-L2498。對于顯式指針則使用箭頭運算符-x-m與(*x).m完全等價。由于它作用于指針-與指針解引用運算符*一樣處于相同的實驗性experimental狀態(tài)使用前需要留意對應的能力開關或目標支持情況。指針類型的完整介紹見 types-pointer.md。四、向量 SwizzleVector Swizzles當成員表達式的基表達式是向量類型vectorT,N時成員表達式就是向量 swizzle 表達式。成員名必須滿足以下約束名稱長度必須為1 到 4 個 ASCII 字符字符只能來自集合(x, y, z, w)或(r, g, b, a)它們分別對應元素下標(0, 1, 2, 3)每個字符對應的元素下標必須小于N即不能越界訪問向量中不存在的分量。結(jié)果的類型規(guī)則若 swizzle 名稱由單個字符構(gòu)成則表達式類型為T等價于對基向量使用相應下標的下標表達式subscript expression若 swizzle 名稱由M 個字符構(gòu)成則結(jié)果是vectorT,M由基向量中對應下標的元素按書寫順序構(gòu)造而成。左值規(guī)則當且僅當基表達式是左值且名稱中各字符對應的下標無重復時向量 swizzle 表達式是左值。換言之v.xy可以出現(xiàn)在賦值左側(cè)而v.xx這類含重復分量的 swizzle 只能作為右值讀取。源碼中的校驗實現(xiàn)語義檢查階段的CheckSwizzleExprsource/slang/slang-check-expr.cpp L8537-L8645完整實現(xiàn)了上述規(guī)則逐字符讀取 swizzle 文本將x/r映射為 0、y/g映射為 1、z/b映射為 2、w/a映射為 3L8555-L8572非法字符、越界下標elementIndex limitElement以及超過 4 個分量都會設置錯誤標志并返回nullptrL8573-L8611檢測重復下標并記錄L8597-L8602單分量時結(jié)果類型為標量baseElementTypeL8619-L8627多分量時構(gòu)造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 語義在代碼生成層是被統(tǒng)一保證的。五、矩陣 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左值規(guī)則當基表達式是左值且 swizzle不選取重復矩陣元素時矩陣 swizzle 表達式是左值。此外對矩陣 swizzle 左值進行常量下標索引constant-indexed subscript的結(jié)果也是左值這使m._12_21[0]這類寫法可用于賦值。源碼中的表示與下降AST 層面對應MatrixSwizzleExprsource/slang/slang-ast-expr.h L371-L379其中MatrixCoordL358-L369以零基的行、列row、col記錄每個被選元素elementCoords[4]最多容納 4 個分量elementCount記錄實際分量數(shù)。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等。六、靜態(tài)成員表達式Static Member Expressions當成員表達式的基表達式是類型而非值時結(jié)果是靜態(tài)成員表達式static member expression。它可以引用結(jié)構(gòu)體類型的靜態(tài)字段static field或靜態(tài)方法static method枚舉類型的枚舉成員case。靜態(tài)成員表達式區(qū)別于一般成員表達式允許使用::代替.來分隔基類型與成員名// 以下兩種寫法完全等價 Color.Red Color::Red需要強調(diào)::只能用于靜態(tài)成員表達式以及命名空間限定查找普通值成員訪問不能使用::。枚舉與結(jié)構(gòu)體的靜態(tài)成員聲明方式見 types-enum.md 與 types-struct.md。實現(xiàn)層面StaticMemberExpr在 source/slang/slang-ast-expr.h L350-L356 定義解析時由parsePostfixExpr在遇到TokenType::Scope即::時構(gòu)造source/slang/slang-parser.cpp L9305-L9323。七、下標運算符與成員訪問運算符原文檔為這兩個運算符保留了獨立小節(jié)但內(nèi)容仍標記為 TODO下標運算符[]TODO。成員訪問運算符.TODO。盡管文檔尚未展開從編譯器現(xiàn)狀看這兩者都已具備完整實現(xiàn)[]在解析層生成IndexExprsource/slang/slang-ast-expr.h L323-L332支持多下標、記錄括號與逗號位置供語言服務使用解析見 source/slang/slang-parser.cpp L9251-L9275語義檢查與代碼生成中由CheckIndexExpr等路徑處理.即本文通篇討論的MemberExpr。需要了解運算符優(yōu)先級與結(jié)合性的讀者可參考 expressions-operator-precedence.md后綴.、::、-、[]屬于最高優(yōu)先級的一類。八、小結(jié)與速查基表達式運算符表達式含義左值條件命名空間標識符./::命名空間限定查找值/類型/嵌套命名空間依成員而定類型表達式./::靜態(tài)成員查找靜態(tài)字段/方法、枚舉 case依成員而定標量/向量/矩陣/元組值.swizzle 表達式基表達式為左值且無重復分量結(jié)構(gòu)體值.字段/函數(shù)成員或?qū)傩詆et/set保持基表達式值類別指針類類型如ConstantBufferT.隱式解引用后訪問成員保持基表達式值類別顯式指針-(*x).m與指針解引用同處實驗狀態(tài)保持基表達式值類別成員訪問表達式是 Slang 語言中連接命名空間、類型系統(tǒng)與值語義的關鍵樞紐它的四種語法形態(tài)分別對應限定查找、靜態(tài)查找、swizzle 重組與解引用訪問其完整規(guī)則既反映在 expressions-member-access.md 的規(guī)范描述中也精確落實于 source/slang/slang-ast-expr.h、source/slang/slang-parser.cpp 與 source/slang/slang-check-expr.cpp 的編譯器實現(xiàn)里并有tests/language-feature/swizzles下的多后端測試作為行為保證?!久赓M下載鏈接】slangMaking it easier to work with shaders項目地址: https://gitcode.com/GitHub_Trending/sl/slang創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考