1 // 2 // Copyright 2021 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // CLKernelVk.h: Defines the class interface for CLKernelVk, implementing CLKernelImpl. 7 8 #ifndef LIBANGLE_RENDERER_VULKAN_CLKERNELVK_H_ 9 #define LIBANGLE_RENDERER_VULKAN_CLKERNELVK_H_ 10 11 #include "libANGLE/renderer/vulkan/cl_types.h" 12 #include "libANGLE/renderer/vulkan/vk_cache_utils.h" 13 #include "libANGLE/renderer/vulkan/vk_helpers.h" 14 #include "libANGLE/renderer/vulkan/vk_utils.h" 15 16 #include "libANGLE/renderer/CLKernelImpl.h" 17 #include "vulkan/vulkan_core.h" 18 19 namespace rx 20 { 21 22 struct CLKernelArgument 23 { 24 CLKernelImpl::ArgInfo info{}; 25 uint32_t type = 0; 26 uint32_t ordinal = 0; 27 size_t handleSize = 0; 28 void *handle = nullptr; 29 bool used = false; 30 31 // Shared operand words/regions for "OpExtInst" type spv instructions 32 // (starts from spv word index/offset 7 and onward) 33 // https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpExtInst 34 // https://github.com/google/clspv/blob/main/docs/OpenCLCOnVulkan.md#kernels 35 union 36 { 37 uint32_t op3; 38 uint32_t descriptorSet; 39 uint32_t pushConstOffset; 40 uint32_t workgroupSpecId; 41 }; 42 union 43 { 44 uint32_t op4; 45 uint32_t descriptorBinding; 46 uint32_t pushConstantSize; 47 uint32_t workgroupSize; 48 }; 49 union 50 { 51 uint32_t op5; 52 uint32_t podStorageBufferOffset; 53 uint32_t podUniformOffset; 54 uint32_t pointerUniformOffset; 55 }; 56 union 57 { 58 uint32_t op6; 59 uint32_t podStorageBufferSize; 60 uint32_t podUniformSize; 61 uint32_t pointerUniformSize; 62 }; 63 }; 64 using CLKernelArguments = std::vector<CLKernelArgument>; 65 using CLKernelArgsMap = angle::HashMap<std::string, CLKernelArguments>; 66 67 class CLKernelVk : public CLKernelImpl 68 { 69 public: 70 using Ptr = std::unique_ptr<CLKernelVk>; 71 72 struct KernelSpecConstant 73 { 74 uint32_t ID; 75 uint32_t data; 76 }; 77 // Setting a reasonable initial value 78 // https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_API.html#CL_DEVICE_MAX_PARAMETER_SIZE 79 using KernelSpecConstants = angle::FastVector<KernelSpecConstant, 128>; 80 81 CLKernelVk(const cl::Kernel &kernel, 82 std::string &name, 83 std::string &attributes, 84 CLKernelArguments &args); 85 ~CLKernelVk() override; 86 87 angle::Result init(); 88 89 angle::Result setArg(cl_uint argIndex, size_t argSize, const void *argValue) override; 90 91 angle::Result createInfo(CLKernelImpl::Info *infoOut) const override; 92 getProgram()93 CLProgramVk *getProgram() { return mProgram; } getKernelName()94 const std::string &getKernelName() { return mName; } getArgs()95 const CLKernelArguments &getArgs() { return mArgs; } initPipelineLayout()96 angle::Result initPipelineLayout() 97 { 98 PipelineLayoutCache *pipelineLayoutCache = mContext->getPipelineLayoutCache(); 99 return pipelineLayoutCache->getPipelineLayout(mContext, mPipelineLayoutDesc, 100 mDescriptorSetLayouts, &mPipelineLayout); 101 } getPipelineLayout()102 const vk::PipelineLayout &getPipelineLayout() const { return *mPipelineLayout; } getDescriptorSetLayouts()103 vk::DescriptorSetLayoutPointerArray &getDescriptorSetLayouts() { return mDescriptorSetLayouts; } getFrontendObject()104 cl::Kernel &getFrontendObject() { return const_cast<cl::Kernel &>(mKernel); } 105 106 angle::Result getOrCreateComputePipeline(vk::PipelineCacheAccess *pipelineCache, 107 const cl::NDRange &ndrange, 108 const cl::Device &device, 109 vk::PipelineHelper **pipelineOut, 110 cl::WorkgroupCount *workgroupCountOut); 111 getDescriptorSetLayoutDesc(DescriptorSetIndex index)112 const vk::DescriptorSetLayoutDesc &getDescriptorSetLayoutDesc(DescriptorSetIndex index) const 113 { 114 return mDescriptorSetLayoutDescs[index]; 115 } getKernelArgDescriptorSetDesc()116 const vk::DescriptorSetLayoutDesc &getKernelArgDescriptorSetDesc() const 117 { 118 return getDescriptorSetLayoutDesc(DescriptorSetIndex::KernelArguments); 119 } getLiteralSamplerDescriptorSetDesc()120 const vk::DescriptorSetLayoutDesc &getLiteralSamplerDescriptorSetDesc() const 121 { 122 return getDescriptorSetLayoutDesc(DescriptorSetIndex::LiteralSampler); 123 } getPrintfDescriptorSetDesc()124 const vk::DescriptorSetLayoutDesc &getPrintfDescriptorSetDesc() const 125 { 126 return getDescriptorSetLayoutDesc(DescriptorSetIndex::Printf); 127 } 128 getPipelineLayoutDesc()129 const vk::PipelineLayoutDesc &getPipelineLayoutDesc() { return mPipelineLayoutDesc; } 130 getDescriptorSet(DescriptorSetIndex index)131 VkDescriptorSet getDescriptorSet(DescriptorSetIndex index) 132 { 133 return mDescriptorSets[index]->getDescriptorSet(); 134 } 135 getPodArgumentsData()136 std::vector<uint8_t> &getPodArgumentsData() { return mPodArgumentsData; } 137 138 bool usesPrintf() const; 139 140 angle::Result allocateDescriptorSet( 141 DescriptorSetIndex index, 142 angle::EnumIterator<DescriptorSetIndex> layoutIndex, 143 vk::OutsideRenderPassCommandBufferHelper *computePassCommands); 144 145 private: 146 static constexpr std::array<size_t, 3> kEmptyWorkgroupSize = {0, 0, 0}; 147 148 CLProgramVk *mProgram; 149 CLContextVk *mContext; 150 std::string mName; 151 std::string mAttributes; 152 CLKernelArguments mArgs; 153 154 // Copy of the pod data 155 std::vector<uint8_t> mPodArgumentsData; 156 157 vk::ShaderProgramHelper mShaderProgramHelper; 158 vk::ComputePipelineCache mComputePipelineCache; 159 KernelSpecConstants mSpecConstants; 160 vk::PipelineLayoutPtr mPipelineLayout; 161 vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts{}; 162 163 vk::DescriptorSetArray<vk::DescriptorSetPointer> mDescriptorSets; 164 165 vk::DescriptorSetArray<vk::DescriptorSetLayoutDesc> mDescriptorSetLayoutDescs; 166 vk::PipelineLayoutDesc mPipelineLayoutDesc; 167 }; 168 169 } // namespace rx 170 171 #endif // LIBANGLE_RENDERER_VULKAN_CLKERNELVK_H_ 172