Flutter Engine
 
Loading...
Searching...
No Matches
shader_stage_compatibility_checker.h
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef FLUTTER_IMPELLER_RENDERER_SHADER_STAGE_COMPATIBILITY_CHECKER_H_
6#define FLUTTER_IMPELLER_RENDERER_SHADER_STAGE_COMPATIBILITY_CHECKER_H_
7
8#include <cstddef>
9
11
12namespace impeller {
13
14//------------------------------------------------------------------------------
15/// @brief Checks, at C++ compile-time, if the two pipeline stages are
16/// compatible.
17///
18/// Stages may be incompatible if the outputs declared in the vertex
19/// stage don't line up with the inputs declared in the fragment
20/// stage. Additionally, the types of the inputs and outputs need to
21/// be identical. Some drivers like the one on the PowerVR GE8320
22/// also have bugs the require the precision qualifier of the stage
23/// interfaces to match exactly.
24///
25/// Not ensuring stage compatibility will cause pipeline creation
26/// errors that will only be caught at runtime. In addition to the
27/// bugs discovered related to precision qualifier, some errors may
28/// only manifest at runtime on some devices.
29///
30/// This static compile-time C++ check ensures that all the possible
31/// runtime errors will be caught at build time.
32///
33/// There is no runtime overhead to using this class.
34///
35/// @tparam VertexShaderT The vertex shader stage metadata.
36/// @tparam FragmentShaderT The fragment shader stage metadata.
37///
38template <typename VertexShaderT, typename FragmentShaderT>
40 public:
41 static constexpr bool CompileTimeStrEqual(const char* str1,
42 const char* str2) {
43 return *str1 == *str2 &&
44 (*str1 == '\0' || CompileTimeStrEqual(str1 + 1, str2 + 1));
45 }
46
47 /// Returns `true` if the shader input slots for the fragment shader match the
48 /// ones declared as outputs in the vertex shader.
49 static constexpr bool Check() {
50 constexpr size_t num_outputs = VertexShaderT::kAllShaderStageOutputs.size();
51 constexpr size_t num_inputs = FragmentShaderT::kAllShaderStageInputs.size();
52
53 if (num_inputs > num_outputs) {
54 return false;
55 }
56
57 for (size_t i = 0; i < num_inputs; ++i) {
58 const ShaderStageIOSlot* input_slot =
59 FragmentShaderT::kAllShaderStageInputs[i];
60 for (size_t j = 0; j < num_outputs; ++j) {
61 const ShaderStageIOSlot* output_slot =
62 VertexShaderT::kAllShaderStageOutputs[j];
63 if (input_slot->location == output_slot->location) {
64 if (!CompileTimeStrEqual(input_slot->name, output_slot->name) ||
65 input_slot->set != output_slot->set ||
66 input_slot->binding != output_slot->binding ||
67 input_slot->type != output_slot->type ||
68 input_slot->bit_width != output_slot->bit_width ||
69 input_slot->vec_size != output_slot->vec_size ||
70 input_slot->columns != output_slot->columns ||
71 input_slot->offset != output_slot->offset ||
72 input_slot->relaxed_precision != output_slot->relaxed_precision) {
73 return false;
74 }
75 }
76 }
77 }
78
79 return true;
80 }
81};
82
83} // namespace impeller
84
85#endif // FLUTTER_IMPELLER_RENDERER_SHADER_STAGE_COMPATIBILITY_CHECKER_H_
Checks, at C++ compile-time, if the two pipeline stages are compatible.
static constexpr bool CompileTimeStrEqual(const char *str1, const char *str2)