aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaebaek Seo <duke.acacia@gmail.com>2018-12-01 23:47:57 -0500
committerDavid Neto <dneto@google.com>2018-12-01 23:47:57 -0500
commitc244ec886ce0775f92664e89b285b6bdae44a593 (patch)
treeb0b7985f670075674d32a7e38505e8186803cefd
parentdf01fbd43429ab383525b72882ee907ef4b46340 (diff)
downloadamber-c244ec886ce0775f92664e89b285b6bdae44a593.tar.gz
Vulkan: handle probe ssbo command (#101)
Vulkan: handle probe ssbo command Related to #32
-rw-r--r--src/dawn/find_dawn.cmake3
-rw-r--r--src/vulkan/buffer.cc55
-rw-r--r--src/vulkan/buffer.h23
-rw-r--r--src/vulkan/compute_pipeline.cc2
-rw-r--r--src/vulkan/descriptor.h5
-rw-r--r--src/vulkan/engine_vulkan.cc14
-rw-r--r--src/vulkan/frame_buffer.h4
-rw-r--r--src/vulkan/graphics_pipeline.cc2
-rw-r--r--src/vulkan/image.cc8
-rw-r--r--src/vulkan/image.h12
-rw-r--r--src/vulkan/pipeline.cc42
-rw-r--r--src/vulkan/pipeline.h12
-rw-r--r--src/vulkan/resource.cc8
-rw-r--r--src/vulkan/resource.h17
-rw-r--r--src/vulkan/storage_buffer_descriptor.cc17
-rw-r--r--src/vulkan/storage_buffer_descriptor.h5
-rw-r--r--tests/cases/compute_ssbo.amber54
17 files changed, 242 insertions, 41 deletions
diff --git a/src/dawn/find_dawn.cmake b/src/dawn/find_dawn.cmake
index 5222408..40d4158 100644
--- a/src/dawn/find_dawn.cmake
+++ b/src/dawn/find_dawn.cmake
@@ -39,7 +39,8 @@ set(Dawn_FOUND FALSE)
#
# -DDawn_INCLUDE_DIR=<directory containing dawn/dawn_export.h>
# -DDawn_GEN_INCLUDE_DIR=<directory containing dawn/dawn.h>
-# -DDawn_LIBRARY_DIR=<directory containing dawn_native>
+# -DDawn_LIBRARY_DIR=<directory containing dawn_native library
+# e.g., libdawn_native.a>
find_path(Dawn_INCLUDE_DIR
diff --git a/src/vulkan/buffer.cc b/src/vulkan/buffer.cc
index d71d4bb..bb4ac0b 100644
--- a/src/vulkan/buffer.cc
+++ b/src/vulkan/buffer.cc
@@ -34,8 +34,10 @@ Result Buffer::Initialize(const VkBufferUsageFlags usage) {
if (!allocate_result.r.IsSuccess())
return allocate_result.r;
- if (CheckMemoryHostAccessible(allocate_result.memory_type_index)) {
+ if (IsMemoryHostAccessible(allocate_result.memory_type_index)) {
is_buffer_host_accessible_ = true;
+ is_buffer_host_coherent_ =
+ IsMemoryHostCoherent(allocate_result.memory_type_index);
return MapMemory(memory_);
}
@@ -58,17 +60,32 @@ Result Buffer::CreateVkBufferView(VkFormat format) {
return {};
}
-void Buffer::CopyToDevice(VkCommandBuffer command) {
+Result Buffer::CopyToDevice(VkCommandBuffer command) {
if (is_buffer_host_accessible_)
- return;
+ return FlushMemoryIfNeeded();
VkBufferCopy region = {};
region.srcOffset = 0;
region.dstOffset = 0;
- region.size = GetSize();
+ region.size = GetSizeInBytes();
vkCmdCopyBuffer(command, GetHostAccessibleBuffer(), buffer_, 1, &region);
MemoryBarrier(command);
+ return {};
+}
+
+Result Buffer::CopyToHost(VkCommandBuffer command) {
+ if (is_buffer_host_accessible_)
+ return InvalidateMemoryIfNeeded();
+
+ VkBufferCopy region = {};
+ region.srcOffset = 0;
+ region.dstOffset = 0;
+ region.size = GetSizeInBytes();
+
+ vkCmdCopyBuffer(command, buffer_, GetHostAccessibleBuffer(), 1, &region);
+ MemoryBarrier(command);
+ return {};
}
void Buffer::Shutdown() {
@@ -90,5 +107,35 @@ void Buffer::Shutdown() {
}
}
+Result Buffer::InvalidateMemoryIfNeeded() {
+ if (is_buffer_host_coherent_)
+ return {};
+
+ VkMappedMemoryRange range = {};
+ range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
+ range.memory = GetHostAccessMemory();
+ range.offset = 0;
+ range.size = VK_WHOLE_SIZE;
+ if (vkInvalidateMappedMemoryRanges(GetDevice(), 1, &range) != VK_SUCCESS)
+ return Result("Vulkan: vkInvalidateMappedMemoryRanges fail");
+
+ return {};
+}
+
+Result Buffer::FlushMemoryIfNeeded() {
+ if (is_buffer_host_coherent_)
+ return {};
+
+ VkMappedMemoryRange range = {};
+ range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
+ range.memory = GetHostAccessMemory();
+ range.offset = 0;
+ range.size = VK_WHOLE_SIZE;
+ if (vkFlushMappedMemoryRanges(GetDevice(), 1, &range) != VK_SUCCESS)
+ return Result("Vulkan: vkFlushMappedMemoryRanges fail");
+
+ return {};
+}
+
} // namespace vulkan
} // namespace amber
diff --git a/src/vulkan/buffer.h b/src/vulkan/buffer.h
index 9ec1dd2..f88d9e1 100644
--- a/src/vulkan/buffer.h
+++ b/src/vulkan/buffer.h
@@ -34,8 +34,14 @@ class Buffer : public Resource {
Result CreateVkBufferView(VkFormat format);
VkBufferView GetVkBufferView() const { return view_; }
- // TODO(jaebaek): Determine copy all or partial data
- void CopyToDevice(VkCommandBuffer command);
+ // If this buffer is host accessible and has coherent memory, this
+ // method does nothing. If this buffer is host accessible but it does
+ // not have coherent memory, this method flush the memory to make the
+ // writes from host effective to device. Otherwise, this method records
+ // the command for copying the secondary host-accessible buffer to
+ // this device local buffer. Note that it only records the command and
+ // the actual submission must be done later.
+ Result CopyToDevice(VkCommandBuffer command);
// Resource
VkDeviceMemory GetHostAccessMemory() const override {
@@ -45,13 +51,26 @@ class Buffer : public Resource {
return Resource::GetHostAccessMemory();
}
+ // If this buffer is host accessible and has coherent memory, this
+ // method does nothing. If this buffer is host accessible but it does
+ // not have coherent memory, this method invalidate the memory to make the
+ // writes from device visible to host. Otherwise, this method records
+ // the command for copying this buffer to its secondary host-accessible
+ // buffer. Note that it only records the command and the actual
+ // submission must be done later.
+ Result CopyToHost(VkCommandBuffer command) override;
+
void Shutdown() override;
private:
+ Result InvalidateMemoryIfNeeded();
+ Result FlushMemoryIfNeeded();
+
VkBuffer buffer_ = VK_NULL_HANDLE;
VkBufferView view_ = VK_NULL_HANDLE;
VkDeviceMemory memory_ = VK_NULL_HANDLE;
bool is_buffer_host_accessible_ = false;
+ bool is_buffer_host_coherent_ = false;
};
} // namespace vulkan
diff --git a/src/vulkan/compute_pipeline.cc b/src/vulkan/compute_pipeline.cc
index a4f94f6..4f6f61a 100644
--- a/src/vulkan/compute_pipeline.cc
+++ b/src/vulkan/compute_pipeline.cc
@@ -70,7 +70,7 @@ Result ComputePipeline::Compute(uint32_t x, uint32_t y, uint32_t z) {
if (!r.IsSuccess())
return r;
- r = SendDescriptorDataToGPUIfNeeded();
+ r = SendDescriptorDataToDeviceIfNeeded();
if (!r.IsSuccess())
return r;
diff --git a/src/vulkan/descriptor.h b/src/vulkan/descriptor.h
index eb70001..0cf38b0 100644
--- a/src/vulkan/descriptor.h
+++ b/src/vulkan/descriptor.h
@@ -18,6 +18,7 @@
#include <memory>
#include "amber/result.h"
+#include "src/engine.h"
#include "vulkan/vulkan.h"
namespace amber {
@@ -86,7 +87,9 @@ class Descriptor {
bool IsDataAlreadySent() { return is_data_already_sent_; }
virtual Result UpdateDescriptorSet(VkDescriptorSet descriptor_set) = 0;
- virtual void SendDataToGPUIfNeeded(VkCommandBuffer command) = 0;
+ virtual void SendDataToDeviceIfNeeded(VkCommandBuffer command) = 0;
+ virtual Result SendDataToHostIfNeeded(VkCommandBuffer command) = 0;
+ virtual ResourceInfo GetResourceInfo() = 0;
virtual void Shutdown() = 0;
protected:
diff --git a/src/vulkan/engine_vulkan.cc b/src/vulkan/engine_vulkan.cc
index bdcd786..d546761 100644
--- a/src/vulkan/engine_vulkan.cc
+++ b/src/vulkan/engine_vulkan.cc
@@ -297,10 +297,16 @@ Result EngineVulkan::GetFrameBufferInfo(ResourceInfo* info) {
return {};
}
-Result EngineVulkan::GetDescriptorInfo(const uint32_t,
- const uint32_t,
- ResourceInfo*) {
- return Result("EngineVulkan::GetDescriptorInfo not implemented");
+Result EngineVulkan::GetDescriptorInfo(const uint32_t descriptor_set,
+ const uint32_t binding,
+ ResourceInfo* info) {
+ assert(info);
+ Result r = pipeline_->CopyDescriptorToHost(descriptor_set, binding);
+ if (!r.IsSuccess())
+ return r;
+
+ pipeline_->GetDescriptorInfo(descriptor_set, binding, info);
+ return {};
}
Result EngineVulkan::DoBuffer(const BufferCommand* command) {
diff --git a/src/vulkan/frame_buffer.h b/src/vulkan/frame_buffer.h
index bfee4c3..7e3a214 100644
--- a/src/vulkan/frame_buffer.h
+++ b/src/vulkan/frame_buffer.h
@@ -47,6 +47,10 @@ class FrameBuffer {
return color_image_->HostAccessibleMemoryPtr();
}
VkImage GetColorImage() const { return color_image_->GetVkImage(); }
+
+ // Only record the command for copying the image that backs this
+ // framebuffer to the host accessible buffer. The actual submission
+ // of the command must be done later.
Result CopyColorImageToHost(VkCommandBuffer command) {
ChangeFrameImageLayout(command, FrameImageState::kProbe);
return color_image_->CopyToHost(command);
diff --git a/src/vulkan/graphics_pipeline.cc b/src/vulkan/graphics_pipeline.cc
index c9c9eed..1c182be 100644
--- a/src/vulkan/graphics_pipeline.cc
+++ b/src/vulkan/graphics_pipeline.cc
@@ -481,7 +481,7 @@ Result GraphicsPipeline::Draw(const DrawArraysCommand* command) {
if (!r.IsSuccess())
return r;
- r = SendDescriptorDataToGPUIfNeeded();
+ r = SendDescriptorDataToDeviceIfNeeded();
if (!r.IsSuccess())
return r;
diff --git a/src/vulkan/image.cc b/src/vulkan/image.cc
index 0e0f588..87f9c05 100644
--- a/src/vulkan/image.cc
+++ b/src/vulkan/image.cc
@@ -79,7 +79,6 @@ Result Image::Initialize(VkImageUsageFlags usage) {
// is optimal, read/write data from CPU does not show correct values. We need
// a secondary buffer to convert the GPU-optimial data to CPU-readable data
// and vice versa.
- is_image_host_accessible_ = false;
return Resource::Initialize();
}
@@ -123,9 +122,6 @@ void Image::Shutdown() {
}
Result Image::CopyToHost(VkCommandBuffer command) {
- if (is_image_host_accessible_)
- return {};
-
VkBufferImageCopy copy_region = {};
copy_region.bufferOffset = 0;
copy_region.bufferRowLength = 0;
@@ -206,10 +202,6 @@ void Image::ChangeLayout(VkCommandBuffer command,
break;
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
- // An image becomes "host readable transfer src" only when we directly
- // probe it from CPU.
- if (is_image_host_accessible_)
- barrier.dstAccessMask |= VK_ACCESS_HOST_READ_BIT;
break;
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
// An image becomes "transfer dst" only when we send a buffer data to
diff --git a/src/vulkan/image.h b/src/vulkan/image.h
index 36186a2..4668f71 100644
--- a/src/vulkan/image.h
+++ b/src/vulkan/image.h
@@ -36,9 +36,6 @@ class Image : public Resource {
VkImage GetVkImage() const { return image_; }
VkImageView GetVkImageView() const { return view_; }
- // TODO(jaebaek): Determine copy all or partial data
- Result CopyToHost(VkCommandBuffer command);
-
// TODO(jaebaek): Implement CopyToDevice
void ChangeLayout(VkCommandBuffer command,
@@ -49,12 +46,14 @@ class Image : public Resource {
// Resource
VkDeviceMemory GetHostAccessMemory() const override {
- if (is_image_host_accessible_)
- return memory_;
-
return Resource::GetHostAccessMemory();
}
+ // Only record the command for copying this image to its secondary
+ // host-accessible buffer. The actual submission of the command
+ // must be done later.
+ Result CopyToHost(VkCommandBuffer command) override;
+
void Shutdown() override;
private:
@@ -65,7 +64,6 @@ class Image : public Resource {
VkImage image_ = VK_NULL_HANDLE;
VkImageView view_ = VK_NULL_HANDLE;
VkDeviceMemory memory_ = VK_NULL_HANDLE;
- bool is_image_host_accessible_ = false;
};
} // namespace vulkan
diff --git a/src/vulkan/pipeline.cc b/src/vulkan/pipeline.cc
index 5050ea0..89d357a 100644
--- a/src/vulkan/pipeline.cc
+++ b/src/vulkan/pipeline.cc
@@ -15,10 +15,12 @@
#include "src/vulkan/pipeline.h"
#include <algorithm>
+#include <cassert>
#include <limits>
#include <utility>
#include "src/command.h"
+#include "src/engine.h"
#include "src/make_unique.h"
#include "src/vulkan/compute_pipeline.h"
#include "src/vulkan/graphics_pipeline.h"
@@ -247,7 +249,7 @@ Result Pipeline::AddDescriptor(const BufferCommand* buffer_command) {
return {};
}
-Result Pipeline::SendDescriptorDataToGPUIfNeeded() {
+Result Pipeline::SendDescriptorDataToDeviceIfNeeded() {
if (descriptors_.size() == 0)
return {};
@@ -267,7 +269,7 @@ Result Pipeline::SendDescriptorDataToGPUIfNeeded() {
return r;
for (const auto& desc : descriptors_)
- desc->SendDataToGPUIfNeeded(command_->GetCommandBuffer());
+ desc->SendDataToDeviceIfNeeded(command_->GetCommandBuffer());
return {};
}
@@ -287,5 +289,41 @@ void Pipeline::BindVkPipeline() {
pipeline_);
}
+Result Pipeline::CopyDescriptorToHost(const uint32_t descriptor_set,
+ const uint32_t binding) {
+ Result r = command_->BeginIfNotInRecording();
+ if (!r.IsSuccess())
+ return r;
+
+ for (size_t i = 0; i < descriptors_.size(); ++i) {
+ if (descriptors_[i]->GetDescriptorSet() == descriptor_set &&
+ descriptors_[i]->GetBinding() == binding) {
+ return descriptors_[i]->SendDataToHostIfNeeded(
+ command_->GetCommandBuffer());
+ }
+ }
+
+ return Result("Vulkan::Pipeline descriptor with descriptor set: " +
+ std::to_string(descriptor_set) +
+ ", binding: " + std::to_string(binding) + " does not exist");
+}
+
+Result Pipeline::GetDescriptorInfo(const uint32_t descriptor_set,
+ const uint32_t binding,
+ ResourceInfo* info) {
+ assert(info);
+ for (size_t i = 0; i < descriptors_.size(); ++i) {
+ if (descriptors_[i]->GetDescriptorSet() == descriptor_set &&
+ descriptors_[i]->GetBinding() == binding) {
+ *info = descriptors_[i]->GetResourceInfo();
+ return {};
+ }
+ }
+
+ return Result("Vulkan::Pipeline descriptor with descriptor set: " +
+ std::to_string(descriptor_set) +
+ ", binding: " + std::to_string(binding) + " does not exist");
+}
+
} // namespace vulkan
} // namespace amber
diff --git a/src/vulkan/pipeline.h b/src/vulkan/pipeline.h
index 8b56391..a20ec5d 100644
--- a/src/vulkan/pipeline.h
+++ b/src/vulkan/pipeline.h
@@ -45,6 +45,16 @@ class Pipeline {
Result AddDescriptor(const BufferCommand*);
+ // Copy the contents of the resource bound to the given descriptor
+ // to host memory.
+ Result CopyDescriptorToHost(const uint32_t descriptor_set,
+ const uint32_t binding);
+
+ // Get the information of the resource bound to the given descriptor.
+ Result GetDescriptorInfo(const uint32_t descriptor_set,
+ const uint32_t binding,
+ ResourceInfo* info);
+
virtual void Shutdown();
virtual Result ProcessCommands() = 0;
@@ -58,7 +68,7 @@ class Pipeline {
Result InitializeCommandBuffer(VkCommandPool pool, VkQueue queue);
Result CreateVkDescriptorRelatedObjects();
- Result SendDescriptorDataToGPUIfNeeded();
+ Result SendDescriptorDataToDeviceIfNeeded();
void BindVkPipeline();
void BindVkDescriptorSets();
diff --git a/src/vulkan/resource.cc b/src/vulkan/resource.cc
index 5916c28..c5f02c2 100644
--- a/src/vulkan/resource.cc
+++ b/src/vulkan/resource.cc
@@ -47,9 +47,11 @@ VkMemoryBarrier kMemoryBarrierForAll = {
} // namespace
Resource::Resource(VkDevice device,
- size_t size,
+ size_t size_in_bytes,
const VkPhysicalDeviceMemoryProperties& properties)
- : device_(device), size_(size), physical_memory_properties_(properties) {}
+ : device_(device),
+ size_in_bytes_(size_in_bytes),
+ physical_memory_properties_(properties) {}
Resource::~Resource() = default;
@@ -84,7 +86,7 @@ Result Resource::CreateVkBuffer(VkBuffer* buffer, VkBufferUsageFlags usage) {
VkBufferCreateInfo buffer_info = {};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- buffer_info.size = size_;
+ buffer_info.size = size_in_bytes_;
buffer_info.usage = usage;
if (vkCreateBuffer(device_, &buffer_info, nullptr, buffer) != VK_SUCCESS)
diff --git a/src/vulkan/resource.h b/src/vulkan/resource.h
index 9bb763c..7243f8b 100644
--- a/src/vulkan/resource.h
+++ b/src/vulkan/resource.h
@@ -31,10 +31,14 @@ class Resource {
return host_accessible_memory_;
}
+ virtual Result CopyToHost(VkCommandBuffer command) = 0;
+
virtual void Shutdown();
void* HostAccessibleMemoryPtr() const { return memory_ptr_; }
+ size_t GetSizeInBytes() const { return size_in_bytes_; }
+
protected:
Resource(VkDevice device,
size_t size,
@@ -45,8 +49,6 @@ class Resource {
VkDevice GetDevice() const { return device_; }
VkBuffer GetHostAccessibleBuffer() const { return host_accessible_buffer_; }
- size_t GetSize() const { return size_; }
-
struct AllocateResult {
Result r;
uint32_t memory_type_index;
@@ -61,13 +63,20 @@ class Resource {
VkMemoryPropertyFlags flags,
bool force_flags);
- bool CheckMemoryHostAccessible(uint32_t memory_type_index) {
+ bool IsMemoryHostAccessible(uint32_t memory_type_index) {
return (physical_memory_properties_.memoryTypes[memory_type_index]
.propertyFlags &
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ==
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
}
+ bool IsMemoryHostCoherent(uint32_t memory_type_index) {
+ return (physical_memory_properties_.memoryTypes[memory_type_index]
+ .propertyFlags &
+ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) ==
+ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ }
+
Result MapMemory(VkDeviceMemory memory);
void UnMapMemory(VkDeviceMemory memory);
@@ -91,7 +100,7 @@ class Resource {
const VkMemoryRequirements GetVkImageMemoryRequirements(VkImage image) const;
VkDevice device_ = VK_NULL_HANDLE;
- size_t size_ = 0;
+ size_t size_in_bytes_ = 0;
VkPhysicalDeviceMemoryProperties physical_memory_properties_;
VkBuffer host_accessible_buffer_ = VK_NULL_HANDLE;
diff --git a/src/vulkan/storage_buffer_descriptor.cc b/src/vulkan/storage_buffer_descriptor.cc
index 3202bae..f8a7c15 100644
--- a/src/vulkan/storage_buffer_descriptor.cc
+++ b/src/vulkan/storage_buffer_descriptor.cc
@@ -16,6 +16,7 @@
#include <vector>
+#include "src/engine.h"
#include "src/make_unique.h"
namespace amber {
@@ -98,7 +99,8 @@ Result StorageBufferDescriptor::Initialize(DataType type,
return {};
}
-void StorageBufferDescriptor::SendDataToGPUIfNeeded(VkCommandBuffer command) {
+void StorageBufferDescriptor::SendDataToDeviceIfNeeded(
+ VkCommandBuffer command) {
// TODO(jaebaek): VkRunner script allows data updating after initialiation.
// Support updating data.
if (IsDataAlreadySent())
@@ -108,6 +110,11 @@ void StorageBufferDescriptor::SendDataToGPUIfNeeded(VkCommandBuffer command) {
SetDataSent();
}
+Result StorageBufferDescriptor::SendDataToHostIfNeeded(
+ VkCommandBuffer command) {
+ return buffer_->CopyToHost(command);
+}
+
Result StorageBufferDescriptor::UpdateDescriptorSet(
VkDescriptorSet descriptor_set) {
VkDescriptorBufferInfo buffer_info = {};
@@ -119,6 +126,14 @@ Result StorageBufferDescriptor::UpdateDescriptorSet(
descriptor_set, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, buffer_info);
}
+ResourceInfo StorageBufferDescriptor::GetResourceInfo() {
+ ResourceInfo info = {};
+ info.type = ResourceInfoType::kBuffer;
+ info.size_in_bytes = buffer_->GetSizeInBytes();
+ info.cpu_memory = buffer_->HostAccessibleMemoryPtr();
+ return info;
+}
+
void StorageBufferDescriptor::Shutdown() {
buffer_->Shutdown();
}
diff --git a/src/vulkan/storage_buffer_descriptor.h b/src/vulkan/storage_buffer_descriptor.h
index e8af632..a30bcd5 100644
--- a/src/vulkan/storage_buffer_descriptor.h
+++ b/src/vulkan/storage_buffer_descriptor.h
@@ -20,6 +20,7 @@
#include "amber/result.h"
#include "src/datum_type.h"
+#include "src/engine.h"
#include "src/value.h"
#include "src/vulkan/buffer.h"
#include "src/vulkan/descriptor.h"
@@ -40,8 +41,10 @@ class StorageBufferDescriptor : public Descriptor {
Result Initialize(DataType type, const std::vector<Value>& values);
// Descriptor
- void SendDataToGPUIfNeeded(VkCommandBuffer command) override;
+ void SendDataToDeviceIfNeeded(VkCommandBuffer command) override;
+ Result SendDataToHostIfNeeded(VkCommandBuffer command) override;
Result UpdateDescriptorSet(VkDescriptorSet descriptor_set) override;
+ ResourceInfo GetResourceInfo() override;
void Shutdown() override;
private:
diff --git a/tests/cases/compute_ssbo.amber b/tests/cases/compute_ssbo.amber
new file mode 100644
index 0000000..24b112c
--- /dev/null
+++ b/tests/cases/compute_ssbo.amber
@@ -0,0 +1,54 @@
+# Copyright 2018 The Amber Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+[compute shader]
+#version 430
+
+layout(set = 0, binding = 0) buffer block0 {
+ float data_set0_binding0[3];
+};
+
+layout(set = 1, binding = 2) buffer block1 {
+ float data_set1_binding2[3];
+};
+
+layout(set = 2, binding = 1) buffer block2 {
+ float data_set2_binding1[3];
+};
+
+layout(set = 2, binding = 3) buffer block3 {
+ float data_set2_binding3[3];
+};
+
+void main() {
+ const uint index = gl_WorkGroupID.x;
+ data_set0_binding0[index] = data_set0_binding0[index] + 1.0f;
+ data_set1_binding2[index] = data_set2_binding1[index] -
+ data_set1_binding2[index];
+ data_set2_binding1[index] = 10.0f * data_set2_binding3[index] +
+ data_set2_binding1[index];
+ data_set2_binding3[index] = 30.0f * data_set2_binding3[index];
+}
+
+[test]
+ssbo 0:0 subdata vec3 0 1.0 2.0 3.0
+ssbo 1:2 subdata vec3 0 4.0 5.0 6.0
+ssbo 2:1 subdata vec3 0 21.0 22.0 23.0
+ssbo 2:3 subdata vec3 0 0.7 0.8 0.9
+compute 3 1 1
+
+probe ssbo vec3 0:0 0 ~= 2.0 3.0 4.0
+probe ssbo vec3 1:2 0 ~= 17.0 17.0 17.0
+probe ssbo vec3 2:1 0 ~= 28.0 30.0 32.0
+probe ssbo vec3 2:3 0 ~= 21.0 24.0 27.0