mirror of
https://github.com/godotengine/godot.git
synced 2024-11-24 21:22:48 +00:00
Replaced GLSLang reflection by SPIRV-Reflect, eventually allowing to move GLSLang out.
This commit is contained in:
parent
0586e18449
commit
60c7498cee
@ -33,6 +33,7 @@ else:
|
||||
|
||||
# Core dependencies
|
||||
SConscript("png/SCsub")
|
||||
SConscript("spirv-reflect/SCsub")
|
||||
|
||||
if env['vsproj']:
|
||||
import os
|
||||
|
16
drivers/spirv-reflect/SCsub
Normal file
16
drivers/spirv-reflect/SCsub
Normal file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
Import('env')
|
||||
|
||||
env_spirv_reflect = env.Clone()
|
||||
|
||||
thirdparty_dir = "#thirdparty/spirv-reflect/"
|
||||
thirdparty_sources = [
|
||||
"spirv_reflect.c"
|
||||
]
|
||||
|
||||
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
|
||||
|
||||
env_spirv_reflect.add_source_files(env.drivers_sources, thirdparty_sources)
|
||||
|
||||
Export('env')
|
@ -1,10 +1,11 @@
|
||||
#include "rendering_device_vulkan.h"
|
||||
#include "drivers/vulkan/vulkan_context.h"
|
||||
|
||||
#include "core/hashfuncs.h"
|
||||
#include "core/os/file_access.h"
|
||||
#include "core/project_settings.h"
|
||||
#include "drivers/vulkan/vulkan_context.h"
|
||||
#include "thirdparty/glslang/SPIRV/GlslangToSpv.h"
|
||||
#include "thirdparty/glslang/glslang/Include/Types.h"
|
||||
#include "thirdparty/spirv-reflect/spirv_reflect.h"
|
||||
|
||||
void RenderingDeviceVulkan::_add_dependency(RID p_id, RID p_depends_on) {
|
||||
|
||||
@ -2371,7 +2372,6 @@ PoolVector<uint8_t> RenderingDeviceVulkan::texture_get_data(RID p_texture, uint3
|
||||
image_copy_region.extent.depth = mm_depth;
|
||||
|
||||
vkCmdCopyImage(command_buffer, tex->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy_region);
|
||||
print_line("copying mipmap " + itos(i) + " w: " + itos(mm_width) + " h " + itos(mm_height) + " d " + itos(mm_depth));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3568,7 +3568,7 @@ RID RenderingDeviceVulkan::shader_create_from_source(const Vector<ShaderStageSou
|
||||
glslang::TShader::ForbidIncluder includer;
|
||||
|
||||
//descriptor layouts
|
||||
Vector<Vector<VkDescriptorSetLayoutBinding> > bindings;
|
||||
Vector<Vector<VkDescriptorSetLayoutBinding> > set_bindings;
|
||||
Vector<Vector<UniformInfo> > uniform_info;
|
||||
Shader::PushConstant push_constant;
|
||||
push_constant.push_constant_size = 0;
|
||||
@ -3652,11 +3652,27 @@ RID RenderingDeviceVulkan::shader_create_from_source(const Vector<ShaderStageSou
|
||||
return RID();
|
||||
}
|
||||
|
||||
#if 0
|
||||
//obtain bindings for descriptor layout
|
||||
program.mapIO();
|
||||
program.buildReflection(EShReflectionAllBlockVariables);
|
||||
//program.dumpReflection();
|
||||
|
||||
for (int j = 0; j < program.getNumUniformBlocks(); j++) {
|
||||
const glslang::TObjectReflection &reflection = program.getUniformBlock(j);
|
||||
if (reflection.getType()->getBasicType() == glslang::EbtBlock && reflection.getType()->getQualifier().storage == glslang::EvqUniform && reflection.getType()->getQualifier().layoutPushConstant) {
|
||||
uint32_t len = reflection.size;
|
||||
if (push_constant_debug.push_constant_size != 0 && push_constant_debug.push_constant_size != len) {
|
||||
print_line("eep");
|
||||
}
|
||||
|
||||
push_constant_debug.push_constant_size = len;
|
||||
push_constant_debug.push_constants_vk_stage |= shader_stage_masks[p_stages[i].shader_stage];
|
||||
//print_line("Debug stage " + String(shader_stage_names[p_stages[i].shader_stage]) + " push constant size: " + itos(push_constant_debug.push_constant_size));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < program.getNumUniformVariables(); j++) {
|
||||
if (!_uniform_add_binding(bindings, uniform_info, program.getUniform(j), p_stages[i].shader_stage, push_constant, r_error)) {
|
||||
return RID();
|
||||
@ -3698,11 +3714,233 @@ RID RenderingDeviceVulkan::shader_create_from_source(const Vector<ShaderStageSou
|
||||
fragment_outputs = program.getNumPipeOutputs();
|
||||
}
|
||||
|
||||
#endif
|
||||
std::vector<uint32_t> SpirV;
|
||||
spv::SpvBuildLogger logger;
|
||||
glslang::SpvOptions spvOptions;
|
||||
glslang::GlslangToSpv(*program.getIntermediate(stages[p_stages[i].shader_stage]), SpirV, &logger, &spvOptions);
|
||||
|
||||
{
|
||||
SpvReflectShaderModule module;
|
||||
SpvReflectResult result = spvReflectCreateShaderModule(SpirV.size() * sizeof(uint32_t), &SpirV[0], &module);
|
||||
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 parsing shader.");
|
||||
|
||||
uint32_t binding_count = 0;
|
||||
result = spvReflectEnumerateDescriptorBindings(&module, &binding_count, NULL);
|
||||
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 descriptor bindings.");
|
||||
|
||||
uint32_t stage = p_stages[i].shader_stage;
|
||||
|
||||
if (binding_count > 0) {
|
||||
|
||||
//Parse bindings
|
||||
|
||||
Vector<SpvReflectDescriptorBinding *> bindings;
|
||||
bindings.resize(binding_count);
|
||||
result = spvReflectEnumerateDescriptorBindings(&module, &binding_count, bindings.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 getting descriptor bindings.");
|
||||
|
||||
for (uint32_t j = 0; j < binding_count; j++) {
|
||||
const SpvReflectDescriptorBinding &binding = *bindings[j];
|
||||
|
||||
VkDescriptorSetLayoutBinding layout_binding;
|
||||
UniformInfo info;
|
||||
|
||||
bool need_array_dimensions = false;
|
||||
bool need_block_size = false;
|
||||
|
||||
switch (binding.descriptor_type) {
|
||||
case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER: {
|
||||
layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
|
||||
info.type = UNIFORM_TYPE_SAMPLER;
|
||||
need_array_dimensions = true;
|
||||
} break;
|
||||
case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
|
||||
layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
info.type = UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
|
||||
need_array_dimensions = true;
|
||||
} break;
|
||||
case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {
|
||||
layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
info.type = UNIFORM_TYPE_TEXTURE;
|
||||
need_array_dimensions = true;
|
||||
} break;
|
||||
case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
|
||||
layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
info.type = UNIFORM_TYPE_IMAGE;
|
||||
need_array_dimensions = true;
|
||||
} break;
|
||||
case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: {
|
||||
layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
|
||||
info.type = UNIFORM_TYPE_TEXTURE_BUFFER;
|
||||
need_array_dimensions = true;
|
||||
} break;
|
||||
case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
|
||||
layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
|
||||
info.type = UNIFORM_TYPE_IMAGE_BUFFER;
|
||||
need_array_dimensions = true;
|
||||
} break;
|
||||
case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER: {
|
||||
layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
info.type = UNIFORM_TYPE_UNIFORM_BUFFER;
|
||||
need_block_size = true;
|
||||
} break;
|
||||
case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER: {
|
||||
layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
info.type = UNIFORM_TYPE_STORAGE_BUFFER;
|
||||
need_block_size = true;
|
||||
} break;
|
||||
case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: {
|
||||
ERR_PRINT("Dynamic uniform buffer not supported.");
|
||||
continue;
|
||||
} break;
|
||||
case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
|
||||
ERR_PRINT("Dynamic storage buffer not supported.");
|
||||
continue;
|
||||
} break;
|
||||
case SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
|
||||
layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
||||
info.type = UNIFORM_TYPE_INPUT_ATTACHMENT;
|
||||
} break;
|
||||
}
|
||||
|
||||
if (need_array_dimensions) {
|
||||
if (binding.array.dims_count == 0) {
|
||||
info.length = 1;
|
||||
} else {
|
||||
for (uint32_t k = 0; k < binding.array.dims_count; k++) {
|
||||
if (k == 0) {
|
||||
info.length = binding.array.dims[0];
|
||||
} else {
|
||||
info.length *= binding.array.dims[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layout_binding.descriptorCount = info.length;
|
||||
|
||||
} else if (need_block_size) {
|
||||
info.length = binding.block.size;
|
||||
layout_binding.descriptorCount = 1;
|
||||
} else {
|
||||
info.length = 0;
|
||||
layout_binding.descriptorCount = 1;
|
||||
}
|
||||
|
||||
info.binding = binding.binding;
|
||||
uint32_t set = binding.set;
|
||||
|
||||
//print_line("Stage: " + String(shader_stage_names[stage]) + " set=" + itos(set) + " binding=" + itos(info.binding) + " type=" + shader_uniform_names[info.type] + " length=" + itos(info.length));
|
||||
|
||||
ERR_FAIL_COND_V_MSG(set >= MAX_UNIFORM_SETS, RID(),
|
||||
"On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' uses a set (" + itos(set) + ") index larger than what is supported (" + itos(MAX_UNIFORM_SETS) + ").");
|
||||
|
||||
ERR_FAIL_COND_V_MSG(set >= limits.maxBoundDescriptorSets, RID(),
|
||||
"On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' uses a set (" + itos(set) + ") index larger than what is supported by the hardware (" + itos(limits.maxBoundDescriptorSets) + ").");
|
||||
|
||||
if (set < (uint32_t)set_bindings.size()) {
|
||||
//check if this already exists
|
||||
bool exists = false;
|
||||
for (int k = 0; k < set_bindings[set].size(); k++) {
|
||||
if (set_bindings[set][k].binding == (uint32_t)info.binding) {
|
||||
//already exists, verify that it's the same type
|
||||
ERR_FAIL_COND_V_MSG(set_bindings[set][k].descriptorType != layout_binding.descriptorType, RID(),
|
||||
"On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(info.binding) + " with different uniform type.");
|
||||
|
||||
//also, verify that it's the same size
|
||||
ERR_FAIL_COND_V_MSG(set_bindings[set][k].descriptorCount != layout_binding.descriptorCount || uniform_info[set][k].length != info.length, RID(),
|
||||
"On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(info.binding) + " with different uniform size.");
|
||||
|
||||
//just append stage mask and return
|
||||
set_bindings.write[set].write[k].stageFlags |= shader_stage_masks[stage];
|
||||
uniform_info.write[set].write[k].stages |= 1 << stage;
|
||||
exists = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
continue; //merged
|
||||
}
|
||||
}
|
||||
|
||||
layout_binding.binding = info.binding;
|
||||
layout_binding.stageFlags = shader_stage_masks[stage];
|
||||
layout_binding.pImmutableSamplers = NULL; //no support for this yet
|
||||
|
||||
info.stages = 1 << stage;
|
||||
info.binding = info.binding;
|
||||
|
||||
if (set >= (uint32_t)set_bindings.size()) {
|
||||
set_bindings.resize(set + 1);
|
||||
uniform_info.resize(set + 1);
|
||||
}
|
||||
|
||||
set_bindings.write[set].push_back(layout_binding);
|
||||
uniform_info.write[set].push_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
if (stage == SHADER_STAGE_FRAGMENT) {
|
||||
|
||||
uint32_t ov_count = 0;
|
||||
result = spvReflectEnumerateOutputVariables(&module, &ov_count, NULL);
|
||||
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 output variables.");
|
||||
|
||||
if (ov_count) {
|
||||
Vector<SpvReflectInterfaceVariable *> output_vars;
|
||||
output_vars.resize(ov_count);
|
||||
|
||||
result = spvReflectEnumerateOutputVariables(&module, &ov_count, output_vars.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 output variables.");
|
||||
|
||||
for (uint32_t j = 0; j < ov_count; j++) {
|
||||
if (output_vars[j]) {
|
||||
fragment_outputs = MAX(fragment_outputs, output_vars[j]->location + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t pc_count = 0;
|
||||
result = spvReflectEnumeratePushConstantBlocks(&module, &pc_count, NULL);
|
||||
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 push constants.");
|
||||
|
||||
if (pc_count) {
|
||||
ERR_FAIL_COND_V_MSG(pc_count > 1, RID(),
|
||||
"Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "': Only one push constant is supported, which should be the same across shader stages.");
|
||||
|
||||
Vector<SpvReflectBlockVariable *> pconstants;
|
||||
pconstants.resize(pc_count);
|
||||
result = spvReflectEnumeratePushConstantBlocks(&module, &pc_count, pconstants.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 push constants.");
|
||||
#if 0
|
||||
if (pconstants[0] == NULL) {
|
||||
FileAccess *f = FileAccess::open("res://popo.spv", FileAccess::WRITE);
|
||||
f->store_buffer((const uint8_t *)&SpirV[0], SpirV.size() * sizeof(uint32_t));
|
||||
memdelete(f);
|
||||
}
|
||||
#endif
|
||||
|
||||
ERR_FAIL_COND_V_MSG(push_constant.push_constant_size && push_constant.push_constant_size != pconstants[0]->size, RID(),
|
||||
"Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "': Push constant block must be the same across shader stages.");
|
||||
|
||||
push_constant.push_constant_size = pconstants[0]->size;
|
||||
push_constant.push_constants_vk_stage |= shader_stage_masks[stage];
|
||||
|
||||
//print_line("Stage: " + String(shader_stage_names[stage]) + " push constant of size=" + itos(push_constant.push_constant_size));
|
||||
}
|
||||
|
||||
// Destroy the reflection data when no longer required.
|
||||
spvReflectDestroyShaderModule(&module);
|
||||
}
|
||||
|
||||
spirv_code.push_back(SpirV);
|
||||
|
||||
stages_processed |= (1 << p_stages[i].shader_stage);
|
||||
@ -3758,15 +3996,15 @@ RID RenderingDeviceVulkan::shader_create_from_source(const Vector<ShaderStageSou
|
||||
|
||||
if (success) {
|
||||
|
||||
for (int i = 0; i < bindings.size(); i++) {
|
||||
for (int i = 0; i < set_bindings.size(); i++) {
|
||||
|
||||
//empty ones are fine if they were not used according to spec (binding count will be 0)
|
||||
VkDescriptorSetLayoutCreateInfo layout_create_info;
|
||||
layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
layout_create_info.pNext = NULL;
|
||||
layout_create_info.flags = 0;
|
||||
layout_create_info.bindingCount = bindings[i].size();
|
||||
layout_create_info.pBindings = bindings[i].ptr();
|
||||
layout_create_info.bindingCount = set_bindings[i].size();
|
||||
layout_create_info.pBindings = set_bindings[i].ptr();
|
||||
|
||||
VkDescriptorSetLayout layout;
|
||||
VkResult res = vkCreateDescriptorSetLayout(device, &layout_create_info, NULL, &layout);
|
||||
@ -4108,7 +4346,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
|
||||
const Uniform &uniform = uniforms[uniform_idx];
|
||||
|
||||
ERR_FAIL_COND_V_MSG(uniform.type != set_uniform.type, RID(),
|
||||
"Mismatch uniform type for binding (" + itos(set_uniform.binding) + ").");
|
||||
"Mismatch uniform type for binding (" + itos(set_uniform.binding) + "). Expected '" + shader_uniform_names[set_uniform.type] + "', supplied: '" + shader_uniform_names[uniform.type] + "'.");
|
||||
|
||||
VkWriteDescriptorSet write; //common header
|
||||
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
@ -6048,7 +6286,6 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context) {
|
||||
}
|
||||
texture_upload_region_size_px = GLOBAL_DEF("rendering/vulkan/staging_buffer/texture_upload_region_size_px", 64);
|
||||
texture_upload_region_size_px = nearest_power_of_2_templated(texture_upload_region_size_px);
|
||||
print_line("update size: " + itos(texture_upload_region_size_px));
|
||||
|
||||
frames_drawn = frame_count; //start from frame count, so everything else is immediately old
|
||||
|
||||
|
@ -410,7 +410,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
|
||||
r_gen_code.uniform_total_size = offset;
|
||||
print_line("uniform total: " + itos(r_gen_code.uniform_total_size));
|
||||
if (r_gen_code.uniform_total_size % 16 != 0) { //UBO sizes must be multiples of 16
|
||||
//r_gen_code.uniform_total_size += 16 - (r_gen_code.uniform_total_size % 16);
|
||||
r_gen_code.uniform_total_size += 16 - (r_gen_code.uniform_total_size % 16);
|
||||
}
|
||||
#else
|
||||
// add up
|
||||
|
1077
thirdparty/spirv-reflect/include/spirv/unified1/spirv.h
vendored
Normal file
1077
thirdparty/spirv-reflect/include/spirv/unified1/spirv.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4442
thirdparty/spirv-reflect/spirv_reflect.c
vendored
Normal file
4442
thirdparty/spirv-reflect/spirv_reflect.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2045
thirdparty/spirv-reflect/spirv_reflect.h
vendored
Normal file
2045
thirdparty/spirv-reflect/spirv_reflect.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user