Skip to content

Commit a4441fc

Browse files
committed
[mlir][vulkan-runner] Avoid dependency on LLVM libraries
The Vulkan runtime wrapper will be compiled to a shared library that are loaded by the JIT runner. Depending on LLVM libraries means that LLVM symbols will be compiled into the shared library. That can cause problems if we are using it with other shared libraries depending on LLVM, notably Mesa, the open-source graphics driver framework. The Vulkan API wrappers invoked by the JIT runner links to the system libvulkan.so. If it's Mesa providing the implementation, Mesa will normally try to load the system libLLVM.so for its shader compilation. That causes issues because the JIT runner already loaded the Vulkan runtime wrapper which has LLVM sybmols compiled in. So system linker will instruct Mesa to use those symbols instead. Differential Revision: https://reviews.llvm.org/D79860
1 parent d02fce2 commit a4441fc

File tree

4 files changed

+76
-79
lines changed

4 files changed

+76
-79
lines changed

mlir/tools/mlir-vulkan-runner/CMakeLists.txt

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,12 @@ if (MLIR_VULKAN_RUNNER_ENABLED)
3838
VulkanRuntime.cpp
3939
)
4040

41-
target_include_directories(vulkan-runtime-wrappers
42-
PRIVATE ${Vulkan_INCLUDE_DIR}
43-
LLVMSupport
44-
)
45-
41+
# *IMPORTANT*: This library cannot depend on LLVM libraries. Otherwise,
42+
# it may cause LLVM version conflict when used together with other shared
43+
# libraries depending on LLVM. Notably, Mesa, who implemnents Vulkan
44+
# drivers on Linux, depends on the system libLLVM.so.
4645
target_link_libraries(vulkan-runtime-wrappers
4746
PUBLIC
48-
LLVMCore
49-
LLVMSupport
5047
${Vulkan_LIBRARY}
5148
)
5249

mlir/tools/mlir-vulkan-runner/VulkanRuntime.cpp

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,22 @@
1313

1414
#include "VulkanRuntime.h"
1515

16-
#include "llvm/Support/Format.h"
1716
#include <chrono>
17+
#include <cstring>
18+
// TODO(antiagainst): It's generally bad to access stdout/stderr in a library.
19+
// Figure out a better way for error reporting.
20+
#include <iomanip>
21+
#include <iostream>
22+
23+
inline void emitVulkanError(const char *api, VkResult error) {
24+
std::cerr << " failed with error code " << error << " when executing " << api;
25+
}
26+
27+
#define RETURN_ON_VULKAN_ERROR(result, api) \
28+
if ((result) != VK_SUCCESS) { \
29+
emitVulkanError(api, (result)); \
30+
return failure(); \
31+
}
1832

1933
using namespace mlir;
2034

@@ -32,7 +46,7 @@ void VulkanRuntime::setResourceData(
3246
const VulkanHostMemoryBuffer &hostMemBuffer) {
3347
resourceData[desIndex][bindIndex] = hostMemBuffer;
3448
resourceStorageClassData[desIndex][bindIndex] =
35-
spirv::StorageClass::StorageBuffer;
49+
SPIRVStorageClass::StorageBuffer;
3650
}
3751

3852
void VulkanRuntime::setEntryPoint(const char *entryPointName) {
@@ -49,33 +63,27 @@ void VulkanRuntime::setShaderModule(uint8_t *shader, uint32_t size) {
4963
}
5064

5165
LogicalResult VulkanRuntime::mapStorageClassToDescriptorType(
52-
spirv::StorageClass storageClass, VkDescriptorType &descriptorType) {
66+
SPIRVStorageClass storageClass, VkDescriptorType &descriptorType) {
5367
switch (storageClass) {
54-
case spirv::StorageClass::StorageBuffer:
68+
case SPIRVStorageClass::StorageBuffer:
5569
descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
5670
break;
57-
case spirv::StorageClass::Uniform:
71+
case SPIRVStorageClass::Uniform:
5872
descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
5973
break;
60-
default:
61-
llvm::errs() << "unsupported storage class";
62-
return failure();
6374
}
6475
return success();
6576
}
6677

6778
LogicalResult VulkanRuntime::mapStorageClassToBufferUsageFlag(
68-
spirv::StorageClass storageClass, VkBufferUsageFlagBits &bufferUsage) {
79+
SPIRVStorageClass storageClass, VkBufferUsageFlagBits &bufferUsage) {
6980
switch (storageClass) {
70-
case spirv::StorageClass::StorageBuffer:
81+
case SPIRVStorageClass::StorageBuffer:
7182
bufferUsage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
7283
break;
73-
case spirv::StorageClass::Uniform:
84+
case SPIRVStorageClass::Uniform:
7485
bufferUsage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
7586
break;
76-
default:
77-
llvm::errs() << "unsupported storage class";
78-
return failure();
7987
}
8088
return success();
8189
}
@@ -87,8 +95,7 @@ LogicalResult VulkanRuntime::countDeviceMemorySize() {
8795
if (resourceDataBindingPair.second.size) {
8896
memorySize += resourceDataBindingPair.second.size;
8997
} else {
90-
llvm::errs()
91-
<< "expected buffer size greater than zero for resource data";
98+
std::cerr << "expected buffer size greater than zero for resource data";
9299
return failure();
93100
}
94101
}
@@ -98,11 +105,11 @@ LogicalResult VulkanRuntime::countDeviceMemorySize() {
98105

99106
LogicalResult VulkanRuntime::initRuntime() {
100107
if (!resourceData.size()) {
101-
llvm::errs() << "Vulkan runtime needs at least one resource";
108+
std::cerr << "Vulkan runtime needs at least one resource";
102109
return failure();
103110
}
104111
if (!binarySize || !binary) {
105-
llvm::errs() << "binary shader size must be greater than zero";
112+
std::cerr << "binary shader size must be greater than zero";
106113
return failure();
107114
}
108115
if (failed(countDeviceMemorySize())) {
@@ -130,7 +137,7 @@ LogicalResult VulkanRuntime::destroy() {
130137
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
131138
vkDestroyPipeline(device, pipeline, nullptr);
132139
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
133-
for (auto &descriptorSetLayout: descriptorSetLayouts) {
140+
for (auto &descriptorSetLayout : descriptorSetLayouts) {
134141
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
135142
}
136143
vkDestroyShaderModule(device, shaderModule, nullptr);
@@ -199,12 +206,12 @@ LogicalResult VulkanRuntime::run() {
199206
VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT),
200207
"vkGetQueryPoolResults");
201208
float microsec = (timestamps[1] - timestamps[0]) * timestampPeriod / 1000;
202-
llvm::outs() << "Compute shader execution time: "
203-
<< llvm::format("%0.3fus\n", microsec);
209+
std::cout << "Compute shader execution time: " << std::setprecision(3)
210+
<< microsec << "us\n";
204211
}
205212

206-
llvm::outs() << "Command buffer submit time: " << submitDuration.count()
207-
<< "us\nWait idle time: " << execDuration.count() << "us\n";
213+
std::cout << "Command buffer submit time: " << submitDuration.count()
214+
<< "us\nWait idle time: " << execDuration.count() << "us\n";
208215

209216
return success();
210217
}
@@ -240,7 +247,7 @@ LogicalResult VulkanRuntime::createDevice() {
240247
vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, 0),
241248
"vkEnumeratePhysicalDevices");
242249

243-
llvm::SmallVector<VkPhysicalDevice, 1> physicalDevices(physicalDeviceCount);
250+
std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
244251
RETURN_ON_VULKAN_ERROR(vkEnumeratePhysicalDevices(instance,
245252
&physicalDeviceCount,
246253
physicalDevices.data()),
@@ -313,7 +320,7 @@ LogicalResult VulkanRuntime::getBestComputeQueue() {
313320
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice,
314321
&queueFamilyPropertiesCount, 0);
315322

316-
SmallVector<VkQueueFamilyProperties, 1> familyProperties(
323+
std::vector<VkQueueFamilyProperties> familyProperties(
317324
queueFamilyPropertiesCount);
318325
vkGetPhysicalDeviceQueueFamilyProperties(
319326
physicalDevice, &queueFamilyPropertiesCount, familyProperties.data());
@@ -339,14 +346,14 @@ LogicalResult VulkanRuntime::getBestComputeQueue() {
339346
}
340347
}
341348

342-
llvm::errs() << "cannot find valid queue";
349+
std::cerr << "cannot find valid queue";
343350
return failure();
344351
}
345352

346353
LogicalResult VulkanRuntime::createMemoryBuffers() {
347354
// For each descriptor set.
348355
for (const auto &resourceDataMapPair : resourceData) {
349-
llvm::SmallVector<VulkanDeviceMemoryBuffer, 1> deviceMemoryBuffers;
356+
std::vector<VulkanDeviceMemoryBuffer> deviceMemoryBuffers;
350357
const auto descriptorSetIndex = resourceDataMapPair.first;
351358
const auto &resourceDataMap = resourceDataMapPair.second;
352359

@@ -362,7 +369,7 @@ LogicalResult VulkanRuntime::createMemoryBuffers() {
362369
const auto resourceStorageClassMapIt =
363370
resourceStorageClassData.find(descriptorSetIndex);
364371
if (resourceStorageClassMapIt == resourceStorageClassData.end()) {
365-
llvm::errs()
372+
std::cerr
366373
<< "cannot find storage class for resource in descriptor set: "
367374
<< descriptorSetIndex;
368375
return failure();
@@ -373,7 +380,7 @@ LogicalResult VulkanRuntime::createMemoryBuffers() {
373380
const auto resourceStorageClassIt =
374381
resourceStorageClassMap.find(resourceDataBindingPair.first);
375382
if (resourceStorageClassIt == resourceStorageClassMap.end()) {
376-
llvm::errs()
383+
std::cerr
377384
<< "cannot find storage class for resource with descriptor index: "
378385
<< resourceDataBindingPair.first;
379386
return failure();
@@ -384,10 +391,10 @@ LogicalResult VulkanRuntime::createMemoryBuffers() {
384391
descriptorType)) ||
385392
failed(mapStorageClassToBufferUsageFlag(resourceStorageClassBinding,
386393
bufferUsage))) {
387-
llvm::errs() << "storage class for resource with descriptor binding: "
388-
<< resourceDataBindingPair.first
389-
<< " in the descriptor set: " << descriptorSetIndex
390-
<< " is not supported ";
394+
std::cerr << "storage class for resource with descriptor binding: "
395+
<< resourceDataBindingPair.first
396+
<< " in the descriptor set: " << descriptorSetIndex
397+
<< " is not supported ";
391398
return failure();
392399
}
393400

@@ -464,7 +471,7 @@ LogicalResult VulkanRuntime::createShaderModule() {
464471

465472
void VulkanRuntime::initDescriptorSetLayoutBindingMap() {
466473
for (const auto &deviceMemoryBufferMapPair : deviceMemoryBufferMap) {
467-
SmallVector<VkDescriptorSetLayoutBinding, 1> descriptorSetLayoutBindings;
474+
std::vector<VkDescriptorSetLayoutBinding> descriptorSetLayoutBindings;
468475
const auto &deviceMemoryBuffers = deviceMemoryBufferMapPair.second;
469476
const auto descriptorSetIndex = deviceMemoryBufferMapPair.first;
470477

@@ -495,8 +502,8 @@ LogicalResult VulkanRuntime::createDescriptorSetLayout() {
495502
descriptorSetLayoutBindingMap.find(descriptorSetIndex);
496503

497504
if (descriptorSetLayoutBindingIt == descriptorSetLayoutBindingMap.end()) {
498-
llvm::errs() << "cannot find layout bindings for the set with number: "
499-
<< descriptorSetIndex;
505+
std::cerr << "cannot find layout bindings for the set with number: "
506+
<< descriptorSetIndex;
500507
return failure();
501508
}
502509

@@ -573,7 +580,7 @@ LogicalResult VulkanRuntime::createComputePipeline() {
573580
}
574581

575582
LogicalResult VulkanRuntime::createDescriptorPool() {
576-
llvm::SmallVector<VkDescriptorPoolSize, 1> descriptorPoolSizes;
583+
std::vector<VkDescriptorPoolSize> descriptorPoolSizes;
577584
for (const auto &descriptorSetInfo : descriptorSetInfoPool) {
578585
// For each descriptor set populate descriptor pool size.
579586
VkDescriptorPoolSize descriptorPoolSize = {};
@@ -616,7 +623,7 @@ LogicalResult VulkanRuntime::allocateDescriptorSets() {
616623

617624
LogicalResult VulkanRuntime::setWriteDescriptors() {
618625
if (descriptorSets.size() != descriptorSetInfoPool.size()) {
619-
llvm::errs() << "Each descriptor set must have descriptor set information";
626+
std::cerr << "Each descriptor set must have descriptor set information";
620627
return failure();
621628
}
622629
// For each descriptor set.

mlir/tools/mlir-vulkan-runner/VulkanRuntime.h

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,10 @@
1313
#ifndef VULKAN_RUNTIME_H
1414
#define VULKAN_RUNTIME_H
1515

16-
#include "mlir/Dialect/SPIRV/SPIRVOps.h"
17-
#include "mlir/Dialect/SPIRV/Serialization.h"
18-
#include "mlir/IR/Module.h"
1916
#include "mlir/Support/LogicalResult.h"
20-
#include "llvm/ADT/DenseMap.h"
21-
#include "llvm/ADT/StringExtras.h"
22-
#include "llvm/Support/ToolOutputFile.h"
2317

18+
#include <unordered_map>
19+
#include <vector>
2420
#include <vulkan/vulkan.h>
2521

2622
using namespace mlir;
@@ -64,25 +60,23 @@ struct DescriptorSetInfo {
6460
};
6561

6662
/// VulkanHostMemoryBuffer mapped into a descriptor set and a binding.
67-
using ResourceData =
68-
llvm::DenseMap<DescriptorSetIndex,
69-
llvm::DenseMap<BindingIndex, VulkanHostMemoryBuffer>>;
63+
using ResourceData = std::unordered_map<
64+
DescriptorSetIndex,
65+
std::unordered_map<BindingIndex, VulkanHostMemoryBuffer>>;
66+
67+
/// SPIR-V storage classes.
68+
/// Note that this duplicates spirv::StorageClass but it keeps the Vulkan
69+
/// runtime library detached from SPIR-V dialect, so we can avoid pick up lots
70+
/// of dependencies.
71+
enum class SPIRVStorageClass {
72+
Uniform = 2,
73+
StorageBuffer = 12,
74+
};
7075

7176
/// StorageClass mapped into a descriptor set and a binding.
7277
using ResourceStorageClassBindingMap =
73-
llvm::DenseMap<DescriptorSetIndex,
74-
llvm::DenseMap<BindingIndex, mlir::spirv::StorageClass>>;
75-
76-
inline void emitVulkanError(const llvm::Twine &message, VkResult error) {
77-
llvm::errs()
78-
<< message.concat(" failed with error code ").concat(llvm::Twine{error});
79-
}
80-
81-
#define RETURN_ON_VULKAN_ERROR(result, msg) \
82-
if ((result) != VK_SUCCESS) { \
83-
emitVulkanError(msg, (result)); \
84-
return failure(); \
85-
}
78+
std::unordered_map<DescriptorSetIndex,
79+
std::unordered_map<BindingIndex, SPIRVStorageClass>>;
8680

8781
/// Vulkan runtime.
8882
/// The purpose of this class is to run SPIR-V compute shader on Vulkan
@@ -150,12 +144,12 @@ class VulkanRuntime {
150144

151145
/// Maps storage class to a descriptor type.
152146
LogicalResult
153-
mapStorageClassToDescriptorType(spirv::StorageClass storageClass,
147+
mapStorageClassToDescriptorType(SPIRVStorageClass storageClass,
154148
VkDescriptorType &descriptorType);
155149

156150
/// Maps storage class to buffer usage flags.
157151
LogicalResult
158-
mapStorageClassToBufferUsageFlag(spirv::StorageClass storageClass,
152+
mapStorageClassToBufferUsageFlag(SPIRVStorageClass storageClass,
159153
VkBufferUsageFlagBits &bufferUsage);
160154

161155
LogicalResult countDeviceMemorySize();
@@ -170,28 +164,27 @@ class VulkanRuntime {
170164
VkQueue queue{VK_NULL_HANDLE};
171165

172166
/// Specifies VulkanDeviceMemoryBuffers divided into sets.
173-
llvm::DenseMap<DescriptorSetIndex,
174-
llvm::SmallVector<VulkanDeviceMemoryBuffer, 1>>
167+
std::unordered_map<DescriptorSetIndex, std::vector<VulkanDeviceMemoryBuffer>>
175168
deviceMemoryBufferMap;
176169

177170
/// Specifies shader module.
178171
VkShaderModule shaderModule{VK_NULL_HANDLE};
179172

180173
/// Specifies layout bindings.
181-
llvm::DenseMap<DescriptorSetIndex,
182-
llvm::SmallVector<VkDescriptorSetLayoutBinding, 1>>
174+
std::unordered_map<DescriptorSetIndex,
175+
std::vector<VkDescriptorSetLayoutBinding>>
183176
descriptorSetLayoutBindingMap;
184177

185178
/// Specifies layouts of descriptor sets.
186-
llvm::SmallVector<VkDescriptorSetLayout, 1> descriptorSetLayouts;
179+
std::vector<VkDescriptorSetLayout> descriptorSetLayouts;
187180
VkPipelineLayout pipelineLayout{VK_NULL_HANDLE};
188181

189182
/// Specifies descriptor sets.
190-
llvm::SmallVector<VkDescriptorSet, 1> descriptorSets;
183+
std::vector<VkDescriptorSet> descriptorSets;
191184

192185
/// Specifies a pool of descriptor set info, each descriptor set must have
193186
/// information such as type, index and amount of bindings.
194-
llvm::SmallVector<DescriptorSetInfo, 1> descriptorSetInfoPool;
187+
std::vector<DescriptorSetInfo> descriptorSetInfoPool;
195188
VkDescriptorPool descriptorPool{VK_NULL_HANDLE};
196189

197190
/// Timestamp query.
@@ -202,7 +195,7 @@ class VulkanRuntime {
202195
/// Computation pipeline.
203196
VkPipeline pipeline{VK_NULL_HANDLE};
204197
VkCommandPool commandPool{VK_NULL_HANDLE};
205-
llvm::SmallVector<VkCommandBuffer, 1> commandBuffers;
198+
std::vector<VkCommandBuffer> commandBuffers;
206199

207200
//===--------------------------------------------------------------------===//
208201
// Vulkan memory context.

mlir/tools/mlir-vulkan-runner/vulkan-runtime-wrappers.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include <iostream>
1314
#include <mutex>
1415
#include <numeric>
1516

1617
#include "VulkanRuntime.h"
17-
#include "llvm/Support/raw_ostream.h"
1818

1919
namespace {
2020

@@ -51,7 +51,7 @@ class VulkanRuntimeManager {
5151
if (failed(vulkanRuntime.initRuntime()) || failed(vulkanRuntime.run()) ||
5252
failed(vulkanRuntime.updateHostMemoryBuffers()) ||
5353
failed(vulkanRuntime.destroy())) {
54-
llvm::errs() << "runOnVulkan failed";
54+
std::cerr << "runOnVulkan failed";
5555
}
5656
}
5757

0 commit comments

Comments
 (0)