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