This document proposes adding support for new SPIR-V instructions to construct composites with a replicated value.

1. Problem Statement

Several recent or in-development extensions require a way of constructing SPIR-V composite values whose top-level constituents all have the same value. Doing so with current SPIR-V requires the desired value to be repeated once for each constituent of the composite value. This is undesirable from a succinctness and code size point of view. As a result extensions have been modifying existing core SPIR-V instructions. For example, SPV_KHR_cooperative_matrix modifies the behavior of the core OpConstantComposite instruction for cooperative matrix types. Other extensions in development face the same issue and will likely adopt a similar solution if SPIR-V does not introduce standard support for this in time.

These modifications go against some of the key design principles for SPIR-V: that instructions should not behave differently depending on the types they operate on.

Furthermore, there are scenarios in which the number of constituents of a composite is not known at SPIR-V module production time (e.g. an array whose Length is a specialization constant) and providing a value for each of the constituents is not only undesirable in that case but simply impossible.

Lastly, high-level languages often allow the initialization of composite objects from a replicated value. Compilers currently have to duplicate those initialisers when generating SPIR-V modules.

2. Solution Space

  1. Do nothing. Some extensions can modify the behavior of core SPIR-V, in a way that is undesirable, or accept the code size issues. Some patterns are not expressible.

  2. Provide new SPIR-V instructions to create composites with a replicated value. This is the proposed solution.

3. Proposal

3.1. SPIR-V

Add three new instructions to SPIR-V that enable creating composite values from a replicated value:

  • OpConstantCompositeReplicateEXT can be used to declare a new composite constant whose constituents all have the same value.

  • OpSpecConstantCompositeReplicateEXT can be used to declare a new composite specialization constant whose constituents all have the same value.

  • OpCompositeConstructReplicateEXT can be used to construct a new composite object whose constituents all have the same value.

A new ReplicatedCompositesEXT capability enables the three new instructions.

3.2. Vulkan API

Add a VkPhysicalDeviceShaderReplicatedCompositesFeaturesEXT structure that comprises a single shaderReplicatedComposites feature that specifies whether the ReplicatedCompositesEXT capability can be used in shader modules:

typedef struct VkPhysicalDeviceShaderReplicatedCompositesFeaturesEXT {
    VkStructureType sType;
    void*           pNext;
    VkBool32        shaderReplicatedComposites;
} VkPhysicalDeviceShaderReplicatedCompositesFeaturesEXT;

4. Examples

Declare a constant vector of 4 integers with the value 42:

%uint = OpTypeInt 32 0
%uint_42 = OpConstant %uint 42
%vector = OpTypeVector %uint 4
%vector_of_42 = OpConstantCompositeReplicateEXT %vector %uint_42

Construct a structure object whose all constituents have the value 1:

%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%struct = OpTypeStruct %uint %uint %uint
%struct_all_ones = OpCompositeConstructReplicateEXT %struct %uint_1

Declare an array constant whose length is a specicialisation constant and all elements have the value 15:

%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%uint_15 = OpConstant %uint 15
%length = OpSpecConstant %uint %uint_1
%array = OpTypeArray %uint %length
%array_of_15 = OpSpecConstantCompositeReplicateEXT %array %uint_15

5. Issues