Path: blob/master/servers/rendering/rendering_shader_container.cpp
20872 views
/**************************************************************************/1/* rendering_shader_container.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "rendering_shader_container.h"3132#include "core/io/compression.h"3334#include "servers/rendering/renderer_rd/shader_rd.h"35#include "thirdparty/spirv-reflect/spirv_reflect.h"3637static inline uint32_t aligned_to(uint32_t p_size, uint32_t p_alignment) {38if (p_size % p_alignment) {39return p_size + (p_alignment - (p_size % p_alignment));40} else {41return p_size;42}43}4445template <class T>46const T &RenderingShaderContainer::ReflectSymbol<T>::get_spv_reflect(RDC::ShaderStage p_stage) const {47const T *info = _spv_reflect[get_index_for_stage(p_stage)];48DEV_ASSERT(info != nullptr); // Caller is expected to specify valid shader stages49return *info;50}5152template <class T>53void RenderingShaderContainer::ReflectSymbol<T>::set_spv_reflect(RDC::ShaderStage p_stage, const T *p_spv) {54stages.set_flag(1 << p_stage);55_spv_reflect[get_index_for_stage(p_stage)] = p_spv;56}5758RenderingShaderContainer::ReflectShaderStage::ReflectShaderStage() {59_module = memnew(SpvReflectShaderModule);60memset(_module, 0, sizeof(SpvReflectShaderModule));61}6263RenderingShaderContainer::ReflectShaderStage::~ReflectShaderStage() {64spvReflectDestroyShaderModule(_module);65memdelete(_module);66_module = nullptr;67}6869const SpvReflectShaderModule &RenderingShaderContainer::ReflectShaderStage::module() const {70return *_module;71}7273const Span<uint32_t> RenderingShaderContainer::ReflectShaderStage::spirv() const {74return _spirv_data.span().reinterpret<uint32_t>();75}7677uint32_t RenderingShaderContainer::_from_bytes_header_extra_data(const uint8_t *p_bytes) {78return 0;79}8081uint32_t RenderingShaderContainer::_from_bytes_reflection_extra_data(const uint8_t *p_bytes) {82return 0;83}8485uint32_t RenderingShaderContainer::_from_bytes_reflection_binding_uniform_extra_data_start(const uint8_t *p_bytes) {86return 0;87}8889uint32_t RenderingShaderContainer::_from_bytes_reflection_binding_uniform_extra_data(const uint8_t *p_bytes, uint32_t p_index) {90return 0;91}9293uint32_t RenderingShaderContainer::_from_bytes_reflection_specialization_extra_data_start(const uint8_t *p_bytes) {94return 0;95}9697uint32_t RenderingShaderContainer::_from_bytes_reflection_specialization_extra_data(const uint8_t *p_bytes, uint32_t p_index) {98return 0;99}100101uint32_t RenderingShaderContainer::_from_bytes_shader_extra_data_start(const uint8_t *p_bytes) {102return 0;103}104105uint32_t RenderingShaderContainer::_from_bytes_shader_extra_data(const uint8_t *p_bytes, uint32_t p_index) {106return 0;107}108109uint32_t RenderingShaderContainer::_from_bytes_footer_extra_data(const uint8_t *p_bytes) {110return 0;111}112113uint32_t RenderingShaderContainer::_to_bytes_header_extra_data(uint8_t *) const {114return 0;115}116117uint32_t RenderingShaderContainer::_to_bytes_reflection_extra_data(uint8_t *) const {118return 0;119}120121uint32_t RenderingShaderContainer::_to_bytes_reflection_binding_uniform_extra_data(uint8_t *, uint32_t) const {122return 0;123}124125uint32_t RenderingShaderContainer::_to_bytes_reflection_specialization_extra_data(uint8_t *, uint32_t) const {126return 0;127}128129uint32_t RenderingShaderContainer::_to_bytes_shader_extra_data(uint8_t *, uint32_t) const {130return 0;131}132133uint32_t RenderingShaderContainer::_to_bytes_footer_extra_data(uint8_t *) const {134return 0;135}136137void RenderingShaderContainer::_set_from_shader_reflection_post(const ReflectShader &p_shader) {138// Do nothing.139}140141static RenderingDeviceCommons::DataFormat spv_image_format_to_data_format(const SpvImageFormat p_format) {142using RDC = RenderingDeviceCommons;143switch (p_format) {144case SpvImageFormatUnknown:145return RDC::DATA_FORMAT_MAX;146case SpvImageFormatRgba32f:147return RDC::DATA_FORMAT_R32G32B32A32_SFLOAT;148case SpvImageFormatRgba16f:149return RDC::DATA_FORMAT_R16G16B16A16_SFLOAT;150case SpvImageFormatR32f:151return RDC::DATA_FORMAT_R32_SFLOAT;152case SpvImageFormatRgba8:153return RDC::DATA_FORMAT_R8G8B8A8_UNORM;154case SpvImageFormatRgba8Snorm:155return RDC::DATA_FORMAT_R8G8B8A8_SNORM;156case SpvImageFormatRg32f:157return RDC::DATA_FORMAT_R32G32_SFLOAT;158case SpvImageFormatRg16f:159return RDC::DATA_FORMAT_R16G16_SFLOAT;160case SpvImageFormatR11fG11fB10f:161return RDC::DATA_FORMAT_B10G11R11_UFLOAT_PACK32;162case SpvImageFormatR16f:163return RDC::DATA_FORMAT_R16_SFLOAT;164case SpvImageFormatRgba16:165return RDC::DATA_FORMAT_R16G16B16A16_UNORM;166case SpvImageFormatRgb10A2:167return RDC::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;168case SpvImageFormatRg16:169return RDC::DATA_FORMAT_R16G16_UNORM;170case SpvImageFormatRg8:171return RDC::DATA_FORMAT_R8G8_UNORM;172case SpvImageFormatR16:173return RDC::DATA_FORMAT_R16_UNORM;174case SpvImageFormatR8:175return RDC::DATA_FORMAT_R8_UNORM;176case SpvImageFormatRgba16Snorm:177return RDC::DATA_FORMAT_R16G16B16A16_SNORM;178case SpvImageFormatRg16Snorm:179return RDC::DATA_FORMAT_R16G16_SNORM;180case SpvImageFormatRg8Snorm:181return RDC::DATA_FORMAT_R8G8_SNORM;182case SpvImageFormatR16Snorm:183return RDC::DATA_FORMAT_R16_SNORM;184case SpvImageFormatR8Snorm:185return RDC::DATA_FORMAT_R8_SNORM;186case SpvImageFormatRgba32i:187return RDC::DATA_FORMAT_R32G32B32A32_SINT;188case SpvImageFormatRgba16i:189return RDC::DATA_FORMAT_R16G16B16A16_SINT;190case SpvImageFormatRgba8i:191return RDC::DATA_FORMAT_R8G8B8A8_SINT;192case SpvImageFormatR32i:193return RDC::DATA_FORMAT_R32_SINT;194case SpvImageFormatRg32i:195return RDC::DATA_FORMAT_R32G32_SINT;196case SpvImageFormatRg16i:197return RDC::DATA_FORMAT_R16G16_SINT;198case SpvImageFormatRg8i:199return RDC::DATA_FORMAT_R8G8_SINT;200case SpvImageFormatR16i:201return RDC::DATA_FORMAT_R16_SINT;202case SpvImageFormatR8i:203return RDC::DATA_FORMAT_R8_SINT;204case SpvImageFormatRgba32ui:205return RDC::DATA_FORMAT_R32G32B32A32_UINT;206case SpvImageFormatRgba16ui:207return RDC::DATA_FORMAT_R16G16B16A16_UINT;208case SpvImageFormatRgba8ui:209return RDC::DATA_FORMAT_R8G8B8A8_UINT;210case SpvImageFormatR32ui:211return RDC::DATA_FORMAT_R32_UINT;212case SpvImageFormatRgb10a2ui:213return RDC::DATA_FORMAT_A2B10G10R10_UINT_PACK32;214case SpvImageFormatRg32ui:215return RDC::DATA_FORMAT_R32G32_UINT;216case SpvImageFormatRg16ui:217return RDC::DATA_FORMAT_R16G16_UINT;218case SpvImageFormatRg8ui:219return RDC::DATA_FORMAT_R8G8_UINT;220case SpvImageFormatR16ui:221return RDC::DATA_FORMAT_R16_UINT;222case SpvImageFormatR8ui:223return RDC::DATA_FORMAT_R8_UINT;224case SpvImageFormatR64ui:225return RDC::DATA_FORMAT_R64_UINT;226case SpvImageFormatR64i:227return RDC::DATA_FORMAT_R64_SINT;228case SpvImageFormatMax:229return RDC::DATA_FORMAT_MAX;230}231return RDC::DATA_FORMAT_MAX;232}233234Error RenderingShaderContainer::reflect_spirv(const String &p_shader_name, Span<RDC::ShaderStageSPIRVData> p_spirv, ReflectShader &r_shader) {235ReflectShader &reflection = r_shader;236237shader_name = p_shader_name.utf8();238239const uint32_t spirv_size = p_spirv.size() + 0;240241LocalVector<ReflectShaderStage> &r_refl = r_shader.shader_stages;242r_refl.resize(spirv_size);243244bool pipeline_type_detected = false;245for (uint32_t i = 0; i < spirv_size; i++) {246RDC::ShaderStage stage = p_spirv[i].shader_stage;247RDC::ShaderStage stage_flag = (RDC::ShaderStage)(1 << stage);248r_refl[i].shader_stage = stage;249r_refl[i]._spirv_data = p_spirv[i].spirv;250251if (!pipeline_type_detected) {252switch (stage) {253case RDC::SHADER_STAGE_VERTEX:254case RDC::SHADER_STAGE_FRAGMENT:255case RDC::SHADER_STAGE_TESSELATION_CONTROL:256case RDC::SHADER_STAGE_TESSELATION_EVALUATION:257r_shader.pipeline_type = RDC::PIPELINE_TYPE_RASTERIZATION;258break;259case RDC::SHADER_STAGE_COMPUTE:260r_shader.pipeline_type = RDC::PIPELINE_TYPE_COMPUTE;261break;262case RDC::SHADER_STAGE_RAYGEN:263case RDC::SHADER_STAGE_ANY_HIT:264case RDC::SHADER_STAGE_CLOSEST_HIT:265case RDC::SHADER_STAGE_MISS:266case RDC::SHADER_STAGE_INTERSECTION:267r_shader.pipeline_type = RDC::PIPELINE_TYPE_RAYTRACING;268break;269default:270DEV_ASSERT(false && "Unknown shader stage.");271}272273pipeline_type_detected = true;274}275276const Vector<uint64_t> &dynamic_buffers = p_spirv[i].dynamic_buffers;277278if (stage == RDC::SHADER_STAGE_COMPUTE) {279ERR_FAIL_COND_V_MSG(spirv_size != 1, FAILED,280"Compute shaders can only receive one stage, dedicated to compute.");281}282ERR_FAIL_COND_V_MSG(reflection.stages_bits.has_flag(stage_flag), FAILED,283"Stage " + String(RDC::SHADER_STAGE_NAMES[stage]) + " submitted more than once.");284reflection.stages_bits.set_flag(stage_flag);285286{287SpvReflectShaderModule &module = *r_refl.ptr()[i]._module;288const uint8_t *spirv = p_spirv[i].spirv.ptr();289SpvReflectResult result = spvReflectCreateShaderModule2(SPV_REFLECT_MODULE_FLAG_NO_COPY, p_spirv[i].spirv.size(), spirv, &module);290ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,291"Reflection of SPIR-V shader stage '" + String(RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage]) + "' failed parsing shader.");292293for (uint32_t j = 0; j < module.capability_count; j++) {294if (module.capabilities[j].value == SpvCapabilityMultiView) {295reflection.has_multiview = true;296break;297}298}299300if (reflection.is_compute()) {301reflection.compute_local_size[0] = module.entry_points->local_size.x;302reflection.compute_local_size[1] = module.entry_points->local_size.y;303reflection.compute_local_size[2] = module.entry_points->local_size.z;304}305uint32_t binding_count = 0;306result = spvReflectEnumerateDescriptorBindings(&module, &binding_count, nullptr);307ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,308"Reflection of SPIR-V shader stage '" + String(RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage]) + "' failed enumerating descriptor bindings.");309310if (binding_count > 0) {311// Parse bindings.312313Vector<SpvReflectDescriptorBinding *> bindings;314bindings.resize(binding_count);315result = spvReflectEnumerateDescriptorBindings(&module, &binding_count, bindings.ptrw());316317ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,318"Reflection of SPIR-V shader stage '" + String(RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage]) + "' failed getting descriptor bindings.");319320for (uint32_t j = 0; j < binding_count; j++) {321const SpvReflectDescriptorBinding &binding = *bindings[j];322323ReflectUniform uniform;324uniform.set_spv_reflect(stage, &binding);325326bool need_array_dimensions = false;327bool need_block_size = false;328bool may_be_writable = false;329bool is_image = false;330331switch (binding.descriptor_type) {332case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER: {333uniform.type = RDC::UNIFORM_TYPE_SAMPLER;334need_array_dimensions = true;335} break;336case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {337uniform.type = RDC::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;338need_array_dimensions = true;339is_image = true;340} break;341case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {342uniform.type = RDC::UNIFORM_TYPE_TEXTURE;343need_array_dimensions = true;344is_image = true;345} break;346case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE: {347uniform.type = RDC::UNIFORM_TYPE_IMAGE;348need_array_dimensions = true;349may_be_writable = true;350is_image = true;351} break;352case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: {353uniform.type = RDC::UNIFORM_TYPE_TEXTURE_BUFFER;354need_array_dimensions = true;355is_image = true;356} break;357case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {358uniform.type = RDC::UNIFORM_TYPE_IMAGE_BUFFER;359need_array_dimensions = true;360may_be_writable = true;361is_image = true;362} break;363case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER: {364const uint64_t key = ShaderRD::DynamicBuffer::encode(binding.set, binding.binding);365if (dynamic_buffers.has(key)) {366uniform.type = RDC::UNIFORM_TYPE_UNIFORM_BUFFER_DYNAMIC;367reflection.has_dynamic_buffers = true;368} else {369uniform.type = RDC::UNIFORM_TYPE_UNIFORM_BUFFER;370}371need_block_size = true;372} break;373case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER: {374const uint64_t key = ShaderRD::DynamicBuffer::encode(binding.set, binding.binding);375if (dynamic_buffers.has(key)) {376uniform.type = RDC::UNIFORM_TYPE_STORAGE_BUFFER_DYNAMIC;377reflection.has_dynamic_buffers = true;378} else {379uniform.type = RDC::UNIFORM_TYPE_STORAGE_BUFFER;380}381need_block_size = true;382may_be_writable = true;383} break;384case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: {385ERR_PRINT("Dynamic uniform buffer not supported.");386continue;387} break;388case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {389ERR_PRINT("Dynamic storage buffer not supported.");390continue;391} break;392case SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {393uniform.type = RDC::UNIFORM_TYPE_INPUT_ATTACHMENT;394need_array_dimensions = true;395is_image = true;396} break;397case SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: {398uniform.type = RDC::UNIFORM_TYPE_ACCELERATION_STRUCTURE;399} break;400}401402if (need_array_dimensions) {403uniform.length = 1;404for (uint32_t k = 0; k < binding.array.dims_count; k++) {405uniform.length *= binding.array.dims[k];406}407} else if (need_block_size) {408uniform.length = binding.block.size;409} else {410uniform.length = 0;411}412413if (may_be_writable) {414if (binding.descriptor_type == SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE) {415uniform.writable = !(binding.decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE);416} else {417uniform.writable = !(binding.decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE) && !(binding.block.decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE);418}419} else {420uniform.writable = false;421}422423if (is_image) {424uniform.image.format = spv_image_format_to_data_format(binding.image.image_format);425}426427uniform.binding = binding.binding;428uint32_t set = binding.set;429430ERR_FAIL_COND_V_MSG(set >= RDC::MAX_UNIFORM_SETS, FAILED,431"On shader stage '" + String(RDC::SHADER_STAGE_NAMES[stage]) + "', uniform '" + binding.name + "' uses a set (" + itos(set) + ") index larger than what is supported (" + itos(RDC::MAX_UNIFORM_SETS) + ").");432433if (set < (uint32_t)reflection.uniform_sets.size()) {434// Check if this already exists.435bool exists = false;436for (uint32_t k = 0; k < reflection.uniform_sets[set].size(); k++) {437if (reflection.uniform_sets[set][k].binding == uniform.binding) {438// Already exists, verify that it's the same type.439ERR_FAIL_COND_V_MSG(reflection.uniform_sets[set][k].type != uniform.type, FAILED,440"On shader stage '" + String(RDC::SHADER_STAGE_NAMES[stage]) + "', uniform '" + binding.name + "' trying to reuse location for set=" + itos(set) + ", binding=" + itos(uniform.binding) + " with different uniform type.");441442// Also, verify that it's the same size.443ERR_FAIL_COND_V_MSG(reflection.uniform_sets[set][k].length != uniform.length, FAILED,444"On shader stage '" + String(RDC::SHADER_STAGE_NAMES[stage]) + "', uniform '" + binding.name + "' trying to reuse location for set=" + itos(set) + ", binding=" + itos(uniform.binding) + " with different uniform size.");445446// Also, verify that it has the same writability.447ERR_FAIL_COND_V_MSG(reflection.uniform_sets[set][k].writable != uniform.writable, FAILED,448"On shader stage '" + String(RDC::SHADER_STAGE_NAMES[stage]) + "', uniform '" + binding.name + "' trying to reuse location for set=" + itos(set) + ", binding=" + itos(uniform.binding) + " with different writability.");449450// Just append stage mask and return.451reflection.uniform_sets[set][k].stages.set_flag(stage_flag);452exists = true;453break;454}455}456457if (exists) {458continue; // Merged.459}460}461462uniform.stages.set_flag(stage_flag);463464if (set >= (uint32_t)reflection.uniform_sets.size()) {465reflection.uniform_sets.resize(set + 1);466}467468reflection.uniform_sets[set].push_back(uniform);469}470}471472{473// Specialization constants.474475uint32_t sc_count = 0;476result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, nullptr);477ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,478"Reflection of SPIR-V shader stage '" + String(RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage]) + "' failed enumerating specialization constants.");479480if (sc_count) {481Vector<SpvReflectSpecializationConstant *> spec_constants;482spec_constants.resize(sc_count);483484result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, spec_constants.ptrw());485ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,486"Reflection of SPIR-V shader stage '" + String(RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage]) + "' failed obtaining specialization constants.");487488for (uint32_t j = 0; j < sc_count; j++) {489int32_t existing = -1;490ReflectSpecializationConstant sconst;491SpvReflectSpecializationConstant *spc = spec_constants[j];492sconst.set_spv_reflect(stage, spc);493494if (spc->default_value_size != 4) {495ERR_FAIL_V_MSG(FAILED, vformat("Reflection of SPIR-V shader stage '%s' failed because the specialization constant #%d's default value is not 4 bytes long (%d) and is currently not supported.", RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage], spc->constant_id, spc->default_value_size));496}497498sconst.constant_id = spc->constant_id;499sconst.int_value = 0; // Clear previous value JIC.500501switch (spc->type_description->op) {502case SpvOpTypeBool:503sconst.type = RDC::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;504sconst.bool_value = *(uint32_t *)(spc->default_value);505break;506case SpvOpTypeInt:507sconst.type = RDC::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;508sconst.int_value = *(uint32_t *)(spc->default_value);509break;510case SpvOpTypeFloat:511sconst.type = RDC::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;512sconst.float_value = *(float *)(spc->default_value);513break;514default:515ERR_FAIL_V_MSG(FAILED, vformat("Reflection of SPIR-V shader stage '%s' failed because the specialization constant #%d does not use a known operation (%d).", RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage], spc->constant_id, spc->type_description->op));516break;517}518519sconst.stages.set_flag(stage_flag);520521for (uint32_t k = 0; k < reflection.specialization_constants.size(); k++) {522if (reflection.specialization_constants[k].constant_id == sconst.constant_id) {523ERR_FAIL_COND_V_MSG(reflection.specialization_constants[k].type != sconst.type, FAILED, "More than one specialization constant used for id (" + itos(sconst.constant_id) + "), but their types differ.");524ERR_FAIL_COND_V_MSG(reflection.specialization_constants[k].int_value != sconst.int_value, FAILED, "More than one specialization constant used for id (" + itos(sconst.constant_id) + "), but their default values differ.");525existing = k;526break;527}528}529530if (existing >= 0) {531reflection.specialization_constants[existing].stages.set_flag(stage_flag);532} else {533reflection.specialization_constants.push_back(sconst);534}535}536537reflection.specialization_constants.sort();538}539}540541if (stage == RDC::SHADER_STAGE_VERTEX || stage == RDC::SHADER_STAGE_FRAGMENT) {542uint32_t iv_count = 0;543result = spvReflectEnumerateInputVariables(&module, &iv_count, nullptr);544ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,545"Reflection of SPIR-V shader stage '" + String(RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage]) + "' failed enumerating input variables.");546547if (iv_count) {548Vector<SpvReflectInterfaceVariable *> input_vars;549input_vars.resize(iv_count);550551result = spvReflectEnumerateInputVariables(&module, &iv_count, input_vars.ptrw());552ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,553"Reflection of SPIR-V shader stage '" + String(RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage]) + "' failed obtaining input variables.");554555for (const SpvReflectInterfaceVariable *v : input_vars) {556if (!v) {557continue;558}559if (stage == RDC::SHADER_STAGE_VERTEX) {560if (v->decoration_flags == 0) { // Regular input.561reflection.vertex_input_mask |= (((uint64_t)1) << v->location);562}563}564if (v->built_in == SpvBuiltInViewIndex) {565reflection.has_multiview = true;566}567}568}569}570571if (stage == RDC::SHADER_STAGE_FRAGMENT) {572uint32_t ov_count = 0;573result = spvReflectEnumerateOutputVariables(&module, &ov_count, nullptr);574ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,575"Reflection of SPIR-V shader stage '" + String(RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage]) + "' failed enumerating output variables.");576577if (ov_count) {578Vector<SpvReflectInterfaceVariable *> output_vars;579output_vars.resize(ov_count);580581result = spvReflectEnumerateOutputVariables(&module, &ov_count, output_vars.ptrw());582ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,583"Reflection of SPIR-V shader stage '" + String(RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage]) + "' failed obtaining output variables.");584585for (const SpvReflectInterfaceVariable *refvar : output_vars) {586if (!refvar) {587continue;588}589if (refvar->built_in != SpvBuiltInFragDepth) {590reflection.fragment_output_mask |= 1 << refvar->location;591}592}593}594}595596uint32_t pc_count = 0;597result = spvReflectEnumeratePushConstantBlocks(&module, &pc_count, nullptr);598ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,599"Reflection of SPIR-V shader stage '" + String(RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage]) + "' failed enumerating push constants.");600601if (pc_count) {602ERR_FAIL_COND_V_MSG(pc_count > 1, FAILED,603"Reflection of SPIR-V shader stage '" + String(RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage]) + "': Only one push constant is supported, which should be the same across shader stages.");604605Vector<SpvReflectBlockVariable *> pconstants;606pconstants.resize(pc_count);607result = spvReflectEnumeratePushConstantBlocks(&module, &pc_count, pconstants.ptrw());608ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, FAILED,609"Reflection of SPIR-V shader stage '" + String(RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage]) + "' failed obtaining push constants.");610#if 0611if (pconstants[0] == nullptr) {612Ref<FileAccess> f = FileAccess::open("res://popo.spv", FileAccess::WRITE);613f->store_buffer((const uint8_t *)&SpirV[0], SpirV.size() * sizeof(uint32_t));614}615#endif616617ERR_FAIL_COND_V_MSG(reflection.push_constant_size && reflection.push_constant_size != pconstants[0]->size, FAILED,618"Reflection of SPIR-V shader stage '" + String(RDC::SHADER_STAGE_NAMES[p_spirv[i].shader_stage]) + "': Push constant block must be the same across shader stages.");619620reflection.push_constant_size = pconstants[0]->size;621reflection.push_constant_stages.set_flag(stage_flag);622623//print_line("Stage: " + String(RDC::SHADER_STAGE_NAMES[stage]) + " push constant of size=" + itos(push_constant.push_constant_size));624}625}626}627628// Sort all uniform_sets by binding.629for (uint32_t i = 0; i < reflection.uniform_sets.size(); i++) {630reflection.uniform_sets[i].sort();631}632633set_from_shader_reflection(reflection);634635return OK;636}637638void RenderingShaderContainer::set_from_shader_reflection(const ReflectShader &p_reflection) {639reflection_binding_set_uniforms_count.clear();640reflection_binding_set_uniforms_data.clear();641reflection_specialization_data.clear();642reflection_shader_stages.clear();643644reflection_data.vertex_input_mask = p_reflection.vertex_input_mask;645reflection_data.fragment_output_mask = p_reflection.fragment_output_mask;646reflection_data.specialization_constants_count = p_reflection.specialization_constants.size();647reflection_data.pipeline_type = p_reflection.pipeline_type;648reflection_data.has_multiview = p_reflection.has_multiview;649reflection_data.has_dynamic_buffers = p_reflection.has_dynamic_buffers;650reflection_data.compute_local_size[0] = p_reflection.compute_local_size[0];651reflection_data.compute_local_size[1] = p_reflection.compute_local_size[1];652reflection_data.compute_local_size[2] = p_reflection.compute_local_size[2];653reflection_data.set_count = p_reflection.uniform_sets.size();654reflection_data.push_constant_size = p_reflection.push_constant_size;655reflection_data.push_constant_stages_mask = uint32_t(p_reflection.push_constant_stages);656reflection_data.shader_name_len = shader_name.length();657658ReflectionBindingData binding_data;659for (const ReflectDescriptorSet &uniform_set : p_reflection.uniform_sets) {660for (const ReflectUniform &uniform : uniform_set) {661binding_data.type = uint32_t(uniform.type);662binding_data.binding = uniform.binding;663binding_data.stages = uint32_t(uniform.stages);664binding_data.length = uniform.length;665binding_data.writable = uint32_t(uniform.writable);666reflection_binding_set_uniforms_data.push_back(binding_data);667}668669reflection_binding_set_uniforms_count.push_back(uniform_set.size());670}671672ReflectionSpecializationData specialization_data;673for (const ReflectSpecializationConstant &spec : p_reflection.specialization_constants) {674specialization_data.type = uint32_t(spec.type);675specialization_data.constant_id = spec.constant_id;676specialization_data.int_value = spec.int_value;677specialization_data.stage_flags = uint32_t(spec.stages);678reflection_specialization_data.push_back(specialization_data);679}680681for (uint32_t i = 0; i < RDC::SHADER_STAGE_MAX; i++) {682if (p_reflection.stages_bits.has_flag(RDC::ShaderStage(1U << i))) {683reflection_shader_stages.push_back(RDC::ShaderStage(i));684}685}686687reflection_data.stage_count = reflection_shader_stages.size();688689_set_from_shader_reflection_post(p_reflection);690}691692bool RenderingShaderContainer::set_code_from_spirv(const String &p_shader_name, Span<RDC::ShaderStageSPIRVData> p_spirv) {693ReflectShader shader;694ERR_FAIL_COND_V(reflect_spirv(p_shader_name, p_spirv, shader) != OK, false);695return _set_code_from_spirv(shader);696}697698RenderingDeviceCommons::ShaderReflection RenderingShaderContainer::get_shader_reflection() const {699RDC::ShaderReflection shader_refl;700shader_refl.push_constant_size = reflection_data.push_constant_size;701shader_refl.push_constant_stages = reflection_data.push_constant_stages_mask;702shader_refl.vertex_input_mask = reflection_data.vertex_input_mask;703shader_refl.fragment_output_mask = reflection_data.fragment_output_mask;704shader_refl.pipeline_type = reflection_data.pipeline_type;705shader_refl.has_multiview = reflection_data.has_multiview;706shader_refl.has_dynamic_buffers = reflection_data.has_dynamic_buffers;707shader_refl.compute_local_size[0] = reflection_data.compute_local_size[0];708shader_refl.compute_local_size[1] = reflection_data.compute_local_size[1];709shader_refl.compute_local_size[2] = reflection_data.compute_local_size[2];710shader_refl.uniform_sets.resize(reflection_data.set_count);711shader_refl.specialization_constants.resize(reflection_data.specialization_constants_count);712shader_refl.stages_vector.resize(reflection_data.stage_count);713714DEV_ASSERT(reflection_binding_set_uniforms_count.size() == reflection_data.set_count && "The amount of elements in the reflection and the shader container can't be different.");715uint32_t uniform_index = 0;716for (uint32_t i = 0; i < reflection_data.set_count; i++) {717Vector<RDC::ShaderUniform> &uniform_set = shader_refl.uniform_sets.ptrw()[i];718uint32_t uniforms_count = reflection_binding_set_uniforms_count[i];719uniform_set.resize(uniforms_count);720for (uint32_t j = 0; j < uniforms_count; j++) {721const ReflectionBindingData &binding = reflection_binding_set_uniforms_data[uniform_index++];722RDC::ShaderUniform &uniform = uniform_set.ptrw()[j];723uniform.type = RDC::UniformType(binding.type);724uniform.writable = binding.writable;725uniform.length = binding.length;726uniform.binding = binding.binding;727uniform.stages = binding.stages;728}729}730731shader_refl.specialization_constants.resize(reflection_data.specialization_constants_count);732for (uint32_t i = 0; i < reflection_data.specialization_constants_count; i++) {733const ReflectionSpecializationData &spec = reflection_specialization_data[i];734RDC::ShaderSpecializationConstant &sc = shader_refl.specialization_constants.ptrw()[i];735sc.type = RDC::PipelineSpecializationConstantType(spec.type);736sc.constant_id = spec.constant_id;737sc.int_value = spec.int_value;738sc.stages = spec.stage_flags;739}740741shader_refl.stages_vector.resize(reflection_data.stage_count);742for (uint32_t i = 0; i < reflection_data.stage_count; i++) {743shader_refl.stages_vector.set(i, reflection_shader_stages[i]);744shader_refl.stages_bits.set_flag(RDC::ShaderStage(1U << reflection_shader_stages[i]));745}746747return shader_refl;748}749750bool RenderingShaderContainer::from_bytes(const PackedByteArray &p_bytes) {751const uint64_t alignment = sizeof(uint32_t);752const uint8_t *bytes_ptr = p_bytes.ptr();753uint64_t bytes_offset = 0;754755// Read container header.756ERR_FAIL_COND_V_MSG(int64_t(bytes_offset + sizeof(ContainerHeader)) > p_bytes.size(), false, "Not enough bytes for a container header in shader container.");757const ContainerHeader &container_header = *(const ContainerHeader *)(&bytes_ptr[bytes_offset]);758bytes_offset += sizeof(ContainerHeader);759bytes_offset += _from_bytes_header_extra_data(&bytes_ptr[bytes_offset]);760761ERR_FAIL_COND_V_MSG(container_header.magic_number != CONTAINER_MAGIC_NUMBER, false, "Incorrect magic number in shader container.");762ERR_FAIL_COND_V_MSG(container_header.version > CONTAINER_VERSION, false, "Unsupported version in shader container.");763ERR_FAIL_COND_V_MSG(container_header.format != _format(), false, "Incorrect format in shader container.");764ERR_FAIL_COND_V_MSG(container_header.format_version > _format_version(), false, "Unsupported format version in shader container.");765766// Adjust shaders to the size indicated by the container header.767shaders.resize(container_header.shader_count);768769// Read reflection data.770ERR_FAIL_COND_V_MSG(int64_t(bytes_offset + sizeof(ReflectionData)) > p_bytes.size(), false, "Not enough bytes for reflection data in shader container.");771reflection_data = *(const ReflectionData *)(&bytes_ptr[bytes_offset]);772bytes_offset += sizeof(ReflectionData);773bytes_offset += _from_bytes_reflection_extra_data(&bytes_ptr[bytes_offset]);774775// Read shader name.776ERR_FAIL_COND_V_MSG(int64_t(bytes_offset + reflection_data.shader_name_len) > p_bytes.size(), false, "Not enough bytes for shader name in shader container.");777if (reflection_data.shader_name_len > 0) {778String shader_name_str;779shader_name_str.append_utf8((const char *)(&bytes_ptr[bytes_offset]), reflection_data.shader_name_len);780shader_name = shader_name_str.utf8();781bytes_offset = aligned_to(bytes_offset + reflection_data.shader_name_len, alignment);782} else {783shader_name = CharString();784}785786reflection_binding_set_uniforms_count.resize(reflection_data.set_count);787reflection_binding_set_uniforms_data.clear();788789uint32_t uniform_index = 0;790for (uint32_t i = 0; i < reflection_data.set_count; i++) {791ERR_FAIL_COND_V_MSG(int64_t(bytes_offset + sizeof(uint32_t)) > p_bytes.size(), false, "Not enough bytes for uniform set count in shader container.");792uint32_t uniforms_count = *(uint32_t *)(&bytes_ptr[bytes_offset]);793reflection_binding_set_uniforms_count.ptrw()[i] = uniforms_count;794bytes_offset += sizeof(uint32_t);795796reflection_binding_set_uniforms_data.resize(reflection_binding_set_uniforms_data.size() + uniforms_count);797bytes_offset += _from_bytes_reflection_binding_uniform_extra_data_start(&bytes_ptr[bytes_offset]);798799for (uint32_t j = 0; j < uniforms_count; j++) {800ERR_FAIL_COND_V_MSG(int64_t(bytes_offset + sizeof(ReflectionBindingData)) > p_bytes.size(), false, "Not enough bytes for uniform in shader container.");801memcpy(&reflection_binding_set_uniforms_data.ptrw()[uniform_index], &bytes_ptr[bytes_offset], sizeof(ReflectionBindingData));802bytes_offset += sizeof(ReflectionBindingData);803bytes_offset += _from_bytes_reflection_binding_uniform_extra_data(&bytes_ptr[bytes_offset], uniform_index);804uniform_index++;805}806}807808reflection_specialization_data.resize(reflection_data.specialization_constants_count);809bytes_offset += _from_bytes_reflection_specialization_extra_data_start(&bytes_ptr[bytes_offset]);810811for (uint32_t i = 0; i < reflection_data.specialization_constants_count; i++) {812ERR_FAIL_COND_V_MSG(int64_t(bytes_offset + sizeof(ReflectionSpecializationData)) > p_bytes.size(), false, "Not enough bytes for specialization in shader container.");813memcpy(&reflection_specialization_data.ptrw()[i], &bytes_ptr[bytes_offset], sizeof(ReflectionSpecializationData));814bytes_offset += sizeof(ReflectionSpecializationData);815bytes_offset += _from_bytes_reflection_specialization_extra_data(&bytes_ptr[bytes_offset], i);816}817818const uint32_t stage_count = reflection_data.stage_count;819if (stage_count > 0) {820ERR_FAIL_COND_V_MSG(int64_t(bytes_offset + stage_count * sizeof(RDC::ShaderStage)) > p_bytes.size(), false, "Not enough bytes for stages in shader container.");821reflection_shader_stages.resize(stage_count);822bytes_offset += _from_bytes_shader_extra_data_start(&bytes_ptr[bytes_offset]);823memcpy(reflection_shader_stages.ptrw(), &bytes_ptr[bytes_offset], stage_count * sizeof(RDC::ShaderStage));824bytes_offset += stage_count * sizeof(RDC::ShaderStage);825}826827// Read shaders.828for (int64_t i = 0; i < shaders.size(); i++) {829ERR_FAIL_COND_V_MSG(int64_t(bytes_offset + sizeof(ShaderHeader)) > p_bytes.size(), false, "Not enough bytes for shader header in shader container.");830const ShaderHeader &header = *(const ShaderHeader *)(&bytes_ptr[bytes_offset]);831bytes_offset += sizeof(ShaderHeader);832833ERR_FAIL_COND_V_MSG(int64_t(bytes_offset + header.code_compressed_size) > p_bytes.size(), false, "Not enough bytes for a shader in shader container.");834Shader &shader = shaders.ptrw()[i];835shader.shader_stage = RDC::ShaderStage(header.shader_stage);836shader.code_compression_flags = header.code_compression_flags;837shader.code_decompressed_size = header.code_decompressed_size;838shader.code_compressed_bytes.resize(header.code_compressed_size);839memcpy(shader.code_compressed_bytes.ptrw(), &bytes_ptr[bytes_offset], header.code_compressed_size);840bytes_offset = aligned_to(bytes_offset + header.code_compressed_size, alignment);841bytes_offset += _from_bytes_shader_extra_data(&bytes_ptr[bytes_offset], i);842}843844bytes_offset += _from_bytes_footer_extra_data(&bytes_ptr[bytes_offset]);845846ERR_FAIL_COND_V_MSG(bytes_offset != (uint64_t)p_bytes.size(), false, "Amount of bytes in the container does not match the amount of bytes read.");847return true;848}849850PackedByteArray RenderingShaderContainer::to_bytes() const {851// Compute the exact size the container will require for writing everything out.852const uint64_t alignment = sizeof(uint32_t);853uint64_t total_size = 0;854total_size += sizeof(ContainerHeader) + _to_bytes_header_extra_data(nullptr);855total_size += sizeof(ReflectionData) + _to_bytes_reflection_extra_data(nullptr);856total_size += aligned_to(reflection_data.shader_name_len, alignment);857total_size += reflection_binding_set_uniforms_count.size() * sizeof(uint32_t);858total_size += reflection_binding_set_uniforms_data.size() * sizeof(ReflectionBindingData);859total_size += reflection_specialization_data.size() * sizeof(ReflectionSpecializationData);860total_size += reflection_shader_stages.size() * sizeof(RDC::ShaderStage);861862for (uint32_t i = 0; i < reflection_binding_set_uniforms_data.size(); i++) {863total_size += _to_bytes_reflection_binding_uniform_extra_data(nullptr, i);864}865866for (uint32_t i = 0; i < reflection_specialization_data.size(); i++) {867total_size += _to_bytes_reflection_specialization_extra_data(nullptr, i);868}869870for (uint32_t i = 0; i < shaders.size(); i++) {871total_size += sizeof(ShaderHeader);872total_size += shaders[i].code_compressed_bytes.size();873total_size = aligned_to(total_size, alignment);874total_size += _to_bytes_shader_extra_data(nullptr, i);875}876877total_size += _to_bytes_footer_extra_data(nullptr);878879// Create the array that will hold all of the data.880PackedByteArray bytes;881bytes.resize_initialized(total_size);882883// Write out the data to the array.884uint64_t bytes_offset = 0;885uint8_t *bytes_ptr = bytes.ptrw();886ContainerHeader &container_header = *(ContainerHeader *)(&bytes_ptr[bytes_offset]);887container_header.magic_number = CONTAINER_MAGIC_NUMBER;888container_header.version = CONTAINER_VERSION;889container_header.format = _format();890container_header.format_version = _format_version();891container_header.shader_count = shaders.size();892bytes_offset += sizeof(ContainerHeader);893bytes_offset += _to_bytes_header_extra_data(&bytes_ptr[bytes_offset]);894895memcpy(&bytes_ptr[bytes_offset], &reflection_data, sizeof(ReflectionData));896bytes_offset += sizeof(ReflectionData);897bytes_offset += _to_bytes_reflection_extra_data(&bytes_ptr[bytes_offset]);898899if (shader_name.size() > 0) {900memcpy(&bytes_ptr[bytes_offset], shader_name.ptr(), reflection_data.shader_name_len);901bytes_offset = aligned_to(bytes_offset + reflection_data.shader_name_len, alignment);902}903904uint32_t uniform_index = 0;905for (uint32_t uniform_count : reflection_binding_set_uniforms_count) {906memcpy(&bytes_ptr[bytes_offset], &uniform_count, sizeof(uniform_count));907bytes_offset += sizeof(uint32_t);908909for (uint32_t i = 0; i < uniform_count; i++) {910memcpy(&bytes_ptr[bytes_offset], &reflection_binding_set_uniforms_data[uniform_index], sizeof(ReflectionBindingData));911bytes_offset += sizeof(ReflectionBindingData);912bytes_offset += _to_bytes_reflection_binding_uniform_extra_data(&bytes_ptr[bytes_offset], uniform_index);913uniform_index++;914}915}916917for (uint32_t i = 0; i < reflection_specialization_data.size(); i++) {918memcpy(&bytes_ptr[bytes_offset], &reflection_specialization_data.ptr()[i], sizeof(ReflectionSpecializationData));919bytes_offset += sizeof(ReflectionSpecializationData);920bytes_offset += _to_bytes_reflection_specialization_extra_data(&bytes_ptr[bytes_offset], i);921}922923if (!reflection_shader_stages.is_empty()) {924uint32_t stage_count = reflection_shader_stages.size();925memcpy(&bytes_ptr[bytes_offset], reflection_shader_stages.ptr(), stage_count * sizeof(RDC::ShaderStage));926bytes_offset += stage_count * sizeof(RDC::ShaderStage);927}928929for (uint32_t i = 0; i < shaders.size(); i++) {930const Shader &shader = shaders[i];931ShaderHeader &header = *(ShaderHeader *)(&bytes.ptr()[bytes_offset]);932header.shader_stage = shader.shader_stage;933header.code_compressed_size = uint32_t(shader.code_compressed_bytes.size());934header.code_compression_flags = shader.code_compression_flags;935header.code_decompressed_size = shader.code_decompressed_size;936bytes_offset += sizeof(ShaderHeader);937memcpy(&bytes.ptrw()[bytes_offset], shader.code_compressed_bytes.ptr(), shader.code_compressed_bytes.size());938bytes_offset = aligned_to(bytes_offset + shader.code_compressed_bytes.size(), alignment);939bytes_offset += _to_bytes_shader_extra_data(&bytes_ptr[bytes_offset], i);940}941942bytes_offset += _to_bytes_footer_extra_data(&bytes_ptr[bytes_offset]);943944ERR_FAIL_COND_V_MSG(bytes_offset != total_size, PackedByteArray(), "Amount of bytes written does not match the amount of bytes reserved for the container.");945return bytes;946}947948bool RenderingShaderContainer::compress_code(const uint8_t *p_decompressed_bytes, uint32_t p_decompressed_size, uint8_t *p_compressed_bytes, uint32_t *r_compressed_size, uint32_t *r_compressed_flags) const {949DEV_ASSERT(p_decompressed_bytes != nullptr);950DEV_ASSERT(p_decompressed_size > 0);951DEV_ASSERT(p_compressed_bytes != nullptr);952DEV_ASSERT(r_compressed_size != nullptr);953DEV_ASSERT(r_compressed_flags != nullptr);954955*r_compressed_flags = 0;956957PackedByteArray zstd_bytes;958const int64_t zstd_max_bytes = Compression::get_max_compressed_buffer_size(p_decompressed_size, Compression::MODE_ZSTD);959zstd_bytes.resize(zstd_max_bytes);960961const int64_t zstd_size = Compression::compress(zstd_bytes.ptrw(), p_decompressed_bytes, p_decompressed_size, Compression::MODE_ZSTD);962if (zstd_size > 0 && (uint32_t)(zstd_size) < p_decompressed_size) {963// Only choose Zstd if it results in actual compression.964memcpy(p_compressed_bytes, zstd_bytes.ptr(), zstd_size);965*r_compressed_size = zstd_size;966*r_compressed_flags |= COMPRESSION_FLAG_ZSTD;967} else {968// Just copy the input to the output directly.969memcpy(p_compressed_bytes, p_decompressed_bytes, p_decompressed_size);970*r_compressed_size = p_decompressed_size;971}972973return true;974}975976bool RenderingShaderContainer::decompress_code(const uint8_t *p_compressed_bytes, uint32_t p_compressed_size, uint32_t p_compressed_flags, uint8_t *p_decompressed_bytes, uint32_t p_decompressed_size) const {977DEV_ASSERT(p_compressed_bytes != nullptr);978DEV_ASSERT(p_compressed_size > 0);979DEV_ASSERT(p_decompressed_bytes != nullptr);980DEV_ASSERT(p_decompressed_size > 0);981982bool uses_zstd = p_compressed_flags & COMPRESSION_FLAG_ZSTD;983if (uses_zstd) {984if (!Compression::decompress(p_decompressed_bytes, p_decompressed_size, p_compressed_bytes, p_compressed_size, Compression::MODE_ZSTD)) {985ERR_FAIL_V_MSG(false, "Malformed zstd input for decompressing shader code.");986}987} else {988memcpy(p_decompressed_bytes, p_compressed_bytes, MIN(p_compressed_size, p_decompressed_size));989}990991return true;992}993994RenderingShaderContainer::RenderingShaderContainer() {}995996RenderingShaderContainer::~RenderingShaderContainer() {}997998999