Skip to content

igl | Shader constants. Metal:MTLFunctionConstantValues. Vulkan:SpecializationInfo.#378

Closed
vinsentli wants to merge 5 commits into
facebook:mainfrom
vinsentli:shader_constants
Closed

igl | Shader constants. Metal:MTLFunctionConstantValues. Vulkan:SpecializationInfo.#378
vinsentli wants to merge 5 commits into
facebook:mainfrom
vinsentli:shader_constants

Conversation

@vinsentli

Copy link
Copy Markdown
Contributor

No description provided.

@meta-cla meta-cla Bot added the cla signed label Apr 29, 2026
@vinsentli vinsentli changed the title igl | Shader constants Apr 29, 2026
Comment thread src/igl/Shader.h Outdated
* Metal:MTLFunctionConstantValues.
* Vulkan:SpecializationInfo.
* key:constant_id, value:constant value.*/
std::map<uint8_t, int> functionConstantValues;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be std::vector indexed by constant_id.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I think using std::map might be better. Sometimes I only need to modify a subset of the constant values, which is achievable with std::map. If I used std::vector, I'd have to update all the constant values at once.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I used std::vector, I'd have to update all the constant values at once.

What do you mean? You can still access each individual constant value by changing one vector element at functionConstantValues[constant_id]. The vector can have "holes" of course.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

layout (constant_id = 0) const int value0 = 0;

layout (constant_id = 1) const int value1 = 1;

layout (constant_id = 2) const int value2 = 2;

If I want to modify value2, I can simply use functionConstantValues[2] = xxxwith std::map. However, if I do the same with std::vector, it would implicitly modify functionConstantValues[0]and functionConstantValues[1]as well. I can't just change value2because I don't know whether value0and value1should be updated or not.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It all can be much simpler than that. Please take a look here for a much cleaner implementation https://github.com/corporateshark/lightweightvk/blob/e910eba1bf198baad83094f7c439e53ba6dbafb4/lvk/LVK.h#L745

There's absolutely no need to wield an std::map to do it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've looked at SpecializationConstantDesc, and while it's very flexible and covers all scenarios, it can be somewhat complex to use. Our current discussion involves using a map, a vector, or SpecializationConstantDesc—these are different implementations with different interfaces. Perhaps we should design a clean interface that hides the implementation details. I find the Metal API design quite convenient. Could we design an interface like that?

enum DataType{
kDataTypeInt,
kDataTypeInt2,
kDataTypeInt3,
kDataTypeInt4,

kDataTypeFloat,
kDataTypeFloat2,
kDataTypeFloat3,
kDataTypeFloat4,

......
}

struct ShaderModuleInfo {
  ShaderStage stage = ShaderStage::Fragment;

  std::string entryPoint;

  void setFunctionConstantValue(int index, DataType type, void* value);

  std::string debugName;
}

I originally used std::map<uint8_t, int>because I only wanted to handle intvalues. Since intsatisfies our current use cases, I didn't want to deal with other data types. However, as a public API, handling all data types is an inevitable requirement.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would be a hypothetical implementation of setFunctionConstantValue() look like in this case?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've implemented a version, you can take a look.

# Conflicts:
#	src/igl/vulkan/Common.cpp
#	src/igl/vulkan/Common.h
#	src/igl/vulkan/ComputePipelineState.cpp
#	src/igl/vulkan/RenderPipelineState.cpp
#	src/igl/vulkan/VulkanHelpers.c
#	src/igl/vulkan/VulkanHelpers.h

Add Shader Constants.--P2

# Conflicts:
#	src/igl/vulkan/ComputePipelineState.cpp
#	src/igl/vulkan/RenderPipelineState.cpp

Add Shader Constants.--P3, VulkanSpecializationInfo

# Conflicts:
#	src/igl/vulkan/Common.cpp
#	src/igl/vulkan/Common.h

Fix vulkan

add comment

use std::vector

code review

code review
@vinsentli

Copy link
Copy Markdown
Contributor Author

https://docs.vulkan.org/spec/latest/chapters/pipelines.html#pipelines-specialization-constants

It is legal for a SPIR-V module with specializations to be compiled into a pipeline where no specialization information was provided. SPIR-V specialization constants contain default values such that if a specialization is not provided, the default value will be used. In the examples above, it would be valid for an application to only specialize some of the specialization constants within the SPIR-V module, and let the other constants use their default values encoded within the OpSpecConstant declarations.

According to the Vulkan spec, partial updates to constants are allowed. But testing on two mobile devices showed that all constants must be set. Am I interpreting this wrong?

@corporateshark

Copy link
Copy Markdown
Contributor

According to the Vulkan spec, partial updates to constants are allowed. But testing on two mobile devices showed that all constants must be set. Am I interpreting this wrong?

If there are no other validation errors, you can report this to GPU vendors.

@meta-codesync

meta-codesync Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

@corporateshark has imported this pull request. If you are a Meta employee, you can view this in D103906352.

@meta-codesync meta-codesync Bot closed this in 7fb685a May 7, 2026
@meta-codesync

meta-codesync Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

@corporateshark merged this pull request in 7fb685a.

@vinsentli vinsentli deleted the shader_constants branch June 15, 2026 01:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

2 participants