blob: 4c8033097d1cf993e9c60a1b40948b5494b1febe [file] [log] [blame]
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CLProgramVk.h: Defines the class interface for CLProgramVk, implementing CLProgramImpl.
#ifndef LIBANGLE_RENDERER_VULKAN_CLPROGRAMVK_H_
#define LIBANGLE_RENDERER_VULKAN_CLPROGRAMVK_H_
#include "libANGLE/renderer/vulkan/CLKernelVk.h"
#include "libANGLE/renderer/vulkan/cl_types.h"
#include "libANGLE/renderer/vulkan/vk_cache_utils.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"
#include "libANGLE/renderer/CLProgramImpl.h"
#include "libANGLE/CLProgram.h"
#include "clspv/Compiler.h"
#include "vulkan/vulkan_core.h"
#include "spirv-tools/libspirv.h"
namespace rx
{
class CLProgramVk : public CLProgramImpl
{
public:
struct SpvReflectionData
{
angle::HashMap<uint32_t, uint32_t> spvIntLookup;
angle::HashMap<uint32_t, std::string> spvStrLookup;
angle::HashMap<uint32_t, CLKernelVk::ArgInfo> kernelArgInfos;
angle::HashMap<std::string, uint32_t> kernelFlags;
angle::HashMap<std::string, std::string> kernelAttributes;
angle::HashMap<std::string, std::array<uint32_t, 3>> kernelCompileWGS;
angle::HashMap<uint32_t, VkPushConstantRange> pushConstants;
std::array<uint32_t, 3> specConstantWGS{0, 0, 0};
CLKernelArgsMap kernelArgsMap;
};
// Output binary structure (for CL_PROGRAM_BINARIES query)
struct ProgramBinaryOutputHeader
{
uint32_t headerVersion{1};
cl_program_binary_type binaryType{CL_PROGRAM_BINARY_TYPE_NONE};
};
static constexpr uint32_t LatestSupportedBinaryVersion = 1;
struct ScopedClspvContext : angle::NonCopyable
{
ScopedClspvContext() = default;
~ScopedClspvContext() { clspvFreeOutputBuildObjs(mOutputBin, mOutputBuildLog); }
size_t mOutputBinSize{0};
char *mOutputBin{nullptr};
char *mOutputBuildLog{nullptr};
};
struct ScopedProgramCallback : angle::NonCopyable
{
ScopedProgramCallback() = delete;
ScopedProgramCallback(cl::Program *notify) : mNotify(notify) {}
~ScopedProgramCallback()
{
if (mNotify)
{
mNotify->callback();
}
}
cl::Program *mNotify{nullptr};
};
enum class BuildType
{
BUILD = 0,
COMPILE,
LINK,
BINARY
};
struct DeviceProgramData
{
std::vector<char> IR;
std::string buildLog;
angle::spirv::Blob binary;
SpvReflectionData reflectionData;
VkPushConstantRange pushConstRange{};
cl_build_status buildStatus{CL_BUILD_NONE};
cl_program_binary_type binaryType{CL_PROGRAM_BINARY_TYPE_NONE};
size_t numKernels() const { return reflectionData.kernelArgsMap.size(); }
size_t numKernelArgs(const std::string &kernelName) const
{
return containsKernel(kernelName) ? getKernelArgsMap().at(kernelName).size() : 0;
}
const CLKernelArgsMap &getKernelArgsMap() const { return reflectionData.kernelArgsMap; }
bool containsKernel(const std::string &name) const
{
return reflectionData.kernelArgsMap.contains(name);
}
std::string getKernelNames() const
{
std::string names;
for (auto name = getKernelArgsMap().begin(); name != getKernelArgsMap().end(); ++name)
{
names += name->first + (std::next(name) != getKernelArgsMap().end() ? ";" : "\0");
}
return names;
}
CLKernelArguments getKernelArguments(const std::string &kernelName) const
{
CLKernelArguments kargsCopy;
if (containsKernel(kernelName))
{
const CLKernelArguments &kargs = getKernelArgsMap().at(kernelName);
for (const CLKernelArgument &karg : kargs)
{
kargsCopy.push_back(karg);
}
}
return kargsCopy;
}
cl::CompiledWorkgroupSize getCompiledWGS(const std::string &kernelName) const
{
cl::CompiledWorkgroupSize compiledWGS{0, 0, 0};
if (reflectionData.kernelCompileWGS.contains(kernelName))
{
compiledWGS = reflectionData.kernelCompileWGS.at(kernelName);
}
return compiledWGS;
}
std::string getKernelAttributes(const std::string &kernelName) const
{
if (containsKernel(kernelName))
{
return reflectionData.kernelAttributes.at(kernelName.c_str());
}
return std::string{};
}
};
using DevicePrograms = angle::HashMap<const _cl_device_id *, DeviceProgramData>;
using DeviceProgramDatas = std::vector<const DeviceProgramData *>;
CLProgramVk(const cl::Program &program);
~CLProgramVk() override;
angle::Result init();
angle::Result init(const size_t *lengths, const unsigned char **binaries, cl_int *binaryStatus);
angle::Result build(const cl::DevicePtrs &devices,
const char *options,
cl::Program *notify) override;
angle::Result compile(const cl::DevicePtrs &devices,
const char *options,
const cl::ProgramPtrs &inputHeaders,
const char **headerIncludeNames,
cl::Program *notify) override;
angle::Result getInfo(cl::ProgramInfo name,
size_t valueSize,
void *value,
size_t *valueSizeRet) const override;
angle::Result getBuildInfo(const cl::Device &device,
cl::ProgramBuildInfo name,
size_t valueSize,
void *value,
size_t *valueSizeRet) const override;
angle::Result createKernel(const cl::Kernel &kernel,
const char *name,
CLKernelImpl::Ptr *kernelOut) override;
angle::Result createKernels(cl_uint numKernels,
CLKernelImpl::CreateFuncs &createFuncs,
cl_uint *numKernelsRet) override;
const DeviceProgramData *getDeviceProgramData(const char *kernelName) const;
const DeviceProgramData *getDeviceProgramData(const _cl_device_id *device) const;
bool buildInternal(const cl::DevicePtrs &devices,
std::string options,
std::string internalOptions,
BuildType buildType,
const DeviceProgramDatas &inputProgramDatas);
angle::spirv::Blob stripReflection(const DeviceProgramData *deviceProgramData);
private:
CLContextVk *mContext;
std::string mProgramOpts;
DevicePrograms mAssociatedDevicePrograms;
PipelineLayoutCache mPipelineLayoutCache;
vk::MetaDescriptorPool mMetaDescriptorPool;
DescriptorSetLayoutCache mDescSetLayoutCache;
vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts;
vk::DescriptorSetArray<vk::DescriptorPoolPointer> mDescriptorPools;
std::mutex mProgramMutex;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_CLPROGRAMVK_H_