1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "tests/Test.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "experimental/graphite/include/Context.h" 11cb93a386Sopenharmony_ci#include "experimental/graphite/src/ContextPriv.h" 12cb93a386Sopenharmony_ci 13cb93a386Sopenharmony_ci#include "experimental/graphite/include/mtl/MtlTypes.h" 14cb93a386Sopenharmony_ci#include "experimental/graphite/src/Buffer.h" 15cb93a386Sopenharmony_ci#include "experimental/graphite/src/CommandBuffer.h" 16cb93a386Sopenharmony_ci#include "experimental/graphite/src/Gpu.h" 17cb93a386Sopenharmony_ci#include "experimental/graphite/src/GraphicsPipeline.h" 18cb93a386Sopenharmony_ci#include "experimental/graphite/src/ResourceProvider.h" 19cb93a386Sopenharmony_ci#include "experimental/graphite/src/Texture.h" 20cb93a386Sopenharmony_ci#include "experimental/graphite/src/TextureProxy.h" 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ci#if GRAPHITE_TEST_UTILS 23cb93a386Sopenharmony_ci// set to 1 if you want to do GPU capture of the commandBuffer 24cb93a386Sopenharmony_ci#define CAPTURE_COMMANDBUFFER 0 25cb93a386Sopenharmony_ci#endif 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ciusing namespace skgpu; 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci/* 30cb93a386Sopenharmony_ci * This is to test the various pieces of the CommandBuffer interface. 31cb93a386Sopenharmony_ci */ 32cb93a386Sopenharmony_ciDEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) { 33cb93a386Sopenharmony_ci constexpr int kTextureWidth = 1024; 34cb93a386Sopenharmony_ci constexpr int kTextureHeight = 768; 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ci auto gpu = context->priv().gpu(); 37cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, gpu); 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci#if GRAPHITE_TEST_UTILS && CAPTURE_COMMANDBUFFER 40cb93a386Sopenharmony_ci gpu->testingOnly_startCapture(); 41cb93a386Sopenharmony_ci#endif 42cb93a386Sopenharmony_ci auto commandBuffer = gpu->resourceProvider()->createCommandBuffer(); 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci SkISize textureSize = { kTextureWidth, kTextureHeight }; 45cb93a386Sopenharmony_ci#ifdef SK_METAL 46cb93a386Sopenharmony_ci skgpu::mtl::TextureInfo mtlTextureInfo = { 47cb93a386Sopenharmony_ci 1, 48cb93a386Sopenharmony_ci 1, 49cb93a386Sopenharmony_ci 70, // MTLPixelFormatRGBA8Unorm 50cb93a386Sopenharmony_ci 0x0005, // MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead 51cb93a386Sopenharmony_ci 2, // MTLStorageModePrivate 52cb93a386Sopenharmony_ci false, // framebufferOnly 53cb93a386Sopenharmony_ci }; 54cb93a386Sopenharmony_ci TextureInfo textureInfo(mtlTextureInfo); 55cb93a386Sopenharmony_ci#else 56cb93a386Sopenharmony_ci TextureInfo textureInfo; 57cb93a386Sopenharmony_ci#endif 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ci auto target = sk_sp<TextureProxy>(new TextureProxy(textureSize, textureInfo)); 60cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, target); 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ci RenderPassDesc renderPassDesc = {}; 63cb93a386Sopenharmony_ci renderPassDesc.fColorAttachment.fTextureProxy = target; 64cb93a386Sopenharmony_ci renderPassDesc.fColorAttachment.fLoadOp = LoadOp::kClear; 65cb93a386Sopenharmony_ci renderPassDesc.fColorAttachment.fStoreOp = StoreOp::kStore; 66cb93a386Sopenharmony_ci renderPassDesc.fClearColor = { 1, 0, 0, 1 }; // red 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci target->instantiate(gpu->resourceProvider()); 69cb93a386Sopenharmony_ci commandBuffer->beginRenderPass(renderPassDesc); 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci // Shared uniform buffer 72cb93a386Sopenharmony_ci struct UniformData { 73cb93a386Sopenharmony_ci SkPoint fScale; 74cb93a386Sopenharmony_ci SkPoint fTranslate; 75cb93a386Sopenharmony_ci SkColor4f fColor; 76cb93a386Sopenharmony_ci }; 77cb93a386Sopenharmony_ci sk_sp<Buffer> uniformBuffer = gpu->resourceProvider()->findOrCreateBuffer( 78cb93a386Sopenharmony_ci 2*sizeof(UniformData), BufferType::kUniform, PrioritizeGpuReads::kNo); 79cb93a386Sopenharmony_ci size_t uniformOffset = 0; 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci // Draw blue rectangle over entire rendertarget (which was red) 82cb93a386Sopenharmony_ci GraphicsPipelineDesc pipelineDesc; 83cb93a386Sopenharmony_ci pipelineDesc.setTestingOnlyShaderIndex(0); 84cb93a386Sopenharmony_ci auto graphicsPipeline = gpu->resourceProvider()->findOrCreateGraphicsPipeline(pipelineDesc); 85cb93a386Sopenharmony_ci commandBuffer->bindGraphicsPipeline(std::move(graphicsPipeline)); 86cb93a386Sopenharmony_ci commandBuffer->draw(PrimitiveType::kTriangleStrip, 0, 4); 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci // Draw inset yellow rectangle using uniforms 89cb93a386Sopenharmony_ci pipelineDesc.setTestingOnlyShaderIndex(1); 90cb93a386Sopenharmony_ci graphicsPipeline = gpu->resourceProvider()->findOrCreateGraphicsPipeline(pipelineDesc); 91cb93a386Sopenharmony_ci commandBuffer->bindGraphicsPipeline(std::move(graphicsPipeline)); 92cb93a386Sopenharmony_ci UniformData* uniforms = (UniformData*)uniformBuffer->map(); 93cb93a386Sopenharmony_ci uniforms->fScale = SkPoint({1.8, 1.8}); 94cb93a386Sopenharmony_ci uniforms->fTranslate = SkPoint({-0.9, -0.9}); 95cb93a386Sopenharmony_ci uniforms->fColor = SkColors::kYellow; 96cb93a386Sopenharmony_ci commandBuffer->bindUniformBuffer(uniformBuffer, uniformOffset); 97cb93a386Sopenharmony_ci commandBuffer->draw(PrimitiveType::kTriangleStrip, 0, 4); 98cb93a386Sopenharmony_ci uniformOffset += sizeof(UniformData); 99cb93a386Sopenharmony_ci ++uniforms; 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci // Draw inset magenta rectangle with triangles in vertex buffer 102cb93a386Sopenharmony_ci pipelineDesc.setTestingOnlyShaderIndex(2); 103cb93a386Sopenharmony_ci skgpu::GraphicsPipelineDesc::Attribute vertexAttributes[1] = { 104cb93a386Sopenharmony_ci { "position", VertexAttribType::kFloat2, SLType::kFloat2 } 105cb93a386Sopenharmony_ci }; 106cb93a386Sopenharmony_ci pipelineDesc.setVertexAttributes(vertexAttributes, 1); 107cb93a386Sopenharmony_ci graphicsPipeline = gpu->resourceProvider()->findOrCreateGraphicsPipeline(pipelineDesc); 108cb93a386Sopenharmony_ci commandBuffer->bindGraphicsPipeline(std::move(graphicsPipeline)); 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci struct VertexData { 111cb93a386Sopenharmony_ci SkPoint fPosition; 112cb93a386Sopenharmony_ci }; 113cb93a386Sopenharmony_ci sk_sp<Buffer> vertexBuffer = gpu->resourceProvider()->findOrCreateBuffer( 114cb93a386Sopenharmony_ci 4*sizeof(VertexData), BufferType::kVertex, PrioritizeGpuReads::kNo); 115cb93a386Sopenharmony_ci sk_sp<Buffer> indexBuffer = gpu->resourceProvider()->findOrCreateBuffer( 116cb93a386Sopenharmony_ci 6*sizeof(uint16_t), BufferType::kIndex, PrioritizeGpuReads::kNo); 117cb93a386Sopenharmony_ci auto vertices = (VertexData*)vertexBuffer->map(); 118cb93a386Sopenharmony_ci vertices[0].fPosition = SkPoint({0.25f, 0.25f}); 119cb93a386Sopenharmony_ci vertices[1].fPosition = SkPoint({0.25f, 0.75f}); 120cb93a386Sopenharmony_ci vertices[2].fPosition = SkPoint({0.75f, 0.25f}); 121cb93a386Sopenharmony_ci vertices[3].fPosition = SkPoint({0.75f, 0.75f}); 122cb93a386Sopenharmony_ci vertexBuffer->unmap(); 123cb93a386Sopenharmony_ci auto indices = (uint16_t*)indexBuffer->map(); 124cb93a386Sopenharmony_ci indices[0] = 0; 125cb93a386Sopenharmony_ci indices[1] = 1; 126cb93a386Sopenharmony_ci indices[2] = 2; 127cb93a386Sopenharmony_ci indices[3] = 2; 128cb93a386Sopenharmony_ci indices[4] = 1; 129cb93a386Sopenharmony_ci indices[5] = 3; 130cb93a386Sopenharmony_ci indexBuffer->unmap(); 131cb93a386Sopenharmony_ci commandBuffer->bindVertexBuffers(vertexBuffer, 0, nullptr, 0); 132cb93a386Sopenharmony_ci commandBuffer->bindIndexBuffer(indexBuffer, 0); 133cb93a386Sopenharmony_ci uniforms->fScale = SkPoint({2, 2}); 134cb93a386Sopenharmony_ci uniforms->fTranslate = SkPoint({-1, -1}); 135cb93a386Sopenharmony_ci uniforms->fColor = SkColors::kMagenta; 136cb93a386Sopenharmony_ci commandBuffer->bindUniformBuffer(uniformBuffer, uniformOffset); 137cb93a386Sopenharmony_ci commandBuffer->drawIndexed(PrimitiveType::kTriangles, 0, 6, 0); 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ci // draw rects using instance buffer 140cb93a386Sopenharmony_ci pipelineDesc.setTestingOnlyShaderIndex(3); 141cb93a386Sopenharmony_ci skgpu::GraphicsPipelineDesc::Attribute instanceAttributes[3] = { 142cb93a386Sopenharmony_ci { "position", VertexAttribType::kFloat2, SLType::kFloat2 }, 143cb93a386Sopenharmony_ci { "dims", VertexAttribType::kFloat2, SLType::kFloat2 }, 144cb93a386Sopenharmony_ci { "color", VertexAttribType::kFloat4, SLType::kFloat4 } 145cb93a386Sopenharmony_ci }; 146cb93a386Sopenharmony_ci pipelineDesc.setVertexAttributes(nullptr, 0); 147cb93a386Sopenharmony_ci pipelineDesc.setInstanceAttributes(instanceAttributes, 3); 148cb93a386Sopenharmony_ci graphicsPipeline = gpu->resourceProvider()->findOrCreateGraphicsPipeline(pipelineDesc); 149cb93a386Sopenharmony_ci commandBuffer->bindGraphicsPipeline(std::move(graphicsPipeline)); 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci struct InstanceData { 152cb93a386Sopenharmony_ci SkPoint fPosition; 153cb93a386Sopenharmony_ci SkPoint fDims; 154cb93a386Sopenharmony_ci SkColor4f fColor; 155cb93a386Sopenharmony_ci }; 156cb93a386Sopenharmony_ci sk_sp<Buffer> instanceBuffer = gpu->resourceProvider()->findOrCreateBuffer( 157cb93a386Sopenharmony_ci 2*sizeof(InstanceData), BufferType::kVertex, PrioritizeGpuReads::kNo); 158cb93a386Sopenharmony_ci auto instances = (InstanceData*)instanceBuffer->map(); 159cb93a386Sopenharmony_ci instances[0].fPosition = SkPoint({-0.4, -0.4}); 160cb93a386Sopenharmony_ci instances[0].fDims = SkPoint({0.4, 0.4}); 161cb93a386Sopenharmony_ci instances[0].fColor = SkColors::kGreen; 162cb93a386Sopenharmony_ci instances[1].fPosition = SkPoint({0, 0}); 163cb93a386Sopenharmony_ci instances[1].fDims = SkPoint({0.25, 0.25}); 164cb93a386Sopenharmony_ci instances[1].fColor = SkColors::kCyan; 165cb93a386Sopenharmony_ci instanceBuffer->unmap(); 166cb93a386Sopenharmony_ci commandBuffer->bindVertexBuffers(nullptr, 0, instanceBuffer, 0); 167cb93a386Sopenharmony_ci// commandBuffer->drawInstanced(PrimitiveType::kTriangleStrip, 0, 4, 0, 2); 168cb93a386Sopenharmony_ci commandBuffer->drawIndexedInstanced(PrimitiveType::kTriangles, 0, 6, 0, 0, 2); 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci commandBuffer->endRenderPass(); 171cb93a386Sopenharmony_ci 172cb93a386Sopenharmony_ci uniformBuffer->unmap(); 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci // Do readback 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_ci // TODO: add 4-byte transfer buffer alignment for Mac to Caps 177cb93a386Sopenharmony_ci // add bpp to Caps 178cb93a386Sopenharmony_ci size_t rowBytes = 4*kTextureWidth; 179cb93a386Sopenharmony_ci size_t bufferSize = rowBytes*kTextureHeight; 180cb93a386Sopenharmony_ci sk_sp<Buffer> copyBuffer = gpu->resourceProvider()->findOrCreateBuffer( 181cb93a386Sopenharmony_ci bufferSize, BufferType::kXferGpuToCpu, PrioritizeGpuReads::kNo); 182cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, copyBuffer); 183cb93a386Sopenharmony_ci SkIRect srcRect = { 0, 0, kTextureWidth, kTextureHeight }; 184cb93a386Sopenharmony_ci commandBuffer->copyTextureToBuffer(target->refTexture(), srcRect, copyBuffer, 0, rowBytes); 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_ci bool result = gpu->submit(commandBuffer); 187cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, result); 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci gpu->checkForFinishedWork(skgpu::SyncToCpu::kYes); 190cb93a386Sopenharmony_ci uint32_t* pixels = (uint32_t*)(copyBuffer->map()); 191cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pixels[0] == 0xffff0000); 192cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pixels[51 + 38*kTextureWidth] == 0xff00ffff); 193cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pixels[256 + 192*kTextureWidth] == 0xffff00ff); 194cb93a386Sopenharmony_ci copyBuffer->unmap(); 195cb93a386Sopenharmony_ci 196cb93a386Sopenharmony_ci#if GRAPHITE_TEST_UTILS && CAPTURE_COMMANDBUFFER 197cb93a386Sopenharmony_ci gpu->testingOnly_endCapture(); 198cb93a386Sopenharmony_ci#endif 199cb93a386Sopenharmony_ci} 200