aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorasuonpaa <34128694+asuonpaa@users.noreply.github.com>2021-01-27 16:10:05 +0200
committerGitHub <noreply@github.com>2021-01-27 14:10:05 +0000
commitcbecdfcfccc9b5d04601b48c9d244fd5e3a434b0 (patch)
tree35c3753fd76d9549d0a073a33ef6091f052161b0
parentaee124f78b78101b62a2371f57216bf91ab8561f (diff)
downloadamber-cbecdfcfccc9b5d04601b48c9d244fd5e3a434b0.tar.gz
Support binding the same vertex buffer to multiple locations (#936)
There's no need to restrict binding a vertex buffer to multiple locations. Now that we have OFFSET supported this has a real use case where the same buffer is used with different offsets.
-rw-r--r--src/amberscript/parser_bind_test.cc24
-rw-r--r--src/pipeline.cc2
-rw-r--r--src/vulkan/vertex_buffer.cc19
-rw-r--r--src/vulkan/vertex_buffer.h2
-rw-r--r--tests/cases/vertex_data_two_locations.amber84
5 files changed, 119 insertions, 12 deletions
diff --git a/src/amberscript/parser_bind_test.cc b/src/amberscript/parser_bind_test.cc
index 64e6692..64f3948 100644
--- a/src/amberscript/parser_bind_test.cc
+++ b/src/amberscript/parser_bind_test.cc
@@ -731,14 +731,30 @@ PIPELINE graphics my_pipeline
ATTACH my_fragment
VERTEX_DATA my_buf LOCATION 0
- VERTEX_DATA my_buf LOCATION 1
+ VERTEX_DATA my_buf LOCATION 1 OFFSET 10
END)";
Parser parser;
Result r = parser.Parse(in);
- ASSERT_FALSE(r.IsSuccess());
- EXPECT_EQ("13: vertex buffer may only be bound to a PIPELINE once",
- r.Error());
+ ASSERT_TRUE(r.IsSuccess());
+
+ auto script = parser.GetScript();
+ const auto& pipelines = script->GetPipelines();
+ ASSERT_EQ(1U, pipelines.size());
+
+ const auto* pipeline = pipelines[0].get();
+ const auto& vertex_buffers = pipeline->GetVertexBuffers();
+ ASSERT_EQ(2u, vertex_buffers.size());
+
+ const auto& info1 = vertex_buffers[0];
+ ASSERT_TRUE(info1.buffer != nullptr);
+ EXPECT_EQ(0u, info1.location);
+ EXPECT_EQ(0u, info1.offset);
+
+ const auto& info2 = vertex_buffers[1];
+ ASSERT_TRUE(info2.buffer != nullptr);
+ EXPECT_EQ(1u, info2.location);
+ EXPECT_EQ(10u, info2.offset);
}
TEST_F(AmberScriptParserTest, BindVertexDataMissingBuffer) {
diff --git a/src/pipeline.cc b/src/pipeline.cc
index ca1a561..55c6bae 100644
--- a/src/pipeline.cc
+++ b/src/pipeline.cc
@@ -430,8 +430,6 @@ Result Pipeline::AddVertexBuffer(Buffer* buf,
for (const auto& vtex : vertex_buffers_) {
if (vtex.location == location)
return Result("can not bind two vertex buffers to the same LOCATION");
- if (vtex.buffer == buf)
- return Result("vertex buffer may only be bound to a PIPELINE once");
}
vertex_buffers_.push_back(BufferInfo{buf});
diff --git a/src/vulkan/vertex_buffer.cc b/src/vulkan/vertex_buffer.cc
index ea7e5eb..7503681 100644
--- a/src/vulkan/vertex_buffer.cc
+++ b/src/vulkan/vertex_buffer.cc
@@ -61,23 +61,28 @@ void VertexBuffer::BindToCommandBuffer(CommandBuffer* command) {
std::vector<VkBuffer> buffers;
std::vector<VkDeviceSize> offsets;
- for (const auto& buf : transfer_buffers_) {
- buffers.push_back(buf->GetVkBuffer());
+ for (const auto& buf : data_) {
+ buffers.push_back(buffer_to_vk_buffer_[buf]);
offsets.push_back(0);
}
device_->GetPtrs()->vkCmdBindVertexBuffers(
- command->GetVkCommandBuffer(), 0,
- static_cast<uint32_t>(transfer_buffers_.size()), buffers.data(),
- offsets.data());
+ command->GetVkCommandBuffer(), 0, static_cast<uint32_t>(buffers.size()),
+ buffers.data(), offsets.data());
}
Result VertexBuffer::SendVertexData(CommandBuffer* command) {
if (!is_vertex_data_pending_)
return Result("Vulkan::Vertices data was already sent");
+ buffer_to_vk_buffer_.clear();
+
for (const auto& buf : data_) {
- uint32_t bytes = buf->GetSizeInBytes();
+ if (buffer_to_vk_buffer_.count(buf) != 0) {
+ continue;
+ }
+ // Create a new transfer buffer to hold vertex data.
+ uint32_t bytes = buf->GetSizeInBytes();
transfer_buffers_.push_back(
MakeUnique<TransferBuffer>(device_, bytes, nullptr));
Result r = transfer_buffers_.back()->Initialize(
@@ -89,6 +94,8 @@ Result VertexBuffer::SendVertexData(CommandBuffer* command) {
if (!r.IsSuccess())
return r;
+
+ buffer_to_vk_buffer_[buf] = transfer_buffers_.back()->GetVkBuffer();
}
is_vertex_data_pending_ = false;
diff --git a/src/vulkan/vertex_buffer.h b/src/vulkan/vertex_buffer.h
index 4c49e46..871a9cc 100644
--- a/src/vulkan/vertex_buffer.h
+++ b/src/vulkan/vertex_buffer.h
@@ -15,6 +15,7 @@
#ifndef SRC_VULKAN_VERTEX_BUFFER_H_
#define SRC_VULKAN_VERTEX_BUFFER_H_
+#include <map>
#include <memory>
#include <vector>
@@ -68,6 +69,7 @@ class VertexBuffer {
std::vector<Buffer*> data_;
std::vector<VkVertexInputBindingDescription> vertex_binding_desc_;
std::vector<VkVertexInputAttributeDescription> vertex_attr_desc_;
+ std::map<Buffer*, VkBuffer> buffer_to_vk_buffer_;
};
} // namespace vulkan
diff --git a/tests/cases/vertex_data_two_locations.amber b/tests/cases/vertex_data_two_locations.amber
new file mode 100644
index 0000000..a9a4491
--- /dev/null
+++ b/tests/cases/vertex_data_two_locations.amber
@@ -0,0 +1,84 @@
+#!amber
+# Copyright 2021 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.
+
+SHADER vertex vtex_shader GLSL
+#version 430
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec4 vert_color0;
+layout(location = 2) in vec4 vert_color1;
+layout(location = 0) out vec4 frag_color;
+
+void main()
+{
+ gl_Position = position;
+ frag_color = vert_color0 + vert_color1;
+}
+END
+
+SHADER fragment frag_shader GLSL
+#version 430
+
+layout(location = 0) in vec4 frag_color;
+layout(location = 0) out vec4 final_color;
+
+void main()
+{
+ final_color = frag_color;
+}
+END
+
+BUFFER position_buf DATA_TYPE R8G8_SNORM DATA
+-128 -128
+ 127 127
+-128 127
+-128 -128
+ 127 127
+ 127 -128
+END
+
+BUFFER vert_color DATA_TYPE R8G8B8A8_UNORM DATA
+255 0 0 255
+255 0 0 255
+255 0 0 255
+255 0 0 255
+255 0 0 255
+255 0 0 255
+
+ 0 255 0 255
+ 0 255 0 255
+ 0 255 0 255
+ 0 255 0 255
+ 0 255 0 255
+ 0 255 0 255
+END
+
+BUFFER framebuffer FORMAT B8G8R8A8_UNORM
+
+PIPELINE graphics pipeline
+ ATTACH vtex_shader
+ ATTACH frag_shader
+
+ VERTEX_DATA position_buf LOCATION 0
+ VERTEX_DATA vert_color LOCATION 1
+ VERTEX_DATA vert_color LOCATION 2 OFFSET 24
+
+ BIND BUFFER framebuffer AS color LOCATION 0
+END
+
+CLEAR pipeline
+
+RUN pipeline DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 6
+EXPECT framebuffer IDX 0 0 SIZE 250 250 EQ_RGBA 255 255 0 255