Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions impeller/renderer/pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,73 @@ PipelineFuture<ComputePipelineDescriptor> CreatePipelineFuture(
const Context& context,
std::optional<ComputePipelineDescriptor> desc);

/// This is a classed use to check that the input slots of fragment shaders
/// match the output slots of the vertex shaders.
/// It's not used at runtime.
template <typename VertexShaderT, typename FragmentShaderT>
class ShaderBindingComparator {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a class because it's required for partial specialization. Also I wish we got better feedback when this failed, but I couldn't figure out how to get multiple static asserts happening in the loop, that's why it returns bool.

public:
static constexpr bool CompileTimeStrEqual(const char* str1,
const char* str2) {
return *str1 == *str2 &&
(*str1 == '\0' || CompileTimeStrEqual(str1 + 1, str2 + 1));
}

static constexpr bool Compare() {
constexpr size_t num_outputs = VertexShaderT::kAllShaderStageOutputs.size();
constexpr size_t num_inputs = FragmentShaderT::kAllShaderStageInputs.size();

if (num_inputs > num_outputs) {
return false;
}

for (size_t i = 0; i < num_inputs; ++i) {
const ShaderStageIOSlot* input_slot =
FragmentShaderT::kAllShaderStageInputs[i];
for (size_t j = 0; j < num_outputs; ++j) {
const ShaderStageIOSlot* output_slot =
VertexShaderT::kAllShaderStageOutputs[j];
if (input_slot->location == output_slot->location) {
if (!CompileTimeStrEqual(input_slot->name, output_slot->name) ||
input_slot->set != output_slot->set ||
input_slot->binding != output_slot->binding ||
input_slot->type != output_slot->type ||
input_slot->bit_width != output_slot->bit_width ||
input_slot->vec_size != output_slot->vec_size ||
input_slot->columns != output_slot->columns ||
input_slot->offset != output_slot->offset) {
return false;
}
}
}
}

return true;
}
};

// The following shaders don't define output slots.
// TODO(tbd): Make impellerc emit an empty array for output slots.
struct CheckerboardVertexShader;
struct ClipVertexShader;

template <typename FragmentShaderT>
class ShaderBindingComparator<CheckerboardVertexShader, FragmentShaderT> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another idea for if you don't want to update the code gen template, you could have a third template size_t argument that is the count of the array elements and have a specialization for zero that is true.

public:
static constexpr bool Compare() { return true; }
};

template <typename FragmentShaderT>
class ShaderBindingComparator<ClipVertexShader, FragmentShaderT> {
public:
static constexpr bool Compare() { return true; }
};

template <class VertexShader_, class FragmentShader_>
class RenderPipelineT {
static_assert(
ShaderBindingComparator<VertexShader_, FragmentShader_>::Compare());

public:
using VertexShader = VertexShader_;
using FragmentShader = FragmentShader_;
Expand Down