// // Copyright 2024 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // #ifndef COMPILER_TRANSLATOR_WGSL_OUTPUT_UNIFORM_BLOCKS_H_ #define COMPILER_TRANSLATOR_WGSL_OUTPUT_UNIFORM_BLOCKS_H_ #include "compiler/translator/Common.h" #include "compiler/translator/Compiler.h" #include "compiler/translator/IntermNode.h" namespace sh { const char kDefaultUniformBlockVarType[] = "ANGLE_DefaultUniformBlock"; const char kDefaultUniformBlockVarName[] = "ANGLE_defaultUniformBlock"; enum WgslBindGroupNumbers : uint32_t { kDefaultUniformBlockBindGroup = 0, kTextureAndSamplerBindGroup = 1, kDriverUniformBindGroup = 2, kMaxBindGroup = 2 }; const uint32_t kDefaultVertexUniformBlockBinding = 0; const uint32_t kDefaultFragmentUniformBlockBinding = 1; const uint32_t kDriverUniformBlockBinding = 0; // The translator emits this dummy location, which needs to be replaced when linking the two // separate shader stages. const char kTextureSamplerBindingMarker[] = "@group(1) @binding(@@@@@@) var "; // The translator emits split samplers/textures for GLSL's combined textures/samplers (combined // textures/samplers are not supported by WGSL). The new variables are prefixed with these // constants, respectively. const char kAngleSamplerPrefix[] = "ANGLE_sampler_"; const char kAngleTexturePrefix[] = "ANGLE_texture_"; const char kWrappedStructFieldName[] = "elem"; struct UniformBlockMetadata { // A list of structs used anywhere in the uniform address space. These will require special // handling (@align() attributes, wrapping of basic types, etc.) to ensure they fit WGSL's // uniform layout requirements. // The key is TSymbolUniqueId::get(). TUnorderedSet structsInUniformAddressSpace; }; // Given a GLSL AST `root`, fills in `outMetadata`, to be used when outputting WGSL. // If the AST is manipulated after calling this, it may be out of sync with the data recorded in // `outMetadata`. bool RecordUniformBlockMetadata(TIntermBlock *root, UniformBlockMetadata &outMetadata); // Based on the GLSL, some extra WGSL will have to be generated so it can be referenced by // the WGSL generated by the traverser, This tracks exactly which WGSL snippets will need to be // generated, struct WGSLGenerationMetadataForUniforms { // Arrays must have a stride of at least 16 if used in the uniform address spaces. If the array // element type doesn't have an aligned size of a multiple of 16 (e.g. f32), the element type // must be wrapped in a struct which is then aligned to 16. Adding to // `arrayElementTypesInUniforms` will cause `OutputUniformWrapperStructsAndConversions` to // generate a WGSL wrapper struct of the form: // // struct ANGLE_wrapper_f32 { // @align(16) elem : f32; // }; TSet arrayElementTypesInUniforms; // If we need to convert arrays with wrapped element types into arrays with unwrapped element // types, the necessary conversions are listed here. TSet arrayElementTypesThatNeedUnwrappingConversions; // MatCx2 in a uniform will be represented as array to match std140 (WGSL // uniforms pack their matrices a bit tighter). These will have to be converted back to matCx2 // for all other purposes (e.g. multiplication). // If this set isn't empty, ANGLE_wrapped_vec2 will be generated even if it // hasn't been yet. TSet outputMatCx2Conversion; }; bool OutputUniformWrapperStructsAndConversions( TInfoSinkBase &output, const WGSLGenerationMetadataForUniforms &wgslGenerationMetadataForUniforms); bool IsMatCx2(const TType *type); ImmutableString MakeUnwrappingArrayConversionFunctionName(const TType *type); ImmutableString MakeMatCx2ConversionFunctionName(const TType *type); // Bools and bvecN are represented in WGSL's uniform address space with u32 and uvecN respectively. // This outputs the beginning of a conversion necessary to convert the bool or bvecN represented by // `type` into an actual WGSL bool or vecN. E.g. for regular bools this will output `bool(`. // The caller is responsible for closing the parentheses, e.g. output << // "uniforms.bool_represented_by_u32)"; bool OutputUniformBoolOrBvecConversion(TInfoSinkBase &output, const TType &type); // TODO(anglebug.com/42267100): for now does not output all uniform blocks, // just the default block. // `uniformBlock` is the variable declaring an interface block of default uniforms. bool OutputUniformBlocksAndSamplers(TCompiler *compiler, TIntermBlock *root, const TVariable *defaultUniformBlock); // GLSL sampler uniforms are extracted from structs. Given a GLSL sampler's associated name string, // this function retrieves its new WGSL name and strips off array indices. std::string WGSLGetMappedSamplerName(const std::string &originalName); } // namespace sh #endif // COMPILER_TRANSLATOR_WGSL_OUTPUT_UNIFORM_BLOCKS_H_