diff --git a/engine/src/flutter/impeller/fixtures/dart_tests.dart b/engine/src/flutter/impeller/fixtures/dart_tests.dart index f1e8a952a8..ca9bccd919 100644 --- a/engine/src/flutter/impeller/fixtures/dart_tests.dart +++ b/engine/src/flutter/impeller/fixtures/dart_tests.dart @@ -66,17 +66,16 @@ ByteData float32(List values) { @pragma('vm:entry-point') void canCreateRenderPassAndSubmit(int width, int height) { - final gpu.Texture? renderTexture = gpu.gpuContext.createTexture( + final gpu.Texture renderTexture = gpu.gpuContext.createTexture( gpu.StorageMode.devicePrivate, width, height, ); - assert(renderTexture != null); final gpu.CommandBuffer commandBuffer = gpu.gpuContext.createCommandBuffer(); final gpu.RenderTarget renderTarget = gpu.RenderTarget.singleColor( - gpu.ColorAttachment(texture: renderTexture!), + gpu.ColorAttachment(texture: renderTexture), ); final gpu.RenderPass encoder = commandBuffer.createRenderPass(renderTarget); diff --git a/engine/src/flutter/lib/gpu/lib/src/buffer.dart b/engine/src/flutter/lib/gpu/lib/src/buffer.dart index aed4cff4e8..59da03408c 100644 --- a/engine/src/flutter/lib/gpu/lib/src/buffer.dart +++ b/engine/src/flutter/lib/gpu/lib/src/buffer.dart @@ -244,9 +244,6 @@ base class HostBuffer { StorageMode.hostVisible, length, ); - if (buffer == null) { - throw Exception('Failed to allocate DeviceBuffer of length $length'); - } return buffer; } diff --git a/engine/src/flutter/lib/gpu/lib/src/context.dart b/engine/src/flutter/lib/gpu/lib/src/context.dart index 6574b215e6..e86ec6bd21 100644 --- a/engine/src/flutter/lib/gpu/lib/src/context.dart +++ b/engine/src/flutter/lib/gpu/lib/src/context.dart @@ -63,8 +63,8 @@ base class GpuContext extends NativeFieldWrapperClass1 { /// The [storageMode] must be either [StorageMode.hostVisible] or /// [StorageMode.devicePrivate], otherwise an exception will be thrown. /// - /// Returns [null] if the [DeviceBuffer] creation failed. - DeviceBuffer? createDeviceBuffer(StorageMode storageMode, int sizeInBytes) { + /// Throws an exception if the [DeviceBuffer] creation failed. + DeviceBuffer createDeviceBuffer(StorageMode storageMode, int sizeInBytes) { if (storageMode == StorageMode.deviceTransient) { throw Exception( 'DeviceBuffers cannot be set to StorageMode.deviceTransient', @@ -75,7 +75,10 @@ base class GpuContext extends NativeFieldWrapperClass1 { storageMode, sizeInBytes, ); - return result.isValid ? result : null; + if (!result.isValid) { + throw Exception('DeviceBuffer creation failed'); + } + return result; } /// Allocates a new region of host-visible GPU-resident memory, initialized @@ -85,10 +88,13 @@ base class GpuContext extends NativeFieldWrapperClass1 { /// from the host, the [StorageMode] of the new [DeviceBuffer] is /// automatically set to [StorageMode.hostVisible]. /// - /// Returns [null] if the [DeviceBuffer] creation failed. - DeviceBuffer? createDeviceBufferWithCopy(ByteData data) { + /// Throws an exception if the [DeviceBuffer] creation failed. + DeviceBuffer createDeviceBufferWithCopy(ByteData data) { DeviceBuffer result = DeviceBuffer._initializeWithHostData(this, data); - return result.isValid ? result : null; + if (!result.isValid) { + throw Exception('DeviceBuffer creation failed'); + } + return result; } /// Creates a bump allocator that managed a [DeviceBuffer] block list. @@ -102,8 +108,8 @@ base class GpuContext extends NativeFieldWrapperClass1 { /// Allocates a new texture in GPU-resident memory. /// - /// Returns [null] if the [Texture] creation failed. - Texture? createTexture( + /// Throws an exception if the [Texture] creation failed. + Texture createTexture( StorageMode storageMode, int width, int height, { @@ -127,7 +133,10 @@ base class GpuContext extends NativeFieldWrapperClass1 { enableShaderReadUsage, enableShaderWriteUsage, ); - return result.isValid ? result : null; + if (!result.isValid) { + throw Exception('Texture creation failed'); + } + return result; } /// Create a new command buffer that can be used to submit GPU commands. diff --git a/engine/src/flutter/lib/gpu/lib/src/texture.dart b/engine/src/flutter/lib/gpu/lib/src/texture.dart index 02ba6198a7..4c266e37c8 100644 --- a/engine/src/flutter/lib/gpu/lib/src/texture.dart +++ b/engine/src/flutter/lib/gpu/lib/src/texture.dart @@ -73,7 +73,7 @@ base class Texture extends NativeFieldWrapperClass1 { return _bytesPerTexel(); } - int GetBaseMipLevelSizeInBytes() { + int getBaseMipLevelSizeInBytes() { return bytesPerTexel * width * height; } @@ -86,21 +86,23 @@ base class Texture extends NativeFieldWrapperClass1 { /// level, otherwise an exception will be thrown. The size of the base mip /// level is always `width * height * bytesPerPixel`. /// - /// Returns [true] if the write was successful, or [false] if the write - /// failed due to an internal error. - bool overwrite(ByteData sourceBytes) { + /// Throws an exception if the write failed due to an internal error. + void overwrite(ByteData sourceBytes) { if (storageMode != StorageMode.hostVisible) { throw Exception( 'Texture.overwrite can only be used with Textures that are host visible', ); } - int baseMipSize = GetBaseMipLevelSizeInBytes(); + int baseMipSize = getBaseMipLevelSizeInBytes(); if (sourceBytes.lengthInBytes != baseMipSize) { throw Exception( 'The length of sourceBytes (bytes: ${sourceBytes.lengthInBytes}) must exactly match the size of the base mip level (bytes: ${baseMipSize})', ); } - return _overwrite(sourceBytes); + bool success = _overwrite(sourceBytes); + if (!success) { + throw Exception("Texture overwrite failed"); + } } ui.Image asImage() { diff --git a/engine/src/flutter/testing/dart/gpu_test.dart b/engine/src/flutter/testing/dart/gpu_test.dart index 3d5c82d142..41af26798a 100644 --- a/engine/src/flutter/testing/dart/gpu_test.dart +++ b/engine/src/flutter/testing/dart/gpu_test.dart @@ -52,26 +52,24 @@ class RenderPassState { /// Create a simple RenderPass with simple color and depth-stencil attachments. RenderPassState createSimpleRenderPass({Vector4? clearColor}) { - final gpu.Texture? renderTexture = gpu.gpuContext.createTexture( + final gpu.Texture renderTexture = gpu.gpuContext.createTexture( gpu.StorageMode.devicePrivate, 100, 100, ); - assert(renderTexture != null); - final gpu.Texture? depthStencilTexture = gpu.gpuContext.createTexture( + final gpu.Texture depthStencilTexture = gpu.gpuContext.createTexture( gpu.StorageMode.deviceTransient, 100, 100, format: gpu.gpuContext.defaultDepthStencilFormat, ); - assert(depthStencilTexture != null); final gpu.CommandBuffer commandBuffer = gpu.gpuContext.createCommandBuffer(); final gpu.RenderTarget renderTarget = gpu.RenderTarget.singleColor( - gpu.ColorAttachment(texture: renderTexture!, clearValue: clearColor), - depthStencilAttachment: gpu.DepthStencilAttachment(texture: depthStencilTexture!), + gpu.ColorAttachment(texture: renderTexture, clearValue: clearColor), + depthStencilAttachment: gpu.DepthStencilAttachment(texture: depthStencilTexture), ); final gpu.RenderPass renderPass = commandBuffer.createRenderPass(renderTarget); @@ -83,49 +81,46 @@ RenderPassState createSimpleRenderPassWithMSAA() { // Create transient MSAA attachments, which will live entirely in tile memory // for most GPUs. - final gpu.Texture? renderTexture = gpu.gpuContext.createTexture( + final gpu.Texture renderTexture = gpu.gpuContext.createTexture( gpu.StorageMode.deviceTransient, 100, 100, format: gpu.gpuContext.defaultColorFormat, sampleCount: 4, ); - assert(renderTexture != null); - final gpu.Texture? depthStencilTexture = gpu.gpuContext.createTexture( + final gpu.Texture depthStencilTexture = gpu.gpuContext.createTexture( gpu.StorageMode.deviceTransient, 100, 100, format: gpu.gpuContext.defaultDepthStencilFormat, sampleCount: 4, ); - assert(depthStencilTexture != null); // Create the single-sample resolve texture that live in DRAM and will be // drawn to the screen. - final gpu.Texture? resolveTexture = gpu.gpuContext.createTexture( + final gpu.Texture resolveTexture = gpu.gpuContext.createTexture( gpu.StorageMode.devicePrivate, 100, 100, format: gpu.gpuContext.defaultColorFormat, ); - assert(resolveTexture != null); final gpu.CommandBuffer commandBuffer = gpu.gpuContext.createCommandBuffer(); final gpu.RenderTarget renderTarget = gpu.RenderTarget.singleColor( gpu.ColorAttachment( - texture: renderTexture!, + texture: renderTexture, resolveTexture: resolveTexture, storeAction: gpu.StoreAction.multisampleResolve, ), - depthStencilAttachment: gpu.DepthStencilAttachment(texture: depthStencilTexture!), + depthStencilAttachment: gpu.DepthStencilAttachment(texture: depthStencilTexture), ); final gpu.RenderPass renderPass = commandBuffer.createRenderPass(renderTarget); - return RenderPassState(resolveTexture!, commandBuffer, renderPass); + return RenderPassState(resolveTexture, commandBuffer, renderPass); } void drawTriangle(RenderPassState state, Vector4 color) { @@ -228,23 +223,21 @@ void main() async { }, skip: !impellerEnabled); test('GpuContext.createDeviceBuffer', () async { - final gpu.DeviceBuffer? deviceBuffer = gpu.gpuContext.createDeviceBuffer( + final gpu.DeviceBuffer deviceBuffer = gpu.gpuContext.createDeviceBuffer( gpu.StorageMode.hostVisible, 4, ); - assert(deviceBuffer != null); - expect(deviceBuffer!.sizeInBytes, 4); + expect(deviceBuffer.sizeInBytes, 4); }, skip: !impellerEnabled); test('DeviceBuffer.overwrite', () async { - final gpu.DeviceBuffer? deviceBuffer = gpu.gpuContext.createDeviceBuffer( + final gpu.DeviceBuffer deviceBuffer = gpu.gpuContext.createDeviceBuffer( gpu.StorageMode.hostVisible, 4, ); - assert(deviceBuffer != null); - final bool success = deviceBuffer!.overwrite( + final bool success = deviceBuffer.overwrite( Int8List.fromList([0, 1, 2, 3]).buffer.asByteData(), ); deviceBuffer.flush(); @@ -252,13 +245,12 @@ void main() async { }, skip: !impellerEnabled); test('DeviceBuffer.overwrite fails when out of bounds', () async { - final gpu.DeviceBuffer? deviceBuffer = gpu.gpuContext.createDeviceBuffer( + final gpu.DeviceBuffer deviceBuffer = gpu.gpuContext.createDeviceBuffer( gpu.StorageMode.hostVisible, 4, ); - assert(deviceBuffer != null); - final bool success = deviceBuffer!.overwrite( + final bool success = deviceBuffer.overwrite( Int8List.fromList([0, 1, 2, 3]).buffer.asByteData(), destinationOffsetInBytes: 1, ); @@ -267,14 +259,13 @@ void main() async { }, skip: !impellerEnabled); test('DeviceBuffer.overwrite throws for negative destination offset', () async { - final gpu.DeviceBuffer? deviceBuffer = gpu.gpuContext.createDeviceBuffer( + final gpu.DeviceBuffer deviceBuffer = gpu.gpuContext.createDeviceBuffer( gpu.StorageMode.hostVisible, 4, ); - assert(deviceBuffer != null); try { - deviceBuffer!.overwrite( + deviceBuffer.overwrite( Int8List.fromList([0, 1, 2, 3]).buffer.asByteData(), destinationOffsetInBytes: -1, ); @@ -286,15 +277,10 @@ void main() async { }, skip: !impellerEnabled); test('GpuContext.createTexture', () async { - final gpu.Texture? texture = gpu.gpuContext.createTexture( - gpu.StorageMode.hostVisible, - 100, - 100, - ); - assert(texture != null); + final gpu.Texture texture = gpu.gpuContext.createTexture(gpu.StorageMode.hostVisible, 100, 100); // Check the defaults. - expect(texture!.coordinateSystem, gpu.TextureCoordinateSystem.renderToTexture); + expect(texture.coordinateSystem, gpu.TextureCoordinateSystem.renderToTexture); expect(texture.width, 100); expect(texture.height, 100); expect(texture.storageMode, gpu.StorageMode.hostVisible); @@ -304,33 +290,25 @@ void main() async { expect(texture.enableShaderReadUsage, true); expect(!texture.enableShaderWriteUsage, true); expect(texture.bytesPerTexel, 4); - expect(texture.GetBaseMipLevelSizeInBytes(), 40000); + expect(texture.getBaseMipLevelSizeInBytes(), 40000); }, skip: !impellerEnabled); test('Texture.overwrite', () async { - final gpu.Texture? texture = gpu.gpuContext.createTexture(gpu.StorageMode.hostVisible, 2, 2); - assert(texture != null); + final gpu.Texture texture = gpu.gpuContext.createTexture(gpu.StorageMode.hostVisible, 2, 2); const ui.Color red = ui.Color.fromARGB(0xFF, 0xFF, 0, 0); const ui.Color green = ui.Color.fromARGB(0xFF, 0, 0xFF, 0); - final bool success = texture!.overwrite( + texture.overwrite( Int32List.fromList([red.value, green.value, green.value, red.value]).buffer.asByteData(), ); - - expect(success, true); }, skip: !impellerEnabled); test('Texture.overwrite throws for wrong buffer size', () async { - final gpu.Texture? texture = gpu.gpuContext.createTexture( - gpu.StorageMode.hostVisible, - 100, - 100, - ); - assert(texture != null); + final gpu.Texture texture = gpu.gpuContext.createTexture(gpu.StorageMode.hostVisible, 100, 100); const ui.Color red = ui.Color.fromARGB(0xFF, 0xFF, 0, 0); try { - texture!.overwrite( + texture.overwrite( Int32List.fromList([red.value, red.value, red.value, red.value]).buffer.asByteData(), ); fail('Exception not thrown for wrong buffer size.'); @@ -345,29 +323,23 @@ void main() async { }, skip: !impellerEnabled); test('Texture.asImage returns a valid ui.Image handle', () async { - final gpu.Texture? texture = gpu.gpuContext.createTexture( - gpu.StorageMode.hostVisible, - 100, - 100, - ); - assert(texture != null); + final gpu.Texture texture = gpu.gpuContext.createTexture(gpu.StorageMode.hostVisible, 100, 100); - final ui.Image image = texture!.asImage(); + final ui.Image image = texture.asImage(); expect(image.width, 100); expect(image.height, 100); }, skip: !impellerEnabled); test('Texture.asImage throws when not shader readable', () async { - final gpu.Texture? texture = gpu.gpuContext.createTexture( + final gpu.Texture texture = gpu.gpuContext.createTexture( gpu.StorageMode.hostVisible, 100, 100, enableShaderReadUsage: false, ); - assert(texture != null); try { - texture!.asImage(); + texture.asImage(); fail('Exception not thrown when not shader readable.'); } catch (e) { expect( @@ -457,8 +429,11 @@ void main() async { // purposes of testing this error. final gpu.UniformSlot vertInfo = pipeline.vertexShader.getUniformSlot('VertInfo'); - final gpu.Texture texture = - gpu.gpuContext.createTexture(gpu.StorageMode.deviceTransient, 100, 100)!; + final gpu.Texture texture = gpu.gpuContext.createTexture( + gpu.StorageMode.deviceTransient, + 100, + 100, + ); try { state.renderPass.bindTexture(vertInfo, texture); @@ -495,7 +470,7 @@ void main() async { 0, 0, 0, 1, // mvp 0, 1, 0, 1, // color ]); - final uniformBuffer = gpu.gpuContext.createDeviceBufferWithCopy(vertInfoData)!; + final uniformBuffer = gpu.gpuContext.createDeviceBufferWithCopy(vertInfoData); final gooduniformBufferView = gpu.BufferView( uniformBuffer, offsetInBytes: 0,