1 /*
2  * Copyright 2018 Google Inc.
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 // This is a GPU-backend specific test. It relies on static intializers to work
9 
10 #include "SkTypes.h"
11 
12 #if defined(SK_VULKAN)
13 
14 #include "vk/GrVkVulkan.h"
15 
16 #include "GrBackendSurface.h"
17 #include "GrContextFactory.h"
18 #include "GrContextPriv.h"
19 #include "GrTexture.h"
20 #include "Test.h"
21 #include "vk/GrVkCopyPipeline.h"
22 #include "vk/GrVkGpu.h"
23 #include "vk/GrVkRenderTarget.h"
24 #include "vk/GrVkUtil.h"
25 
26 using sk_gpu_test::GrContextFactory;
27 
28 class TestVkCopyProgram {
29 public:
TestVkCopyProgram()30     TestVkCopyProgram()
31             : fVertShaderModule(VK_NULL_HANDLE)
32             , fFragShaderModule(VK_NULL_HANDLE)
33             , fPipelineLayout(VK_NULL_HANDLE) {}
34 
test(GrVkGpu * gpu,skiatest::Reporter * reporter)35     void test(GrVkGpu* gpu, skiatest::Reporter* reporter) {
36         const char vertShaderText[] =
37             "#extension GL_ARB_separate_shader_objects : enable\n"
38             "#extension GL_ARB_shading_language_420pack : enable\n"
39 
40             "layout(set = 0, binding = 0) uniform vertexUniformBuffer {"
41             "half4 uPosXform;"
42             "half4 uTexCoordXform;"
43             "};"
44             "layout(location = 0) in float2 inPosition;"
45             "layout(location = 1) out half2 vTexCoord;"
46 
47             "// Copy Program VS\n"
48             "void main() {"
49             "vTexCoord = inPosition * uTexCoordXform.xy + uTexCoordXform.zw;"
50             "sk_Position.xy = inPosition * uPosXform.xy + uPosXform.zw;"
51             "sk_Position.zw = half2(0, 1);"
52             "}";
53 
54         const char fragShaderText[] =
55             "#extension GL_ARB_separate_shader_objects : enable\n"
56             "#extension GL_ARB_shading_language_420pack : enable\n"
57 
58             "layout(set = 1, binding = 0) uniform sampler2D uTextureSampler;"
59             "layout(location = 1) in half2 vTexCoord;"
60 
61             "// Copy Program FS\n"
62             "void main() {"
63             "sk_FragColor = texture(uTextureSampler, vTexCoord);"
64             "}";
65 
66         SkSL::Program::Settings settings;
67         SkSL::String spirv;
68         SkSL::Program::Inputs inputs;
69         if (!GrCompileVkShaderModule(gpu, vertShaderText, VK_SHADER_STAGE_VERTEX_BIT,
70                                      &fVertShaderModule, &fShaderStageInfo[0], settings,
71                                      &spirv, &inputs)) {
72             this->destroyResources(gpu);
73             REPORTER_ASSERT(reporter, false);
74             return;
75         }
76         SkASSERT(inputs.isEmpty());
77 
78         if (!GrCompileVkShaderModule(gpu, fragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT,
79                                      &fFragShaderModule, &fShaderStageInfo[1], settings,
80                                      &spirv, &inputs)) {
81             this->destroyResources(gpu);
82             REPORTER_ASSERT(reporter, false);
83             return;
84         }
85 
86         VkDescriptorSetLayout dsLayout[2];
87 
88         GrVkResourceProvider& resourceProvider = gpu->resourceProvider();
89 
90         dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();
91 
92         uint32_t samplerVisibility = kFragment_GrShaderFlag;
93         SkTArray<uint32_t> visibilityArray(&samplerVisibility, 1);
94 
95         resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
96                                                        visibilityArray, &fSamplerDSHandle);
97         dsLayout[GrVkUniformHandler::kSamplerDescSet] =
98                 resourceProvider.getSamplerDSLayout(fSamplerDSHandle);
99 
100         // Create the VkPipelineLayout
101         VkPipelineLayoutCreateInfo layoutCreateInfo;
102         memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
103         layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
104         layoutCreateInfo.pNext = 0;
105         layoutCreateInfo.flags = 0;
106         layoutCreateInfo.setLayoutCount = 2;
107         layoutCreateInfo.pSetLayouts = dsLayout;
108         layoutCreateInfo.pushConstantRangeCount = 0;
109         layoutCreateInfo.pPushConstantRanges = nullptr;
110 
111         VkResult err = GR_VK_CALL(gpu->vkInterface(), CreatePipelineLayout(gpu->device(),
112                                                                            &layoutCreateInfo,
113                                                                            nullptr,
114                                                                            &fPipelineLayout));
115         if (err) {
116             this->destroyResources(gpu);
117             REPORTER_ASSERT(reporter, false);
118             return;
119         }
120 
121         GrSurfaceDesc surfDesc;
122         surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
123         surfDesc.fWidth = 16;
124         surfDesc.fHeight = 16;
125         surfDesc.fConfig = kRGBA_8888_GrPixelConfig;
126         surfDesc.fSampleCnt = 1;
127         sk_sp<GrTexture> tex = gpu->createTexture(surfDesc, SkBudgeted::kNo);
128         if (!tex) {
129             this->destroyResources(gpu);
130             REPORTER_ASSERT(reporter, tex.get());
131             return;
132 
133         }
134         GrRenderTarget* rt = tex->asRenderTarget();
135         REPORTER_ASSERT(reporter, rt);
136         GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
137 
138         GrVkCopyPipeline* copyPipeline = GrVkCopyPipeline::Create(gpu,
139                                                                   fShaderStageInfo,
140                                                                   fPipelineLayout,
141                                                                   1,
142                                                                   *vkRT->simpleRenderPass(),
143                                                                   VK_NULL_HANDLE);
144 
145         REPORTER_ASSERT(reporter, copyPipeline);
146         if (copyPipeline) {
147             copyPipeline->unref(gpu);
148         }
149 
150         this->destroyResources(gpu);
151     }
152 
destroyResources(GrVkGpu * gpu)153     void destroyResources(GrVkGpu* gpu) {
154         if (VK_NULL_HANDLE != fVertShaderModule) {
155             GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fVertShaderModule,
156                                                                nullptr));
157             fVertShaderModule = VK_NULL_HANDLE;
158         }
159 
160         if (VK_NULL_HANDLE != fFragShaderModule) {
161             GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fFragShaderModule,
162                                                                nullptr));
163             fFragShaderModule = VK_NULL_HANDLE;
164         }
165 
166         if (VK_NULL_HANDLE != fPipelineLayout) {
167             GR_VK_CALL(gpu->vkInterface(), DestroyPipelineLayout(gpu->device(), fPipelineLayout,
168                                                                  nullptr));
169             fPipelineLayout = VK_NULL_HANDLE;
170         }
171     }
172 
173     VkShaderModule fVertShaderModule;
174     VkShaderModule fFragShaderModule;
175     VkPipelineShaderStageCreateInfo fShaderStageInfo[2];
176 
177     GrVkDescriptorSetManager::Handle fSamplerDSHandle;
178     VkPipelineLayout fPipelineLayout;
179 
180 };
181 
DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkMakeCopyPipelineTest,reporter,ctxInfo)182 DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkMakeCopyPipelineTest, reporter, ctxInfo) {
183     GrContext* context = ctxInfo.grContext();
184     GrVkGpu* gpu = static_cast<GrVkGpu*>(context->contextPriv().getGpu());
185 
186     TestVkCopyProgram copyProgram;
187     copyProgram.test(gpu, reporter);
188 }
189 
190 #endif
191