Flutter Impeller
renderer_golden_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Golden tests for the low-level renderer API. Unlike renderer_unittests.cc,
6 // which opens an interactive playground, the tests here render through the
7 // golden harness and have their output uploaded to Skia Gold. They only build
8 // as part of the golden test executable.
9 
10 #ifdef IMPELLER_GOLDEN_TESTS
11 
12 #include <array>
13 #include <cstdint>
14 #include <vector>
15 
18 #include "impeller/core/formats.h"
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"
40 
41 // TODO(zanderso): https://github.com/flutter/flutter/issues/127701
42 // NOLINTBEGIN(bugprone-unchecked-optional-access)
43 
44 namespace impeller {
45 namespace testing {
46 
47 using RendererGoldenTest = GoldenPlaygroundTest;
48 INSTANTIATE_PLAYGROUND_SUITE(RendererGoldenTest);
49 
50 // Ported from RendererTest.BabysFirstTriangle. Draws a single gradient
51 // triangle straight through the renderer API. The shader's time uniform is
52 // pinned to zero so the golden is deterministic.
53 TEST_P(RendererGoldenTest, BabysFirstTriangle) {
54  using VS = BabyVertexShader;
55  using FS = BabyFragmentShader;
56 
57  std::shared_ptr<Context> context = GetContext();
58  ASSERT_TRUE(context);
59 
61  ASSERT_TRUE(desc.has_value());
62  // Match the golden harness render target: single-sampled, no depth/stencil.
63  // `ClearStencilAttachments` also resets the stencil pixel format on the
64  // pipeline, which Metal validation requires to match the target's lack of a
65  // stencil texture; `SetStencilAttachmentDescriptors(nullopt)` alone leaves
66  // the format set and trips that validation.
67  desc->SetSampleCount(SampleCount::kCount1);
68  desc->ClearStencilAttachments();
69  desc->ClearDepthAttachment();
70  auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
71  ASSERT_TRUE(pipeline);
72 
73  VertexBufferBuilder<VS::PerVertexData> vertex_buffer_builder;
74  vertex_buffer_builder.AddVertices({
75  {{-0.5, -0.5}, Color::Red(), Color::Green()},
76  {{0.0, 0.5}, Color::Green(), Color::Blue()},
77  {{0.5, -0.5}, Color::Blue(), Color::Red()},
78  });
79  auto vertex_buffer = vertex_buffer_builder.CreateVertexBuffer(
80  *context->GetResourceAllocator());
81 
82  auto host_buffer = HostBuffer::Create(
83  context->GetResourceAllocator(), context->GetIdleWaiter(),
84  context->GetCapabilities()->GetMinimumUniformAlignment());
85 
86  ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
87  // The harness runs the callback once per pass; start each from a clean
88  // host buffer.
89  host_buffer->Reset();
90  pass.SetPipeline(pipeline);
91  pass.SetVertexBuffer(vertex_buffer);
92 
93  FS::FragInfo frag_info;
94  frag_info.time = 0.0f;
95  FS::BindFragInfo(pass, host_buffer->EmplaceUniform(frag_info));
96 
97  return pass.Draw().ok();
98  }));
99 }
100 
101 // Ported from RendererTest.CanRenderInstancedWithVertexAttributes. Renders an
102 // instanced draw whose per-instance data arrives through an instance-rate
103 // vertex buffer binding rather than an instance-ID builtin. This is the only
104 // portable instancing mechanism on OpenGL ES. Per-instance offsets and colors
105 // are fixed so the golden is deterministic.
106 TEST_P(RendererGoldenTest, CanRenderInstancedWithVertexAttributes) {
107  using VS = InstancedAttributesVertexShader;
108  using FS = InstancedAttributesFragmentShader;
109 
110  std::shared_ptr<Context> context = GetContext();
111  ASSERT_TRUE(context);
112 
114  ASSERT_TRUE(desc.has_value());
115  // Match the golden harness render target: single-sampled, no depth/stencil.
116  desc->SetSampleCount(SampleCount::kCount1);
117  desc->ClearStencilAttachments();
118  desc->ClearDepthAttachment();
119 
120  // Per-instance data is laid out contiguously, one record per instance.
121  struct InstanceData {
122  Vector2 offset;
123  Vector4 color;
124  };
125 
126  // Two vertex bindings: binding 0 carries per-vertex geometry and advances
127  // once per vertex; binding 1 carries per-instance data and advances once
128  // per instance.
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,
140  color_slot};
141  const std::vector<ShaderStageBufferLayout> layouts = {
142  ShaderStageBufferLayout{.stride = sizeof(Vector2),
143  .binding = 0,
144  .input_rate = VertexInputRate::kVertex},
145  ShaderStageBufferLayout{.stride = sizeof(InstanceData),
146  .binding = 1,
147  .input_rate = VertexInputRate::kInstance},
148  };
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));
153  auto pipeline =
154  context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
155  ASSERT_TRUE(pipeline);
156 
157  // A single triangle, drawn once per instance.
158  std::array<Vector2, 3> geometry = {
159  Vector2{0, 0},
160  Vector2{0, 100},
161  Vector2{100, 0},
162  };
163 
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}},
170  };
171 
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);
179 
180  auto host_buffer = HostBuffer::Create(
181  context->GetResourceAllocator(), context->GetIdleWaiter(),
182  context->GetCapabilities()->GetMinimumUniformAlignment());
183 
184  ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
185  // The harness runs the callback once per pass; start each from a clean
186  // host buffer.
187  host_buffer->Reset();
188  pass.SetCommandLabel("InstancedAttributes");
189  pass.SetPipeline(pipeline);
190 
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))),
196  };
197  pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size());
198  pass.SetElementCount(geometry.size());
199  pass.SetInstanceCount(kInstanceCount);
200 
201  VS::FrameInfo frame_info;
202  frame_info.mvp =
203  pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
204  VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
205 
206  return pass.Draw().ok();
207  }));
208 }
209 
210 // Samples a sample-only block-compressed texture across a fullscreen quad
211 // through the golden harness. The pixel format and the raw block bytes are the
212 // only things that differ between the compressed families; the texture upload,
213 // pipeline, quad, and draw are shared by every compressed-format golden below.
214 static void DrawCompressedTextureGolden(GoldenPlaygroundTest& test,
215  PixelFormat format,
216  const std::vector<uint8_t>& block_data,
217  ISize size) {
218  using VS = TextureVertexShader;
219  using FS = TextureFragmentShader;
220 
221  std::shared_ptr<Context> context = test.GetContext();
222  ASSERT_TRUE(context);
223 
224  TextureDescriptor texture_desc;
225  texture_desc.storage_mode = StorageMode::kHostVisible;
226  texture_desc.format = format;
227  texture_desc.size = size;
228  texture_desc.mip_count = 1u;
229  texture_desc.usage = TextureUsage::kShaderRead;
230  auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
231  ASSERT_TRUE(texture);
232  ASSERT_TRUE(texture->SetContents(block_data.data(), block_data.size()));
233 
235  ASSERT_TRUE(desc.has_value());
236  desc->SetSampleCount(SampleCount::kCount1);
237  desc->ClearStencilAttachments();
238  desc->ClearDepthAttachment();
239  auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
240  ASSERT_TRUE(pipeline);
241 
242  // A fullscreen quad in normalized device coordinates with an identity MVP.
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}},
251  });
252  auto vertex_buffer = vertex_buffer_builder.CreateVertexBuffer(
253  *context->GetResourceAllocator());
254 
255  const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
256 
257  auto host_buffer = HostBuffer::Create(
258  context->GetResourceAllocator(), context->GetIdleWaiter(),
259  context->GetCapabilities()->GetMinimumUniformAlignment());
260 
261  ASSERT_TRUE(test.OpenPlaygroundHere([&](RenderPass& pass) -> bool {
262  host_buffer->Reset();
263  pass.SetPipeline(pipeline);
264  pass.SetVertexBuffer(vertex_buffer);
265 
266  VS::UniformBuffer uniforms;
267  uniforms.mvp = Matrix();
268  VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
269  FS::BindTextureContents(pass, texture, sampler);
270 
271  return pass.Draw().ok();
272  }));
273 }
274 
275 // Uploads a block-compressed (BC1/DXT1) texture and samples it onto a
276 // fullscreen quad. The texture is an 8x8 image laid out as a 2x2 grid of solid
277 // color blocks, so the golden is four colored quadrants. BC1 is the most widely
278 // supported compressed family on desktop GPUs; backends without it are skipped.
279 TEST_P(RendererGoldenTest, CanRenderBC1CompressedTexture) {
280  std::shared_ptr<Context> context = GetContext();
281  ASSERT_TRUE(context);
282  if (!context->GetCapabilities()->SupportsTextureCompression(
284  GTEST_SKIP() << "Backend does not support BC texture compression.";
285  }
286 
287  // A solid-color BC1 block stores the color in both RGB565 endpoints with
288  // all-zero selector bits, which decodes to a single opaque color.
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}};
293  };
294  // RGB565: red, green, blue, white.
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());
301  }
302 
303  DrawCompressedTextureGolden(*this, PixelFormat::kBC1RGBAUNormInt, data,
304  ISize{8, 8});
305 }
306 
307 // Uploads an ETC2 RGB8 texture and samples it onto a fullscreen quad. ETC2 is
308 // the standard compressed family on OpenGL ES 3.0 and mobile GPUs; backends
309 // without it are skipped. The 8x8 image is a 2x2 grid of solid color blocks, so
310 // the golden is the same four colored quadrants as the BC1 and ASTC goldens.
311 TEST_P(RendererGoldenTest, CanRenderETC2CompressedTexture) {
312  std::shared_ptr<Context> context = GetContext();
313  ASSERT_TRUE(context);
314  if (!context->GetCapabilities()->SupportsTextureCompression(
316  GTEST_SKIP() << "Backend does not support ETC2 texture compression.";
317  }
318 
319  // A solid-color ETC2 RGB8 block in "individual" mode (differential bit 0,
320  // which decodes like ETC1). The 64-bit block is laid out big-endian (byte 0
321  // most significant): byte 0 = R nibbles (R1,R2), byte 1 = G, byte 2 = B,
322  // byte 3 = codeword/diff/flip bits (all 0), bytes 4..7 = the two pixel-index
323  // bit planes. Both sub-blocks share the base color and every texel uses index
324  // 0 (all-zero planes), so the block is one flat color.
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}};
328  };
329  // Red, green, blue, white. Each channel byte is 0xFF (nibble 0xF, ~255) or
330  // 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());
337  }
338 
339  DrawCompressedTextureGolden(*this, PixelFormat::kETC2RGB8UNormInt, data,
340  ISize{8, 8});
341 }
342 
343 // Uploads an ASTC 4x4 LDR texture and samples it onto a fullscreen quad. ASTC
344 // is common on modern mobile and some desktop GPUs; backends without it are
345 // skipped. The 8x8 image is a 2x2 grid of solid color blocks, so the golden is
346 // the same four colored quadrants as the BC1 and ETC2 goldens.
347 TEST_P(RendererGoldenTest, CanRenderASTCCompressedTexture) {
348  std::shared_ptr<Context> context = GetContext();
349  ASSERT_TRUE(context);
350  if (!context->GetCapabilities()->SupportsTextureCompression(
352  GTEST_SKIP() << "Backend does not support ASTC texture compression.";
353  }
354 
355  // An ASTC void-extent block encodes one constant color directly: the 0xFC
356  // 0xFD header marks a 2D LDR void-extent with the "no extent" sentinel
357  // coordinates (all ones), followed by four little-endian UNORM16 channels
358  // (R, G, B, A). Alpha is opaque.
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,
365  0xFF}};
366  };
367  // Red, green, blue, white.
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());
375  }
376 
377  DrawCompressedTextureGolden(*this, PixelFormat::kASTC4x4LDR, data,
378  ISize{8, 8});
379 }
380 
381 // Samples a texture whose mip chain was populated by hand (the base level via
382 // SetContents, the 4x4 second level via a blit copy) rather than by the
383 // GenerateMipmap blit, then samples it at the given LOD. Such a texture has
384 // mip_count > 1 with NeedsMipmapGeneration() == true; sampling it used to fail
385 // the (now-removed) bind-time mipmap validation on desktop Metal and OpenGL ES,
386 // so the golden would have been blank there. The base is four colored quadrants
387 // and the second level is solid orange, so LOD 0 renders the quadrants and LOD
388 // 1 renders solid orange.
389 static void DrawManuallyMippedTextureGolden(GoldenPlaygroundTest& test,
390  float lod) {
391  using VS = MipmapsVertexShader;
392  using FS = MipmapsFragmentShader;
393 
394  std::shared_ptr<Context> context = test.GetContext();
395  ASSERT_TRUE(context);
396 
397  TextureDescriptor texture_desc;
398  texture_desc.storage_mode = StorageMode::kHostVisible;
399  texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
400  texture_desc.size = ISize{8, 8};
401  texture_desc.mip_count = 2u; // base 8x8 + one 4x4 mip; populated by hand.
402  texture_desc.usage = TextureUsage::kShaderRead;
403  auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
404  ASSERT_TRUE(texture);
405 
406  // Base level: a 2x2 grid of red/green/blue/white quadrants.
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) {
415  r = 0xFF; // top-left: red.
416  } else if (right && !bottom) {
417  g = 0xFF; // top-right: green.
418  } else if (!right && bottom) {
419  b = 0xFF; // bottom-left: blue.
420  } else {
421  r = g = b = 0xFF; // bottom-right: white.
422  }
423  base_data[i] = r;
424  base_data[i + 1] = g;
425  base_data[i + 2] = b;
426  base_data[i + 3] = 0xFF;
427  }
428  }
429  ASSERT_TRUE(texture->SetContents(base_data.data(), base_data.size()));
430 
431  // Second level (4x4), solid orange so it is distinct from the base and from
432  // an empty level. Uploaded by hand via a blit copy rather than the
433  // GenerateMipmap blit, which keeps NeedsMipmapGeneration() true. This
434  // initializes the whole mip chain so the texture is complete on backends
435  // that require it (OpenGL ES samples a mipmapped texture as incomplete
436  // otherwise).
437  std::vector<uint8_t> mip_data(4 * 4 * 4);
438  for (size_t i = 0; i < mip_data.size(); i += 4) {
439  mip_data[i] = 0xFF; // r
440  mip_data[i + 1] = 0x80; // g
441  mip_data[i + 2] = 0x00; // b
442  mip_data[i + 3] = 0xFF; // a
443  }
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);
451  // The destination region must match the 4x4 second level, not the 8x8 base,
452  // or the copy size check rejects the smaller source buffer.
453  ASSERT_TRUE(
454  blit_pass->AddCopy(DeviceBuffer::AsBufferView(mip_buffer), texture,
455  /*destination_region=*/IRect::MakeSize(ISize{4, 4}),
456  /*label=*/"Upload mip 1", /*mip_level=*/1u));
457  ASSERT_TRUE(blit_pass->EncodeCommands());
458  ASSERT_TRUE(context->GetCommandQueue()->Submit({cmd_buffer}).ok());
459 
461  ASSERT_TRUE(desc.has_value());
462  desc->SetSampleCount(SampleCount::kCount1);
463  desc->ClearStencilAttachments();
464  desc->ClearDepthAttachment();
465  auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
466  ASSERT_TRUE(pipeline);
467 
468  // A fullscreen quad in normalized device coordinates with an identity MVP.
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}},
477  });
478  auto vertex_buffer = vertex_buffer_builder.CreateVertexBuffer(
479  *context->GetResourceAllocator());
480 
481  const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
482 
483  auto host_buffer = HostBuffer::Create(
484  context->GetResourceAllocator(), context->GetIdleWaiter(),
485  context->GetCapabilities()->GetMinimumUniformAlignment());
486 
487  ASSERT_TRUE(test.OpenPlaygroundHere([&](RenderPass& pass) -> bool {
488  host_buffer->Reset();
489  pass.SetPipeline(pipeline);
490  pass.SetVertexBuffer(vertex_buffer);
491 
492  VS::FrameInfo frame_info;
493  frame_info.mvp = Matrix();
494  VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
495 
496  FS::FragInfo frag_info;
497  frag_info.lod = lod;
498  FS::BindFragInfo(pass, host_buffer->EmplaceUniform(frag_info));
499 
500  FS::BindTex(pass, texture, sampler);
501 
502  return pass.Draw().ok();
503  }));
504 }
505 
506 // LOD 0 reads the base level, so the golden is the four colored quadrants.
507 TEST_P(RendererGoldenTest, CanSampleManuallyMippedTexture) {
508  DrawManuallyMippedTextureGolden(*this, /*lod=*/0.0f);
509 }
510 
511 // LOD 1 reads the hand-uploaded second level, so the golden is solid orange.
512 TEST_P(RendererGoldenTest, CanSampleManuallyMippedTextureLod1) {
513  DrawManuallyMippedTextureGolden(*this, /*lod=*/1.0f);
514 }
515 
516 } // namespace testing
517 } // namespace impeller
518 
519 // NOLINTEND(bugprone-unchecked-optional-access)
520 
521 #endif // IMPELLER_GOLDEN_TESTS
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)
Definition: host_buffer.cc:21
int32_t x
TEST_P(AiksTest, DrawAtlasNoColor)
INSTANTIATE_PLAYGROUND_SUITE(AiksTest)
Point Vector2
Definition: point.h:430
@ 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,...
Definition: formats.h:99
@ 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
ISize64 ISize
Definition: size.h:162
std::shared_ptr< ContextGLES > context
std::shared_ptr< PipelineGLES > pipeline
static constexpr Color Red()
Definition: color.h:277
static constexpr Color Blue()
Definition: color.h:281
static constexpr Color Green()
Definition: color.h:279
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
static std::optional< PipelineDescriptor > MakeDefaultPipelineDescriptor(const Context &context, const std::vector< Scalar > &constants={})
Create a default pipeline descriptor using the combination reflected shader information....
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:150