cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
233 lines
8.1 KiB
C++
233 lines
8.1 KiB
C++
//===- VulkanRuntime.cpp - MLIR Vulkan runtime ------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file declares Vulkan runtime API.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef VULKAN_RUNTIME_H
|
|
#define VULKAN_RUNTIME_H
|
|
|
|
#include "mlir/Support/LLVM.h"
|
|
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
#include <vulkan/vulkan.h>
|
|
|
|
using namespace mlir;
|
|
|
|
using DescriptorSetIndex = uint32_t;
|
|
using BindingIndex = uint32_t;
|
|
|
|
/// Struct containing information regarding to a device memory buffer.
|
|
struct VulkanDeviceMemoryBuffer {
|
|
BindingIndex bindingIndex{0};
|
|
VkDescriptorType descriptorType{VK_DESCRIPTOR_TYPE_MAX_ENUM};
|
|
VkDescriptorBufferInfo bufferInfo{};
|
|
VkBuffer hostBuffer{VK_NULL_HANDLE};
|
|
VkDeviceMemory hostMemory{VK_NULL_HANDLE};
|
|
VkBuffer deviceBuffer{VK_NULL_HANDLE};
|
|
VkDeviceMemory deviceMemory{VK_NULL_HANDLE};
|
|
uint32_t bufferSize{0};
|
|
};
|
|
|
|
/// Struct containing information regarding to a host memory buffer.
|
|
struct VulkanHostMemoryBuffer {
|
|
/// Pointer to a host memory.
|
|
void *ptr{nullptr};
|
|
/// Size of a host memory in bytes.
|
|
uint32_t size{0};
|
|
};
|
|
|
|
/// Struct containing the number of local workgroups to dispatch for each
|
|
/// dimension.
|
|
struct NumWorkGroups {
|
|
uint32_t x{1};
|
|
uint32_t y{1};
|
|
uint32_t z{1};
|
|
};
|
|
|
|
/// Struct containing information regarding a descriptor set.
|
|
struct DescriptorSetInfo {
|
|
/// Index of a descriptor set in descriptor sets.
|
|
DescriptorSetIndex descriptorSet{0};
|
|
/// Number of descriptors in a set.
|
|
uint32_t descriptorSize{0};
|
|
/// Type of a descriptor set.
|
|
VkDescriptorType descriptorType{VK_DESCRIPTOR_TYPE_MAX_ENUM};
|
|
};
|
|
|
|
/// VulkanHostMemoryBuffer mapped into a descriptor set and a binding.
|
|
using ResourceData = std::unordered_map<
|
|
DescriptorSetIndex,
|
|
std::unordered_map<BindingIndex, VulkanHostMemoryBuffer>>;
|
|
|
|
/// SPIR-V storage classes.
|
|
/// Note that this duplicates spirv::StorageClass but it keeps the Vulkan
|
|
/// runtime library detached from SPIR-V dialect, so we can avoid pick up lots
|
|
/// of dependencies.
|
|
enum class SPIRVStorageClass {
|
|
Uniform = 2,
|
|
StorageBuffer = 12,
|
|
};
|
|
|
|
/// StorageClass mapped into a descriptor set and a binding.
|
|
using ResourceStorageClassBindingMap =
|
|
std::unordered_map<DescriptorSetIndex,
|
|
std::unordered_map<BindingIndex, SPIRVStorageClass>>;
|
|
|
|
/// Vulkan runtime.
|
|
/// The purpose of this class is to run SPIR-V compute shader on Vulkan
|
|
/// device.
|
|
/// Before the run, user must provide and set resource data with descriptors,
|
|
/// SPIR-V shader, number of work groups and entry point. After the creation of
|
|
/// VulkanRuntime, special methods must be called in the following
|
|
/// sequence: initRuntime(), run(), updateHostMemoryBuffers(), destroy();
|
|
/// each method in the sequence returns success or failure depends on the Vulkan
|
|
/// result code.
|
|
class VulkanRuntime {
|
|
public:
|
|
explicit VulkanRuntime() = default;
|
|
VulkanRuntime(const VulkanRuntime &) = delete;
|
|
VulkanRuntime &operator=(const VulkanRuntime &) = delete;
|
|
|
|
/// Sets needed data for Vulkan runtime.
|
|
void setResourceData(const ResourceData &resData);
|
|
void setResourceData(const DescriptorSetIndex desIndex,
|
|
const BindingIndex bindIndex,
|
|
const VulkanHostMemoryBuffer &hostMemBuffer);
|
|
void setShaderModule(uint8_t *shader, uint32_t size);
|
|
void setNumWorkGroups(const NumWorkGroups &numberWorkGroups);
|
|
void setResourceStorageClassBindingMap(
|
|
const ResourceStorageClassBindingMap &stClassData);
|
|
void setEntryPoint(const char *entryPointName);
|
|
|
|
/// Runtime initialization.
|
|
LogicalResult initRuntime();
|
|
|
|
/// Runs runtime.
|
|
LogicalResult run();
|
|
|
|
/// Updates host memory buffers.
|
|
LogicalResult updateHostMemoryBuffers();
|
|
|
|
/// Destroys all created vulkan objects and resources.
|
|
LogicalResult destroy();
|
|
|
|
private:
|
|
//===--------------------------------------------------------------------===//
|
|
// Pipeline creation methods.
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
LogicalResult createInstance();
|
|
LogicalResult createDevice();
|
|
LogicalResult getBestComputeQueue();
|
|
LogicalResult createMemoryBuffers();
|
|
LogicalResult createShaderModule();
|
|
void initDescriptorSetLayoutBindingMap();
|
|
LogicalResult createDescriptorSetLayout();
|
|
LogicalResult createPipelineLayout();
|
|
LogicalResult createComputePipeline();
|
|
LogicalResult createDescriptorPool();
|
|
LogicalResult allocateDescriptorSets();
|
|
LogicalResult setWriteDescriptors();
|
|
LogicalResult createCommandPool();
|
|
LogicalResult createQueryPool();
|
|
LogicalResult createComputeCommandBuffer();
|
|
LogicalResult submitCommandBuffersToQueue();
|
|
// Copy resources from host (staging buffer) to device buffer or from device
|
|
// buffer to host buffer.
|
|
LogicalResult copyResource(bool deviceToHost);
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Helper methods.
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
/// Maps storage class to a descriptor type.
|
|
LogicalResult
|
|
mapStorageClassToDescriptorType(SPIRVStorageClass storageClass,
|
|
VkDescriptorType &descriptorType);
|
|
|
|
/// Maps storage class to buffer usage flags.
|
|
LogicalResult
|
|
mapStorageClassToBufferUsageFlag(SPIRVStorageClass storageClass,
|
|
VkBufferUsageFlagBits &bufferUsage);
|
|
|
|
LogicalResult countDeviceMemorySize();
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Vulkan objects.
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
VkInstance instance{VK_NULL_HANDLE};
|
|
VkPhysicalDevice physicalDevice{VK_NULL_HANDLE};
|
|
VkDevice device{VK_NULL_HANDLE};
|
|
VkQueue queue{VK_NULL_HANDLE};
|
|
|
|
/// Specifies VulkanDeviceMemoryBuffers divided into sets.
|
|
std::unordered_map<DescriptorSetIndex, std::vector<VulkanDeviceMemoryBuffer>>
|
|
deviceMemoryBufferMap;
|
|
|
|
/// Specifies shader module.
|
|
VkShaderModule shaderModule{VK_NULL_HANDLE};
|
|
|
|
/// Specifies layout bindings.
|
|
std::unordered_map<DescriptorSetIndex,
|
|
std::vector<VkDescriptorSetLayoutBinding>>
|
|
descriptorSetLayoutBindingMap;
|
|
|
|
/// Specifies layouts of descriptor sets.
|
|
std::vector<VkDescriptorSetLayout> descriptorSetLayouts;
|
|
VkPipelineLayout pipelineLayout{VK_NULL_HANDLE};
|
|
|
|
/// Specifies descriptor sets.
|
|
std::vector<VkDescriptorSet> descriptorSets;
|
|
|
|
/// Specifies a pool of descriptor set info, each descriptor set must have
|
|
/// information such as type, index and amount of bindings.
|
|
std::vector<DescriptorSetInfo> descriptorSetInfoPool;
|
|
VkDescriptorPool descriptorPool{VK_NULL_HANDLE};
|
|
|
|
/// Timestamp query.
|
|
VkQueryPool queryPool{VK_NULL_HANDLE};
|
|
// Number of nonoseconds for timestamp to increase 1
|
|
float timestampPeriod{0.f};
|
|
|
|
/// Computation pipeline.
|
|
VkPipeline pipeline{VK_NULL_HANDLE};
|
|
VkCommandPool commandPool{VK_NULL_HANDLE};
|
|
std::vector<VkCommandBuffer> commandBuffers;
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Vulkan memory context.
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
uint32_t queueFamilyIndex{0};
|
|
VkQueueFamilyProperties queueFamilyProperties{};
|
|
uint32_t hostMemoryTypeIndex{VK_MAX_MEMORY_TYPES};
|
|
uint32_t deviceMemoryTypeIndex{VK_MAX_MEMORY_TYPES};
|
|
VkDeviceSize memorySize{0};
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Vulkan execution context.
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
NumWorkGroups numWorkGroups;
|
|
const char *entryPoint{nullptr};
|
|
uint8_t *binary{nullptr};
|
|
uint32_t binarySize{0};
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Vulkan resource data and storage classes.
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
ResourceData resourceData;
|
|
ResourceStorageClassBindingMap resourceStorageClassData;
|
|
};
|
|
#endif
|