1212#include < sstream>
1313
1414#include " flutter/fml/logging.h"
15+ #include " fml/backtrace.h"
1516#include " impeller/base/strings.h"
1617#include " impeller/base/validation.h"
1718#include " impeller/compiler/code_gen_template.h"
2324#include " impeller/geometry/half.h"
2425#include " impeller/geometry/matrix.h"
2526#include " impeller/geometry/scalar.h"
27+ #include " impeller/runtime_stage/runtime_stage.h"
28+ #include " spirv_common.hpp"
2629
2730namespace impeller {
2831namespace compiler {
2932
30- static std::string BaseTypeToString (spirv_cross::SPIRType::BaseType type) {
31- using Type = spirv_cross::SPIRType::BaseType;
32- switch (type) {
33- case Type::Void:
34- return " ShaderType::kVoid" ;
35- case Type::Boolean:
36- return " ShaderType::kBoolean" ;
37- case Type::SByte:
38- return " ShaderType::kSignedByte" ;
39- case Type::UByte:
40- return " ShaderType::kUnsignedByte" ;
41- case Type::Short:
42- return " ShaderType::kSignedShort" ;
43- case Type::UShort:
44- return " ShaderType::kUnsignedShort" ;
45- case Type::Int:
46- return " ShaderType::kSignedInt" ;
47- case Type::UInt:
48- return " ShaderType::kUnsignedInt" ;
49- case Type::Int64:
50- return " ShaderType::kSignedInt64" ;
51- case Type::UInt64:
52- return " ShaderType::kUnsignedInt64" ;
53- case Type::AtomicCounter:
54- return " ShaderType::kAtomicCounter" ;
55- case Type::Half:
56- return " ShaderType::kHalfFloat" ;
57- case Type::Float:
58- return " ShaderType::kFloat" ;
59- case Type::Double:
60- return " ShaderType::kDouble" ;
61- case Type::Struct:
62- return " ShaderType::kStruct" ;
63- case Type::Image:
64- return " ShaderType::kImage" ;
65- case Type::SampledImage:
66- return " ShaderType::kSampledImage" ;
67- case Type::Sampler:
68- return " ShaderType::kSampler" ;
69- default :
70- return " ShaderType::kUnknown" ;
71- }
72- }
73-
7433static std::string ExecutionModelToString (spv::ExecutionModel model) {
7534 switch (model) {
7635 case spv::ExecutionModel::ExecutionModelVertex:
@@ -370,7 +329,6 @@ std::shared_ptr<RuntimeStageData::Shader> Reflector::GenerateRuntimeStageData()
370329 // Sort the IR so that the uniforms are in declaration order.
371330 std::vector<spirv_cross::ID> uniforms =
372331 SortUniforms (ir_.get (), compiler_.GetCompiler ());
373-
374332 for (auto & sorted_id : uniforms) {
375333 auto var = ir_->ids [sorted_id].get <spirv_cross::SPIRVariable>();
376334 const auto spir_type = compiler_->get_type (var.basetype );
@@ -383,9 +341,69 @@ std::shared_ptr<RuntimeStageData::Shader> Reflector::GenerateRuntimeStageData()
383341 uniform_description.columns = spir_type.columns ;
384342 uniform_description.bit_width = spir_type.width ;
385343 uniform_description.array_elements = GetArrayElements (spir_type);
344+ FML_CHECK (data->backend != RuntimeStageBackend::kVulkan ||
345+ spir_type.basetype ==
346+ spirv_cross::SPIRType::BaseType::SampledImage)
347+ << " Vulkan runtime effect had unexpected uniforms outside of the "
348+ " uniform buffer object." ;
386349 data->uniforms .emplace_back (std::move (uniform_description));
387350 }
388351
352+ const auto ubos = compiler_->get_shader_resources ().uniform_buffers ;
353+ if (data->backend == RuntimeStageBackend::kVulkan && !ubos.empty ()) {
354+ if (ubos.size () != 1 && ubos[0 ].name != RuntimeStage::kVulkanUBOName ) {
355+ VALIDATION_LOG << " Expected a single UBO resource named "
356+ " '"
357+ << RuntimeStage::kVulkanUBOName
358+ << " ' "
359+ " for Vulkan runtime stage backend." ;
360+ return nullptr ;
361+ }
362+
363+ const auto & ubo = ubos[0 ];
364+
365+ auto members = ReadStructMembers (ubo.type_id );
366+ std::vector<uint8_t > struct_layout;
367+ size_t float_count = 0 ;
368+
369+ for (size_t i = 0 ; i < members.size (); i += 1 ) {
370+ const auto & member = members[i];
371+ std::vector<int > bytes;
372+ switch (member.underlying_type ) {
373+ case StructMember::UnderlyingType::kPadding : {
374+ size_t padding_count =
375+ (member.size + sizeof (float ) - 1 ) / sizeof (float );
376+ while (padding_count > 0 ) {
377+ struct_layout.push_back (0 );
378+ padding_count--;
379+ }
380+ break ;
381+ }
382+ case StructMember::UnderlyingType::kFloat : {
383+ size_t member_float_count = member.byte_length / sizeof (float );
384+ float_count += member_float_count;
385+ while (member_float_count > 0 ) {
386+ struct_layout.push_back (1 );
387+ member_float_count--;
388+ }
389+ break ;
390+ }
391+ case StructMember::UnderlyingType::kOther :
392+ VALIDATION_LOG << " Non-floating-type struct member " << member.name
393+ << " is not supported." ;
394+ return nullptr ;
395+ }
396+ }
397+ data->uniforms .emplace_back (UniformDescription{
398+ .name = ubo.name ,
399+ .location = 64 , // Magic constant that must match the descriptor set
400+ // location for fragment programs.
401+ .type = spirv_cross::SPIRType::Struct,
402+ .struct_layout = std::move (struct_layout),
403+ .struct_float_count = float_count,
404+ });
405+ }
406+
389407 // We only need to worry about storing vertex attributes.
390408 if (entrypoints.front ().execution_model == spv::ExecutionModelVertex) {
391409 const auto inputs = compiler_->get_shader_resources ().stage_inputs ;
@@ -532,6 +550,8 @@ static std::string ToString(CompilerBackend::Type type) {
532550 return " Metal Shading Language" ;
533551 case CompilerBackend::Type::kGLSL :
534552 return " OpenGL Shading Language" ;
553+ case CompilerBackend::Type::kGLSLVulkan :
554+ return " OpenGL Shading Language (Relaxed Vulkan Semantics)" ;
535555 case CompilerBackend::Type::kSkSL :
536556 return " SkSL Shading Language" ;
537557 }
@@ -627,7 +647,7 @@ std::optional<nlohmann::json::object_t> Reflector::ReflectType(
627647
628648 const auto type = compiler_->get_type (type_id);
629649
630- result[" type_name" ] = BaseTypeToString (type.basetype );
650+ result[" type_name" ] = StructMember:: BaseTypeToString (type.basetype );
631651 result[" bit_width" ] = type.width ;
632652 result[" vec_size" ] = type.vecsize ;
633653 result[" columns" ] = type.columns ;
@@ -637,7 +657,8 @@ std::optional<nlohmann::json::object_t> Reflector::ReflectType(
637657 auto member = nlohmann::json::object_t {};
638658 member[" name" ] = struct_member.name ;
639659 member[" type" ] = struct_member.type ;
640- member[" base_type" ] = BaseTypeToString (struct_member.base_type );
660+ member[" base_type" ] =
661+ StructMember::BaseTypeToString (struct_member.base_type );
641662 member[" offset" ] = struct_member.offset ;
642663 member[" size" ] = struct_member.size ;
643664 member[" byte_length" ] = struct_member.byte_length ;
@@ -1117,7 +1138,8 @@ nlohmann::json::object_t Reflector::EmitStructDefinition(
11171138 auto & member = members.emplace_back (nlohmann::json::object_t {});
11181139 member[" name" ] = struct_member.name ;
11191140 member[" type" ] = struct_member.type ;
1120- member[" base_type" ] = BaseTypeToString (struct_member.base_type );
1141+ member[" base_type" ] =
1142+ StructMember::BaseTypeToString (struct_member.base_type );
11211143 member[" offset" ] = struct_member.offset ;
11221144 member[" byte_length" ] = struct_member.byte_length ;
11231145 if (struct_member.array_elements .has_value ()) {
@@ -1142,7 +1164,7 @@ static VertexType VertexTypeFromInputResource(
11421164 const spirv_cross::Resource* resource) {
11431165 VertexType result;
11441166 result.variable_name = resource->name ;
1145- const auto type = compiler.get_type (resource->type_id );
1167+ const auto & type = compiler.get_type (resource->type_id );
11461168 result.base_type = type.basetype ;
11471169 const auto total_size = type.columns * type.vecsize * type.width / 8u ;
11481170 result.byte_length = total_size;
0 commit comments