17#include "third_party/abseil-cpp/absl/status/status.h"
18#include "third_party/abseil-cpp/absl/status/statusor.h"
19#include "third_party/abseil-cpp/absl/strings/str_cat.h"
30 std::shared_ptr<impeller::VertexDescriptor> vertex_descriptor)
31 : vertex_shader_(
std::move(vertex_shader)),
32 fragment_shader_(
std::move(fragment_shader)),
33 vertex_descriptor_(
std::move(vertex_descriptor)) {
38 vertex_descriptor_->RegisterDescriptorSetLayouts(
41 vertex_descriptor_->RegisterDescriptorSetLayouts(
63struct VertexFormatInfo {
70constexpr std::array<VertexFormatInfo, 12> kVertexFormatTable = {{
88constexpr size_t kBufferLayoutInts = 2;
96constexpr size_t kAttributeInts = 3;
110absl::StatusOr<std::shared_ptr<impeller::VertexDescriptor>>
112 std::span<const int32_t> buffer_layouts,
113 std::span<const int32_t> attributes,
114 std::span<const char> attribute_names) {
115 const size_t buffer_layout_count = buffer_layouts.size() / kBufferLayoutInts;
116 const size_t attribute_count = attributes.size() / kAttributeInts;
119 std::vector<impeller::ShaderStageBufferLayout> stage_layouts;
120 stage_layouts.reserve(buffer_layout_count);
121 std::vector<impeller::ShaderStageIOSlot> stage_inputs;
122 stage_inputs.reserve(attribute_count);
124 size_t attr_cursor = 0;
125 size_t name_cursor = 0;
126 for (
size_t buffer_index = 0; buffer_index < buffer_layout_count;
128 const int32_t stride = buffer_layouts[buffer_index * kBufferLayoutInts + 0];
129 const int32_t attr_count_in_buffer =
130 buffer_layouts[buffer_index * kBufferLayoutInts + 1];
132 return absl::InvalidArgumentError(
133 absl::StrCat(
"VertexBuffer.strideInBytes must be positive (got ",
134 stride,
") on buffer at index ", buffer_index,
"."));
136 if (attr_count_in_buffer < 0 ||
137 attr_cursor +
static_cast<size_t>(attr_count_in_buffer) >
139 return absl::InvalidArgumentError(
140 "Internal error: attribute count overruns the packed attributes "
143 stage_layouts.push_back({
static_cast<size_t>(stride), buffer_index});
152 std::vector<AttrRange> ranges_in_buffer;
153 ranges_in_buffer.reserve(attr_count_in_buffer);
155 for (
size_t a = 0; a < static_cast<size_t>(attr_count_in_buffer); ++a) {
156 const int32_t offset = attributes[attr_cursor * kAttributeInts + 0];
157 const int32_t format_index = attributes[attr_cursor * kAttributeInts + 1];
158 const int32_t name_byte_length =
159 attributes[attr_cursor * kAttributeInts + 2];
162 if (name_byte_length <= 0 ||
163 name_cursor +
static_cast<size_t>(name_byte_length) >
164 attribute_names.size()) {
165 return absl::InvalidArgumentError(
166 "Internal error: attribute name overruns the packed names blob.");
168 const std::string_view
name(attribute_names.data() + name_cursor,
169 static_cast<size_t>(name_byte_length));
170 name_cursor +=
static_cast<size_t>(name_byte_length);
173 return absl::InvalidArgumentError(absl::StrCat(
174 "VertexAttribute '",
name,
175 "' offsetInBytes must be non-negative (got ", offset,
")."));
177 if (format_index < 0 ||
178 static_cast<size_t>(format_index) >= kVertexFormatTable.size()) {
179 return absl::InvalidArgumentError(
180 absl::StrCat(
"VertexAttribute '",
name,
"' format index ",
181 format_index,
" is out of range."));
183 const VertexFormatInfo&
format = kVertexFormatTable[format_index];
185 if (
static_cast<size_t>(offset) +
format.bytes_per_element >
186 static_cast<size_t>(stride)) {
187 return absl::InvalidArgumentError(absl::StrCat(
188 "VertexAttribute '",
name,
"' (offset ", offset,
" + ",
189 format.bytes_per_element,
" bytes) overruns stride of ", stride,
190 " on buffer at index ", buffer_index,
"."));
196 const size_t begin =
static_cast<size_t>(offset);
197 const size_t end = begin +
format.bytes_per_element;
198 const std::string name_owned(
name);
199 for (
const auto& other : ranges_in_buffer) {
200 if (begin < other.end && other.begin <
end) {
201 return absl::InvalidArgumentError(
202 absl::StrCat(
"VertexAttribute '",
name,
"' (bytes [", begin,
", ",
203 end,
")) overlaps VertexAttribute '", other.name,
204 "' (bytes [", other.begin,
", ", other.end,
205 ")) on buffer at index ", buffer_index,
"."));
208 ranges_in_buffer.push_back({name_owned, begin,
end});
218 for (
const auto& slot : shader_inputs) {
219 if (slot.name !=
nullptr &&
220 std::strcmp(slot.name, name_owned.c_str()) == 0) {
225 if (shader_slot ==
nullptr) {
226 return absl::InvalidArgumentError(absl::StrCat(
227 "VertexAttribute name '",
name,
228 "' does not match any input declared by the bound vertex "
245 return absl::InvalidArgumentError(absl::StrCat(
246 "VertexAttribute '",
name,
247 "' format does not match the vertex shader's declared input "
253 built.
offset =
static_cast<size_t>(offset);
254 stage_inputs.push_back(built);
258 if (attr_cursor != attribute_count) {
259 return absl::InvalidArgumentError(
260 "Internal error: attributes blob has trailing rows not consumed "
263 if (name_cursor != attribute_names.size()) {
264 return absl::InvalidArgumentError(
265 "Internal error: attribute names blob has trailing bytes.");
268 auto descriptor = std::make_shared<impeller::VertexDescriptor>();
269 descriptor->SetStageInputs(stage_inputs, stage_layouts);
287 Dart_Handle buffer_layouts_handle,
288 Dart_Handle attributes_handle,
289 Dart_Handle attribute_names_handle) {
294 std::shared_ptr<impeller::VertexDescriptor> vertex_descriptor;
296 const bool buffer_layouts_provided = !Dart_IsNull(buffer_layouts_handle);
297 const bool attributes_provided = !Dart_IsNull(attributes_handle);
298 const bool attribute_names_provided = !Dart_IsNull(attribute_names_handle);
299 if (buffer_layouts_provided != attributes_provided ||
300 attributes_provided != attribute_names_provided) {
302 "VertexLayout requires buffer layouts, attributes, and attribute "
303 "names to be provided together.");
306 if (buffer_layouts_provided) {
314 std::vector<int32_t> buffer_layouts_ints;
315 std::vector<int32_t> attribute_ints;
316 std::vector<char> attribute_names_bytes;
317 std::string copy_error;
323 (flutter::gpu::kBufferLayoutInts *
sizeof(int32_t)) !=
326 "Internal error: buffer layouts ByteData has invalid length.";
328 (flutter::gpu::kAttributeInts *
sizeof(int32_t)) !=
330 copy_error =
"Internal error: attributes ByteData has invalid length.";
332 const auto* buffer_layouts_src =
333 static_cast<const int32_t*
>(buffer_layouts_data.
data());
334 const auto* attributes_src =
335 static_cast<const int32_t*
>(attributes_data.
data());
336 const auto* names_src =
337 static_cast<const char*
>(attribute_names_data.
data());
338 buffer_layouts_ints.assign(
342 attribute_ints.assign(
345 attribute_names_bytes.assign(
349 if (!copy_error.empty()) {
353 absl::StatusOr<std::shared_ptr<impeller::VertexDescriptor>> built =
354 flutter::gpu::BuildCustomVertexDescriptor(
356 std::span<const int32_t>(buffer_layouts_ints.data(),
357 buffer_layouts_ints.size()),
358 std::span<const int32_t>(attribute_ints.data(),
359 attribute_ints.size()),
360 std::span<const char>(attribute_names_bytes.data(),
361 attribute_names_bytes.size()));
365 vertex_descriptor = *std::move(built);
370 auto res = fml::MakeRefCounted<flutter::gpu::RenderPipeline>(
373 std::move(vertex_descriptor));
374 res->AssociateWithDartWrapper(wrapper);
~RenderPipeline() override
void BindToPipelineDescriptor(impeller::ShaderLibrary &library, impeller::PipelineDescriptor &desc)
RenderPipeline(fml::RefPtr< flutter::gpu::Shader > vertex_shader, fml::RefPtr< flutter::gpu::Shader > fragment_shader, std::shared_ptr< impeller::VertexDescriptor > vertex_descriptor)
An immutable collection of shaders loaded from a shader bundle asset.
bool RegisterSync(Context &context)
const std::vector< impeller::ShaderStageIOSlot > & GetStageInputs() const
std::shared_ptr< impeller::VertexDescriptor > CreateVertexDescriptor() const
const std::vector< impeller::DescriptorSetLayout > & GetDescriptorSetLayouts() const
std::shared_ptr< const impeller::ShaderFunction > GetFunctionFromLibrary(impeller::ShaderLibrary &library)
PipelineDescriptor & SetVertexDescriptor(std::shared_ptr< VertexDescriptor > vertex_descriptor)
PipelineDescriptor & AddStageEntrypoint(std::shared_ptr< const ShaderFunction > function)
const void * data() const
size_t length_in_bytes() const
#define IMPLEMENT_WRAPPERTYPEINFO(LibraryName, ClassName)
uint32_t uint32_t * format
DEF_SWITCHES_START aot vmservice shared library name
Dart_Handle ToDart(const T &object)
Dart_Handle InternalFlutterGpu_RenderPipeline_Initialize(Dart_Handle wrapper, flutter::gpu::Context *gpu_context, flutter::gpu::Shader *vertex_shader, flutter::gpu::Shader *fragment_shader, Dart_Handle buffer_layouts_handle, Dart_Handle attributes_handle, Dart_Handle attribute_names_handle)
impeller::ShaderType type