diff options
author | asuonpaa <34128694+asuonpaa@users.noreply.github.com> | 2020-12-16 16:40:10 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-16 14:40:10 +0000 |
commit | f8a6fdbe4dc9890fa967091f43b5f7669962c403 (patch) | |
tree | f7156dbafad1c5aa1ab7ac4e78a035647f5da589 | |
parent | cc1dec6104f5e0e656d8439296265a19393628df (diff) | |
download | amber-f8a6fdbe4dc9890fa967091f43b5f7669962c403.tar.gz |
VERTEX_DATA: add format, offset, stride parameters (#929)
Adds parameters to the VERTEX_DATA AmberScript command: FORMAT, OFFSET, STRIDE.
-rw-r--r-- | docs/amber_script.md | 12 | ||||
-rw-r--r-- | src/amberscript/parser.cc | 60 | ||||
-rw-r--r-- | src/amberscript/parser_bind_test.cc | 310 | ||||
-rw-r--r-- | src/pipeline.cc | 8 | ||||
-rw-r--r-- | src/pipeline.h | 16 | ||||
-rw-r--r-- | src/pipeline_test.cc | 10 | ||||
-rw-r--r-- | src/vkscript/parser.cc | 4 | ||||
-rw-r--r-- | src/vulkan/engine_vulkan.cc | 10 | ||||
-rw-r--r-- | src/vulkan/vertex_buffer.cc | 12 | ||||
-rw-r--r-- | src/vulkan/vertex_buffer.h | 7 | ||||
-rw-r--r-- | src/vulkan/vertex_buffer_test.cc | 3 | ||||
-rw-r--r-- | tests/cases/draw_triangle_list_format.amber | 91 | ||||
-rw-r--r-- | tests/cases/draw_triangle_list_offset.amber | 147 | ||||
-rw-r--r-- | tests/cases/draw_triangle_list_stride.amber | 106 |
14 files changed, 767 insertions, 29 deletions
diff --git a/docs/amber_script.md b/docs/amber_script.md index 6dd2443..c4d249f 100644 --- a/docs/amber_script.md +++ b/docs/amber_script.md @@ -587,9 +587,15 @@ when using dynamic buffers with BUFFER_ARRAY. ``` ```groovy - # Set |buffer_name| as the vertex data at location |val|. `RATE` defines the - # input rate for vertex attribute reading. - VERTEX_DATA {buffer_name} LOCATION _val_ [ RATE { vertex | instance } (default vertex) ] + # Set |buffer_name| as the vertex data at location |val|. RATE defines the + # input rate for vertex attribute reading. OFFSET sets the byte offset for the + # vertex data within the buffer |buffer_name|, which by default is 0. FORMAT + # sets the vertex buffer format, which by default is the format of the buffer + # |buffer_name|. STRIDE sets the byte stride, which by default is the stride + # of the format (set explicitly via FORMAT or from the format of the buffer + # |buffer_name|). + VERTEX_DATA {buffer_name} LOCATION _val_ [ RATE { vertex | instance } (default vertex) ] \ + [ FORMAT {format} ] [ OFFSET {offset} ] [ STRIDE {stride} ] # Set |buffer_name| as the index data to use for `INDEXED` draw commands. INDEX_DATA {buffer_name} diff --git a/src/amberscript/parser.cc b/src/amberscript/parser.cc index 1a5a197..778a659 100644 --- a/src/amberscript/parser.cc +++ b/src/amberscript/parser.cc @@ -1301,20 +1301,60 @@ Result Parser::ParsePipelineVertexData(Pipeline* pipeline) { const uint32_t location = token->AsUint32(); InputRate rate = InputRate::kVertex; + uint32_t offset = 0; + Format* format = buffer->GetFormat(); + uint32_t stride = 0; + token = tokenizer_->PeekNextToken(); - if (token->IsIdentifier() && token->AsString() == "RATE") { - tokenizer_->NextToken(); - token = tokenizer_->NextToken(); - if (!token->IsIdentifier()) - return Result("missing input rate value for RATE"); - if (token->AsString() == "instance") { - rate = InputRate::kInstance; - } else if (token->AsString() != "vertex") { - return Result("expecting 'vertex' or 'instance' for RATE value"); + while (token->IsIdentifier()) { + if (token->AsString() == "RATE") { + tokenizer_->NextToken(); + token = tokenizer_->NextToken(); + if (!token->IsIdentifier()) + return Result("missing input rate value for RATE"); + if (token->AsString() == "instance") { + rate = InputRate::kInstance; + } else if (token->AsString() != "vertex") { + return Result("expecting 'vertex' or 'instance' for RATE value"); + } + } else if (token->AsString() == "OFFSET") { + tokenizer_->NextToken(); + token = tokenizer_->NextToken(); + if (!token->IsInteger()) + return Result("expected unsigned integer for OFFSET"); + offset = token->AsUint32(); + } else if (token->AsString() == "STRIDE") { + tokenizer_->NextToken(); + token = tokenizer_->NextToken(); + if (!token->IsInteger()) + return Result("expected unsigned integer for STRIDE"); + stride = token->AsUint32(); + if (stride == 0) + return Result("STRIDE needs to be larger than zero"); + } else if (token->AsString() == "FORMAT") { + tokenizer_->NextToken(); + token = tokenizer_->NextToken(); + if (!token->IsIdentifier()) + return Result("vertex data FORMAT must be an identifier"); + auto type = script_->ParseType(token->AsString()); + if (!type) + return Result("invalid vertex data FORMAT"); + auto fmt = MakeUnique<Format>(type); + format = fmt.get(); + script_->RegisterFormat(std::move(fmt)); + } else { + return Result("unexpected identifier for VERTEX_DATA command: " + + token->ToOriginalString()); } + + token = tokenizer_->PeekNextToken(); } - Result r = pipeline->AddVertexBuffer(buffer, location, rate); + if (stride == 0) + stride = format->SizeInBytes(); + + Result r = + pipeline->AddVertexBuffer(buffer, location, rate, format, offset, stride); if (!r.IsSuccess()) return r; diff --git a/src/amberscript/parser_bind_test.cc b/src/amberscript/parser_bind_test.cc index 7f07980..64e6692 100644 --- a/src/amberscript/parser_bind_test.cc +++ b/src/amberscript/parser_bind_test.cc @@ -842,7 +842,8 @@ END)"; Parser parser; Result r = parser.Parse(in); ASSERT_FALSE(r.IsSuccess()); - EXPECT_EQ("12: extra parameters after VERTEX_DATA command: EXTRA", r.Error()); + EXPECT_EQ("12: unexpected identifier for VERTEX_DATA command: EXTRA", + r.Error()); } TEST_F(AmberScriptParserTest, BindVertexDataInputRate) { @@ -927,6 +928,313 @@ END)"; EXPECT_EQ("12: expecting 'vertex' or 'instance' for RATE value", r.Error()); } +TEST_F(AmberScriptParserTest, BindVertexDataOffset) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5 +BUFFER my_buf2 DATA_TYPE int8 SIZE 5 FILL 5 + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + + VERTEX_DATA my_buf LOCATION 0 OFFSET 5 + VERTEX_DATA my_buf2 LOCATION 1 OFFSET 10 +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_TRUE(r.IsSuccess()) << r.Error(); + + 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(5u, 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, BindVertexDataOffsetMissingValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5 + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + + VERTEX_DATA my_buf LOCATION 0 OFFSET +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()); + EXPECT_EQ("13: expected unsigned integer for OFFSET", r.Error()); +} + +TEST_F(AmberScriptParserTest, BindVertexDataOffsetIncorrectValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5 + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + + VERTEX_DATA my_buf LOCATION 0 OFFSET foo +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()); + EXPECT_EQ("12: expected unsigned integer for OFFSET", r.Error()); +} + +TEST_F(AmberScriptParserTest, BindVertexDataStride) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5 +BUFFER my_buf2 DATA_TYPE int8 SIZE 5 FILL 5 + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + + VERTEX_DATA my_buf LOCATION 0 STRIDE 5 + VERTEX_DATA my_buf2 LOCATION 1 STRIDE 10 +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_TRUE(r.IsSuccess()) << r.Error(); + + 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(5u, info1.stride); + + const auto& info2 = vertex_buffers[1]; + ASSERT_TRUE(info2.buffer != nullptr); + EXPECT_EQ(1u, info2.location); + EXPECT_EQ(10u, info2.stride); +} + +TEST_F(AmberScriptParserTest, BindVertexDataStrideFromFormat) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5 +BUFFER my_buf2 DATA_TYPE int8 SIZE 5 FILL 5 + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + + VERTEX_DATA my_buf LOCATION 0 + VERTEX_DATA my_buf2 LOCATION 1 FORMAT R16_UINT +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_TRUE(r.IsSuccess()) << r.Error(); + + 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(1u, info1.stride); + + const auto& info2 = vertex_buffers[1]; + ASSERT_TRUE(info2.buffer != nullptr); + EXPECT_EQ(1u, info2.location); + EXPECT_EQ(2u, info2.stride); +} + +TEST_F(AmberScriptParserTest, BindVertexDataStrideMissingValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5 + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + + VERTEX_DATA my_buf LOCATION 0 STRIDE +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()); + EXPECT_EQ("13: expected unsigned integer for STRIDE", r.Error()); +} + +TEST_F(AmberScriptParserTest, BindVertexDataStrideIncorrectValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5 + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + + VERTEX_DATA my_buf LOCATION 0 STRIDE foo +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()); + EXPECT_EQ("12: expected unsigned integer for STRIDE", r.Error()); +} + +TEST_F(AmberScriptParserTest, BindVertexDataStrideZero) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5 + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + + VERTEX_DATA my_buf LOCATION 0 STRIDE 0 +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()); + EXPECT_EQ("12: STRIDE needs to be larger than zero", r.Error()); +} + +TEST_F(AmberScriptParserTest, BindVertexDataFormat) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5 +BUFFER my_buf2 DATA_TYPE int8 SIZE 5 FILL 5 + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + + VERTEX_DATA my_buf LOCATION 0 FORMAT R8G8_UNORM + VERTEX_DATA my_buf2 LOCATION 1 FORMAT R8_SRGB +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_TRUE(r.IsSuccess()) << r.Error(); + + 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(FormatType::kR8G8_UNORM, info1.format->GetFormatType()); + + const auto& info2 = vertex_buffers[1]; + ASSERT_TRUE(info2.buffer != nullptr); + EXPECT_EQ(1u, info2.location); + EXPECT_EQ(FormatType::kR8_SRGB, info2.format->GetFormatType()); +} + +TEST_F(AmberScriptParserTest, BindVertexDataFormatMissingValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5 + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + + VERTEX_DATA my_buf LOCATION 0 FORMAT +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()); + EXPECT_EQ("13: vertex data FORMAT must be an identifier", r.Error()); +} + +TEST_F(AmberScriptParserTest, BindVertexDataFormatIncorrectValue) { + std::string in = R"( +SHADER vertex my_shader PASSTHROUGH +SHADER fragment my_fragment GLSL +# GLSL Shader +END +BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5 + +PIPELINE graphics my_pipeline + ATTACH my_shader + ATTACH my_fragment + + VERTEX_DATA my_buf LOCATION 0 FORMAT foo +END)"; + + Parser parser; + Result r = parser.Parse(in); + ASSERT_FALSE(r.IsSuccess()); + EXPECT_EQ("12: invalid vertex data FORMAT", r.Error()); +} + TEST_F(AmberScriptParserTest, BindIndexData) { std::string in = R"( SHADER vertex my_shader PASSTHROUGH diff --git a/src/pipeline.cc b/src/pipeline.cc index beb09b1..ca1a561 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -423,7 +423,10 @@ Result Pipeline::SetIndexBuffer(Buffer* buf) { Result Pipeline::AddVertexBuffer(Buffer* buf, uint32_t location, - InputRate rate) { + InputRate rate, + Format* format, + uint32_t offset, + uint32_t stride) { for (const auto& vtex : vertex_buffers_) { if (vtex.location == location) return Result("can not bind two vertex buffers to the same LOCATION"); @@ -435,6 +438,9 @@ Result Pipeline::AddVertexBuffer(Buffer* buf, vertex_buffers_.back().location = location; vertex_buffers_.back().type = BufferType::kVertex; vertex_buffers_.back().input_rate = rate; + vertex_buffers_.back().format = format; + vertex_buffers_.back().offset = offset; + vertex_buffers_.back().stride = stride; return {}; } diff --git a/src/pipeline.h b/src/pipeline.h index bdb1679..ec38a3a 100644 --- a/src/pipeline.h +++ b/src/pipeline.h @@ -199,7 +199,10 @@ class Pipeline { uint32_t arg_no = 0; BufferType type = BufferType::kUnknown; InputRate input_rate = InputRate::kVertex; - Sampler* sampler; + Format* format; + uint32_t offset = 0; + uint32_t stride = 0; + Sampler* sampler = nullptr; }; /// Information on a sampler attached to the pipeline. @@ -315,8 +318,15 @@ class Pipeline { return vertex_buffers_; } /// Adds |buf| as a vertex buffer at |location| in the pipeline using |rate| - /// as the input rate. - Result AddVertexBuffer(Buffer* buf, uint32_t location, InputRate rate); + /// as the input rate, |format| as vertex data format, |offset| as a starting + /// offset for the vertex buffer data, and |stride| for the data stride in + /// bytes. + Result AddVertexBuffer(Buffer* buf, + uint32_t location, + InputRate rate, + Format* format, + uint32_t offset, + uint32_t stride); /// Binds |buf| as the index buffer for this pipeline. Result SetIndexBuffer(Buffer* buf); diff --git a/src/pipeline_test.cc b/src/pipeline_test.cc index 96a62aa..e16313c 100644 --- a/src/pipeline_test.cc +++ b/src/pipeline_test.cc @@ -353,7 +353,11 @@ TEST_F(PipelineTest, Clone) { auto vtex_buf = MakeUnique<Buffer>(); vtex_buf->SetName("vertex_buffer"); - p.AddVertexBuffer(vtex_buf.get(), 1, InputRate::kVertex); + TypeParser parser; + auto int_type = parser.Parse("R32_SINT"); + auto int_fmt = MakeUnique<Format>(int_type.get()); + p.AddVertexBuffer(vtex_buf.get(), 1, InputRate::kVertex, int_fmt.get(), 5, + 10); auto idx_buf = MakeUnique<Buffer>(); idx_buf->SetName("Index Buffer"); @@ -385,6 +389,10 @@ TEST_F(PipelineTest, Clone) { ASSERT_EQ(1U, vtex_buffers.size()); EXPECT_EQ(1, vtex_buffers[0].location); EXPECT_EQ("vertex_buffer", vtex_buffers[0].buffer->GetName()); + EXPECT_EQ(InputRate::kVertex, vtex_buffers[0].input_rate); + EXPECT_EQ(FormatType::kR32_SINT, vtex_buffers[0].format->GetFormatType()); + EXPECT_EQ(5, vtex_buffers[0].offset); + EXPECT_EQ(10, vtex_buffers[0].stride); auto bufs = clone->GetBuffers(); ASSERT_EQ(2U, bufs.size()); diff --git a/src/vkscript/parser.cc b/src/vkscript/parser.cc index aae55cc..c84e2d9 100644 --- a/src/vkscript/parser.cc +++ b/src/vkscript/parser.cc @@ -444,7 +444,9 @@ Result Parser::ProcessVertexDataBlock(const SectionParser::Section& section) { script_->AddBuffer(std::move(buffer)); - pipeline->AddVertexBuffer(buf, headers[i].location, InputRate::kVertex); + pipeline->AddVertexBuffer(buf, headers[i].location, InputRate::kVertex, + buf->GetFormat(), 0, + buf->GetFormat()->SizeInBytes()); } return {}; diff --git a/src/vulkan/engine_vulkan.cc b/src/vulkan/engine_vulkan.cc index 035c269..536993f 100644 --- a/src/vulkan/engine_vulkan.cc +++ b/src/vulkan/engine_vulkan.cc @@ -209,7 +209,9 @@ Result EngineVulkan::CreatePipeline(amber::Pipeline* pipeline) { info.vertex_buffer = MakeUnique<VertexBuffer>(device_.get()); info.vertex_buffer->SetData(static_cast<uint8_t>(vtex_info.location), - vtex_info.buffer, vtex_info.input_rate); + vtex_info.buffer, vtex_info.input_rate, + vtex_info.format, vtex_info.offset, + vtex_info.stride); } if (pipeline->GetIndexBuffer()) { @@ -502,7 +504,8 @@ Result EngineVulkan::DoDrawRect(const DrawRectCommand* command) { buf->SetData(std::move(values)); auto vertex_buffer = MakeUnique<VertexBuffer>(device_.get()); - vertex_buffer->SetData(0, buf.get(), InputRate::kVertex); + vertex_buffer->SetData(0, buf.get(), InputRate::kVertex, buf->GetFormat(), 0, + buf->GetFormat()->SizeInBytes()); DrawArraysCommand draw(command->GetPipeline(), *command->GetPipelineData()); draw.SetTopology(command->IsPatch() ? Topology::kPatchList @@ -589,7 +592,8 @@ Result EngineVulkan::DoDrawGrid(const DrawGridCommand* command) { buf->SetData(std::move(values)); auto vertex_buffer = MakeUnique<VertexBuffer>(device_.get()); - vertex_buffer->SetData(0, buf.get(), InputRate::kVertex); + vertex_buffer->SetData(0, buf.get(), InputRate::kVertex, buf->GetFormat(), 0, + buf->GetFormat()->SizeInBytes()); DrawArraysCommand draw(command->GetPipeline(), *command->GetPipelineData()); draw.SetTopology(Topology::kTriangleList); diff --git a/src/vulkan/vertex_buffer.cc b/src/vulkan/vertex_buffer.cc index 409c0f1..ea7e5eb 100644 --- a/src/vulkan/vertex_buffer.cc +++ b/src/vulkan/vertex_buffer.cc @@ -36,18 +36,22 @@ VertexBuffer::VertexBuffer(Device* device) : device_(device) {} VertexBuffer::~VertexBuffer() = default; -void VertexBuffer::SetData(uint8_t location, Buffer* buffer, InputRate rate) { - auto format = buffer->GetFormat(); +void VertexBuffer::SetData(uint8_t location, + Buffer* buffer, + InputRate rate, + Format* format, + uint32_t offset, + uint32_t stride) { const uint32_t binding = static_cast<uint32_t>(vertex_attr_desc_.size()); vertex_attr_desc_.emplace_back(); vertex_attr_desc_.back().binding = binding; vertex_attr_desc_.back().location = location; - vertex_attr_desc_.back().offset = 0u; + vertex_attr_desc_.back().offset = offset; vertex_attr_desc_.back().format = device_->GetVkFormat(*format); vertex_binding_desc_.emplace_back(); vertex_binding_desc_.back().binding = binding; - vertex_binding_desc_.back().stride = format->SizeInBytes(); + vertex_binding_desc_.back().stride = stride; vertex_binding_desc_.back().inputRate = GetVkInputRate(rate); data_.push_back(buffer); diff --git a/src/vulkan/vertex_buffer.h b/src/vulkan/vertex_buffer.h index 2837a9e..4c49e46 100644 --- a/src/vulkan/vertex_buffer.h +++ b/src/vulkan/vertex_buffer.h @@ -40,7 +40,12 @@ class VertexBuffer { Result SendVertexData(CommandBuffer* command); bool VertexDataSent() const { return !is_vertex_data_pending_; } - void SetData(uint8_t location, Buffer* buffer, InputRate rate); + void SetData(uint8_t location, + Buffer* buffer, + InputRate rate, + Format* format, + uint32_t offset, + uint32_t stride); const std::vector<VkVertexInputAttributeDescription>& GetVkVertexInputAttr() const { diff --git a/src/vulkan/vertex_buffer_test.cc b/src/vulkan/vertex_buffer_test.cc index 914933e..eb8a7bd 100644 --- a/src/vulkan/vertex_buffer_test.cc +++ b/src/vulkan/vertex_buffer_test.cc @@ -151,7 +151,8 @@ class VertexBufferTest : public testing::Test { buffer->SetFormat(format); buffer->SetData(std::move(values)); - vertex_buffer_->SetData(location, buffer.get(), InputRate::kVertex); + vertex_buffer_->SetData(location, buffer.get(), InputRate::kVertex, format, + 0, format->SizeInBytes()); return vertex_buffer_->SendVertexData(commandBuffer_.get()); } diff --git a/tests/cases/draw_triangle_list_format.amber b/tests/cases/draw_triangle_list_format.amber new file mode 100644 index 0000000..894a9fb --- /dev/null +++ b/tests/cases/draw_triangle_list_format.amber @@ -0,0 +1,91 @@ +#!amber +# Copyright 2020 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_color; +layout(location = 0) out vec4 frag_color; + +void main() { + gl_Position = position; + frag_color = vert_color; +} +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 + 0 127 +-128 127 +-128 -128 + 0 127 + 0 -128 + + 0 -128 + 127 127 + 0 127 + 0 -128 + 127 127 + 127 -128 +END + +BUFFER vert_color DATA_TYPE R8G8B8A8_UNORM DATA +255 255 255 255 +255 255 255 255 +255 255 255 255 +255 255 255 255 +255 255 255 255 +255 255 255 255 +255 255 255 255 +END + +IMAGE framebuffer FORMAT B8G8R8A8_UNORM DIM_2D WIDTH 64 HEIGHT 64 + +PIPELINE graphics pipeline0 + ATTACH vtex_shader + ATTACH frag_shader + VERTEX_DATA position_buf LOCATION 0 + VERTEX_DATA vert_color LOCATION 1 + BIND BUFFER framebuffer AS color LOCATION 0 + FRAMEBUFFER_SIZE 64 64 +END + +PIPELINE graphics pipeline1 + ATTACH vtex_shader + ATTACH frag_shader + VERTEX_DATA position_buf LOCATION 0 OFFSET 12 + VERTEX_DATA vert_color LOCATION 1 FORMAT R8_UNORM + BIND BUFFER framebuffer AS color LOCATION 0 + FRAMEBUFFER_SIZE 64 64 +END + +CLEAR pipeline0 + +RUN pipeline0 DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 6 +RUN pipeline1 DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 6 + +EXPECT framebuffer IDX 0 0 SIZE 32 64 EQ_RGBA 255 255 255 255 +EXPECT framebuffer IDX 32 0 SIZE 32 64 EQ_RGBA 255 0 0 255 diff --git a/tests/cases/draw_triangle_list_offset.amber b/tests/cases/draw_triangle_list_offset.amber new file mode 100644 index 0000000..e0d3777 --- /dev/null +++ b/tests/cases/draw_triangle_list_offset.amber @@ -0,0 +1,147 @@ +#!amber +# Copyright 2020 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_color; +layout(location = 0) out vec4 frag_color; + +void main() { + gl_Position = position; + frag_color = vert_color; +} +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 + 0 0 +-128 0 +-128 -128 + 0 0 + 0 -128 + + 0 -128 + 127 0 + 0 0 + 0 -128 + 127 0 + 127 -128 + + 0 0 + 127 127 + 0 127 + 0 0 + 127 127 + 127 0 + +-128 0 + 0 127 +-128 127 +-128 0 + 0 127 + 0 0 +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 + + 0 0 255 255 + 0 0 255 255 + 0 0 255 255 + 0 0 255 255 + 0 0 255 255 + 0 0 255 255 + + 0 255 255 255 + 0 255 255 255 + 0 255 255 255 + 0 255 255 255 + 0 255 255 255 + 0 255 255 255 +END + +IMAGE framebuffer FORMAT B8G8R8A8_UNORM DIM_2D WIDTH 64 HEIGHT 64 + +PIPELINE graphics pipeline0 + ATTACH vtex_shader + ATTACH frag_shader + VERTEX_DATA position_buf LOCATION 0 + VERTEX_DATA vert_color LOCATION 1 + BIND BUFFER framebuffer AS color LOCATION 0 + FRAMEBUFFER_SIZE 64 64 +END + +PIPELINE graphics pipeline1 + ATTACH vtex_shader + ATTACH frag_shader + VERTEX_DATA position_buf LOCATION 0 OFFSET 12 + VERTEX_DATA vert_color LOCATION 1 OFFSET 24 + BIND BUFFER framebuffer AS color LOCATION 0 + FRAMEBUFFER_SIZE 64 64 +END + +PIPELINE graphics pipeline2 + ATTACH vtex_shader + ATTACH frag_shader + VERTEX_DATA position_buf LOCATION 0 OFFSET 24 + VERTEX_DATA vert_color LOCATION 1 OFFSET 48 + BIND BUFFER framebuffer AS color LOCATION 0 + FRAMEBUFFER_SIZE 64 64 +END + +PIPELINE graphics pipeline3 + ATTACH vtex_shader + ATTACH frag_shader + VERTEX_DATA position_buf LOCATION 0 OFFSET 36 + VERTEX_DATA vert_color LOCATION 1 OFFSET 72 + BIND BUFFER framebuffer AS color LOCATION 0 + FRAMEBUFFER_SIZE 64 64 +END + +CLEAR pipeline0 + +RUN pipeline0 DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 6 +RUN pipeline1 DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 6 +RUN pipeline2 DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 6 +RUN pipeline3 DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 6 + +EXPECT framebuffer IDX 0 0 SIZE 32 32 EQ_RGBA 255 0 0 255 +EXPECT framebuffer IDX 32 0 SIZE 32 32 EQ_RGBA 0 255 0 255 +EXPECT framebuffer IDX 32 32 SIZE 32 32 EQ_RGBA 0 0 255 255 +EXPECT framebuffer IDX 0 32 SIZE 32 32 EQ_RGBA 0 255 255 255 diff --git a/tests/cases/draw_triangle_list_stride.amber b/tests/cases/draw_triangle_list_stride.amber new file mode 100644 index 0000000..49c1d46 --- /dev/null +++ b/tests/cases/draw_triangle_list_stride.amber @@ -0,0 +1,106 @@ +#!amber +# Copyright 2020 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_color; +layout(location = 0) out vec4 frag_color; + +void main() { + gl_Position = position; + frag_color = vert_color; +} +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 + 0 127 +-128 127 +-128 -128 + 0 127 + 0 -128 + + 0 -128 + 127 127 + 0 127 + 0 -128 + 127 127 + 127 -128 +END + +BUFFER vert_color DATA_TYPE R8G8B8A8_UNORM DATA +255 0 0 255 + 0 255 0 255 +255 0 0 255 + 0 0 0 255 +255 0 0 255 + 0 255 0 255 +255 0 0 255 + 0 0 0 255 +255 0 0 255 + 0 255 0 255 +255 0 0 255 + 0 0 0 255 +255 0 0 255 + 0 255 0 255 +255 0 0 255 + 0 0 0 255 +255 0 0 255 + 0 255 0 255 +255 0 0 255 + 0 0 0 255 +255 0 0 255 + 0 255 0 255 +END + +IMAGE framebuffer FORMAT B8G8R8A8_UNORM DIM_2D WIDTH 64 HEIGHT 64 + +PIPELINE graphics pipeline0 + ATTACH vtex_shader + ATTACH frag_shader + VERTEX_DATA position_buf LOCATION 0 + VERTEX_DATA vert_color LOCATION 1 STRIDE 8 + BIND BUFFER framebuffer AS color LOCATION 0 + FRAMEBUFFER_SIZE 64 64 +END + +PIPELINE graphics pipeline1 + ATTACH vtex_shader + ATTACH frag_shader + VERTEX_DATA position_buf LOCATION 0 OFFSET 12 + VERTEX_DATA vert_color LOCATION 1 OFFSET 4 STRIDE 16 + BIND BUFFER framebuffer AS color LOCATION 0 + FRAMEBUFFER_SIZE 64 64 +END + +CLEAR pipeline0 + +RUN pipeline0 DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 6 +RUN pipeline1 DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 6 + +EXPECT framebuffer IDX 0 0 SIZE 32 64 EQ_RGBA 255 0 0 255 +EXPECT framebuffer IDX 32 0 SIZE 32 64 EQ_RGBA 0 255 0 255 |