skia2/tests/graphite/CommandBufferTest.cpp
Michael Ludwig 497ac0fe23 [graphite] Rename RenderPipeline[Desc] to GraphicsPipeline[Desc]
Also updates MtlRenderPipeline to be MtlGraphicsPipeline to match the
type it extends, although we could choose to have it stay matched with
the backend object (MTLRenderPipeline) that it wraps instead.

Bug: skia:12466
Change-Id: Ida118e68a93d737d21edca15a59f5e64e17b5fd0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/467780
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-11-05 18:58:15 +00:00

198 lines
7.7 KiB
C++

/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "tests/Test.h"
#include "experimental/graphite/include/Context.h"
#include "experimental/graphite/src/ContextPriv.h"
#include "experimental/graphite/include/mtl/MtlTypes.h"
#include "experimental/graphite/src/Buffer.h"
#include "experimental/graphite/src/CommandBuffer.h"
#include "experimental/graphite/src/Gpu.h"
#include "experimental/graphite/src/GraphicsPipeline.h"
#include "experimental/graphite/src/ResourceProvider.h"
#include "experimental/graphite/src/Texture.h"
#if GRAPHITE_TEST_UTILS
// set to 1 if you want to do GPU capture of the commandBuffer
#define CAPTURE_COMMANDBUFFER 0
#endif
using namespace skgpu;
/*
* This is to test the various pieces of the CommandBuffer interface.
*/
DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
constexpr int kTextureWidth = 1024;
constexpr int kTextureHeight = 768;
auto gpu = context->priv().gpu();
REPORTER_ASSERT(reporter, gpu);
#if GRAPHITE_TEST_UTILS && CAPTURE_COMMANDBUFFER
gpu->testingOnly_startCapture();
#endif
auto commandBuffer = gpu->resourceProvider()->createCommandBuffer();
SkISize textureSize = { kTextureWidth, kTextureHeight };
#ifdef SK_METAL
skgpu::mtl::TextureInfo mtlTextureInfo = {
1,
1,
70, // MTLPixelFormatRGBA8Unorm
0x0005, // MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead
2, // MTLStorageModePrivate
};
TextureInfo textureInfo(mtlTextureInfo);
#else
TextureInfo textureInfo;
#endif
sk_sp<Texture> texture = gpu->resourceProvider()->findOrCreateTexture(textureSize,
textureInfo);
REPORTER_ASSERT(reporter, texture);
RenderPassDesc renderPassDesc = {};
renderPassDesc.fColorAttachment.fTexture = texture;
renderPassDesc.fColorAttachment.fLoadOp = LoadOp::kClear;
renderPassDesc.fColorAttachment.fStoreOp = StoreOp::kStore;
renderPassDesc.fClearColor = { 1, 0, 0, 1 }; // red
commandBuffer->beginRenderPass(renderPassDesc);
// Shared uniform buffer
struct UniformData {
SkPoint fScale;
SkPoint fTranslate;
SkColor4f fColor;
};
sk_sp<Buffer> uniformBuffer = gpu->resourceProvider()->findOrCreateBuffer(
2*sizeof(UniformData), BufferType::kUniform, PrioritizeGpuReads::kNo);
size_t uniformOffset = 0;
// Draw blue rectangle over entire rendertarget (which was red)
GraphicsPipelineDesc pipelineDesc;
pipelineDesc.setTestingOnlyShaderIndex(0);
auto graphicsPipeline = gpu->resourceProvider()->findOrCreateGraphicsPipeline(pipelineDesc);
commandBuffer->bindGraphicsPipeline(std::move(graphicsPipeline));
commandBuffer->draw(PrimitiveType::kTriangleStrip, 0, 4);
// Draw inset yellow rectangle using uniforms
pipelineDesc.setTestingOnlyShaderIndex(1);
graphicsPipeline = gpu->resourceProvider()->findOrCreateGraphicsPipeline(pipelineDesc);
commandBuffer->bindGraphicsPipeline(std::move(graphicsPipeline));
UniformData* uniforms = (UniformData*)uniformBuffer->map();
uniforms->fScale = SkPoint({1.8, 1.8});
uniforms->fTranslate = SkPoint({-0.9, -0.9});
uniforms->fColor = SkColors::kYellow;
commandBuffer->bindUniformBuffer(uniformBuffer, uniformOffset);
commandBuffer->draw(PrimitiveType::kTriangleStrip, 0, 4);
uniformOffset += sizeof(UniformData);
++uniforms;
// Draw inset magenta rectangle with triangles in vertex buffer
pipelineDesc.setTestingOnlyShaderIndex(2);
skgpu::GraphicsPipelineDesc::Attribute vertexAttributes[1] = {
{ "position", VertexAttribType::kFloat2, SLType::kFloat2 }
};
pipelineDesc.setVertexAttributes(vertexAttributes, 1);
graphicsPipeline = gpu->resourceProvider()->findOrCreateGraphicsPipeline(pipelineDesc);
commandBuffer->bindGraphicsPipeline(std::move(graphicsPipeline));
struct VertexData {
SkPoint fPosition;
};
sk_sp<Buffer> vertexBuffer = gpu->resourceProvider()->findOrCreateBuffer(
4*sizeof(VertexData), BufferType::kVertex, PrioritizeGpuReads::kNo);
sk_sp<Buffer> indexBuffer = gpu->resourceProvider()->findOrCreateBuffer(
6*sizeof(uint16_t), BufferType::kIndex, PrioritizeGpuReads::kNo);
auto vertices = (VertexData*)vertexBuffer->map();
vertices[0].fPosition = SkPoint({0.25f, 0.25f});
vertices[1].fPosition = SkPoint({0.25f, 0.75f});
vertices[2].fPosition = SkPoint({0.75f, 0.25f});
vertices[3].fPosition = SkPoint({0.75f, 0.75f});
vertexBuffer->unmap();
auto indices = (uint16_t*)indexBuffer->map();
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 2;
indices[4] = 1;
indices[5] = 3;
indexBuffer->unmap();
commandBuffer->bindVertexBuffers(vertexBuffer, nullptr);
commandBuffer->bindIndexBuffer(indexBuffer, 0);
uniforms->fScale = SkPoint({2, 2});
uniforms->fTranslate = SkPoint({-1, -1});
uniforms->fColor = SkColors::kMagenta;
commandBuffer->bindUniformBuffer(uniformBuffer, uniformOffset);
commandBuffer->drawIndexed(PrimitiveType::kTriangles, 0, 6, 0);
// draw rects using instance buffer
pipelineDesc.setTestingOnlyShaderIndex(3);
skgpu::GraphicsPipelineDesc::Attribute instanceAttributes[3] = {
{ "position", VertexAttribType::kFloat2, SLType::kFloat2 },
{ "dims", VertexAttribType::kFloat2, SLType::kFloat2 },
{ "color", VertexAttribType::kFloat4, SLType::kFloat4 }
};
pipelineDesc.setVertexAttributes(nullptr, 0);
pipelineDesc.setInstanceAttributes(instanceAttributes, 3);
graphicsPipeline = gpu->resourceProvider()->findOrCreateGraphicsPipeline(pipelineDesc);
commandBuffer->bindGraphicsPipeline(std::move(graphicsPipeline));
struct InstanceData {
SkPoint fPosition;
SkPoint fDims;
SkColor4f fColor;
};
sk_sp<Buffer> instanceBuffer = gpu->resourceProvider()->findOrCreateBuffer(
2*sizeof(InstanceData), BufferType::kVertex, PrioritizeGpuReads::kNo);
auto instances = (InstanceData*)instanceBuffer->map();
instances[0].fPosition = SkPoint({-0.4, -0.4});
instances[0].fDims = SkPoint({0.4, 0.4});
instances[0].fColor = SkColors::kGreen;
instances[1].fPosition = SkPoint({0, 0});
instances[1].fDims = SkPoint({0.25, 0.25});
instances[1].fColor = SkColors::kCyan;
instanceBuffer->unmap();
commandBuffer->bindVertexBuffers(nullptr, instanceBuffer);
// commandBuffer->drawInstanced(PrimitiveType::kTriangleStrip, 0, 4, 0, 2);
commandBuffer->drawIndexedInstanced(PrimitiveType::kTriangles, 0, 6, 0, 0, 2);
commandBuffer->endRenderPass();
uniformBuffer->unmap();
// Do readback
// TODO: add 4-byte transfer buffer alignment for Mac to Caps
// add bpp to Caps
size_t rowBytes = 4*kTextureWidth;
size_t bufferSize = rowBytes*kTextureHeight;
sk_sp<Buffer> copyBuffer = gpu->resourceProvider()->findOrCreateBuffer(
bufferSize, BufferType::kXferGpuToCpu, PrioritizeGpuReads::kNo);
REPORTER_ASSERT(reporter, copyBuffer);
SkIRect srcRect = { 0, 0, kTextureWidth, kTextureHeight };
commandBuffer->copyTextureToBuffer(texture, srcRect, copyBuffer, 0, rowBytes);
bool result = gpu->submit(commandBuffer);
REPORTER_ASSERT(reporter, result);
gpu->checkForFinishedWork(skgpu::SyncToCpu::kYes);
uint32_t* pixels = (uint32_t*)(copyBuffer->map());
REPORTER_ASSERT(reporter, pixels[0] == 0xffff0000);
REPORTER_ASSERT(reporter, pixels[51 + 38*kTextureWidth] == 0xff00ffff);
REPORTER_ASSERT(reporter, pixels[256 + 192*kTextureWidth] == 0xffff00ff);
copyBuffer->unmap();
#if GRAPHITE_TEST_UTILS && CAPTURE_COMMANDBUFFER
gpu->testingOnly_endCapture();
#endif
}