diff --git a/spec/index.bs b/spec/index.bs index 857b139214..8081fd61f9 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -159,6 +159,7 @@ spec: WGSL; urlPrefix: https://gpuweb.github.io/gpuweb/wgsl/# text: subgroup size; url: subgroup-size type: abstract-op text: SizeOf; url: sizeof + text: AccessibleSlots; url: accessible-slots spec: Internationalization Glossary; urlPrefix: https://www.w3.org/TR/i18n-glossary/# type: dfn text: localizable text; url: dfn-localizable-text @@ -1625,6 +1626,13 @@ A supported limits object has a value for every limit defined by counting any empty slots below the highest index. Validated in {{GPUDevice/createRenderPipeline()}} and [$valid to draw|in draw calls$]. + maxImmediateSize + {{GPUSize32}} [=limit class/maximum=] 64 + + The maximum size, in bytes, of immediate data range used in a pipeline. + + Note: 64 bytes is the size of a 4×4 matrix of f32 values. + maxBindingsPerBindGroup {{GPUSize32}} [=limit class/maximum=] 1000 @@ -1859,6 +1867,7 @@ interface GPUSupportedLimits { readonly attribute unsigned long maxTextureArrayLayers; readonly attribute unsigned long maxBindGroups; readonly attribute unsigned long maxBindGroupsPlusVertexBuffers; + readonly attribute unsigned long maxImmediateSize; readonly attribute unsigned long maxBindingsPerBindGroup; readonly attribute unsigned long maxDynamicUniformBuffersPerPipelineLayout; readonly attribute unsigned long maxDynamicStorageBuffersPerPipelineLayout; @@ -2596,6 +2605,7 @@ Any {{GPUAdapter}} returned by {{GPU/requestAdapter()}} must provide the followi - {{supported limits/maxComputeWorkgroupSizeZ}} must be ≤ {{supported limits/maxComputeInvocationsPerWorkgroup}}. - {{supported limits/maxComputeInvocationsPerWorkgroup}} must be ≤ {{supported limits/maxComputeWorkgroupSizeX}} × {{supported limits/maxComputeWorkgroupSizeY}} × {{supported limits/maxComputeWorkgroupSizeZ}}. +- {{supported limits/maxImmediateSize}} must be a multiple of 4 bytes. ### Adapter Selection ### {#adapter-selection} @@ -6950,6 +6960,11 @@ GPUPipelineLayout includes GPUObjectBase; : \[[bindGroupLayouts]], of type [=list=]<{{GPUBindGroupLayout}}>, readonly :: The {{GPUBindGroupLayout}} objects provided at creation in {{GPUPipelineLayoutDescriptor/bindGroupLayouts|GPUPipelineLayoutDescriptor.bindGroupLayouts}}. + + : \[[immediateSize]], of type {{GPUSize32}}, readonly + :: + The size in bytes of the immediate data range, provided at creation in {{GPUPipelineLayoutDescriptor/immediateSize|GPUPipelineLayoutDescriptor.immediateSize}} + (or by the [$default pipeline layout$]). Note: using the same {{GPUPipelineLayout}} for many {{GPURenderPipeline}} or {{GPUComputePipeline}} pipelines guarantees that the user agent doesn't need to rebind any resources internally when there is a switch between these pipelines. @@ -6979,6 +6994,7 @@ A {{GPUPipelineLayout}} is created via {{GPUDevice/createPipelineLayout()|GPUDev dictionary GPUPipelineLayoutDescriptor : GPUObjectDescriptorBase { required sequence bindGroupLayouts; + GPUSize32 immediateSize = 0; }; @@ -6991,6 +7007,10 @@ pipeline, and have the following members: A list of optional {{GPUBindGroupLayout}}s the pipeline will use. Each element corresponds to a [=@group=] attribute in the {{GPUShaderModule}}, with the `N`th element corresponding with `@group(N)`. + + : immediateSize + :: + The size, in bytes, of the immediate data range used by the pipeline.
@@ -7040,16 +7060,21 @@ pipeline, and have the following members: - The [=list/size=] of |descriptor|.{{GPUPipelineLayoutDescriptor/bindGroupLayouts}} must be ≤ |limits|.{{supported limits/maxBindGroups}}. - |allEntries| must not [=exceeds the binding slot limits|exceed the binding slot limits=] of |limits|. + - |descriptor|.{{GPUPipelineLayoutDescriptor/immediateSize}} must be ≤ + |limits|.{{supported limits/maxImmediateSize}}. + - |descriptor|.{{GPUPipelineLayoutDescriptor/immediateSize}} must be a multiple of 4. 1. Set the |pl|.{{GPUPipelineLayout/[[bindGroupLayouts]]}} to |bindGroupLayouts|. + 1. Set the |pl|.{{GPUPipelineLayout/[[immediateSize]]}} to |descriptor|.{{GPUPipelineLayoutDescriptor/immediateSize}}.
Note: two {{GPUPipelineLayout}} objects are considered equivalent for any usage if their internal {{GPUPipelineLayout/[[bindGroupLayouts]]}} sequences contain -{{GPUBindGroupLayout}} objects that are [=group-equivalent=]. +{{GPUBindGroupLayout}} objects that are [=group-equivalent=] and their +{{GPUPipelineLayout/[[immediateSize]]}} values are equal. ## Example ## {#bindgroup-examples} @@ -7692,6 +7717,7 @@ To create a default pipeline layout for {{GPUPipelineBase run the following [=device timeline=] steps: 1. Let |groupCount| be 0. + 1. Let |immediateSize| be 0. 1. Let |groupDescs| be a sequence of |device|.{{device/[[limits]]}}.{{supported limits/maxBindGroups}} new {{GPUBindGroupLayoutDescriptor}} objects. 1. For each |groupDesc| in |groupDescs|: @@ -7824,6 +7850,11 @@ run the following [=device timeline=] steps: 1. Append |entry| to |groupDescs|[|group|]. + 1. If there is an immediate data variable that is [=statically used=] by |entryPoint| + ([=assert=] there is at most one): + 1. Let |T| be the [=store type=] of the immediate data variable. + 1. Set |immediateSize| to max(|immediateSize|, [=roundUp=](4, [$SizeOf$](|T|))). + 1. Let |groupLayouts| be a new [=list=]. 1. For each |i| from 0 to |groupCount| - 1, inclusive: 1. Let |groupDesc| be |groupDescs|[|i|]. @@ -7833,6 +7864,7 @@ run the following [=device timeline=] steps: 1. Let |desc| be a new {{GPUPipelineLayoutDescriptor}}. 1. Set |desc|.{{GPUPipelineLayoutDescriptor/bindGroupLayouts}} to |groupLayouts|. + 1. Set |desc|.{{GPUPipelineLayoutDescriptor/immediateSize}} to |immediateSize|. 1. Return |device|.{{GPUDevice/createPipelineLayout()}}(|desc|). @@ -8014,6 +8046,11 @@ typedef double GPUPipelineConstantValue; // May represent WGSL's bool, f32, i32, - If the pipeline-overridable constant identified by |key| [=pipeline-overridable constant default value|does not have a default value=], |descriptor|.{{GPUProgrammableStage/constants}} |must| [=map/contain=] |key|. + 1. If there is an immediate data variable that is [=statically used=] by |entryPoint| + ([=assert=] there is at most one): + - Let |T| be the [=store type=] of the immediate data variable. + - Let |requiredSize| be [$SizeOf$](|T|). + - |layout|.{{GPUPipelineLayout/[[immediateSize]]}} must be ≥ |requiredSize|. 1. [=pipeline-creation error|Pipeline-creation=] [=program errors=] |must| not result from the rules of the [[WGSL]] specification. 1. @@ -11263,6 +11300,9 @@ interface mixin GPUBindingCommandsMixin { [AllowShared] Uint32Array dynamicOffsetsData, GPUSize64 dynamicOffsetsDataStart, GPUSize32 dynamicOffsetsDataLength); + + undefined setImmediates(GPUSize32 rangeOffset, AllowSharedBufferSource data, + optional GPUSize64 dataOffset = 0, optional GPUSize64 dataSize); }; @@ -11277,9 +11317,21 @@ It must only be included by interfaces which also include those mixins. :: The current {{GPUBindGroup}} for each index. - : \[[dynamic_offsets]], of type [=ordered map=]<{{GPUIndex32}}, [=list=]<{{GPUBufferDynamicOffset}}>>, initally empty + : \[[dynamic_offsets]], of type [=ordered map=]<{{GPUIndex32}}, [=list=]<{{GPUBufferDynamicOffset}}>>, initially empty :: The current dynamic offsets for each {{GPUBindingCommandsMixin/[[bind_groups]]}} entry. + + : \[[immediate_data]], of type [=byte sequence=] + :: + The current immediate data bytes. + Initially a [=byte sequence=] of length equal to the device's {{supported limits/maxImmediateSize}}, with all bytes set to zero. + Values are set by {{GPUBindingCommandsMixin/setImmediates()}}. + + : \[[immediate_slots_set]], of type [=list=]<{{boolean}}> + :: + Tracks which 32-bit word slots of immediate data have been set. + Initially a [=list=] of length equal to the device's {{supported limits/maxImmediateSize}} divided by 4, with all entries set to `false`. + Each entry corresponds to a 4-byte slot. ## Bind Groups ## {#programmable-passes-bind-groups} @@ -11484,7 +11536,6 @@ It must only be included by interfaces which also include those mixins. -
To Iterate over each dynamic binding offset in a given {{GPUBindGroup}} |bindGroup| with a given list of |steps| to be executed for each dynamic offset, run the following [=device timeline=] steps: @@ -11573,6 +11624,32 @@ It must only be included by interfaces which also include those mixins. Otherwise return `true`.
+
+ Validate immediate data(encoder, pipeline) + + **Arguments:** + + : {{GPUBindingCommandsMixin}} |encoder| + :: Encoder whose immediate data is being validated. + : {{GPUPipelineBase}} |pipeline| + :: Pipeline to validate |encoder|'s immediate data is compatible with. + + [=Device timeline=] steps: + + 1. If any of the following conditions are unsatisfied, return `false`: + +
+ - |pipeline| must not be `null`. + - For each immediate data variable that is [=statically used=] by any entry point in |pipeline|: + - Let |T| be the [=store type=] of the immediate data variable. + - Let |accessibleSlots| be [$AccessibleSlots$](|T|) as defined in [[WGSL]]. + - For each |slotIndex| in |accessibleSlots|: + - |encoder|.{{GPUBindingCommandsMixin/[[immediate_slots_set]]}}[|slotIndex|] must be `true`. +
+ + Otherwise return `true`. +
+
Encoder bind groups alias a writable resource(|encoder|, |pipeline|) if any writable buffer binding range overlaps with any other binding range of the same buffer, @@ -11630,6 +11707,71 @@ It must only be included by interfaces which also include those mixins. Implementations are strongly encouraged to optimize this algorithm.
+## Immediate Data ## {#programmable-passes-immediate-data} + +
+ : setImmediates(rangeOffset, data, dataOffset, dataSize) + :: + Sets immediate data for subsequent render or compute commands. + +
+
+ **Called on:** {{GPUBindingCommandsMixin}} |this|. + + **Arguments:** + +
+                    |rangeOffset|: Offset in bytes into the immediate data range to begin writing at.
+                    |data|: Data to write into the immediate data range.
+                    |dataOffset|: Offset into |data| to begin writing from. Given in elements if
+                        |data| is a {{TypedArray}} and bytes otherwise.
+                    |dataSize|: Size of content to write from |data|. Given in elements if
+                        |data| is a {{TypedArray}} and bytes otherwise.
+                
+ + **Returns:** {{undefined}} + + [=Content timeline=] steps: + + 1. If |data| is an {{ArrayBuffer}} or {{DataView}}, let the element type be "byte". + Otherwise, |data| is a TypedArray; let the element type be the type of the TypedArray. + 1. Let |dataElementCount| be the size of |data|, in elements. + 1. If |dataSize| is missing, + let |contentsSize| be |dataElementCount| − |dataOffset|. + Otherwise, let |contentsSize| be |dataSize|. + 1. If any of the following conditions are unsatisfied, + throw an {{OperationError}} and return. + +
+ - |contentsSize| ≥ 0. + - |dataOffset| + |contentsSize| ≤ |dataElementCount|. + - |contentsSize|, converted to bytes, is a multiple of 4. +
+ 1. Let |dataContents| be [=get a copy of the buffer source|a copy of the bytes held by the buffer source=] |data|. + 1. Let |contents| be the |contentsSize| elements of |dataContents| starting at + an offset of |dataOffset| elements. + 1. Let |contentsBytes| be |contentsSize| converted to bytes. + 1. Issue the subsequent steps on the [=Device timeline=] of |this|.{{GPUObjectBase/[[device]]}}. +
+
+ [=Device timeline=] steps: + + 1. [$Validate the encoder state$] of |this|. If it returns false, return. + 1. If any of the following conditions are unsatisfied, [$invalidate$] |this| and return. + +
+ - |rangeOffset| is a multiple of 4. + - |rangeOffset| + |contentsBytes| ≤ |this|.{{GPUObjectBase/[[device]]}}.{{device/[[limits]]}}.{{supported limits/maxImmediateSize}}. +
+ 1. For each byte |b| at index |i| in |contents|: + 1. Let |byteIndex| be |rangeOffset| + |i|. + 1. Let |slotIndex| be floor(|byteIndex| ÷ 4). + 1. Set |this|.{{GPUBindingCommandsMixin/[[immediate_data]]}}[|byteIndex|] to |b|. + 1. Set |this|.{{GPUBindingCommandsMixin/[[immediate_slots_set]]}}[|slotIndex|] to true. +
+
+
+ # Debug Markers # {#debug-markers} GPUDebugCommandsMixin provides methods to apply debug labels to groups @@ -11918,10 +12060,12 @@ dictionary GPUComputePassDescriptor - |usageScope| must satisfy [=usage scope validation=]. - [$Validate encoder bind groups$](|this|, |this|.{{GPUComputePassEncoder/[[pipeline]]}}) is `true`. + - [$Validate immediate data$](|this|, |this|.{{GPUComputePassEncoder/[[pipeline]]}}) + is `true`. - all of |workgroupCountX|, |workgroupCountY| and |workgroupCountZ| are ≤ |this|.device.limits.{{supported limits/maxComputeWorkgroupsPerDimension}}. - let |workgroupSize| be the computed workgroup size for - |bindingState|.{{GPUComputePassEncoder/[[pipeline]]}}. + |bindingState|.{{GPUComputePassEncoder/[[pipeline]]}}. - the entry point uses the [=builtin/workgroup_index=] built-in value and |workgroupCountX| × |workgroupCountY| × |workgroupCountZ| @@ -11997,6 +12141,8 @@ dictionary GPUComputePassDescriptor - |usageScope| must satisfy [=usage scope validation=]. - [$Validate encoder bind groups$](|this|, |this|.{{GPUComputePassEncoder/[[pipeline]]}}) is `true`. + - [$Validate immediate data$](|this|, |this|.{{GPUComputePassEncoder/[[pipeline]]}}) + is `true`. - |indirectBuffer| is [$valid to use with$] |this|. - |indirectBuffer|.{{GPUBuffer/usage}} contains {{GPUBufferUsage/INDIRECT}}. - |indirectOffset| + sizeof([=indirect dispatch parameters=]) ≤ @@ -13413,6 +13559,8 @@ It must only be included by interfaces which also include those mixins.
- [$Validate encoder bind groups$](|encoder|, |encoder|.{{GPURenderCommandsMixin/[[pipeline]]}}) must be `true`. + - [$Validate immediate data$](|encoder|, |encoder|.{{GPURenderCommandsMixin/[[pipeline]]}}) + must be `true`. - Let |pipelineDescriptor| be |encoder|.{{GPURenderCommandsMixin/[[pipeline]]}}.{{GPURenderPipeline/[[descriptor]]}}. - For each {{GPUIndex32}} |slot| `0` to |pipelineDescriptor|.{{GPURenderPipelineDescriptor/vertex}}.{{GPUVertexState/buffers}}.[=list/size=]: @@ -13731,8 +13879,8 @@ attachments used by this encoder. this render pass. When a {{GPURenderBundle}} is executed, it does not inherit the render pass's pipeline, bind - groups, or vertex and index buffers. After a {{GPURenderBundle}} has executed, the render - pass's pipeline, bind group, and vertex/index buffer state is cleared + groups, immediate data, or vertex and index buffers. After a {{GPURenderBundle}} has executed, the render + pass's pipeline, bind group, immediate data, and vertex/index buffer state is cleared (to the initial, empty values). Note: The state is cleared, not restored to the previous state. @@ -13797,6 +13945,7 @@ attachments used by this encoder. the following [=device timeline=] steps: 1. [=map/Clear=] |encoder|.{{GPUBindingCommandsMixin/[[bind_groups]]}}. + 1. Set each entry of |encoder|.{{GPUBindingCommandsMixin/[[immediate_slots_set]]}} to `false`. 1. Set |encoder|.{{GPURenderCommandsMixin/[[pipeline]]}} to `null`. 1. Set |encoder|.{{GPURenderCommandsMixin/[[index_buffer]]}} to `null`. 1. [=map/Clear=] |encoder|.{{GPURenderCommandsMixin/[[vertex_buffers]]}}. diff --git a/wgsl/index.bs b/wgsl/index.bs index 61201dd777..74e97765f6 100644 --- a/wgsl/index.bs +++ b/wgsl/index.bs @@ -260,6 +260,7 @@ spec: WebGPU; urlPrefix: https://gpuweb.github.io/gpuweb/# text: front-facing; url: front-facing text: shader-output mask; url: shader-output-mask text: framebuffer; url: framebuffer + text: immediateSize; url: dom-gpupipelinelayoutdescriptor-immediatesize text: normalized device coordinates; url: ndc text: clip space coordinates; url: clip-space-coordinates text: clip position; url: clip-position @@ -268,6 +269,7 @@ spec: WebGPU; urlPrefix: https://gpuweb.github.io/gpuweb/# text: rasterizationpoint-depth; url: rasterizationpoint-depth text: rasterizationpoint-perspectivedivisor; url: rasterizationpoint-perspectivedivisor text: fragmentdestination-position; url: fragmentdestination-position + text: setImmediates; url: dom-gpubindingcommandsmixin-setimmediates text: subgroups-feature; url: subgroups text: subgroupMinSize; url: dom-gpuadapterinfo-subgroupminsize text: subgroupMaxSize; url: dom-gpuadapterinfo-subgroupmaxsize @@ -275,6 +277,7 @@ spec: WebGPU; urlPrefix: https://gpuweb.github.io/gpuweb/# text: texture view swizzle; url: dom-gputextureviewdescriptor-swizzle for: supported limits text: maxComputeWorkgroupStorageSize; url: dom-supported-limits-maxcomputeworkgroupstoragesize + text: maxImmediateSize; url: dom-supported-limits-maximmediatesize type: attribute for: GPU text: wgslLanguageFeatures; url: gpuwgsllanguagefeatures @@ -942,6 +945,11 @@ shader that goes beyond the specified limits. This maps the WebGPU [=supported limits/maxComputeWorkgroupStorageSize=] limit into a standalone WGSL limit. [=supported limits/maxComputeWorkgroupStorageSize|16384=] + Maximum [=byte-size=] of an [=immediate data=] [=variable=]. + + This maps the WebGPU [=supported limits/maxImmediateSize=] limit + into a standalone WGSL limit. + [=supported limits/maxImmediateSize|64=] Maximum number of elements in [[#value-constructor-builtin-function|value constructor]] expression of [=array=] type2047 @@ -1499,6 +1507,7 @@ The [=language extension=] names are: * `'texture_and_sampler_let'` * `'texture_formats_tier1'` * `'linear_indexing'` +* `'immediate_data'` ### Interpolation Type Names ### {#interpolation-type-names} @@ -1998,6 +2007,11 @@ Extension names are not [=identifiers=]: they do not [=resolves|resolve=] to [=d Supports the [=built-in values/global_invocation_index=] and [=built-in values/workgroup_index=] [=built-in values=]. + immediate_data + + Enables the [=address spaces/immediate=] address space, allowing variables + to be declared with `var` and bound to small amounts of frequently + updated data passed directly from the command encoder via the WebGPU API. @@ -4910,6 +4924,14 @@ effective-value-type. Yes.
[=uniform buffer=] +[=variable|var=]<[=address spaces/immediate=]> + Immutable + [=module scope|Module=] + [=type/concrete|Concrete=] [=constructible=] [=host-shareable=], excluding arrays and structures containing array members + Disallowed + + Yes.
[=immediate data=] + [=variable|var=]6 Immutable7 [=module scope|Module=] @@ -5194,6 +5216,22 @@ Its [=store type=] must be a [=host-shareable=] type and must satisfy the The variable may be declared with a [=access/read=] or [=access/read_write=] access mode; the default is read. +A variable in the [=address spaces/immediate=] address space is an immediate data variable. +Its [=store type=] [=shader-creation error|must=] be a [=host-shareable=] [=constructible=] type, +excluding arrays and structures that contain array members. +Each [=entry point=] [=shader-creation error|must=] [=statically access=] at most one immediate data variable. +The value of an immediate variable is set via [=setImmediates=] commands recorded by the WebGPU API command encoder, +and remains constant during shader execution. +The variable size is limited by the pipeline layout's [=immediateSize=] configuration. + +
+The [=AccessibleSlots=] exclude padding bytes between structure members and at the end of structures. +Only the accessible slots need to be initialized via the WebGPU API +before the immediate data variable is accessed in a shader. +
+ + A texture resource is a variable whose [=effective-value-type=] is a [=texture type=]. It is declared at [=module scope=]. It holds an opaque handle which is used to access the underlying grid of [=texels=] in a [=texture=]. @@ -7620,17 +7658,17 @@ path: syntax/for_init.syntax.bs.include path: syntax/for_update.syntax.bs.include -The for statement is syntactic sugar over a [=compound statement=] +The for statement is syntactic sugar over a [=compound statement=] containing a [=statement/loop=] statement. -In general, the `for` statement takes the form +In general, the `for` statement takes the form > `for (` *initializer* `;` *condition* `;` *update_part* `) {` *body* `}` When the condition expression is present, the `for` statement desugars to a loop of the form:
- {
    - *initializer* ;
    + {
    + *initializer* ;
    loop {
        if !(*condition*) { break; }
        *body*
        @@ -7641,8 +7679,8 @@ When the condition expression is present, the `for` statement desugars to a loop When the condition expression is absent, the `for` statement desugars to a loop of the form:
- {
    - *initializer* ;
    + {
    + *initializer* ;
    loop {
        *body*
        continuing { *update_part* }
    @@ -9377,6 +9415,7 @@ The interface includes: * [=Shader stage inputs=] * [=Shader stage outputs=] * [=Override-declarations=] +* [=Immediate data=] * Attached [=resources=], which include: * [=Uniform buffers=] * [=Storage buffers=] @@ -9410,6 +9449,8 @@ We can now precisely define the interface of a shader as con [=statically accessed=] by the shader. - The [=override-declarations=] [=statically accessed=] by the shader. + - The [=immediate data=] variables + [=statically accessed=] by the shader. ### Inter-stage Input and Output Interface ### {#stage-inputs-outputs} @@ -10304,7 +10345,7 @@ If not, a [=pipeline-creation error=] [=behavioral requirement|will=] result. ### Resource Interface ### {#resource-interface} A resource is an object which provides access to data external to a [=shader stage=], -and which is not an [=override-declaration=] and not a [[#stage-inputs-outputs|shader stage input or output]]. +and which is not an [=override-declaration=], not an [=immediate data=] variable, and not a [[#stage-inputs-outputs|shader stage input or output]]. Resources are shared by all invocations of the shader. There are four kinds of resources: @@ -10324,6 +10365,9 @@ Together with the shader's stage, these identify the binding address of the resource on the shader's pipeline. See [[WebGPU#gpupipelinelayout]]. +[=Immediate data=] variables do not use [=attribute/group=] or [=attribute/binding=] attributes. + + Two different resource variables in a [=shader=] [=shader-creation error|must not=] have the same [=attribute/group=] and [=attribute/binding=] values, when considered as a pair. @@ -10595,6 +10639,11 @@ table. Invocations in the same [=shader stage=] [=access/read=] For [=storage buffer=] variables + immediate + Invocations in the same [=shader stage=] + [=access/read=] + For [=immediate data=] variables.
+ Each [=entry point=] can [=statically access=] at most one immediate variable. handle Invocations in the same shader stage [=access/read=] @@ -10666,6 +10715,18 @@ and |A| is a host-shareable or fixed footprint array or runtime-sized array: [=StrideOf=](array<|E|, |N|>) = [=roundUp=]([=AlignOf=](E), [=SizeOf=](E))
[=StrideOf=](array<|E|>) = [=roundUp=]([=AlignOf=](E), [=SizeOf=](E))

+* AccessibleBytes(|T|) is the set of byte offsets within an instance of type |T| that contain data. + * If |T| is a scalar or vector, then [=AccessibleBytes=](|T|) is the set of integers `k` such that `0 <= k <` [=SizeOf=](|T|). + * If |T| is a matrix with |C| columns and |R| rows, then [=AccessibleBytes=](|T|) is the set calculated as: + * Let `Stride` be [=roundUp=]([=AlignOf=](vec|R|), [=SizeOf=](vec|R|)). + * For each `i` in `0..C-1`: + * For each `k` in [=AccessibleBytes=](vec|R|): + * The set contains `k + i * Stride`. + * If |T| is a structure |S|, then [=AccessibleBytes=](|T|) is the set calculated as: + * For each member `M_i` at byte offset `Offset` = [=OffsetOfMember=](|S|, `i`): + * For each `k` in [=AccessibleBytes=](`M_i`): + * The set contains `k + Offset`. +* AccessibleSlots(|T|) is the set of integers `i` such that the intersection of the interval `[4*i, 4*i+4)` and [=AccessibleBytes=](|T|) is not empty. ### Alignment and Size ### {#alignment-and-size} @@ -11129,7 +11190,7 @@ sections and then the resulting layout is validated against the [=RequiredAlignOf=](|T|, |C|) rules. --> -When [=language_extension/uniform_buffer_standard_layout=] is **not** supported, +When [=language_extension/uniform_buffer_standard_layout=] is **not** supported, the [=address spaces/uniform=] address space requires that: * Array elements are aligned to 16 byte boundaries. That is, [=StrideOf=](array<|T|,|N|>) = 16 × |k|' for some positive integer |k|'.