Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
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
42 changes: 42 additions & 0 deletions impeller/fixtures/dart_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,48 @@ gpu.RenderPipeline createUnlitRenderPipeline() {
return gpu.gpuContext.createRenderPipeline(vertex!, fragment!);
}

gpu.RenderPass createRenderPass() {
final gpu.Texture? renderTexture =
gpu.gpuContext.createTexture(gpu.StorageMode.devicePrivate, 100, 100);
assert(renderTexture != null);

final gpu.CommandBuffer commandBuffer = gpu.gpuContext.createCommandBuffer();

final gpu.RenderTarget renderTarget = gpu.RenderTarget.singleColor(
gpu.ColorAttachment(texture: renderTexture!),
);
return commandBuffer.createRenderPass(renderTarget);
}

@pragma('vm:entry-point')
void uniformBindFailsForInvalidHostBufferOffset() {
final gpu.RenderPass encoder = createRenderPass();

final gpu.RenderPipeline pipeline = createUnlitRenderPipeline();
encoder.bindPipeline(pipeline);

final gpu.HostBuffer transients = gpu.HostBuffer();
final gpu.BufferView vertInfoData = transients.emplace(float32(<double>[
1, 0, 0, 0, // mvp
0, 1, 0, 0, // mvp
0, 0, 1, 0, // mvp
0, 0, 0, 1, // mvp
0, 1, 0, 1, // color
]));
final gpu.BufferView viewWithBadOffset = gpu.BufferView(vertInfoData.buffer,
offsetInBytes: 1, lengthInBytes: vertInfoData.lengthInBytes);

final gpu.UniformSlot vertInfo =
pipeline.vertexShader.getUniformSlot('VertInfo');
String? exception;
try {
encoder.bindUniform(vertInfo, viewWithBadOffset);
} catch (e) {
exception = e.toString();
}
assert(exception!.contains('Failed to bind uniform'));
}

ByteData float32(List<double> values) {
return Float32List.fromList(values).buffer.asByteData();
}
Expand Down
1 change: 1 addition & 0 deletions impeller/renderer/renderer_dart_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ DART_TEST_CASE(textureAsImageThrowsWhenNotShaderReadable);

DART_TEST_CASE(canCreateShaderLibrary);
DART_TEST_CASE(canReflectUniformStructs);
DART_TEST_CASE(uniformBindFailsForInvalidHostBufferOffset);

DART_TEST_CASE(canCreateRenderPassAndSubmit);

Expand Down
7 changes: 7 additions & 0 deletions lib/gpu/host_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,16 @@ size_t HostBuffer::EmplaceBytes(const tonic::DartByteData& byte_data) {
auto view =
host_buffer_->Emplace(byte_data.data(), byte_data.length_in_bytes(),
impeller::DefaultUniformAlignment());
emplacements_[current_offset_] = view;
current_offset_ += view.range.length;
return view.range.offset;
}

std::optional<impeller::BufferView> HostBuffer::GetBufferViewForOffset(
size_t offset) {
return emplacements_[offset];
}

} // namespace gpu
} // namespace flutter

Expand Down
5 changes: 5 additions & 0 deletions lib/gpu/host_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "flutter/lib/gpu/export.h"
#include "flutter/lib/ui/dart_wrapper.h"
#include "impeller/core/buffer_view.h"
#include "impeller/core/host_buffer.h"
#include "third_party/tonic/typed_data/dart_byte_data.h"

Expand All @@ -26,8 +27,12 @@ class HostBuffer : public RefCountedDartWrappable<HostBuffer> {

size_t EmplaceBytes(const tonic::DartByteData& byte_data);

std::optional<impeller::BufferView> GetBufferViewForOffset(size_t offset);

private:
size_t current_offset_ = 0;
std::shared_ptr<impeller::HostBuffer> host_buffer_;
std::unordered_map<size_t, impeller::BufferView> emplacements_;

FML_DISALLOW_COPY_AND_ASSIGN(HostBuffer);
};
Expand Down
57 changes: 40 additions & 17 deletions lib/gpu/render_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -230,13 +230,13 @@ void InternalFlutterGpu_RenderPass_BindPipeline(

template <typename TBuffer>
static void BindVertexBuffer(flutter::gpu::RenderPass* wrapper,
TBuffer* buffer,
TBuffer buffer,
int offset_in_bytes,
int length_in_bytes,
int vertex_count) {
auto& vertex_buffer = wrapper->GetVertexBuffer();
vertex_buffer.vertex_buffer = impeller::BufferView{
.buffer = buffer->GetBuffer(),
.buffer = buffer,
.range = impeller::Range(offset_in_bytes, length_in_bytes),
};
// If the index type is set, then the `vertex_count` becomes the index
Expand All @@ -258,8 +258,8 @@ void InternalFlutterGpu_RenderPass_BindVertexBufferDevice(
int offset_in_bytes,
int length_in_bytes,
int vertex_count) {
BindVertexBuffer(wrapper, device_buffer, offset_in_bytes, length_in_bytes,
vertex_count);
BindVertexBuffer(wrapper, device_buffer->GetBuffer(), offset_in_bytes,
length_in_bytes, vertex_count);
}

void InternalFlutterGpu_RenderPass_BindVertexBufferHost(
Expand All @@ -268,20 +268,28 @@ void InternalFlutterGpu_RenderPass_BindVertexBufferHost(
int offset_in_bytes,
int length_in_bytes,
int vertex_count) {
BindVertexBuffer(wrapper, host_buffer, offset_in_bytes, length_in_bytes,
vertex_count);
std::optional<impeller::BufferView> view =
host_buffer->GetBufferViewForOffset(offset_in_bytes);
if (!view.has_value()) {
FML_LOG(ERROR)
<< "Failed to bind vertex buffer due to invalid HostBuffer offset: "
<< offset_in_bytes;
return;
}
BindVertexBuffer(wrapper, view->buffer, view->range.offset,
view->range.length, vertex_count);
}

template <typename TBuffer>
static void BindIndexBuffer(flutter::gpu::RenderPass* wrapper,
TBuffer* buffer,
TBuffer buffer,
int offset_in_bytes,
int length_in_bytes,
int index_type,
int index_count) {
auto& vertex_buffer = wrapper->GetVertexBuffer();
vertex_buffer.index_buffer = impeller::BufferView{
.buffer = buffer->GetBuffer(),
.buffer = buffer,
.range = impeller::Range(offset_in_bytes, length_in_bytes),
};
vertex_buffer.index_type = flutter::gpu::ToImpellerIndexType(index_type);
Expand All @@ -295,8 +303,8 @@ void InternalFlutterGpu_RenderPass_BindIndexBufferDevice(
int length_in_bytes,
int index_type,
int index_count) {
BindIndexBuffer(wrapper, device_buffer, offset_in_bytes, length_in_bytes,
index_type, index_count);
BindIndexBuffer(wrapper, device_buffer->GetBuffer(), offset_in_bytes,
length_in_bytes, index_type, index_count);
}

void InternalFlutterGpu_RenderPass_BindIndexBufferHost(
Expand All @@ -306,15 +314,22 @@ void InternalFlutterGpu_RenderPass_BindIndexBufferHost(
int length_in_bytes,
int index_type,
int index_count) {
BindIndexBuffer(wrapper, host_buffer, offset_in_bytes, length_in_bytes,
auto view = host_buffer->GetBufferViewForOffset(offset_in_bytes);
if (!view.has_value()) {
FML_LOG(ERROR)
<< "Failed to bind index buffer due to invalid HostBuffer offset: "
<< offset_in_bytes;
return;
}
BindIndexBuffer(wrapper, view->buffer, view->range.offset, view->range.length,
index_type, index_count);
}

template <typename TBuffer>
static bool BindUniform(flutter::gpu::RenderPass* wrapper,
flutter::gpu::Shader* shader,
Dart_Handle uniform_name_handle,
TBuffer* buffer,
TBuffer buffer,
int offset_in_bytes,
int length_in_bytes) {
auto& command = wrapper->GetCommand();
Expand All @@ -331,7 +346,7 @@ static bool BindUniform(flutter::gpu::RenderPass* wrapper,
return command.BindResource(
shader->GetShaderStage(), uniform_struct->slot, uniform_struct->metadata,
impeller::BufferView{
.buffer = buffer->GetBuffer(),
.buffer = buffer,
.range = impeller::Range(offset_in_bytes, length_in_bytes),
});
}
Expand All @@ -343,8 +358,9 @@ bool InternalFlutterGpu_RenderPass_BindUniformDevice(
flutter::gpu::DeviceBuffer* device_buffer,
int offset_in_bytes,
int length_in_bytes) {
return BindUniform(wrapper, shader, uniform_name_handle, device_buffer,
offset_in_bytes, length_in_bytes);
return BindUniform(wrapper, shader, uniform_name_handle,
device_buffer->GetBuffer(), offset_in_bytes,
length_in_bytes);
}

bool InternalFlutterGpu_RenderPass_BindUniformHost(
Expand All @@ -354,8 +370,15 @@ bool InternalFlutterGpu_RenderPass_BindUniformHost(
flutter::gpu::HostBuffer* host_buffer,
int offset_in_bytes,
int length_in_bytes) {
return BindUniform(wrapper, shader, uniform_name_handle, host_buffer,
offset_in_bytes, length_in_bytes);
auto view = host_buffer->GetBufferViewForOffset(offset_in_bytes);
if (!view.has_value()) {
FML_LOG(ERROR)
<< "Failed to bind index buffer due to invalid HostBuffer offset: "
<< offset_in_bytes;
return false;
}
return BindUniform(wrapper, shader, uniform_name_handle, view->buffer,
view->range.offset, view->range.length);
}

bool InternalFlutterGpu_RenderPass_BindTexture(
Expand Down