Hash :
b9cec916
Author :
Date :
2025-08-12T19:44:18
WGSL: default uniforms gathered in interface block The default uniform struct was being manually output by OutputUniformBlocksAndSamplers(), which did not add the appropriate @align(16) annotations to lay the struct out according to WGSL's uniform address space layout requirements. This CL uses Vulkan's method of gathering the default uniforms into an interface block. The interface block will be output normally by the traverser, including @align() annotations. The variable declaring an instance of the interface block is still output by OutputUniformBlocksAndSamplers() because it needs special @group() and @binding() annotations. Bug: angleproject:376553328 Change-Id: Ib3be7d51ffedefe5ec579a1c9aaf0a535146c694 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/6795028 Commit-Queue: Matthew Denton <mpdenton@chromium.org> Reviewed-by: Liza Burakova <liza@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
//
// 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<int> 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<TType> arrayElementTypesInUniforms;
// If we need to convert arrays with wrapped element types into arrays with unwrapped element
// types, the necessary conversions are listed here.
TSet<TType> arrayElementTypesThatNeedUnwrappingConversions;
// MatCx2 in a uniform will be represented as array<ANGLE_wrapped_vec2, C> 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<TType> 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<bool>. 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_