Implement Specialization Constants
* Added support to our local copy of SpirV Reflect (which does not support it). * Pass them on render or compute pipeline creation. * Not implemented in our shaders yet.
This commit is contained in:
parent
fb3961b2ef
commit
b2f6db7aa8
19
doc/classes/RDPipelineSpecializationConstant.xml
Normal file
19
doc/classes/RDPipelineSpecializationConstant.xml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<class name="RDPipelineSpecializationConstant" inherits="RefCounted" version="4.0">
|
||||||
|
<brief_description>
|
||||||
|
</brief_description>
|
||||||
|
<description>
|
||||||
|
</description>
|
||||||
|
<tutorials>
|
||||||
|
</tutorials>
|
||||||
|
<methods>
|
||||||
|
</methods>
|
||||||
|
<members>
|
||||||
|
<member name="constant_id" type="int" setter="set_constant_id" getter="get_constant_id" default="0">
|
||||||
|
</member>
|
||||||
|
<member name="value" type="Variant" setter="set_value" getter="get_value">
|
||||||
|
</member>
|
||||||
|
</members>
|
||||||
|
<constants>
|
||||||
|
</constants>
|
||||||
|
</class>
|
|
@ -140,6 +140,8 @@
|
||||||
</return>
|
</return>
|
||||||
<argument index="0" name="shader" type="RID">
|
<argument index="0" name="shader" type="RID">
|
||||||
</argument>
|
</argument>
|
||||||
|
<argument index="1" name="specialization_constants" type="RDPipelineSpecializationConstant[]" default="[]">
|
||||||
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
@ -580,6 +582,8 @@
|
||||||
</argument>
|
</argument>
|
||||||
<argument index="9" name="for_render_pass" type="int" default="0">
|
<argument index="9" name="for_render_pass" type="int" default="0">
|
||||||
</argument>
|
</argument>
|
||||||
|
<argument index="10" name="specialization_constants" type="RDPipelineSpecializationConstant[]" default="[]">
|
||||||
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
@ -1709,6 +1713,12 @@
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="SHADER_LANGUAGE_HLSL" value="1" enum="ShaderLanguage">
|
<constant name="SHADER_LANGUAGE_HLSL" value="1" enum="ShaderLanguage">
|
||||||
</constant>
|
</constant>
|
||||||
|
<constant name="PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL" value="0" enum="PipelineSpecializationConstantType">
|
||||||
|
</constant>
|
||||||
|
<constant name="PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT" value="1" enum="PipelineSpecializationConstantType">
|
||||||
|
</constant>
|
||||||
|
<constant name="PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT" value="2" enum="PipelineSpecializationConstantType">
|
||||||
|
</constant>
|
||||||
<constant name="LIMIT_MAX_BOUND_UNIFORM_SETS" value="0" enum="Limit">
|
<constant name="LIMIT_MAX_BOUND_UNIFORM_SETS" value="0" enum="Limit">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS" value="1" enum="Limit">
|
<constant name="LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS" value="1" enum="Limit">
|
||||||
|
|
|
@ -4374,6 +4374,8 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
|
||||||
|
|
||||||
uint32_t stages_processed = 0;
|
uint32_t stages_processed = 0;
|
||||||
|
|
||||||
|
Vector<Shader::SpecializationConstant> specialization_constants;
|
||||||
|
|
||||||
bool is_compute = false;
|
bool is_compute = false;
|
||||||
|
|
||||||
uint32_t compute_local_size[3] = { 0, 0, 0 };
|
uint32_t compute_local_size[3] = { 0, 0, 0 };
|
||||||
|
@ -4560,6 +4562,62 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
//specialization constants
|
||||||
|
|
||||||
|
uint32_t sc_count = 0;
|
||||||
|
result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, nullptr);
|
||||||
|
ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
|
||||||
|
"Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed enumerating specialization constants.");
|
||||||
|
|
||||||
|
if (sc_count) {
|
||||||
|
Vector<SpvReflectSpecializationConstant *> spec_constants;
|
||||||
|
spec_constants.resize(sc_count);
|
||||||
|
|
||||||
|
result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, spec_constants.ptrw());
|
||||||
|
ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
|
||||||
|
"Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed obtaining specialization constants.");
|
||||||
|
|
||||||
|
for (uint32_t j = 0; j < sc_count; j++) {
|
||||||
|
int32_t existing = -1;
|
||||||
|
Shader::SpecializationConstant sconst;
|
||||||
|
sconst.constant.constant_id = spec_constants[j]->constant_id;
|
||||||
|
switch (spec_constants[j]->constant_type) {
|
||||||
|
case SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL: {
|
||||||
|
sconst.constant.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
|
||||||
|
sconst.constant.bool_value = spec_constants[j]->default_value.int_bool_value != 0;
|
||||||
|
} break;
|
||||||
|
case SPV_REFLECT_SPECIALIZATION_CONSTANT_INT: {
|
||||||
|
sconst.constant.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
|
||||||
|
sconst.constant.int_value = spec_constants[j]->default_value.int_bool_value;
|
||||||
|
} break;
|
||||||
|
case SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT: {
|
||||||
|
sconst.constant.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
|
||||||
|
sconst.constant.float_value = spec_constants[j]->default_value.float_value;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
sconst.stage_flags = 1 << p_stages[i].shader_stage;
|
||||||
|
|
||||||
|
print_line("spec constant " + itos(i) + ": " + String(spec_constants[j]->name) + " type " + itos(spec_constants[j]->constant_type) + " id " + itos(spec_constants[j]->constant_id));
|
||||||
|
|
||||||
|
for (int k = 0; k < specialization_constants.size(); k++) {
|
||||||
|
if (specialization_constants[k].constant.constant_id == sconst.constant.constant_id) {
|
||||||
|
ERR_FAIL_COND_V_MSG(specialization_constants[k].constant.type != sconst.constant.type, RID(), "More than one specialization constant used for id (" + itos(sconst.constant.constant_id) + "), but their types differ.");
|
||||||
|
ERR_FAIL_COND_V_MSG(specialization_constants[k].constant.int_value != sconst.constant.int_value, RID(), "More than one specialization constant used for id (" + itos(sconst.constant.constant_id) + "), but their default values differ.");
|
||||||
|
existing = k;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existing > 0) {
|
||||||
|
specialization_constants.write[existing].stage_flags |= sconst.stage_flags;
|
||||||
|
} else {
|
||||||
|
specialization_constants.push_back(sconst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (stage == SHADER_STAGE_VERTEX) {
|
if (stage == SHADER_STAGE_VERTEX) {
|
||||||
uint32_t iv_count = 0;
|
uint32_t iv_count = 0;
|
||||||
result = spvReflectEnumerateInputVariables(&module, &iv_count, nullptr);
|
result = spvReflectEnumerateInputVariables(&module, &iv_count, nullptr);
|
||||||
|
@ -4656,6 +4714,7 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
|
||||||
shader.compute_local_size[0] = compute_local_size[0];
|
shader.compute_local_size[0] = compute_local_size[0];
|
||||||
shader.compute_local_size[1] = compute_local_size[1];
|
shader.compute_local_size[1] = compute_local_size[1];
|
||||||
shader.compute_local_size[2] = compute_local_size[2];
|
shader.compute_local_size[2] = compute_local_size[2];
|
||||||
|
shader.specialization_constants = specialization_constants;
|
||||||
|
|
||||||
String error_text;
|
String error_text;
|
||||||
|
|
||||||
|
@ -5651,7 +5710,7 @@ Vector<uint8_t> RenderingDeviceVulkan::buffer_get_data(RID p_buffer) {
|
||||||
/**** RENDER PIPELINE ****/
|
/**** RENDER PIPELINE ****/
|
||||||
/*************************/
|
/*************************/
|
||||||
|
|
||||||
RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass) {
|
RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const Vector<PipelineSpecializationConstant> &p_specialization_constants) {
|
||||||
_THREAD_SAFE_METHOD_
|
_THREAD_SAFE_METHOD_
|
||||||
|
|
||||||
//needs a shader
|
//needs a shader
|
||||||
|
@ -5969,8 +6028,63 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
|
||||||
graphics_pipeline_create_info.pNext = nullptr;
|
graphics_pipeline_create_info.pNext = nullptr;
|
||||||
graphics_pipeline_create_info.flags = 0;
|
graphics_pipeline_create_info.flags = 0;
|
||||||
|
|
||||||
graphics_pipeline_create_info.stageCount = shader->pipeline_stages.size();
|
Vector<VkPipelineShaderStageCreateInfo> pipeline_stages = shader->pipeline_stages;
|
||||||
graphics_pipeline_create_info.pStages = shader->pipeline_stages.ptr();
|
Vector<VkSpecializationInfo> specialization_info;
|
||||||
|
Vector<Vector<VkSpecializationMapEntry>> specialization_map_entries;
|
||||||
|
Vector<uint32_t> specialization_constant_data;
|
||||||
|
|
||||||
|
if (shader->specialization_constants.size()) {
|
||||||
|
specialization_constant_data.resize(shader->specialization_constants.size());
|
||||||
|
uint32_t *data_ptr = specialization_constant_data.ptrw();
|
||||||
|
specialization_info.resize(pipeline_stages.size());
|
||||||
|
specialization_map_entries.resize(pipeline_stages.size());
|
||||||
|
for (int i = 0; i < shader->specialization_constants.size(); i++) {
|
||||||
|
//see if overriden
|
||||||
|
const Shader::SpecializationConstant &sc = shader->specialization_constants[i];
|
||||||
|
data_ptr[i] = sc.constant.int_value; //just copy the 32 bits
|
||||||
|
|
||||||
|
for (int j = 0; j < p_specialization_constants.size(); j++) {
|
||||||
|
const PipelineSpecializationConstant &psc = p_specialization_constants[j];
|
||||||
|
if (psc.constant_id == sc.constant.constant_id) {
|
||||||
|
ERR_FAIL_COND_V_MSG(psc.type != sc.constant.type, RID(), "Specialization constant provided for id (" + itos(sc.constant.constant_id) + ") is of the wrong type.");
|
||||||
|
data_ptr[i] = sc.constant.int_value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSpecializationMapEntry entry;
|
||||||
|
|
||||||
|
entry.constantID = sc.constant.constant_id;
|
||||||
|
entry.offset = i * sizeof(uint32_t);
|
||||||
|
entry.size = sizeof(uint32_t);
|
||||||
|
|
||||||
|
for (int j = 0; j < SHADER_STAGE_MAX; j++) {
|
||||||
|
if (sc.stage_flags & (1 << j)) {
|
||||||
|
VkShaderStageFlagBits stage = shader_stage_masks[j];
|
||||||
|
for (int k = 0; k < pipeline_stages.size(); k++) {
|
||||||
|
if (pipeline_stages[k].stage == stage) {
|
||||||
|
specialization_map_entries.write[k].push_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int k = 0; k < pipeline_stages.size(); k++) {
|
||||||
|
if (specialization_map_entries[k].size()) {
|
||||||
|
specialization_info.write[k].dataSize = specialization_constant_data.size() * sizeof(uint32_t);
|
||||||
|
specialization_info.write[k].pData = data_ptr;
|
||||||
|
specialization_info.write[k].mapEntryCount = specialization_map_entries[k].size();
|
||||||
|
specialization_info.write[k].pMapEntries = specialization_map_entries[k].ptr();
|
||||||
|
|
||||||
|
pipeline_stages.write[k].pSpecializationInfo = specialization_info.ptr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
graphics_pipeline_create_info.stageCount = pipeline_stages.size();
|
||||||
|
graphics_pipeline_create_info.pStages = pipeline_stages.ptr();
|
||||||
|
|
||||||
graphics_pipeline_create_info.pVertexInputState = &pipeline_vertex_input_state_create_info;
|
graphics_pipeline_create_info.pVertexInputState = &pipeline_vertex_input_state_create_info;
|
||||||
graphics_pipeline_create_info.pInputAssemblyState = &input_assembly_create_info;
|
graphics_pipeline_create_info.pInputAssemblyState = &input_assembly_create_info;
|
||||||
graphics_pipeline_create_info.pTessellationState = &tessellation_create_info;
|
graphics_pipeline_create_info.pTessellationState = &tessellation_create_info;
|
||||||
|
@ -6039,7 +6153,7 @@ bool RenderingDeviceVulkan::render_pipeline_is_valid(RID p_pipeline) {
|
||||||
/**** COMPUTE PIPELINE ****/
|
/**** COMPUTE PIPELINE ****/
|
||||||
/**************************/
|
/**************************/
|
||||||
|
|
||||||
RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader) {
|
RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<PipelineSpecializationConstant> &p_specialization_constants) {
|
||||||
_THREAD_SAFE_METHOD_
|
_THREAD_SAFE_METHOD_
|
||||||
|
|
||||||
//needs a shader
|
//needs a shader
|
||||||
|
@ -6061,6 +6175,44 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader) {
|
||||||
compute_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
|
compute_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
|
||||||
compute_pipeline_create_info.basePipelineIndex = 0;
|
compute_pipeline_create_info.basePipelineIndex = 0;
|
||||||
|
|
||||||
|
VkSpecializationInfo specialization_info;
|
||||||
|
Vector<VkSpecializationMapEntry> specialization_map_entries;
|
||||||
|
Vector<uint32_t> specialization_constant_data;
|
||||||
|
|
||||||
|
if (shader->specialization_constants.size()) {
|
||||||
|
specialization_constant_data.resize(shader->specialization_constants.size());
|
||||||
|
uint32_t *data_ptr = specialization_constant_data.ptrw();
|
||||||
|
for (int i = 0; i < shader->specialization_constants.size(); i++) {
|
||||||
|
//see if overriden
|
||||||
|
const Shader::SpecializationConstant &sc = shader->specialization_constants[i];
|
||||||
|
data_ptr[i] = sc.constant.int_value; //just copy the 32 bits
|
||||||
|
|
||||||
|
for (int j = 0; j < p_specialization_constants.size(); j++) {
|
||||||
|
const PipelineSpecializationConstant &psc = p_specialization_constants[j];
|
||||||
|
if (psc.constant_id == sc.constant.constant_id) {
|
||||||
|
ERR_FAIL_COND_V_MSG(psc.type != sc.constant.type, RID(), "Specialization constant provided for id (" + itos(sc.constant.constant_id) + ") is of the wrong type.");
|
||||||
|
data_ptr[i] = sc.constant.int_value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSpecializationMapEntry entry;
|
||||||
|
|
||||||
|
entry.constantID = sc.constant.constant_id;
|
||||||
|
entry.offset = i * sizeof(uint32_t);
|
||||||
|
entry.size = sizeof(uint32_t);
|
||||||
|
|
||||||
|
specialization_map_entries.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
specialization_info.dataSize = specialization_constant_data.size() * sizeof(uint32_t);
|
||||||
|
specialization_info.pData = data_ptr;
|
||||||
|
specialization_info.mapEntryCount = specialization_map_entries.size();
|
||||||
|
specialization_info.pMapEntries = specialization_map_entries.ptr();
|
||||||
|
|
||||||
|
compute_pipeline_create_info.stage.pSpecializationInfo = &specialization_info;
|
||||||
|
}
|
||||||
|
|
||||||
ComputePipeline pipeline;
|
ComputePipeline pipeline;
|
||||||
VkResult err = vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &compute_pipeline_create_info, nullptr, &pipeline.pipeline);
|
VkResult err = vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &compute_pipeline_create_info, nullptr, &pipeline.pipeline);
|
||||||
ERR_FAIL_COND_V_MSG(err, RID(), "vkCreateComputePipelines failed with error " + itos(err) + ".");
|
ERR_FAIL_COND_V_MSG(err, RID(), "vkCreateComputePipelines failed with error " + itos(err) + ".");
|
||||||
|
|
|
@ -623,11 +623,17 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||||
|
|
||||||
uint32_t compute_local_size[3] = { 0, 0, 0 };
|
uint32_t compute_local_size[3] = { 0, 0, 0 };
|
||||||
|
|
||||||
|
struct SpecializationConstant {
|
||||||
|
PipelineSpecializationConstant constant;
|
||||||
|
uint32_t stage_flags = 0;
|
||||||
|
};
|
||||||
|
|
||||||
bool is_compute = false;
|
bool is_compute = false;
|
||||||
int max_output = 0;
|
int max_output = 0;
|
||||||
Vector<Set> sets;
|
Vector<Set> sets;
|
||||||
Vector<uint32_t> set_formats;
|
Vector<uint32_t> set_formats;
|
||||||
Vector<VkPipelineShaderStageCreateInfo> pipeline_stages;
|
Vector<VkPipelineShaderStageCreateInfo> pipeline_stages;
|
||||||
|
Vector<SpecializationConstant> specialization_constants;
|
||||||
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
|
VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1100,14 +1106,14 @@ public:
|
||||||
/**** RENDER PIPELINE ****/
|
/**** RENDER PIPELINE ****/
|
||||||
/*************************/
|
/*************************/
|
||||||
|
|
||||||
virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0);
|
virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>());
|
||||||
virtual bool render_pipeline_is_valid(RID p_pipeline);
|
virtual bool render_pipeline_is_valid(RID p_pipeline);
|
||||||
|
|
||||||
/**************************/
|
/**************************/
|
||||||
/**** COMPUTE PIPELINE ****/
|
/**** COMPUTE PIPELINE ****/
|
||||||
/**************************/
|
/**************************/
|
||||||
|
|
||||||
virtual RID compute_pipeline_create(RID p_shader);
|
virtual RID compute_pipeline_create(RID p_shader, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>());
|
||||||
virtual bool compute_pipeline_is_valid(RID p_pipeline);
|
virtual bool compute_pipeline_is_valid(RID p_pipeline);
|
||||||
|
|
||||||
/****************/
|
/****************/
|
||||||
|
|
|
@ -207,6 +207,7 @@ void register_server_types() {
|
||||||
ClassDB::register_class<RDShaderSource>();
|
ClassDB::register_class<RDShaderSource>();
|
||||||
ClassDB::register_class<RDShaderBytecode>();
|
ClassDB::register_class<RDShaderBytecode>();
|
||||||
ClassDB::register_class<RDShaderFile>();
|
ClassDB::register_class<RDShaderFile>();
|
||||||
|
ClassDB::register_class<RDPipelineSpecializationConstant>();
|
||||||
|
|
||||||
ClassDB::register_class<CameraFeed>();
|
ClassDB::register_class<CameraFeed>();
|
||||||
|
|
||||||
|
|
|
@ -221,7 +221,36 @@ Error RenderingDevice::_buffer_update(RID p_buffer, uint32_t p_offset, uint32_t
|
||||||
return buffer_update(p_buffer, p_offset, p_size, p_data.ptr(), p_post_barrier);
|
return buffer_update(p_buffer, p_offset, p_size, p_data.ptr(), p_post_barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass) {
|
static Vector<RenderingDevice::PipelineSpecializationConstant> _get_spec_constants(const TypedArray<RDPipelineSpecializationConstant> &p_constants) {
|
||||||
|
Vector<RenderingDevice::PipelineSpecializationConstant> ret;
|
||||||
|
ret.resize(p_constants.size());
|
||||||
|
for (int i = 0; i < p_constants.size(); i++) {
|
||||||
|
Ref<RDPipelineSpecializationConstant> c = p_constants[i];
|
||||||
|
ERR_CONTINUE(c.is_null());
|
||||||
|
RenderingDevice::PipelineSpecializationConstant &sc = ret.write[i];
|
||||||
|
Variant value = c->get_value();
|
||||||
|
switch (value.get_type()) {
|
||||||
|
case Variant::BOOL: {
|
||||||
|
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
|
||||||
|
sc.bool_value = value;
|
||||||
|
} break;
|
||||||
|
case Variant::INT: {
|
||||||
|
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
|
||||||
|
sc.int_value = value;
|
||||||
|
} break;
|
||||||
|
case Variant::FLOAT: {
|
||||||
|
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
|
||||||
|
sc.float_value = value;
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sc.constant_id = c->get_constant_id();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants) {
|
||||||
PipelineRasterizationState rasterization_state;
|
PipelineRasterizationState rasterization_state;
|
||||||
if (p_rasterization_state.is_valid()) {
|
if (p_rasterization_state.is_valid()) {
|
||||||
rasterization_state = p_rasterization_state->base;
|
rasterization_state = p_rasterization_state->base;
|
||||||
|
@ -252,7 +281,11 @@ RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return render_pipeline_create(p_shader, p_framebuffer_format, p_vertex_format, p_render_primitive, rasterization_state, multisample_state, depth_stencil_state, color_blend_state, p_dynamic_state_flags, p_for_render_pass);
|
return render_pipeline_create(p_shader, p_framebuffer_format, p_vertex_format, p_render_primitive, rasterization_state, multisample_state, depth_stencil_state, color_blend_state, p_dynamic_state_flags, p_for_render_pass, _get_spec_constants(p_specialization_constants));
|
||||||
|
}
|
||||||
|
|
||||||
|
RID RenderingDevice::_compute_pipeline_create(RID p_shader, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants = TypedArray<RDPipelineSpecializationConstant>()) {
|
||||||
|
return compute_pipeline_create(p_shader, _get_spec_constants(p_specialization_constants));
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray<RID> &p_storage_textures) {
|
Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray<RID> &p_storage_textures) {
|
||||||
|
@ -348,10 +381,10 @@ void RenderingDevice::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::buffer_clear, DEFVAL(BARRIER_MASK_ALL));
|
ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::buffer_clear, DEFVAL(BARRIER_MASK_ALL));
|
||||||
ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer"), &RenderingDevice::buffer_get_data);
|
ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer"), &RenderingDevice::buffer_get_data);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags", "for_render_pass"), &RenderingDevice::_render_pipeline_create, DEFVAL(0), DEFVAL(0));
|
ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags", "for_render_pass", "specialization_constants"), &RenderingDevice::_render_pipeline_create, DEFVAL(0), DEFVAL(0), DEFVAL(TypedArray<RDPipelineSpecializationConstant>()));
|
||||||
ClassDB::bind_method(D_METHOD("render_pipeline_is_valid", "render_pipeline"), &RenderingDevice::render_pipeline_is_valid);
|
ClassDB::bind_method(D_METHOD("render_pipeline_is_valid", "render_pipeline"), &RenderingDevice::render_pipeline_is_valid);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("compute_pipeline_create", "shader"), &RenderingDevice::compute_pipeline_create);
|
ClassDB::bind_method(D_METHOD("compute_pipeline_create", "shader", "specialization_constants"), &RenderingDevice::_compute_pipeline_create, DEFVAL(TypedArray<RDPipelineSpecializationConstant>()));
|
||||||
ClassDB::bind_method(D_METHOD("compute_pipeline_is_valid", "compute_pieline"), &RenderingDevice::compute_pipeline_is_valid);
|
ClassDB::bind_method(D_METHOD("compute_pipeline_is_valid", "compute_pieline"), &RenderingDevice::compute_pipeline_is_valid);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("screen_get_width", "screen"), &RenderingDevice::screen_get_width, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
|
ClassDB::bind_method(D_METHOD("screen_get_width", "screen"), &RenderingDevice::screen_get_width, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
|
||||||
|
@ -853,6 +886,10 @@ void RenderingDevice::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(SHADER_LANGUAGE_GLSL);
|
BIND_ENUM_CONSTANT(SHADER_LANGUAGE_GLSL);
|
||||||
BIND_ENUM_CONSTANT(SHADER_LANGUAGE_HLSL);
|
BIND_ENUM_CONSTANT(SHADER_LANGUAGE_HLSL);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL);
|
||||||
|
BIND_ENUM_CONSTANT(PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT);
|
||||||
|
BIND_ENUM_CONSTANT(PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(LIMIT_MAX_BOUND_UNIFORM_SETS);
|
BIND_ENUM_CONSTANT(LIMIT_MAX_BOUND_UNIFORM_SETS);
|
||||||
BIND_ENUM_CONSTANT(LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS);
|
BIND_ENUM_CONSTANT(LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS);
|
||||||
BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURES_PER_UNIFORM_SET);
|
BIND_ENUM_CONSTANT(LIMIT_MAX_TEXTURES_PER_UNIFORM_SET);
|
||||||
|
|
|
@ -48,6 +48,7 @@ class RDPipelineMultisampleState;
|
||||||
class RDPipelineDepthStencilState;
|
class RDPipelineDepthStencilState;
|
||||||
class RDPipelineColorBlendState;
|
class RDPipelineColorBlendState;
|
||||||
class RDFramebufferPass;
|
class RDFramebufferPass;
|
||||||
|
class RDPipelineSpecializationConstant;
|
||||||
|
|
||||||
class RenderingDevice : public Object {
|
class RenderingDevice : public Object {
|
||||||
GDCLASS(RenderingDevice, Object)
|
GDCLASS(RenderingDevice, Object)
|
||||||
|
@ -722,6 +723,32 @@ public:
|
||||||
virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
|
virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
|
||||||
virtual Vector<uint8_t> buffer_get_data(RID p_buffer) = 0; //this causes stall, only use to retrieve large buffers for saving
|
virtual Vector<uint8_t> buffer_get_data(RID p_buffer) = 0; //this causes stall, only use to retrieve large buffers for saving
|
||||||
|
|
||||||
|
/******************************************/
|
||||||
|
/**** PIPELINE SPECIALIZATION CONSTANT ****/
|
||||||
|
/******************************************/
|
||||||
|
|
||||||
|
enum PipelineSpecializationConstantType {
|
||||||
|
PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL,
|
||||||
|
PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT,
|
||||||
|
PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PipelineSpecializationConstant {
|
||||||
|
PipelineSpecializationConstantType type;
|
||||||
|
uint32_t constant_id;
|
||||||
|
union {
|
||||||
|
uint32_t int_value;
|
||||||
|
float float_value;
|
||||||
|
bool bool_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
PipelineSpecializationConstant() {
|
||||||
|
type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
|
||||||
|
constant_id = 0;
|
||||||
|
int_value = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*************************/
|
/*************************/
|
||||||
/**** RENDER PIPELINE ****/
|
/**** RENDER PIPELINE ****/
|
||||||
/*************************/
|
/*************************/
|
||||||
|
@ -978,13 +1005,13 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual bool render_pipeline_is_valid(RID p_pipeline) = 0;
|
virtual bool render_pipeline_is_valid(RID p_pipeline) = 0;
|
||||||
virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0) = 0;
|
virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>()) = 0;
|
||||||
|
|
||||||
/**************************/
|
/**************************/
|
||||||
/**** COMPUTE PIPELINE ****/
|
/**** COMPUTE PIPELINE ****/
|
||||||
/**************************/
|
/**************************/
|
||||||
|
|
||||||
virtual RID compute_pipeline_create(RID p_shader) = 0;
|
virtual RID compute_pipeline_create(RID p_shader, const Vector<PipelineSpecializationConstant> &p_specialization_constants = Vector<PipelineSpecializationConstant>()) = 0;
|
||||||
virtual bool compute_pipeline_is_valid(RID p_pipeline) = 0;
|
virtual bool compute_pipeline_is_valid(RID p_pipeline) = 0;
|
||||||
|
|
||||||
/****************/
|
/****************/
|
||||||
|
@ -1173,7 +1200,8 @@ protected:
|
||||||
|
|
||||||
Error _buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL);
|
Error _buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL);
|
||||||
|
|
||||||
RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0);
|
RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants);
|
||||||
|
RID _compute_pipeline_create(RID p_shader, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants);
|
||||||
|
|
||||||
Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const TypedArray<RID> &p_storage_textures = TypedArray<RID>());
|
Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const TypedArray<RID> &p_storage_textures = TypedArray<RID>());
|
||||||
void _draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);
|
void _draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);
|
||||||
|
@ -1205,6 +1233,7 @@ VARIANT_ENUM_CAST(RenderingDevice::LogicOperation)
|
||||||
VARIANT_ENUM_CAST(RenderingDevice::BlendFactor)
|
VARIANT_ENUM_CAST(RenderingDevice::BlendFactor)
|
||||||
VARIANT_ENUM_CAST(RenderingDevice::BlendOperation)
|
VARIANT_ENUM_CAST(RenderingDevice::BlendOperation)
|
||||||
VARIANT_ENUM_CAST(RenderingDevice::PipelineDynamicStateFlags)
|
VARIANT_ENUM_CAST(RenderingDevice::PipelineDynamicStateFlags)
|
||||||
|
VARIANT_ENUM_CAST(RenderingDevice::PipelineSpecializationConstantType)
|
||||||
VARIANT_ENUM_CAST(RenderingDevice::InitialAction)
|
VARIANT_ENUM_CAST(RenderingDevice::InitialAction)
|
||||||
VARIANT_ENUM_CAST(RenderingDevice::FinalAction)
|
VARIANT_ENUM_CAST(RenderingDevice::FinalAction)
|
||||||
VARIANT_ENUM_CAST(RenderingDevice::Limit)
|
VARIANT_ENUM_CAST(RenderingDevice::Limit)
|
||||||
|
|
|
@ -452,6 +452,41 @@ protected:
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_ids", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "_set_ids", "get_ids");
|
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_ids", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "_set_ids", "get_ids");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RDPipelineSpecializationConstant : public RefCounted {
|
||||||
|
GDCLASS(RDPipelineSpecializationConstant, RefCounted)
|
||||||
|
friend class RenderingDevice;
|
||||||
|
|
||||||
|
Variant value = false;
|
||||||
|
uint32_t constant_id;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void set_value(const Variant &p_value) {
|
||||||
|
ERR_FAIL_COND(p_value.get_type() != Variant::BOOL && p_value.get_type() != Variant::INT && p_value.get_type() != Variant::FLOAT);
|
||||||
|
value = p_value;
|
||||||
|
}
|
||||||
|
Variant get_value() const { return value; }
|
||||||
|
|
||||||
|
void set_constant_id(uint32_t p_id) {
|
||||||
|
constant_id = p_id;
|
||||||
|
}
|
||||||
|
uint32_t get_constant_id() const {
|
||||||
|
return constant_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("set_value", "value"), &RDPipelineSpecializationConstant::set_value);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_value"), &RDPipelineSpecializationConstant::get_value);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_constant_id", "constant_id"), &RDPipelineSpecializationConstant::set_constant_id);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_constant_id"), &RDPipelineSpecializationConstant::get_constant_id);
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_value", "get_value");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "constant_id", PROPERTY_HINT_RANGE, "0,65535,0"), "set_constant_id", "get_constant_id");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class RDPipelineRasterizationState : public RefCounted {
|
class RDPipelineRasterizationState : public RefCounted {
|
||||||
GDCLASS(RDPipelineRasterizationState, RefCounted)
|
GDCLASS(RDPipelineRasterizationState, RefCounted)
|
||||||
friend class RenderingDevice;
|
friend class RenderingDevice;
|
||||||
|
|
5
thirdparty/README.md
vendored
5
thirdparty/README.md
vendored
|
@ -616,6 +616,11 @@ Files extracted from upstream source:
|
||||||
- `include` folder
|
- `include` folder
|
||||||
- `LICENSE`
|
- `LICENSE`
|
||||||
|
|
||||||
|
Some downstream changes have been made and are identified by
|
||||||
|
`// -- GODOT begin --` and `// -- GODOT end --` comments.
|
||||||
|
They can be reapplied using the patch included in the `patches`
|
||||||
|
folder.
|
||||||
|
|
||||||
|
|
||||||
## squish
|
## squish
|
||||||
|
|
||||||
|
|
293
thirdparty/spirv-reflect/patches/specialization-constants.patch
vendored
Normal file
293
thirdparty/spirv-reflect/patches/specialization-constants.patch
vendored
Normal file
|
@ -0,0 +1,293 @@
|
||||||
|
diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c
|
||||||
|
index 0fc979a8a4..3e3643717a 100644
|
||||||
|
--- a/thirdparty/spirv-reflect/spirv_reflect.c
|
||||||
|
+++ b/thirdparty/spirv-reflect/spirv_reflect.c
|
||||||
|
@@ -124,6 +124,9 @@ typedef struct Decorations {
|
||||||
|
NumberDecoration location;
|
||||||
|
NumberDecoration offset;
|
||||||
|
NumberDecoration uav_counter_buffer;
|
||||||
|
+// -- GODOT begin --
|
||||||
|
+ NumberDecoration specialization_constant;
|
||||||
|
+// -- GODOT end --
|
||||||
|
StringDecoration semantic;
|
||||||
|
uint32_t array_stride;
|
||||||
|
uint32_t matrix_stride;
|
||||||
|
@@ -610,6 +613,9 @@ static SpvReflectResult ParseNodes(Parser* p_parser)
|
||||||
|
p_parser->nodes[i].decorations.offset.value = (uint32_t)INVALID_VALUE;
|
||||||
|
p_parser->nodes[i].decorations.uav_counter_buffer.value = (uint32_t)INVALID_VALUE;
|
||||||
|
p_parser->nodes[i].decorations.built_in = (SpvBuiltIn)INVALID_VALUE;
|
||||||
|
+// -- GODOT begin --
|
||||||
|
+ p_parser->nodes[i].decorations.specialization_constant.value = (SpvBuiltIn)INVALID_VALUE;
|
||||||
|
+// -- GODOT end --
|
||||||
|
}
|
||||||
|
// Mark source file id node
|
||||||
|
p_parser->source_file_id = (uint32_t)INVALID_VALUE;
|
||||||
|
@@ -800,10 +806,16 @@ static SpvReflectResult ParseNodes(Parser* p_parser)
|
||||||
|
CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
-
|
||||||
|
+// -- GODOT begin --
|
||||||
|
case SpvOpSpecConstantTrue:
|
||||||
|
case SpvOpSpecConstantFalse:
|
||||||
|
- case SpvOpSpecConstant:
|
||||||
|
+ case SpvOpSpecConstant: {
|
||||||
|
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
|
||||||
|
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
|
||||||
|
+ p_node->is_type = true;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+// -- GODOT end --
|
||||||
|
case SpvOpSpecConstantComposite:
|
||||||
|
case SpvOpSpecConstantOp: {
|
||||||
|
CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
|
||||||
|
@@ -1309,6 +1321,9 @@ static SpvReflectResult ParseDecorations(Parser* p_parser)
|
||||||
|
skip = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
+// -- GODOT begin --
|
||||||
|
+ case SpvDecorationSpecId:
|
||||||
|
+// -- GODOT end --
|
||||||
|
case SpvDecorationBlock:
|
||||||
|
case SpvDecorationBufferBlock:
|
||||||
|
case SpvDecorationColMajor:
|
||||||
|
@@ -1441,7 +1456,14 @@ static SpvReflectResult ParseDecorations(Parser* p_parser)
|
||||||
|
p_target_decorations->input_attachment_index.word_offset = word_offset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
-
|
||||||
|
+// -- GODOT begin --
|
||||||
|
+ case SpvDecorationSpecId: {
|
||||||
|
+ uint32_t word_offset = p_node->word_offset + member_offset+ 3;
|
||||||
|
+ CHECKED_READU32(p_parser, word_offset, p_target_decorations->specialization_constant.value);
|
||||||
|
+ p_target_decorations->specialization_constant.word_offset = word_offset;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+// -- GODOT end --
|
||||||
|
case SpvReflectDecorationHlslCounterBufferGOOGLE: {
|
||||||
|
uint32_t word_offset = p_node->word_offset + member_offset+ 3;
|
||||||
|
CHECKED_READU32(p_parser, word_offset, p_target_decorations->uav_counter_buffer.value);
|
||||||
|
@@ -1731,6 +1753,13 @@ static SpvReflectResult ParseType(
|
||||||
|
p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
+// -- GODOT begin --
|
||||||
|
+ case SpvOpSpecConstantTrue:
|
||||||
|
+ case SpvOpSpecConstantFalse:
|
||||||
|
+ case SpvOpSpecConstant: {
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+// -- GODOT end --
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == SPV_REFLECT_RESULT_SUCCESS) {
|
||||||
|
@@ -3187,6 +3216,69 @@ static SpvReflectResult ParseExecutionModes(Parser* p_parser, SpvReflectShaderMo
|
||||||
|
return SPV_REFLECT_RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
+// -- GODOT begin --
|
||||||
|
+static SpvReflectResult ParseSpecializationConstants(Parser* p_parser, SpvReflectShaderModule* p_module)
|
||||||
|
+{
|
||||||
|
+ p_module->specialization_constant_count = 0;
|
||||||
|
+ p_module->specialization_constants = NULL;
|
||||||
|
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
|
||||||
|
+ Node* p_node = &(p_parser->nodes[i]);
|
||||||
|
+ if (p_node->op == SpvOpSpecConstantTrue || p_node->op == SpvOpSpecConstantFalse || p_node->op == SpvOpSpecConstant) {
|
||||||
|
+ p_module->specialization_constant_count++;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (p_module->specialization_constant_count == 0) {
|
||||||
|
+ return SPV_REFLECT_RESULT_SUCCESS;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ p_module->specialization_constants = (SpvReflectSpecializationConstant*)calloc(p_module->specialization_constant_count, sizeof(SpvReflectSpecializationConstant));
|
||||||
|
+
|
||||||
|
+ uint32_t index = 0;
|
||||||
|
+
|
||||||
|
+ for (size_t i = 0; i < p_parser->node_count; ++i) {
|
||||||
|
+ Node* p_node = &(p_parser->nodes[i]);
|
||||||
|
+ switch(p_node->op) {
|
||||||
|
+ default: continue;
|
||||||
|
+ case SpvOpSpecConstantTrue: {
|
||||||
|
+ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL;
|
||||||
|
+ p_module->specialization_constants[index].default_value.int_bool_value = 1;
|
||||||
|
+ } break;
|
||||||
|
+ case SpvOpSpecConstantFalse: {
|
||||||
|
+ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL;
|
||||||
|
+ p_module->specialization_constants[index].default_value.int_bool_value = 0;
|
||||||
|
+ } break;
|
||||||
|
+ case SpvOpSpecConstant: {
|
||||||
|
+ SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS;
|
||||||
|
+ uint32_t element_type_id = (uint32_t)INVALID_VALUE;
|
||||||
|
+ uint32_t default_value = 0;
|
||||||
|
+ IF_READU32(result, p_parser, p_node->word_offset + 1, element_type_id);
|
||||||
|
+ IF_READU32(result, p_parser, p_node->word_offset + 3, default_value);
|
||||||
|
+
|
||||||
|
+ Node* p_next_node = FindNode(p_parser, element_type_id);
|
||||||
|
+
|
||||||
|
+ if (p_next_node->op == SpvOpTypeInt) {
|
||||||
|
+ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_INT;
|
||||||
|
+ } else if (p_next_node->op == SpvOpTypeFloat) {
|
||||||
|
+ p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT;
|
||||||
|
+ } else {
|
||||||
|
+ return SPV_REFLECT_RESULT_ERROR_PARSE_FAILED;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ p_module->specialization_constants[index].default_value.int_bool_value = default_value; //bits are the same for int and float
|
||||||
|
+ } break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ p_module->specialization_constants[index].name = p_node->name;
|
||||||
|
+ p_module->specialization_constants[index].constant_id = p_node->decorations.specialization_constant.value;
|
||||||
|
+ p_module->specialization_constants[index].spirv_id = p_node->result_id;
|
||||||
|
+ index++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return SPV_REFLECT_RESULT_SUCCESS;
|
||||||
|
+}
|
||||||
|
+// -- GODOT end --
|
||||||
|
+
|
||||||
|
static SpvReflectResult ParsePushConstantBlocks(Parser* p_parser, SpvReflectShaderModule* p_module)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < p_parser->node_count; ++i) {
|
||||||
|
@@ -3562,6 +3654,12 @@ SpvReflectResult spvReflectCreateShaderModule(
|
||||||
|
result = ParsePushConstantBlocks(&parser, p_module);
|
||||||
|
SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
|
||||||
|
}
|
||||||
|
+// -- GODOT begin --
|
||||||
|
+ if (result == SPV_REFLECT_RESULT_SUCCESS) {
|
||||||
|
+ result = ParseSpecializationConstants(&parser, p_module);
|
||||||
|
+ SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
|
||||||
|
+ }
|
||||||
|
+// -- GODOT end --
|
||||||
|
if (result == SPV_REFLECT_RESULT_SUCCESS) {
|
||||||
|
result = ParseEntryPoints(&parser, p_module);
|
||||||
|
SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
|
||||||
|
@@ -3691,6 +3789,9 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module)
|
||||||
|
SafeFree(p_entry->used_push_constants);
|
||||||
|
}
|
||||||
|
SafeFree(p_module->entry_points);
|
||||||
|
+// -- GODOT begin --
|
||||||
|
+ SafeFree(p_module->specialization_constants);
|
||||||
|
+// -- GODOT end --
|
||||||
|
|
||||||
|
// Push constants
|
||||||
|
for (size_t i = 0; i < p_module->push_constant_block_count; ++i) {
|
||||||
|
@@ -3959,6 +4060,38 @@ SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables(
|
||||||
|
return SPV_REFLECT_RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
+// -- GODOT begin --
|
||||||
|
+SpvReflectResult spvReflectEnumerateSpecializationConstants(
|
||||||
|
+ const SpvReflectShaderModule* p_module,
|
||||||
|
+ uint32_t* p_count,
|
||||||
|
+ SpvReflectSpecializationConstant** pp_constants
|
||||||
|
+)
|
||||||
|
+{
|
||||||
|
+ if (IsNull(p_module)) {
|
||||||
|
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
|
||||||
|
+ }
|
||||||
|
+ if (IsNull(p_count)) {
|
||||||
|
+ return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (IsNotNull(pp_constants)) {
|
||||||
|
+ if (*p_count != p_module->specialization_constant_count) {
|
||||||
|
+ return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (uint32_t index = 0; index < *p_count; ++index) {
|
||||||
|
+ SpvReflectSpecializationConstant *p_const = &p_module->specialization_constants[index];
|
||||||
|
+ pp_constants[index] = p_const;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ *p_count = p_module->specialization_constant_count;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return SPV_REFLECT_RESULT_SUCCESS;
|
||||||
|
+}
|
||||||
|
+// -- GODOT end --
|
||||||
|
+
|
||||||
|
SpvReflectResult spvReflectEnumerateInputVariables(
|
||||||
|
const SpvReflectShaderModule* p_module,
|
||||||
|
uint32_t* p_count,
|
||||||
|
diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h
|
||||||
|
index a5a956e9e8..21f8160770 100644
|
||||||
|
--- a/thirdparty/spirv-reflect/spirv_reflect.h
|
||||||
|
+++ b/thirdparty/spirv-reflect/spirv_reflect.h
|
||||||
|
@@ -292,6 +292,28 @@ typedef struct SpvReflectTypeDescription {
|
||||||
|
struct SpvReflectTypeDescription* members;
|
||||||
|
} SpvReflectTypeDescription;
|
||||||
|
|
||||||
|
+// -- GODOT begin --
|
||||||
|
+/*! @struct SpvReflectSpecializationConstant
|
||||||
|
+
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
+typedef enum SpvReflectSpecializationConstantType {
|
||||||
|
+ SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL = 0,
|
||||||
|
+ SPV_REFLECT_SPECIALIZATION_CONSTANT_INT = 1,
|
||||||
|
+ SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT = 2,
|
||||||
|
+} SpvReflectSpecializationConstantType;
|
||||||
|
+
|
||||||
|
+typedef struct SpvReflectSpecializationConstant {
|
||||||
|
+ const char* name;
|
||||||
|
+ uint32_t spirv_id;
|
||||||
|
+ uint32_t constant_id;
|
||||||
|
+ SpvReflectSpecializationConstantType constant_type;
|
||||||
|
+ union {
|
||||||
|
+ float float_value;
|
||||||
|
+ uint32_t int_bool_value;
|
||||||
|
+ } default_value;
|
||||||
|
+} SpvReflectSpecializationConstant;
|
||||||
|
+// -- GODOT end --
|
||||||
|
|
||||||
|
/*! @struct SpvReflectInterfaceVariable
|
||||||
|
|
||||||
|
@@ -439,6 +461,10 @@ typedef struct SpvReflectShaderModule {
|
||||||
|
SpvReflectInterfaceVariable* interface_variables;
|
||||||
|
uint32_t push_constant_block_count;
|
||||||
|
SpvReflectBlockVariable* push_constant_blocks;
|
||||||
|
+ // -- GODOT begin --
|
||||||
|
+ uint32_t specialization_constant_count;
|
||||||
|
+ SpvReflectSpecializationConstant* specialization_constants;
|
||||||
|
+ // -- GODOT end --
|
||||||
|
|
||||||
|
struct Internal {
|
||||||
|
size_t spirv_size;
|
||||||
|
@@ -694,6 +720,33 @@ SpvReflectResult spvReflectEnumerateInputVariables(
|
||||||
|
SpvReflectInterfaceVariable** pp_variables
|
||||||
|
);
|
||||||
|
|
||||||
|
+// -- GOODT begin --
|
||||||
|
+/*! @fn spvReflectEnumerateSpecializationConstants
|
||||||
|
+ @brief If the module contains multiple entry points, this will only get
|
||||||
|
+ the specialization constants for the first one.
|
||||||
|
+ @param p_module Pointer to an instance of SpvReflectShaderModule.
|
||||||
|
+ @param p_count If pp_constants is NULL, the module's specialization constant
|
||||||
|
+ count will be stored here.
|
||||||
|
+ If pp_variables is not NULL, *p_count must contain
|
||||||
|
+ the module's specialization constant count.
|
||||||
|
+ @param pp_variables If NULL, the module's specialization constant count will be
|
||||||
|
+ written to *p_count.
|
||||||
|
+ If non-NULL, pp_constants must point to an array with
|
||||||
|
+ *p_count entries, where pointers to the module's
|
||||||
|
+ specialization constants will be written. The caller must not
|
||||||
|
+ free the specialization constants written to this array.
|
||||||
|
+ @return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
|
||||||
|
+ Otherwise, the error code indicates the cause of the
|
||||||
|
+ failure.
|
||||||
|
+
|
||||||
|
+*/
|
||||||
|
+SpvReflectResult spvReflectEnumerateSpecializationConstants(
|
||||||
|
+ const SpvReflectShaderModule* p_module,
|
||||||
|
+ uint32_t* p_count,
|
||||||
|
+ SpvReflectSpecializationConstant** pp_constants
|
||||||
|
+);
|
||||||
|
+// -- GODOT end --
|
||||||
|
+
|
||||||
|
/*! @fn spvReflectEnumerateEntryPointInputVariables
|
||||||
|
@brief Enumerate the input variables for a given entry point.
|
||||||
|
@param entry_point The name of the entry point to get the input variables for.
|
139
thirdparty/spirv-reflect/spirv_reflect.c
vendored
139
thirdparty/spirv-reflect/spirv_reflect.c
vendored
|
@ -124,6 +124,9 @@ typedef struct Decorations {
|
||||||
NumberDecoration location;
|
NumberDecoration location;
|
||||||
NumberDecoration offset;
|
NumberDecoration offset;
|
||||||
NumberDecoration uav_counter_buffer;
|
NumberDecoration uav_counter_buffer;
|
||||||
|
// -- GODOT begin --
|
||||||
|
NumberDecoration specialization_constant;
|
||||||
|
// -- GODOT end --
|
||||||
StringDecoration semantic;
|
StringDecoration semantic;
|
||||||
uint32_t array_stride;
|
uint32_t array_stride;
|
||||||
uint32_t matrix_stride;
|
uint32_t matrix_stride;
|
||||||
|
@ -610,6 +613,9 @@ static SpvReflectResult ParseNodes(Parser* p_parser)
|
||||||
p_parser->nodes[i].decorations.offset.value = (uint32_t)INVALID_VALUE;
|
p_parser->nodes[i].decorations.offset.value = (uint32_t)INVALID_VALUE;
|
||||||
p_parser->nodes[i].decorations.uav_counter_buffer.value = (uint32_t)INVALID_VALUE;
|
p_parser->nodes[i].decorations.uav_counter_buffer.value = (uint32_t)INVALID_VALUE;
|
||||||
p_parser->nodes[i].decorations.built_in = (SpvBuiltIn)INVALID_VALUE;
|
p_parser->nodes[i].decorations.built_in = (SpvBuiltIn)INVALID_VALUE;
|
||||||
|
// -- GODOT begin --
|
||||||
|
p_parser->nodes[i].decorations.specialization_constant.value = (SpvBuiltIn)INVALID_VALUE;
|
||||||
|
// -- GODOT end --
|
||||||
}
|
}
|
||||||
// Mark source file id node
|
// Mark source file id node
|
||||||
p_parser->source_file_id = (uint32_t)INVALID_VALUE;
|
p_parser->source_file_id = (uint32_t)INVALID_VALUE;
|
||||||
|
@ -800,10 +806,16 @@ static SpvReflectResult ParseNodes(Parser* p_parser)
|
||||||
CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
|
CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
// -- GODOT begin --
|
||||||
case SpvOpSpecConstantTrue:
|
case SpvOpSpecConstantTrue:
|
||||||
case SpvOpSpecConstantFalse:
|
case SpvOpSpecConstantFalse:
|
||||||
case SpvOpSpecConstant:
|
case SpvOpSpecConstant: {
|
||||||
|
CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
|
||||||
|
CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
|
||||||
|
p_node->is_type = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// -- GODOT end --
|
||||||
case SpvOpSpecConstantComposite:
|
case SpvOpSpecConstantComposite:
|
||||||
case SpvOpSpecConstantOp: {
|
case SpvOpSpecConstantOp: {
|
||||||
CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
|
CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
|
||||||
|
@ -1309,6 +1321,9 @@ static SpvReflectResult ParseDecorations(Parser* p_parser)
|
||||||
skip = true;
|
skip = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
// -- GODOT begin --
|
||||||
|
case SpvDecorationSpecId:
|
||||||
|
// -- GODOT end --
|
||||||
case SpvDecorationBlock:
|
case SpvDecorationBlock:
|
||||||
case SpvDecorationBufferBlock:
|
case SpvDecorationBufferBlock:
|
||||||
case SpvDecorationColMajor:
|
case SpvDecorationColMajor:
|
||||||
|
@ -1441,7 +1456,14 @@ static SpvReflectResult ParseDecorations(Parser* p_parser)
|
||||||
p_target_decorations->input_attachment_index.word_offset = word_offset;
|
p_target_decorations->input_attachment_index.word_offset = word_offset;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
// -- GODOT begin --
|
||||||
|
case SpvDecorationSpecId: {
|
||||||
|
uint32_t word_offset = p_node->word_offset + member_offset+ 3;
|
||||||
|
CHECKED_READU32(p_parser, word_offset, p_target_decorations->specialization_constant.value);
|
||||||
|
p_target_decorations->specialization_constant.word_offset = word_offset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// -- GODOT end --
|
||||||
case SpvReflectDecorationHlslCounterBufferGOOGLE: {
|
case SpvReflectDecorationHlslCounterBufferGOOGLE: {
|
||||||
uint32_t word_offset = p_node->word_offset + member_offset+ 3;
|
uint32_t word_offset = p_node->word_offset + member_offset+ 3;
|
||||||
CHECKED_READU32(p_parser, word_offset, p_target_decorations->uav_counter_buffer.value);
|
CHECKED_READU32(p_parser, word_offset, p_target_decorations->uav_counter_buffer.value);
|
||||||
|
@ -1731,6 +1753,13 @@ static SpvReflectResult ParseType(
|
||||||
p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE;
|
p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
// -- GODOT begin --
|
||||||
|
case SpvOpSpecConstantTrue:
|
||||||
|
case SpvOpSpecConstantFalse:
|
||||||
|
case SpvOpSpecConstant: {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// -- GODOT end --
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == SPV_REFLECT_RESULT_SUCCESS) {
|
if (result == SPV_REFLECT_RESULT_SUCCESS) {
|
||||||
|
@ -3187,6 +3216,69 @@ static SpvReflectResult ParseExecutionModes(Parser* p_parser, SpvReflectShaderMo
|
||||||
return SPV_REFLECT_RESULT_SUCCESS;
|
return SPV_REFLECT_RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- GODOT begin --
|
||||||
|
static SpvReflectResult ParseSpecializationConstants(Parser* p_parser, SpvReflectShaderModule* p_module)
|
||||||
|
{
|
||||||
|
p_module->specialization_constant_count = 0;
|
||||||
|
p_module->specialization_constants = NULL;
|
||||||
|
for (size_t i = 0; i < p_parser->node_count; ++i) {
|
||||||
|
Node* p_node = &(p_parser->nodes[i]);
|
||||||
|
if (p_node->op == SpvOpSpecConstantTrue || p_node->op == SpvOpSpecConstantFalse || p_node->op == SpvOpSpecConstant) {
|
||||||
|
p_module->specialization_constant_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_module->specialization_constant_count == 0) {
|
||||||
|
return SPV_REFLECT_RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_module->specialization_constants = (SpvReflectSpecializationConstant*)calloc(p_module->specialization_constant_count, sizeof(SpvReflectSpecializationConstant));
|
||||||
|
|
||||||
|
uint32_t index = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < p_parser->node_count; ++i) {
|
||||||
|
Node* p_node = &(p_parser->nodes[i]);
|
||||||
|
switch(p_node->op) {
|
||||||
|
default: continue;
|
||||||
|
case SpvOpSpecConstantTrue: {
|
||||||
|
p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL;
|
||||||
|
p_module->specialization_constants[index].default_value.int_bool_value = 1;
|
||||||
|
} break;
|
||||||
|
case SpvOpSpecConstantFalse: {
|
||||||
|
p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL;
|
||||||
|
p_module->specialization_constants[index].default_value.int_bool_value = 0;
|
||||||
|
} break;
|
||||||
|
case SpvOpSpecConstant: {
|
||||||
|
SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS;
|
||||||
|
uint32_t element_type_id = (uint32_t)INVALID_VALUE;
|
||||||
|
uint32_t default_value = 0;
|
||||||
|
IF_READU32(result, p_parser, p_node->word_offset + 1, element_type_id);
|
||||||
|
IF_READU32(result, p_parser, p_node->word_offset + 3, default_value);
|
||||||
|
|
||||||
|
Node* p_next_node = FindNode(p_parser, element_type_id);
|
||||||
|
|
||||||
|
if (p_next_node->op == SpvOpTypeInt) {
|
||||||
|
p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_INT;
|
||||||
|
} else if (p_next_node->op == SpvOpTypeFloat) {
|
||||||
|
p_module->specialization_constants[index].constant_type = SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT;
|
||||||
|
} else {
|
||||||
|
return SPV_REFLECT_RESULT_ERROR_PARSE_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_module->specialization_constants[index].default_value.int_bool_value = default_value; //bits are the same for int and float
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_module->specialization_constants[index].name = p_node->name;
|
||||||
|
p_module->specialization_constants[index].constant_id = p_node->decorations.specialization_constant.value;
|
||||||
|
p_module->specialization_constants[index].spirv_id = p_node->result_id;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SPV_REFLECT_RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
// -- GODOT end --
|
||||||
|
|
||||||
static SpvReflectResult ParsePushConstantBlocks(Parser* p_parser, SpvReflectShaderModule* p_module)
|
static SpvReflectResult ParsePushConstantBlocks(Parser* p_parser, SpvReflectShaderModule* p_module)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < p_parser->node_count; ++i) {
|
for (size_t i = 0; i < p_parser->node_count; ++i) {
|
||||||
|
@ -3562,6 +3654,12 @@ SpvReflectResult spvReflectCreateShaderModule(
|
||||||
result = ParsePushConstantBlocks(&parser, p_module);
|
result = ParsePushConstantBlocks(&parser, p_module);
|
||||||
SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
|
SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
// -- GODOT begin --
|
||||||
|
if (result == SPV_REFLECT_RESULT_SUCCESS) {
|
||||||
|
result = ParseSpecializationConstants(&parser, p_module);
|
||||||
|
SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
|
||||||
|
}
|
||||||
|
// -- GODOT end --
|
||||||
if (result == SPV_REFLECT_RESULT_SUCCESS) {
|
if (result == SPV_REFLECT_RESULT_SUCCESS) {
|
||||||
result = ParseEntryPoints(&parser, p_module);
|
result = ParseEntryPoints(&parser, p_module);
|
||||||
SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
|
SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
|
||||||
|
@ -3691,6 +3789,9 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module)
|
||||||
SafeFree(p_entry->used_push_constants);
|
SafeFree(p_entry->used_push_constants);
|
||||||
}
|
}
|
||||||
SafeFree(p_module->entry_points);
|
SafeFree(p_module->entry_points);
|
||||||
|
// -- GODOT begin --
|
||||||
|
SafeFree(p_module->specialization_constants);
|
||||||
|
// -- GODOT end --
|
||||||
|
|
||||||
// Push constants
|
// Push constants
|
||||||
for (size_t i = 0; i < p_module->push_constant_block_count; ++i) {
|
for (size_t i = 0; i < p_module->push_constant_block_count; ++i) {
|
||||||
|
@ -3959,6 +4060,38 @@ SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables(
|
||||||
return SPV_REFLECT_RESULT_SUCCESS;
|
return SPV_REFLECT_RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- GODOT begin --
|
||||||
|
SpvReflectResult spvReflectEnumerateSpecializationConstants(
|
||||||
|
const SpvReflectShaderModule* p_module,
|
||||||
|
uint32_t* p_count,
|
||||||
|
SpvReflectSpecializationConstant** pp_constants
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (IsNull(p_module)) {
|
||||||
|
return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
if (IsNull(p_count)) {
|
||||||
|
return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsNotNull(pp_constants)) {
|
||||||
|
if (*p_count != p_module->specialization_constant_count) {
|
||||||
|
return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t index = 0; index < *p_count; ++index) {
|
||||||
|
SpvReflectSpecializationConstant *p_const = &p_module->specialization_constants[index];
|
||||||
|
pp_constants[index] = p_const;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*p_count = p_module->specialization_constant_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SPV_REFLECT_RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
// -- GODOT end --
|
||||||
|
|
||||||
SpvReflectResult spvReflectEnumerateInputVariables(
|
SpvReflectResult spvReflectEnumerateInputVariables(
|
||||||
const SpvReflectShaderModule* p_module,
|
const SpvReflectShaderModule* p_module,
|
||||||
uint32_t* p_count,
|
uint32_t* p_count,
|
||||||
|
|
53
thirdparty/spirv-reflect/spirv_reflect.h
vendored
53
thirdparty/spirv-reflect/spirv_reflect.h
vendored
|
@ -292,6 +292,28 @@ typedef struct SpvReflectTypeDescription {
|
||||||
struct SpvReflectTypeDescription* members;
|
struct SpvReflectTypeDescription* members;
|
||||||
} SpvReflectTypeDescription;
|
} SpvReflectTypeDescription;
|
||||||
|
|
||||||
|
// -- GODOT begin --
|
||||||
|
/*! @struct SpvReflectSpecializationConstant
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum SpvReflectSpecializationConstantType {
|
||||||
|
SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL = 0,
|
||||||
|
SPV_REFLECT_SPECIALIZATION_CONSTANT_INT = 1,
|
||||||
|
SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT = 2,
|
||||||
|
} SpvReflectSpecializationConstantType;
|
||||||
|
|
||||||
|
typedef struct SpvReflectSpecializationConstant {
|
||||||
|
const char* name;
|
||||||
|
uint32_t spirv_id;
|
||||||
|
uint32_t constant_id;
|
||||||
|
SpvReflectSpecializationConstantType constant_type;
|
||||||
|
union {
|
||||||
|
float float_value;
|
||||||
|
uint32_t int_bool_value;
|
||||||
|
} default_value;
|
||||||
|
} SpvReflectSpecializationConstant;
|
||||||
|
// -- GODOT end --
|
||||||
|
|
||||||
/*! @struct SpvReflectInterfaceVariable
|
/*! @struct SpvReflectInterfaceVariable
|
||||||
|
|
||||||
|
@ -439,6 +461,10 @@ typedef struct SpvReflectShaderModule {
|
||||||
SpvReflectInterfaceVariable* interface_variables;
|
SpvReflectInterfaceVariable* interface_variables;
|
||||||
uint32_t push_constant_block_count;
|
uint32_t push_constant_block_count;
|
||||||
SpvReflectBlockVariable* push_constant_blocks;
|
SpvReflectBlockVariable* push_constant_blocks;
|
||||||
|
// -- GODOT begin --
|
||||||
|
uint32_t specialization_constant_count;
|
||||||
|
SpvReflectSpecializationConstant* specialization_constants;
|
||||||
|
// -- GODOT end --
|
||||||
|
|
||||||
struct Internal {
|
struct Internal {
|
||||||
size_t spirv_size;
|
size_t spirv_size;
|
||||||
|
@ -694,6 +720,33 @@ SpvReflectResult spvReflectEnumerateInputVariables(
|
||||||
SpvReflectInterfaceVariable** pp_variables
|
SpvReflectInterfaceVariable** pp_variables
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// -- GOODT begin --
|
||||||
|
/*! @fn spvReflectEnumerateSpecializationConstants
|
||||||
|
@brief If the module contains multiple entry points, this will only get
|
||||||
|
the specialization constants for the first one.
|
||||||
|
@param p_module Pointer to an instance of SpvReflectShaderModule.
|
||||||
|
@param p_count If pp_constants is NULL, the module's specialization constant
|
||||||
|
count will be stored here.
|
||||||
|
If pp_variables is not NULL, *p_count must contain
|
||||||
|
the module's specialization constant count.
|
||||||
|
@param pp_variables If NULL, the module's specialization constant count will be
|
||||||
|
written to *p_count.
|
||||||
|
If non-NULL, pp_constants must point to an array with
|
||||||
|
*p_count entries, where pointers to the module's
|
||||||
|
specialization constants will be written. The caller must not
|
||||||
|
free the specialization constants written to this array.
|
||||||
|
@return If successful, returns SPV_REFLECT_RESULT_SUCCESS.
|
||||||
|
Otherwise, the error code indicates the cause of the
|
||||||
|
failure.
|
||||||
|
|
||||||
|
*/
|
||||||
|
SpvReflectResult spvReflectEnumerateSpecializationConstants(
|
||||||
|
const SpvReflectShaderModule* p_module,
|
||||||
|
uint32_t* p_count,
|
||||||
|
SpvReflectSpecializationConstant** pp_constants
|
||||||
|
);
|
||||||
|
// -- GODOT end --
|
||||||
|
|
||||||
/*! @fn spvReflectEnumerateEntryPointInputVariables
|
/*! @fn spvReflectEnumerateEntryPointInputVariables
|
||||||
@brief Enumerate the input variables for a given entry point.
|
@brief Enumerate the input variables for a given entry point.
|
||||||
@param entry_point The name of the entry point to get the input variables for.
|
@param entry_point The name of the entry point to get the input variables for.
|
||||||
|
|
Loading…
Reference in a new issue