aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/vulkan/device.cc73
-rw-r--r--src/vulkan/device.h16
-rw-r--r--src/vulkan/engine_vulkan.cc18
-rw-r--r--src/vulkan/engine_vulkan.h3
-rw-r--r--tests/cases/compute_in_spirv_generated_by_clspv.amber163
5 files changed, 249 insertions, 24 deletions
diff --git a/src/vulkan/device.cc b/src/vulkan/device.cc
index 98a9c70..cd08d8a 100644
--- a/src/vulkan/device.cc
+++ b/src/vulkan/device.cc
@@ -15,6 +15,7 @@
#include "src/vulkan/device.h"
#include <memory>
+#include <set>
#include <vector>
#include "src/make_unique.h"
@@ -204,8 +205,13 @@ VkPhysicalDeviceFeatures RequestedFeatures(
}
bool AreAllRequiredFeaturesSupported(
- const VkPhysicalDeviceFeatures& available_features,
+ const VkPhysicalDevice& physical_device,
const std::vector<Feature>& required_features) {
+ if (required_features.empty())
+ return true;
+
+ VkPhysicalDeviceFeatures available_features = {};
+ vkGetPhysicalDeviceFeatures(physical_device, &available_features);
for (const auto& feature : required_features) {
switch (feature) {
case Feature::kRobustBufferAccess:
@@ -444,6 +450,40 @@ bool AreAllRequiredFeaturesSupported(
return true;
}
+bool AreAllExtensionsSupported(
+ const VkPhysicalDevice& physical_device,
+ const std::vector<std::string>& required_extensions) {
+ if (required_extensions.empty())
+ return true;
+
+ uint32_t available_extension_count = 0;
+ std::vector<VkExtensionProperties> available_extension_properties;
+
+ if (vkEnumerateDeviceExtensionProperties(physical_device, nullptr,
+ &available_extension_count,
+ nullptr) != VK_SUCCESS) {
+ return false;
+ }
+
+ if (available_extension_count == 0)
+ return false;
+
+ available_extension_properties.resize(available_extension_count);
+ if (vkEnumerateDeviceExtensionProperties(
+ physical_device, nullptr, &available_extension_count,
+ available_extension_properties.data()) != VK_SUCCESS) {
+ return false;
+ }
+
+ std::set<std::string> required_extension_set(required_extensions.begin(),
+ required_extensions.end());
+ for (const auto& property : available_extension_properties) {
+ required_extension_set.erase(property.extensionName);
+ }
+
+ return required_extension_set.empty();
+}
+
} // namespace
Device::Device() = default;
@@ -457,17 +497,18 @@ void Device::Shutdown() {
}
}
-Result Device::Initialize(const std::vector<Feature>& required_features) {
+Result Device::Initialize(const std::vector<Feature>& required_features,
+ const std::vector<std::string>& required_extensions) {
if (device_ == VK_NULL_HANDLE) {
Result r = CreateInstance();
if (!r.IsSuccess())
return r;
- r = ChoosePhysicalDevice(required_features);
+ r = ChoosePhysicalDevice(required_features, required_extensions);
if (!r.IsSuccess())
return r;
- r = CreateDevice(required_features);
+ r = CreateDevice(required_features, required_extensions);
if (!r.IsSuccess())
return r;
}
@@ -526,7 +567,8 @@ Result Device::CreateInstance() {
}
Result Device::ChoosePhysicalDevice(
- const std::vector<Feature>& required_features) {
+ const std::vector<Feature>& required_features,
+ const std::vector<std::string>& required_extensions) {
uint32_t count;
std::vector<VkPhysicalDevice> physical_devices;
@@ -538,11 +580,14 @@ Result Device::ChoosePhysicalDevice(
return Result("Vulkan::Calling vkEnumeratePhysicalDevices Fail");
for (uint32_t i = 0; i < count; ++i) {
- VkPhysicalDeviceFeatures available_features = {};
- vkGetPhysicalDeviceFeatures(physical_devices[i], &available_features);
+ if (!AreAllRequiredFeaturesSupported(physical_devices[i],
+ required_features)) {
+ continue;
+ }
- if (!AreAllRequiredFeaturesSupported(available_features, required_features))
+ if (!AreAllExtensionsSupported(physical_devices[i], required_extensions)) {
continue;
+ }
if (ChooseQueueFamilyIndex(physical_devices[i])) {
physical_device_ = physical_devices[i];
@@ -555,7 +600,9 @@ Result Device::ChoosePhysicalDevice(
return Result("Vulkan::No physical device supports Vulkan");
}
-Result Device::CreateDevice(const std::vector<Feature>& required_features) {
+Result Device::CreateDevice(
+ const std::vector<Feature>& required_features,
+ const std::vector<std::string>& required_extensions) {
VkDeviceQueueCreateInfo queue_info;
const float priorities[] = {1.0f};
@@ -568,11 +615,17 @@ Result Device::CreateDevice(const std::vector<Feature>& required_features) {
info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
info.pQueueCreateInfos = &queue_info;
info.queueCreateInfoCount = 1;
- // TODO(jaebaek): Enable layers, extensions
+ // TODO(jaebaek): Enable layers
VkPhysicalDeviceFeatures requested_features =
RequestedFeatures(required_features);
info.pEnabledFeatures = &requested_features;
+ std::vector<const char*> enabled_extensions;
+ for (size_t i = 0; i < required_extensions.size(); ++i)
+ enabled_extensions.push_back(required_extensions[i].c_str());
+ info.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions.size());
+ info.ppEnabledExtensionNames = enabled_extensions.data();
+
if (vkCreateDevice(physical_device_, &info, nullptr, &device_) != VK_SUCCESS)
return Result("Vulkan::Calling vkCreateDevice Fail");
diff --git a/src/vulkan/device.h b/src/vulkan/device.h
index f636701..07eb709 100644
--- a/src/vulkan/device.h
+++ b/src/vulkan/device.h
@@ -16,6 +16,7 @@
#define SRC_VULKAN_DEVICE_H_
#include <memory>
+#include <string>
#include <vector>
#include "amber/result.h"
@@ -32,7 +33,8 @@ class Device {
explicit Device(VkDevice device);
~Device();
- Result Initialize(const std::vector<Feature>& required_features);
+ Result Initialize(const std::vector<Feature>& required_features,
+ const std::vector<std::string>& required_extensions);
void Shutdown();
VkDevice GetDevice() const { return device_; }
@@ -46,8 +48,10 @@ class Device {
Result CreateInstance();
// Get a physical device by checking if the physical device has a proper
- // queue family.
- Result ChoosePhysicalDevice(const std::vector<Feature>& required_features);
+ // queue family, required features, and required extensions.
+ Result ChoosePhysicalDevice(
+ const std::vector<Feature>& required_features,
+ const std::vector<std::string>& required_extensions);
// Return true if |physical_device| has a queue family that supports both
// graphics and compute or only a compute pipeline. If the proper queue
@@ -56,8 +60,10 @@ class Device {
// queue family does not exist.
bool ChooseQueueFamilyIndex(const VkPhysicalDevice& physical_device);
- // Create a logical device.
- Result CreateDevice(const std::vector<Feature>& required_features);
+ // Create a logical device with enabled features |required_features|
+ // and enabled extensions|required_extensions|.
+ Result CreateDevice(const std::vector<Feature>& required_features,
+ const std::vector<std::string>& required_extensions);
VkInstance instance_ = VK_NULL_HANDLE;
VkPhysicalDevice physical_device_ = VK_NULL_HANDLE;
diff --git a/src/vulkan/engine_vulkan.cc b/src/vulkan/engine_vulkan.cc
index 896f648..b517000 100644
--- a/src/vulkan/engine_vulkan.cc
+++ b/src/vulkan/engine_vulkan.cc
@@ -58,8 +58,9 @@ EngineVulkan::EngineVulkan() : Engine() {}
EngineVulkan::~EngineVulkan() = default;
Result EngineVulkan::InitDeviceAndCreateCommand(
- const std::vector<Feature>& features) {
- Result r = device_->Initialize(features);
+ const std::vector<Feature>& features,
+ const std::vector<std::string>& extensions) {
+ Result r = device_->Initialize(features, extensions);
if (!r.IsSuccess())
return r;
@@ -74,17 +75,18 @@ Result EngineVulkan::InitDeviceAndCreateCommand(
}
Result EngineVulkan::Initialize(const std::vector<Feature>& features,
- const std::vector<std::string>&) {
+ const std::vector<std::string>& extensions) {
if (device_)
return Result("Vulkan::Set device_ already exists");
device_ = MakeUnique<Device>();
- return InitDeviceAndCreateCommand(features);
+ return InitDeviceAndCreateCommand(features, extensions);
}
-Result EngineVulkan::InitializeWithConfig(EngineConfig* config,
- const std::vector<Feature>& features,
- const std::vector<std::string>&) {
+Result EngineVulkan::InitializeWithConfig(
+ EngineConfig* config,
+ const std::vector<Feature>& features,
+ const std::vector<std::string>& extensions) {
if (device_)
return Result("Vulkan::Set device_ already exists");
@@ -93,7 +95,7 @@ Result EngineVulkan::InitializeWithConfig(EngineConfig* config,
return Result("Vulkan::InitializeWithConfig device handle is null.");
device_ = MakeUnique<Device>(vk_config->device);
- return InitDeviceAndCreateCommand(features);
+ return InitDeviceAndCreateCommand(features, extensions);
}
Result EngineVulkan::Shutdown() {
diff --git a/src/vulkan/engine_vulkan.h b/src/vulkan/engine_vulkan.h
index 06da9a4..aa06c0c 100644
--- a/src/vulkan/engine_vulkan.h
+++ b/src/vulkan/engine_vulkan.h
@@ -68,7 +68,8 @@ class EngineVulkan : public Engine {
ResourceInfo* info) override;
private:
- Result InitDeviceAndCreateCommand(const std::vector<Feature>& features);
+ Result InitDeviceAndCreateCommand(const std::vector<Feature>& features,
+ const std::vector<std::string>& extensions);
std::vector<VkPipelineShaderStageCreateInfo> GetShaderStageInfo();
diff --git a/tests/cases/compute_in_spirv_generated_by_clspv.amber b/tests/cases/compute_in_spirv_generated_by_clspv.amber
new file mode 100644
index 0000000..fba1eaf
--- /dev/null
+++ b/tests/cases/compute_in_spirv_generated_by_clspv.amber
@@ -0,0 +1,163 @@
+[comment]
+Source code in OpenCL C:
+
+typedef struct { int arr[2]; } S1;
+typedef struct { S1 s1; int a; S1 s2; } S2;
+
+S2 make_s2(int n) {
+ S2 s2;
+ s2.s1.arr[0] = n;
+ s2.s1.arr[1] = n;
+ s2.a = n;
+ s2.s2.arr[0] = n;
+ s2.s2.arr[1] = n;
+ return s2;
+}
+
+S2 choose(int n) {
+ if (n > 0) return make_s2(n - 5);
+ return make_s2(0);
+}
+
+kernel void foo(global S2 *data, int n) {
+ *data = choose(n);
+}
+
+The following SPIR-V code was generated by CLSPV with -cl-opt-disable option.
+GIT_COMMIT = 8638849b2167fcba90dbff0ee4cfe7dbf0380d24
+
+[compute shader spirv]
+; SPIR-V
+; Version: 1.0
+; Generator: Codeplay; 0
+; Bound: 71
+; Schema: 0
+ OpCapability Shader
+ OpCapability VariablePointers
+ OpExtension "SPV_KHR_storage_buffer_storage_class"
+ OpExtension "SPV_KHR_variable_pointers"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %52 "main"
+ OpSource OpenCL_C 120
+ OpDecorate %24 SpecId 0
+ OpDecorate %25 SpecId 1
+ OpDecorate %26 SpecId 2
+ OpMemberDecorate %_struct_4 0 Offset 0
+ OpMemberDecorate %_struct_5 0 Offset 0
+ OpMemberDecorate %_struct_5 1 Offset 8
+ OpMemberDecorate %_struct_5 2 Offset 12
+ OpDecorate %_runtimearr__struct_5 ArrayStride 20
+ OpMemberDecorate %_struct_7 0 Offset 0
+ OpDecorate %_struct_7 Block
+ OpMemberDecorate %_struct_9 0 Offset 0
+ OpDecorate %_struct_9 Block
+ OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
+ OpDecorate %29 DescriptorSet 0
+ OpDecorate %29 Binding 0
+ OpDecorate %30 DescriptorSet 0
+ OpDecorate %30 Binding 1
+ OpDecorate %_arr_uint_uint_2 ArrayStride 4
+ %uint = OpTypeInt 32 0
+ %uint_2 = OpConstant %uint 2
+%_arr_uint_uint_2 = OpTypeArray %uint %uint_2
+ %_struct_4 = OpTypeStruct %_arr_uint_uint_2
+ %_struct_5 = OpTypeStruct %_struct_4 %uint %_struct_4
+%_runtimearr__struct_5 = OpTypeRuntimeArray %_struct_5
+ %_struct_7 = OpTypeStruct %_runtimearr__struct_5
+%_ptr_StorageBuffer__struct_7 = OpTypePointer StorageBuffer %_struct_7
+ %_struct_9 = OpTypeStruct %uint
+%_ptr_StorageBuffer__struct_9 = OpTypePointer StorageBuffer %_struct_9
+ %void = OpTypeVoid
+ %12 = OpTypeFunction %void
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+ %14 = OpTypeFunction %_struct_5 %uint
+ %bool = OpTypeBool
+ %v3uint = OpTypeVector %uint 3
+%_ptr_Private_v3uint = OpTypePointer Private %v3uint
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %20 = OpUndef %_struct_5
+ %false = OpConstantFalse %bool
+ %true = OpConstantTrue %bool
+%uint_4294967291 = OpConstant %uint 4294967291
+ %24 = OpSpecConstant %uint 1
+ %25 = OpSpecConstant %uint 1
+ %26 = OpSpecConstant %uint 1
+%gl_WorkGroupSize = OpSpecConstantComposite %v3uint %24 %25 %26
+ %28 = OpVariable %_ptr_Private_v3uint Private %gl_WorkGroupSize
+ %29 = OpVariable %_ptr_StorageBuffer__struct_7 StorageBuffer
+ %30 = OpVariable %_ptr_StorageBuffer__struct_9 StorageBuffer
+ %31 = OpFunction %_struct_5 Const %14
+ %32 = OpFunctionParameter %uint
+ %33 = OpLabel
+ %34 = OpCompositeConstruct %_arr_uint_uint_2 %32 %32
+ %35 = OpCompositeConstruct %_struct_4 %34
+ %36 = OpCompositeConstruct %_struct_5 %35 %32 %35
+ OpReturnValue %36
+ OpFunctionEnd
+ %37 = OpFunction %_struct_5 Const %14
+ %38 = OpFunctionParameter %uint
+ %39 = OpLabel
+ %40 = OpSGreaterThan %bool %38 %uint_0
+ %41 = OpLogicalNot %bool %40
+ OpSelectionMerge %44 None
+ OpBranchConditional %41 %42 %44
+ %42 = OpLabel
+ %43 = OpFunctionCall %_struct_5 %31 %uint_0
+ OpBranch %44
+ %44 = OpLabel
+ %46 = OpPhi %bool %false %42 %true %39
+ %45 = OpPhi %_struct_5 %43 %42 %20 %39
+ OpSelectionMerge %47 None
+ OpBranchConditional %46 %49 %47
+ %47 = OpLabel
+ %48 = OpPhi %_struct_5 %45 %44 %51 %49
+ OpReturnValue %48
+ %49 = OpLabel
+ %50 = OpIAdd %uint %38 %uint_4294967291
+ %51 = OpFunctionCall %_struct_5 %31 %50
+ OpBranch %47
+ OpFunctionEnd
+ %52 = OpFunction %void None %12
+ %53 = OpLabel
+ %54 = OpAccessChain %_ptr_StorageBuffer_uint %30 %uint_0
+ %55 = OpLoad %uint %54
+ %56 = OpFunctionCall %_struct_5 %37 %55
+ %57 = OpCompositeExtract %_struct_4 %56 0
+ %58 = OpCompositeExtract %_arr_uint_uint_2 %57 0
+ %59 = OpCompositeExtract %uint %58 0
+ %60 = OpCompositeExtract %uint %58 1
+ %61 = OpCompositeExtract %uint %56 1
+ %62 = OpCompositeExtract %_struct_4 %56 2
+ %63 = OpCompositeExtract %_arr_uint_uint_2 %62 0
+ %64 = OpCompositeExtract %uint %63 0
+ %65 = OpCompositeExtract %uint %63 1
+ %66 = OpAccessChain %_ptr_StorageBuffer_uint %29 %uint_0 %uint_0 %uint_0 %uint_0 %uint_0
+ OpStore %66 %59
+ %67 = OpAccessChain %_ptr_StorageBuffer_uint %29 %uint_0 %uint_0 %uint_0 %uint_0 %uint_1
+ OpStore %67 %60
+ %68 = OpAccessChain %_ptr_StorageBuffer_uint %29 %uint_0 %uint_0 %uint_1
+ OpStore %68 %61
+ %69 = OpAccessChain %_ptr_StorageBuffer_uint %29 %uint_0 %uint_0 %uint_2 %uint_0 %uint_0
+ OpStore %69 %64
+ %70 = OpAccessChain %_ptr_StorageBuffer_uint %29 %uint_0 %uint_0 %uint_2 %uint_0 %uint_1
+ OpStore %70 %65
+ OpReturn
+ OpFunctionEnd
+[require]
+VK_KHR_storage_buffer_storage_class
+VK_KHR_variable_pointers
+
+[test]
+# ssbo [bind] subdata [type] [offset] [values ...]
+ssbo 0 subdata int 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ssbo 1 subdata int 0 13
+
+compute 3 1 1
+
+# probe ssbo [type] [bind] [offset] == [values ...]
+probe ssbo int 0 0 == 8
+probe ssbo int 0 4 == 8
+probe ssbo int 0 8 == 8
+probe ssbo int 0 12 == 8
+probe ssbo int 0 16 == 8