diff options
author | asuonpaa <34128694+asuonpaa@users.noreply.github.com> | 2021-01-27 16:10:05 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-27 14:10:05 +0000 |
commit | cbecdfcfccc9b5d04601b48c9d244fd5e3a434b0 (patch) | |
tree | 35c3753fd76d9549d0a073a33ef6091f052161b0 | |
parent | aee124f78b78101b62a2371f57216bf91ab8561f (diff) | |
download | amber-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.cc | 24 | ||||
-rw-r--r-- | src/pipeline.cc | 2 | ||||
-rw-r--r-- | src/vulkan/vertex_buffer.cc | 19 | ||||
-rw-r--r-- | src/vulkan/vertex_buffer.h | 2 | ||||
-rw-r--r-- | tests/cases/vertex_data_two_locations.amber | 84 |
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 |