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"
47 using RendererGoldenTest = GoldenPlaygroundTest;
53 TEST_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();
106 TEST_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();
214 static 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);
231 ASSERT_TRUE(texture);
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();
279 TEST_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());
311 TEST_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());
347 TEST_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());
389 static 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);
404 ASSERT_TRUE(texture);
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();
507 TEST_P(RendererGoldenTest, CanSampleManuallyMippedTexture) {
508 DrawManuallyMippedTextureGolden(*
this, 0.0f);
512 TEST_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)
TEST_P(AiksTest, DrawAtlasNoColor)
INSTANTIATE_PLAYGROUND_SUITE(AiksTest)
@ 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
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....
constexpr static TRect MakeSize(const TSize< U > &size)