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