10#ifdef IMPELLER_GOLDEN_TESTS
22#include "impeller/fixtures/baby.frag.h"
23#include "impeller/fixtures/baby.vert.h"
24#include "impeller/fixtures/instanced_attributes.frag.h"
25#include "impeller/fixtures/instanced_attributes.vert.h"
26#include "impeller/fixtures/mipmaps.frag.h"
27#include "impeller/fixtures/mipmaps.vert.h"
28#include "impeller/fixtures/texture.frag.h"
29#include "impeller/fixtures/texture.vert.h"
47using RendererGoldenTest = GoldenPlaygroundTest;
53TEST_P(RendererGoldenTest, BabysFirstTriangle) {
54 using VS = BabyVertexShader;
55 using FS = BabyFragmentShader;
57 std::shared_ptr<Context>
context = GetContext();
61 ASSERT_TRUE(desc.has_value());
68 desc->ClearStencilAttachments();
69 desc->ClearDepthAttachment();
73 VertexBufferBuilder<VS::PerVertexData> vertex_buffer_builder;
74 vertex_buffer_builder.AddVertices({
79 auto vertex_buffer = vertex_buffer_builder.CreateVertexBuffer(
80 *
context->GetResourceAllocator());
84 context->GetCapabilities()->GetMinimumUniformAlignment());
86 ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) ->
bool {
91 pass.SetVertexBuffer(vertex_buffer);
93 FS::FragInfo frag_info;
94 frag_info.time = 0.0f;
95 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(frag_info));
97 return pass.Draw().ok();
106TEST_P(RendererGoldenTest, CanRenderInstancedWithVertexAttributes) {
107 using VS = InstancedAttributesVertexShader;
108 using FS = InstancedAttributesFragmentShader;
110 std::shared_ptr<Context>
context = GetContext();
114 ASSERT_TRUE(desc.has_value());
117 desc->ClearStencilAttachments();
118 desc->ClearDepthAttachment();
121 struct InstanceData {
129 auto vertex_desc = std::make_shared<VertexDescriptor>();
130 ShaderStageIOSlot position_slot = VS::kInputVertexPosition;
131 ShaderStageIOSlot offset_slot = VS::kInputInstanceOffset;
132 ShaderStageIOSlot color_slot = VS::kInputInstanceColor;
133 position_slot.binding = 0;
134 position_slot.offset = 0;
135 offset_slot.binding = 1;
136 offset_slot.offset = offsetof(InstanceData, offset);
137 color_slot.binding = 1;
138 color_slot.offset = offsetof(InstanceData, color);
139 const std::vector<ShaderStageIOSlot> io_slots = {position_slot, offset_slot,
141 const std::vector<ShaderStageBufferLayout> layouts = {
142 ShaderStageBufferLayout{.stride =
sizeof(
Vector2),
145 ShaderStageBufferLayout{.stride =
sizeof(InstanceData),
149 vertex_desc->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
150 vertex_desc->RegisterDescriptorSetLayouts(FS::kDescriptorSetLayouts);
151 vertex_desc->SetStageInputs(io_slots, layouts);
152 desc->SetVertexDescriptor(std::move(vertex_desc));
154 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
158 std::array<Vector2, 3> geometry = {
164 static constexpr size_t kInstanceCount = 4u;
165 std::array<InstanceData, kInstanceCount> instances = {
166 InstanceData{
Vector2{0, 0}, Vector4{1, 0, 0, 1}},
167 InstanceData{
Vector2{120, 0}, Vector4{0, 1, 0, 1}},
168 InstanceData{
Vector2{0, 120}, Vector4{0, 0, 1, 1}},
169 InstanceData{
Vector2{120, 120}, Vector4{1, 1, 0, 1}},
172 auto geometry_buffer =
context->GetResourceAllocator()->CreateBufferWithCopy(
173 reinterpret_cast<uint8_t*
>(geometry.data()),
174 geometry.size() *
sizeof(
Vector2));
175 auto instance_buffer =
context->GetResourceAllocator()->CreateBufferWithCopy(
176 reinterpret_cast<uint8_t*
>(instances.data()),
177 instances.size() *
sizeof(InstanceData));
178 ASSERT_TRUE(geometry_buffer && instance_buffer);
182 context->GetCapabilities()->GetMinimumUniformAlignment());
184 ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) ->
bool {
187 host_buffer->Reset();
188 pass.SetCommandLabel(
"InstancedAttributes");
191 std::array<BufferView, 2> vertex_buffers = {
192 BufferView(geometry_buffer,
193 Range(0, geometry.size() *
sizeof(
Vector2))),
194 BufferView(instance_buffer,
195 Range(0, instances.size() *
sizeof(InstanceData))),
197 pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size());
198 pass.SetElementCount(geometry.size());
199 pass.SetInstanceCount(kInstanceCount);
201 VS::FrameInfo frame_info;
204 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
206 return pass.Draw().ok();
214static void DrawCompressedTextureGolden(GoldenPlaygroundTest& test,
216 const std::vector<uint8_t>& block_data,
218 using VS = TextureVertexShader;
219 using FS = TextureFragmentShader;
221 std::shared_ptr<Context>
context = test.GetContext();
224 TextureDescriptor texture_desc;
226 texture_desc.format =
format;
227 texture_desc.size =
size;
228 texture_desc.mip_count = 1u;
230 auto texture =
context->GetResourceAllocator()->CreateTexture(texture_desc);
232 ASSERT_TRUE(
texture->SetContents(block_data.data(), block_data.size()));
235 ASSERT_TRUE(desc.has_value());
237 desc->ClearStencilAttachments();
238 desc->ClearDepthAttachment();
239 auto pipeline =
context->GetPipelineLibrary()->GetPipeline(desc).Get();
243 VertexBufferBuilder<VS::PerVertexData> vertex_buffer_builder;
244 vertex_buffer_builder.AddVertices({
245 {{-1, -1, 0.0}, {0.0, 0.0}},
246 {{1, -1, 0.0}, {1.0, 0.0}},
247 {{1, 1, 0.0}, {1.0, 1.0}},
248 {{-1, -1, 0.0}, {0.0, 0.0}},
249 {{1, 1, 0.0}, {1.0, 1.0}},
250 {{-1, 1, 0.0}, {0.0, 1.0}},
252 auto vertex_buffer = vertex_buffer_builder.CreateVertexBuffer(
253 *
context->GetResourceAllocator());
255 const auto& sampler =
context->GetSamplerLibrary()->GetSampler({});
259 context->GetCapabilities()->GetMinimumUniformAlignment());
261 ASSERT_TRUE(test.OpenPlaygroundHere([&](RenderPass& pass) ->
bool {
262 host_buffer->Reset();
263 pass.SetPipeline(pipeline);
264 pass.SetVertexBuffer(vertex_buffer);
266 VS::UniformBuffer uniforms;
267 uniforms.mvp = Matrix();
268 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
269 FS::BindTextureContents(pass, texture, sampler);
271 return pass.Draw().ok();
279TEST_P(RendererGoldenTest, CanRenderBC1CompressedTexture) {
280 std::shared_ptr<Context>
context = GetContext();
282 if (!
context->GetCapabilities()->SupportsTextureCompression(
284 GTEST_SKIP() <<
"Backend does not support BC texture compression.";
289 auto bc1_solid_block = [](uint16_t rgb565) -> std::array<uint8_t, 8> {
290 const auto lo =
static_cast<uint8_t
>(rgb565 & 0xFF);
291 const auto hi =
static_cast<uint8_t
>(rgb565 >> 8);
292 return {{lo, hi, lo, hi, 0, 0, 0, 0}};
295 const std::array<std::array<uint8_t, 8>, 4> blocks = {
296 {bc1_solid_block(0xF800), bc1_solid_block(0x07E0),
297 bc1_solid_block(0x001F), bc1_solid_block(0xFFFF)}};
298 std::vector<uint8_t>
data;
299 for (
const auto& block : blocks) {
300 data.insert(
data.end(), block.begin(), block.end());
311TEST_P(RendererGoldenTest, CanRenderETC2CompressedTexture) {
312 std::shared_ptr<Context>
context = GetContext();
314 if (!
context->GetCapabilities()->SupportsTextureCompression(
316 GTEST_SKIP() <<
"Backend does not support ETC2 texture compression.";
325 auto etc2_solid_block = [](uint8_t r, uint8_t g,
326 uint8_t
b) -> std::array<uint8_t, 8> {
327 return {{r, g,
b, 0x00, 0x00, 0x00, 0x00, 0x00}};
331 const std::array<std::array<uint8_t, 8>, 4> blocks = {
332 {etc2_solid_block(0xFF, 0x00, 0x00), etc2_solid_block(0x00, 0xFF, 0x00),
333 etc2_solid_block(0x00, 0x00, 0xFF), etc2_solid_block(0xFF, 0xFF, 0xFF)}};
334 std::vector<uint8_t>
data;
335 for (
const auto& block : blocks) {
336 data.insert(
data.end(), block.begin(), block.end());
347TEST_P(RendererGoldenTest, CanRenderASTCCompressedTexture) {
348 std::shared_ptr<Context>
context = GetContext();
350 if (!
context->GetCapabilities()->SupportsTextureCompression(
352 GTEST_SKIP() <<
"Backend does not support ASTC texture compression.";
359 auto astc_solid_block = [](uint16_t r, uint16_t g,
360 uint16_t
b) -> std::array<uint8_t, 16> {
361 return {{0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
362 static_cast<uint8_t
>(r & 0xFF),
static_cast<uint8_t
>(r >> 8),
363 static_cast<uint8_t
>(g & 0xFF),
static_cast<uint8_t
>(g >> 8),
364 static_cast<uint8_t
>(
b & 0xFF),
static_cast<uint8_t
>(b >> 8), 0xFF,
368 const std::array<std::array<uint8_t, 16>, 4> blocks = {
369 {astc_solid_block(0xFFFF, 0, 0), astc_solid_block(0, 0xFFFF, 0),
370 astc_solid_block(0, 0, 0xFFFF),
371 astc_solid_block(0xFFFF, 0xFFFF, 0xFFFF)}};
372 std::vector<uint8_t>
data;
373 for (
const auto& block : blocks) {
374 data.insert(
data.end(), block.begin(), block.end());
389static void DrawManuallyMippedTextureGolden(GoldenPlaygroundTest& test,
391 using VS = MipmapsVertexShader;
392 using FS = MipmapsFragmentShader;
394 std::shared_ptr<Context>
context = test.GetContext();
397 TextureDescriptor texture_desc;
400 texture_desc.size =
ISize{8, 8};
401 texture_desc.mip_count = 2u;
403 auto texture =
context->GetResourceAllocator()->CreateTexture(texture_desc);
407 std::vector<uint8_t> base_data(8 * 8 * 4);
408 for (
int y = 0;
y < 8; ++
y) {
409 for (
int x = 0;
x < 8; ++
x) {
410 const size_t i = (
static_cast<size_t>(
y) * 8 +
x) * 4;
411 const bool right =
x >= 4;
412 const bool bottom =
y >= 4;
413 uint8_t r = 0, g = 0,
b = 0;
414 if (!right && !bottom) {
416 }
else if (right && !bottom) {
418 }
else if (!right && bottom) {
424 base_data[
i + 1] = g;
425 base_data[
i + 2] =
b;
426 base_data[
i + 3] = 0xFF;
429 ASSERT_TRUE(
texture->SetContents(base_data.data(), base_data.size()));
437 std::vector<uint8_t> mip_data(4 * 4 * 4);
438 for (
size_t i = 0;
i < mip_data.size();
i += 4) {
440 mip_data[
i + 1] = 0x80;
441 mip_data[
i + 2] = 0x00;
442 mip_data[
i + 3] = 0xFF;
444 auto mip_buffer =
context->GetResourceAllocator()->CreateBufferWithCopy(
445 mip_data.data(), mip_data.size());
446 ASSERT_TRUE(mip_buffer);
447 auto cmd_buffer =
context->CreateCommandBuffer();
448 ASSERT_TRUE(cmd_buffer);
449 auto blit_pass = cmd_buffer->CreateBlitPass();
450 ASSERT_TRUE(blit_pass);
456 "Upload mip 1", 1u));
457 ASSERT_TRUE(blit_pass->EncodeCommands());
458 ASSERT_TRUE(
context->GetCommandQueue()->Submit({cmd_buffer}).ok());
461 ASSERT_TRUE(desc.has_value());
463 desc->ClearStencilAttachments();
464 desc->ClearDepthAttachment();
465 auto pipeline =
context->GetPipelineLibrary()->GetPipeline(desc).Get();
469 VertexBufferBuilder<VS::PerVertexData> vertex_buffer_builder;
470 vertex_buffer_builder.AddVertices({
471 {{-1, -1}, {0.0, 0.0}},
472 {{1, -1}, {1.0, 0.0}},
473 {{1, 1}, {1.0, 1.0}},
474 {{-1, -1}, {0.0, 0.0}},
475 {{1, 1}, {1.0, 1.0}},
476 {{-1, 1}, {0.0, 1.0}},
478 auto vertex_buffer = vertex_buffer_builder.CreateVertexBuffer(
479 *
context->GetResourceAllocator());
481 const auto& sampler =
context->GetSamplerLibrary()->GetSampler({});
485 context->GetCapabilities()->GetMinimumUniformAlignment());
487 ASSERT_TRUE(test.OpenPlaygroundHere([&](RenderPass& pass) ->
bool {
488 host_buffer->Reset();
489 pass.SetPipeline(pipeline);
490 pass.SetVertexBuffer(vertex_buffer);
492 VS::FrameInfo frame_info;
493 frame_info.mvp = Matrix();
494 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
496 FS::FragInfo frag_info;
498 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(frag_info));
500 FS::BindTex(pass, texture, sampler);
502 return pass.Draw().ok();
507TEST_P(RendererGoldenTest, CanSampleManuallyMippedTexture) {
508 DrawManuallyMippedTextureGolden(*
this, 0.0f);
512TEST_P(RendererGoldenTest, CanSampleManuallyMippedTextureLod1) {
513 DrawManuallyMippedTextureGolden(*
this, 1.0f);
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
static std::shared_ptr< HostBuffer > Create(const std::shared_ptr< Allocator > &allocator, const std::shared_ptr< const IdleWaiter > &idle_waiter, size_t minimum_uniform_alignment)
uint32_t uint32_t * format
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
TEST_P(AiksTest, DrawAtlasNoColor)
@ kInstance
The binding is read once per instance.
@ kVertex
The binding is read once per vertex. This is the default.
LinePipeline::FragmentShader FS
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
@ kBC
S3TC, RGTC, and BPTC (BC1 through BC7). Desktop GPUs.
@ kETC2
ETC2 and EAC. Mobile, OpenGL ES 3.0, and WebGL2.
@ kASTC
ASTC LDR. Modern mobile and some desktop.
LinePipeline::VertexShader VS
#define INSTANTIATE_PLAYGROUND_SUITE(playground)
std::shared_ptr< ContextGLES > context
std::shared_ptr< PipelineGLES > pipeline
static constexpr Color Red()
static constexpr Color Blue()
static constexpr Color Green()
static constexpr Matrix MakeScale(const Vector3 &s)
static std::optional< PipelineDescriptor > MakeDefaultPipelineDescriptor(const Context &context, const std::vector< Scalar > &constants={})
Create a default pipeline descriptor using the combination reflected shader information....
static constexpr TRect MakeSize(const TSize< U > &size)