/* * Copyright 2018 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ // This is a GPU-backend specific test. It relies on static intializers to work #include "SkTypes.h" #if defined(SK_VULKAN) #include "vk/GrVkVulkan.h" #include "GrBackendSurface.h" #include "GrContextFactory.h" #include "GrContextPriv.h" #include "GrTexture.h" #include "Test.h" #include "vk/GrVkCopyPipeline.h" #include "vk/GrVkGpu.h" #include "vk/GrVkRenderTarget.h" #include "vk/GrVkUtil.h" using sk_gpu_test::GrContextFactory; class TestVkCopyProgram { public: TestVkCopyProgram() : fVertShaderModule(VK_NULL_HANDLE) , fFragShaderModule(VK_NULL_HANDLE) , fPipelineLayout(VK_NULL_HANDLE) {} void test(GrVkGpu* gpu, skiatest::Reporter* reporter) { const char vertShaderText[] = "#extension GL_ARB_separate_shader_objects : enable\n" "#extension GL_ARB_shading_language_420pack : enable\n" "layout(set = 0, binding = 0) uniform vertexUniformBuffer {" "half4 uPosXform;" "half4 uTexCoordXform;" "};" "layout(location = 0) in float2 inPosition;" "layout(location = 1) out half2 vTexCoord;" "// Copy Program VS\n" "void main() {" "vTexCoord = half2(inPosition * uTexCoordXform.xy + uTexCoordXform.zw);" "sk_Position.xy = inPosition * uPosXform.xy + uPosXform.zw;" "sk_Position.zw = half2(0, 1);" "}"; const char fragShaderText[] = "#extension GL_ARB_separate_shader_objects : enable\n" "#extension GL_ARB_shading_language_420pack : enable\n" "layout(set = 1, binding = 0) uniform sampler2D uTextureSampler;" "layout(location = 1) in half2 vTexCoord;" "// Copy Program FS\n" "void main() {" "sk_FragColor = texture(uTextureSampler, vTexCoord);" "}"; SkSL::Program::Settings settings; SkSL::String spirv; SkSL::Program::Inputs inputs; if (!GrCompileVkShaderModule(gpu, vertShaderText, VK_SHADER_STAGE_VERTEX_BIT, &fVertShaderModule, &fShaderStageInfo[0], settings, &spirv, &inputs)) { this->destroyResources(gpu); REPORTER_ASSERT(reporter, false); return; } SkASSERT(inputs.isEmpty()); if (!GrCompileVkShaderModule(gpu, fragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, &fFragShaderModule, &fShaderStageInfo[1], settings, &spirv, &inputs)) { this->destroyResources(gpu); REPORTER_ASSERT(reporter, false); return; } VkDescriptorSetLayout dsLayout[2]; GrVkResourceProvider& resourceProvider = gpu->resourceProvider(); dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout(); uint32_t samplerVisibility = kFragment_GrShaderFlag; SkTArray<uint32_t> visibilityArray(&samplerVisibility, 1); resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, visibilityArray, &fSamplerDSHandle); dsLayout[GrVkUniformHandler::kSamplerDescSet] = resourceProvider.getSamplerDSLayout(fSamplerDSHandle); // Create the VkPipelineLayout VkPipelineLayoutCreateInfo layoutCreateInfo; memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags)); layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; layoutCreateInfo.pNext = 0; layoutCreateInfo.flags = 0; layoutCreateInfo.setLayoutCount = 2; layoutCreateInfo.pSetLayouts = dsLayout; layoutCreateInfo.pushConstantRangeCount = 0; layoutCreateInfo.pPushConstantRanges = nullptr; VkResult err = GR_VK_CALL(gpu->vkInterface(), CreatePipelineLayout(gpu->device(), &layoutCreateInfo, nullptr, &fPipelineLayout)); if (err) { this->destroyResources(gpu); REPORTER_ASSERT(reporter, false); return; } GrSurfaceDesc surfDesc; surfDesc.fFlags = kRenderTarget_GrSurfaceFlag; surfDesc.fWidth = 16; surfDesc.fHeight = 16; surfDesc.fConfig = kRGBA_8888_GrPixelConfig; surfDesc.fSampleCnt = 1; sk_sp<GrTexture> tex = gpu->createTexture(surfDesc, SkBudgeted::kNo); if (!tex) { this->destroyResources(gpu); REPORTER_ASSERT(reporter, tex.get()); return; } GrRenderTarget* rt = tex->asRenderTarget(); REPORTER_ASSERT(reporter, rt); GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt); GrVkCopyPipeline* copyPipeline = GrVkCopyPipeline::Create(gpu, fShaderStageInfo, fPipelineLayout, 1, *vkRT->simpleRenderPass(), VK_NULL_HANDLE); REPORTER_ASSERT(reporter, copyPipeline); if (copyPipeline) { copyPipeline->unref(gpu); } this->destroyResources(gpu); } void destroyResources(GrVkGpu* gpu) { if (VK_NULL_HANDLE != fVertShaderModule) { GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fVertShaderModule, nullptr)); fVertShaderModule = VK_NULL_HANDLE; } if (VK_NULL_HANDLE != fFragShaderModule) { GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fFragShaderModule, nullptr)); fFragShaderModule = VK_NULL_HANDLE; } if (VK_NULL_HANDLE != fPipelineLayout) { GR_VK_CALL(gpu->vkInterface(), DestroyPipelineLayout(gpu->device(), fPipelineLayout, nullptr)); fPipelineLayout = VK_NULL_HANDLE; } } VkShaderModule fVertShaderModule; VkShaderModule fFragShaderModule; VkPipelineShaderStageCreateInfo fShaderStageInfo[2]; GrVkDescriptorSetManager::Handle fSamplerDSHandle; VkPipelineLayout fPipelineLayout; }; DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkMakeCopyPipelineTest, reporter, ctxInfo) { GrContext* context = ctxInfo.grContext(); GrVkGpu* gpu = static_cast<GrVkGpu*>(context->priv().getGpu()); TestVkCopyProgram copyProgram; copyProgram.test(gpu, reporter); } #endif