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