| 1002 | return res; |
| 1003 | } |
| 1004 | id define_uniform(const location &, uniform &info) override |
| 1005 | { |
| 1006 | if (_uniforms_to_spec_constants && info.has_initializer_value) |
| 1007 | { |
| 1008 | const id res = emit_constant(info.type, info.initializer_value, true); |
| 1009 | |
| 1010 | add_name(res, info.unique_name.c_str()); |
| 1011 | |
| 1012 | const auto add_spec_constant = [this](const spirv_instruction &inst, const uniform &info, const constant &initializer_value, size_t initializer_offset) { |
| 1013 | assert(inst.op == spv::OpSpecConstant || inst.op == spv::OpSpecConstantTrue || inst.op == spv::OpSpecConstantFalse); |
| 1014 | |
| 1015 | const uint32_t spec_id = static_cast<uint32_t>(_module.spec_constants.size()); |
| 1016 | add_decoration(inst, spv::DecorationSpecId, { spec_id }); |
| 1017 | |
| 1018 | uniform scalar_info = info; |
| 1019 | scalar_info.type.rows = 1; |
| 1020 | scalar_info.type.cols = 1; |
| 1021 | scalar_info.size = 4; |
| 1022 | scalar_info.offset = static_cast<uint32_t>(initializer_offset); |
| 1023 | scalar_info.initializer_value = {}; |
| 1024 | scalar_info.initializer_value.as_uint[0] = initializer_value.as_uint[initializer_offset]; |
| 1025 | |
| 1026 | _module.spec_constants.push_back(std::move(scalar_info)); |
| 1027 | }; |
| 1028 | |
| 1029 | const spirv_instruction &base_inst = _types_and_constants.instructions.back(); |
| 1030 | assert(base_inst == res); |
| 1031 | |
| 1032 | // External specialization constants need to be scalars |
| 1033 | if (info.type.is_scalar()) |
| 1034 | { |
| 1035 | add_spec_constant(base_inst, info, info.initializer_value, 0); |
| 1036 | } |
| 1037 | else |
| 1038 | { |
| 1039 | assert(base_inst.op == spv::OpSpecConstantComposite); |
| 1040 | |
| 1041 | // Add each individual scalar component of the constant as a separate external specialization constant |
| 1042 | for (size_t i = 0; i < (info.type.is_array() ? base_inst.operands.size() : 1); ++i) |
| 1043 | { |
| 1044 | constant initializer_value = info.initializer_value; |
| 1045 | spirv_instruction elem_inst = base_inst; |
| 1046 | |
| 1047 | if (info.type.is_array()) |
| 1048 | { |
| 1049 | elem_inst = *std::find_if(_types_and_constants.instructions.rbegin(), _types_and_constants.instructions.rend(), |
| 1050 | [operand_id = base_inst.operands[i]](const spirv_instruction &inst) { return inst == operand_id; }); |
| 1051 | |
| 1052 | assert(initializer_value.array_data.size() == base_inst.operands.size()); |
| 1053 | initializer_value = initializer_value.array_data[i]; |
| 1054 | } |
| 1055 | |
| 1056 | for (size_t row = 0; row < elem_inst.operands.size(); ++row) |
| 1057 | { |
| 1058 | const spirv_instruction &row_inst = *std::find_if(_types_and_constants.instructions.rbegin(), _types_and_constants.instructions.rend(), |
| 1059 | [operand_id = elem_inst.operands[row]](const spirv_instruction &inst) { return inst == operand_id; }); |
| 1060 | |
| 1061 | if (row_inst.op != spv::OpSpecConstantComposite) |
nothing calls this directly
no test coverage detected