blob: 8aac5e5480560a13b38cc9b6a6af2a89bbd7c74f [file] [log] [blame]
// Copyright 2019 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
//
// http://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 parseried.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "gtest/gtest.h"
#include "src/amberscript/parser.h"
namespace amber {
namespace amberscript {
using AmberScriptParserTest = testing::Test;
TEST_F(AmberScriptParserTest, BindColorBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION 0
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& color_buffers = pipeline->GetColorAttachments();
ASSERT_EQ(1U, color_buffers.size());
const auto& buf_info = color_buffers[0];
ASSERT_TRUE(buf_info.buffer != nullptr);
EXPECT_EQ(0u, buf_info.location);
EXPECT_EQ(250u * 250u, buf_info.buffer->ElementCount());
EXPECT_EQ(250u * 250u * 4u, buf_info.buffer->ValueCount());
EXPECT_EQ(250u * 250u * 4u * sizeof(float),
buf_info.buffer->GetSizeInBytes());
}
TEST_F(AmberScriptParserTest, BindColorBufferTwice) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION 0
BIND BUFFER my_fb AS color LOCATION 1
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: color buffer may only be bound to a PIPELINE once", r.Error());
}
TEST_F(AmberScriptParserTest, BindColorBufferMissingBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER AS color LOCATION 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: unknown buffer: AS", r.Error());
}
TEST_F(AmberScriptParserTest, BindColorBufferNonDeclaredBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("11: unknown buffer: my_fb", r.Error());
}
TEST_F(AmberScriptParserTest, BindColorBufferMissingLocation) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: BIND missing LOCATION", r.Error());
}
TEST_F(AmberScriptParserTest, BindColorBufferMissingLocationIndex) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: invalid value for BIND LOCATION", r.Error());
}
TEST_F(AmberScriptParserTest, BindColorBufferInvalidLocationIndex) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION INVALID
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: invalid value for BIND LOCATION", r.Error());
}
TEST_F(AmberScriptParserTest, BindColorBufferExtraParams) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION 0 EXTRA
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: extra parameters after BIND command: EXTRA", r.Error());
}
TEST_F(AmberScriptParserTest, BindColorBufferDuplicateLocation) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
BUFFER sec_fb FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION 0
BIND BUFFER sec_fb AS color LOCATION 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("14: can not bind two color buffers to the same LOCATION",
r.Error());
}
TEST_F(AmberScriptParserTest, BindColorToTwoPipelinesRequiresMatchingSize) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION 0
END
PIPELINE graphics second_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION 0
FRAMEBUFFER_SIZE 256 300
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("shared framebuffer must have same size over all PIPELINES",
r.Error());
}
TEST_F(AmberScriptParserTest, BindColorTwoPipelines) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
BUFFER second_fb FORMAT R8G8B8A8_UINT
BUFFER depth_1 FORMAT D32_SFLOAT_S8_UINT
BUFFER depth_2 FORMAT D32_SFLOAT_S8_UINT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION 0
BIND BUFFER depth_1 AS depth_stencil
FRAMEBUFFER_SIZE 90 180
END
PIPELINE graphics second_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER second_fb AS color LOCATION 9
BIND BUFFER depth_2 AS depth_stencil
FRAMEBUFFER_SIZE 256 300
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(2U, pipelines.size());
const auto* pipeline = pipelines[0].get();
const auto& color_buffers1 = pipeline->GetColorAttachments();
ASSERT_EQ(1U, color_buffers1.size());
const auto& buf1 = color_buffers1[0];
ASSERT_TRUE(buf1.buffer != nullptr);
EXPECT_EQ(0u, buf1.location);
EXPECT_EQ(90u * 180u, buf1.buffer->ElementCount());
EXPECT_EQ(90u * 180u * 4u, buf1.buffer->ValueCount());
EXPECT_EQ(90u * 180u * 4u * sizeof(float), buf1.buffer->GetSizeInBytes());
pipeline = pipelines[1].get();
const auto& color_buffers2 = pipeline->GetColorAttachments();
const auto& buf2 = color_buffers2[0];
ASSERT_TRUE(buf2.buffer != nullptr);
EXPECT_EQ(9u, buf2.location);
EXPECT_EQ(256u * 300u, buf2.buffer->ElementCount());
EXPECT_EQ(256u * 300u * 4u, buf2.buffer->ValueCount());
EXPECT_EQ(256u * 300u * 4u * sizeof(uint8_t), buf2.buffer->GetSizeInBytes());
}
TEST_F(AmberScriptParserTest, BindColorFBSizeSetBeforeBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
FRAMEBUFFER_SIZE 90 180
BIND BUFFER my_fb AS color LOCATION 0
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& color_buffers1 = pipeline->GetColorAttachments();
ASSERT_EQ(1U, color_buffers1.size());
const auto& buf1 = color_buffers1[0];
ASSERT_TRUE(buf1.buffer != nullptr);
EXPECT_EQ(0u, buf1.location);
EXPECT_EQ(90u * 180u, buf1.buffer->ElementCount());
EXPECT_EQ(90u * 180u * 4u, buf1.buffer->ValueCount());
EXPECT_EQ(90u * 180u * 4u * sizeof(float), buf1.buffer->GetSizeInBytes());
}
TEST_F(AmberScriptParserTest, BindColorFBSizeSetAfterBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION 0
FRAMEBUFFER_SIZE 90 180
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& color_buffers1 = pipeline->GetColorAttachments();
ASSERT_EQ(1U, color_buffers1.size());
const auto& buf1 = color_buffers1[0];
ASSERT_TRUE(buf1.buffer != nullptr);
EXPECT_EQ(0u, buf1.location);
EXPECT_EQ(90u * 180u, buf1.buffer->ElementCount());
EXPECT_EQ(90u * 180u * 4u, buf1.buffer->ValueCount());
EXPECT_EQ(90u * 180u * 4u * sizeof(float), buf1.buffer->GetSizeInBytes());
}
TEST_F(AmberScriptParserTest, BindColorBaseMipLevel) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT MIP_LEVELS 2
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION 0 BASE_MIP_LEVEL 1
FRAMEBUFFER_SIZE 90 180
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& color_buffers1 = pipeline->GetColorAttachments();
ASSERT_EQ(1U, color_buffers1.size());
const auto& buf1 = color_buffers1[0];
ASSERT_TRUE(buf1.buffer != nullptr);
EXPECT_EQ(1u, buf1.base_mip_level);
}
TEST_F(AmberScriptParserTest, BindColorMissingBaseMipLevel) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT MIP_LEVELS 2
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION 0 BASE_MIP_LEVEL
FRAMEBUFFER_SIZE 90 180
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: invalid value for BASE_MIP_LEVEL", r.Error());
}
TEST_F(AmberScriptParserTest, BindColorBaseMipLevelTooLarge) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT MIP_LEVELS 2
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION 0 BASE_MIP_LEVEL 2
FRAMEBUFFER_SIZE 90 180
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ(
"12: base mip level (now 2) needs to be larger than the number of buffer "
"mip maps (2)",
r.Error());
}
TEST_F(AmberScriptParserTest, BindColorTooManyMipLevels) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT MIP_LEVELS 20
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_fb AS color LOCATION 0
FRAMEBUFFER_SIZE 90 180
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ(
"color attachment with 20 mip levels would have zero width for level 7",
r.Error());
}
TEST_F(AmberScriptParserTest, BindDepthBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS depth_stencil
FRAMEBUFFER_SIZE 90 180
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& buf = pipeline->GetDepthStencilBuffer();
ASSERT_TRUE(buf.buffer != nullptr);
EXPECT_EQ(90u * 180u, buf.buffer->ElementCount());
EXPECT_EQ(90u * 180u * 4u, buf.buffer->ValueCount());
EXPECT_EQ(90u * 180u * 4u * sizeof(float), buf.buffer->GetSizeInBytes());
}
TEST_F(AmberScriptParserTest, BindDepthBufferExtraParams) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS depth_stencil EXTRA
FRAMEBUFFER_SIZE 90 180
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: extra parameters after BIND command: EXTRA", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferMissingBufferName) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER AS depth_stencil
FRAMEBUFFER_SIZE 90 180
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: unknown buffer: AS", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferAsMissingType) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS
FRAMEBUFFER_SIZE 90 180
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: invalid token for BUFFER type", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferAsInvalidType) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS
FRAMEBUFFER_SIZE 90 180
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: invalid token for BUFFER type", r.Error());
}
TEST_F(AmberScriptParserTest, BindDepthBufferUnknownBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS depth_stencil
FRAMEBUFFER_SIZE 90 180
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("11: unknown buffer: my_buf", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferMultipleDepthBuffers) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
BUFFER my_buf2 FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS depth_stencil
BIND BUFFER my_buf AS depth_stencil
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("14: can only bind one depth/stencil buffer in a PIPELINE",
r.Error());
}
TEST_F(AmberScriptParserTest, BindVertexData) {
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
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(InputRate::kVertex, info1.input_rate);
const auto& info2 = vertex_buffers[1];
ASSERT_TRUE(info2.buffer != nullptr);
EXPECT_EQ(1u, info2.location);
EXPECT_EQ(InputRate::kVertex, info2.input_rate);
}
TEST_F(AmberScriptParserTest, BindVertexDataDuplicateLocation) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
BUFFER my_buf2 DATA_TYPE int8 SIZE 50 FILL 5
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
VERTEX_DATA my_buf LOCATION 0
VERTEX_DATA my_buf2 LOCATION 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("14: can not bind two vertex buffers to the same LOCATION",
r.Error());
}
TEST_F(AmberScriptParserTest, BindVertexDataDuplicateBinding) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
VERTEX_DATA my_buf LOCATION 0
VERTEX_DATA my_buf LOCATION 1 OFFSET 10
END)";
Parser parser;
Result r = parser.Parse(in);
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) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
VERTEX_DATA LOCATION 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: unknown buffer: LOCATION", r.Error());
}
TEST_F(AmberScriptParserTest, BindVertexDataUnknownBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
VERTEX_DATA my_buf LOCATION 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("11: unknown buffer: my_buf", r.Error());
}
TEST_F(AmberScriptParserTest, BindVertexDataMissingLocation) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
VERTEX_DATA my_buf
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: VERTEX_DATA missing LOCATION", r.Error());
}
TEST_F(AmberScriptParserTest, BindVertexDataMissingLocationValue) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
VERTEX_DATA my_buf LOCATION
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: invalid value for VERTEX_DATA LOCATION", r.Error());
}
TEST_F(AmberScriptParserTest, BindVertexDataExtraParameters) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
VERTEX_DATA my_buf LOCATION 0 EXTRA
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: unexpected identifier for VERTEX_DATA command: EXTRA",
r.Error());
}
TEST_F(AmberScriptParserTest, BindVertexDataInputRate) {
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 RATE vertex
VERTEX_DATA my_buf2 LOCATION 1 RATE instance
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(InputRate::kVertex, info1.input_rate);
const auto& info2 = vertex_buffers[1];
ASSERT_TRUE(info2.buffer != nullptr);
EXPECT_EQ(1u, info2.location);
EXPECT_EQ(InputRate::kInstance, info2.input_rate);
}
TEST_F(AmberScriptParserTest, BindVertexDataInputRateMissingValue) {
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 RATE
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: missing input rate value for RATE", r.Error());
}
TEST_F(AmberScriptParserTest, BindVertexDataInputRateInvalidValue) {
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 RATE foo
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
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
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
INDEX_DATA my_buf
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* buf = pipeline->GetIndexBuffer();
ASSERT_TRUE(buf != nullptr);
}
TEST_F(AmberScriptParserTest, BindIndexataMissingBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
INDEX_DATA
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: missing buffer name in INDEX_DATA command", r.Error());
}
TEST_F(AmberScriptParserTest, BindIndexDataUnknownBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
INDEX_DATA my_buf
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("11: unknown buffer: my_buf", r.Error());
}
TEST_F(AmberScriptParserTest, BindIndexDataExtraParameters) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
INDEX_DATA my_buf EXTRA
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: extra parameters after INDEX_DATA command: EXTRA", r.Error());
}
TEST_F(AmberScriptParserTest, BindIndexDataMultiple) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
INDEX_DATA my_buf
INDEX_DATA my_buf
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: can only bind one INDEX_DATA buffer in a pipeline", r.Error());
}
TEST_F(AmberScriptParserTest, BindBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(1U, bufs.size());
EXPECT_EQ(BufferType::kUniform, bufs[0].type);
EXPECT_EQ(1U, bufs[0].descriptor_set);
EXPECT_EQ(2U, bufs[0].binding);
EXPECT_EQ(0U, bufs[0].descriptor_offset);
EXPECT_EQ(~0ULL, bufs[0].descriptor_range);
EXPECT_EQ(static_cast<uint32_t>(0), bufs[0].location);
EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
bufs[0].buffer->GetFormat()->GetFormatType());
}
TEST_F(AmberScriptParserTest, BindBufferDescriptorOffsetAndRange) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_OFFSET 256 DESCRIPTOR_RANGE 512
BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 3 DESCRIPTOR_OFFSET 256 DESCRIPTOR_RANGE -1
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(2U, bufs.size());
EXPECT_EQ(BufferType::kUniform, bufs[0].type);
EXPECT_EQ(1U, bufs[0].descriptor_set);
EXPECT_EQ(2U, bufs[0].binding);
EXPECT_EQ(256U, bufs[0].descriptor_offset);
EXPECT_EQ(512U, bufs[0].descriptor_range);
EXPECT_EQ(static_cast<uint32_t>(0), bufs[0].location);
EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
bufs[0].buffer->GetFormat()->GetFormatType());
// Verify the descriptor range from the second buffer.
EXPECT_EQ(~0ULL, bufs[1].descriptor_range);
}
TEST_F(AmberScriptParserTest, BindBufferMissingBindingValue) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: invalid value for BINDING in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferMissingBinding) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: missing BINDING for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferMissingDescriptorSetValue) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS uniform DESCRIPTOR_SET BINDING 2
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferMissingDescriptorSet) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS uniform BINDING 2
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindingBufferExtraParams) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 EXTRA
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: extra parameters after BIND command: EXTRA", r.Error());
}
TEST_F(AmberScriptParserTest, BindingBufferInvalidBindingValue) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING INVALID
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: invalid value for BINDING in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindingBufferInvalidDescriptorSetValue) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS uniform DESCRIPTOR_SET INVALID BINDING 2
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindingBufferInvalidBufferType) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS INVALID DESCRIPTOR_SET 1 BINDING 2
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: unknown buffer_type: INVALID", r.Error());
}
struct BufferTypeData {
const char* name;
BufferType type;
};
using AmberScriptParserBufferTypeTest = testing::TestWithParam<BufferTypeData>;
TEST_P(AmberScriptParserBufferTypeTest, BufferType) {
auto test_data = GetParam();
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS )" +
std::string(test_data.name) +
" DESCRIPTOR_SET 0 BINDING 0\nEND";
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(1U, bufs.size());
EXPECT_EQ(test_data.type, bufs[0].type);
}
INSTANTIATE_TEST_SUITE_P(
AmberScriptParserBufferTypeTestSamples,
AmberScriptParserBufferTypeTest,
testing::Values(BufferTypeData{"uniform", BufferType::kUniform},
BufferTypeData{
"storage",
BufferType::kStorage})); // NOLINT(whitespace/parens)
TEST_F(AmberScriptParserTest, BindPushConstants) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf DATA_TYPE float SIZE 20 FILL 5
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS push_constant
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& buf = pipeline->GetPushConstantBuffer();
ASSERT_TRUE(buf.buffer != nullptr);
EXPECT_EQ(20u, buf.buffer->ElementCount());
EXPECT_EQ(20u, buf.buffer->ValueCount());
EXPECT_EQ(20u * sizeof(float), buf.buffer->GetSizeInBytes());
}
TEST_F(AmberScriptParserTest, BindPushConstantsExtraParams) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf DATA_TYPE float SIZE 20 FILL 5
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS push_constant EXTRA
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: extra parameters after BIND command: EXTRA", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferOpenCLArgName) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
BUFFER my_buf DATA_TYPE uint32 DATA 1 END
PIPELINE compute my_pipeline
ATTACH my_shader
BIND BUFFER my_buf AS storage KERNEL ARG_NAME arg
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_TRUE(r.IsSuccess());
}
TEST_F(AmberScriptParserTest, BindBufferOpenCLArgNumber) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
BUFFER my_buf DATA_TYPE uint32 DATA 1 END
PIPELINE compute my_pipeline
ATTACH my_shader
BIND BUFFER my_buf AS storage KERNEL ARG_NUMBER 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_TRUE(r.IsSuccess());
}
TEST_F(AmberScriptParserTest, BindBufferOpenCLArgNameTypeless) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
BUFFER my_buf DATA_TYPE uint32 DATA 1 END
PIPELINE compute my_pipeline
ATTACH my_shader
BIND BUFFER my_buf KERNEL ARG_NAME arg
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_TRUE(r.IsSuccess());
}
TEST_F(AmberScriptParserTest, BindBufferOpenCLArgNumberTypeless) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
BUFFER my_buf DATA_TYPE uint32 DATA 1 END
PIPELINE compute my_pipeline
ATTACH my_shader
BIND BUFFER my_buf KERNEL ARG_NUMBER 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_TRUE(r.IsSuccess());
}
TEST_F(AmberScriptParserTest, BindBufferOpenCLMissingKernel) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
BUFFER my_buf DATA_TYPE uint32 DATA 1 END
PIPELINE compute my_pipeline
ATTACH my_shader
BIND BUFFER my_buf AS storage ARG_NAME arg
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("9: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferOpenCLMissingArg) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
BUFFER my_buf DATA_TYPE uint32 DATA 1 END
PIPELINE compute my_pipeline
ATTACH my_shader
BIND BUFFER my_buf AS storage KERNEL arg
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("9: missing ARG_NAME or ARG_NUMBER keyword", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferOpenCLMissingArgName) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
BUFFER my_buf DATA_TYPE uint32 DATA 1 END
PIPELINE compute my_pipeline
ATTACH my_shader
BIND BUFFER my_buf KERNEL ARG_NAME
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("10: expected argument identifier", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferOpenCLMissingArgNumber) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
BUFFER my_buf DATA_TYPE uint32 DATA 1 END
PIPELINE compute my_pipeline
ATTACH my_shader
BIND BUFFER my_buf AS storage KERNEL ARG_NUMBER
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("10: expected argument number", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferOpenCLArgNameNotString) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
BUFFER my_buf DATA_TYPE uint32 DATA 1 END
PIPELINE compute my_pipeline
ATTACH my_shader
BIND BUFFER my_buf AS storage KERNEL ARG_NAME 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("9: expected argument identifier", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferOpenCLArgNumberNotInteger) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
BUFFER my_buf DATA_TYPE uint32 DATA 1 END
PIPELINE compute my_pipeline
ATTACH my_shader
BIND BUFFER my_buf KERNEL ARG_NUMBER in
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("9: expected argument number", r.Error());
}
TEST_F(AmberScriptParserTest, BindSamplerOpenCLMissingKernel) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
SAMPLER s
PIPELINE compute my_pipeline
ATTACH my_shader
BIND SAMPLER s
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("10: expected a string token for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindSamplerOpenCLInvalidKernel) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
SAMPLER s
PIPELINE compute my_pipeline
ATTACH my_shader
BIND SAMPLER s INVALID
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("9: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindSamplerOpenCLMissingArgument) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
SAMPLER s
PIPELINE compute my_pipeline
ATTACH my_shader
BIND SAMPLER s KERNEL
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("10: missing kernel arg identifier", r.Error());
}
TEST_F(AmberScriptParserTest, BindSamplerOpenCLMissingArgumentName) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
SAMPLER s
PIPELINE compute my_pipeline
ATTACH my_shader
BIND SAMPLER s KERNEL ARG_NAME
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("10: expected argument identifier", r.Error());
}
TEST_F(AmberScriptParserTest, BindSamplerOpenCLArgumentNameNotString) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
SAMPLER s
PIPELINE compute my_pipeline
ATTACH my_shader
BIND SAMPLER s KERNEL ARG_NAME 0
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("9: expected argument identifier", r.Error());
}
TEST_F(AmberScriptParserTest, BindSamplerOpenCLMissingArgumentNumber) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
SAMPLER s
PIPELINE compute my_pipeline
ATTACH my_shader
BIND SAMPLER s KERNEL ARG_NUMBER
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("10: expected argument number", r.Error());
}
TEST_F(AmberScriptParserTest, BindSamplerOpenCLArgumentNumberNotInteger) {
std::string in = R"(
SHADER compute my_shader OPENCL-C
#shader
END
SAMPLER s
PIPELINE compute my_pipeline
ATTACH my_shader
BIND SAMPLER s KERNEL ARG_NUMBER a
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("9: expected argument number", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferStorageImageCompute) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0 BINDING 0
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(1U, bufs.size());
EXPECT_EQ(BufferType::kStorageImage, bufs[0].type);
}
TEST_F(AmberScriptParserTest, BindBufferStorageImageGraphics) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
BUFFER framebuffer FORMAT R8G8B8A8_UNORM
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0 BINDING 0
BIND BUFFER framebuffer AS color LOCATION 0
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(1U, bufs.size());
EXPECT_EQ(BufferType::kStorageImage, bufs[0].type);
}
TEST_F(AmberScriptParserTest, BindBufferStorageImageMissingDescriptorSetValue) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS storage_image DESCRIPTOR_SET BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("10: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferStorageImageMissingDescriptorSet) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS storage_image BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("10: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferStorageImageMissingBindingValue) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0 BINDING
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("11: invalid value for BINDING in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferStorageImageMissingBinding) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("11: missing BINDING for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferSampledImage) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
BUFFER framebuffer FORMAT R8G8B8A8_UNORM
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS sampled_image DESCRIPTOR_SET 0 BINDING 0
BIND BUFFER framebuffer AS color LOCATION 0
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(1U, bufs.size());
EXPECT_EQ(BufferType::kSampledImage, bufs[0].type);
}
TEST_F(AmberScriptParserTest, BindBufferSampledImageMissingDescriptorSetValue) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS sampled_image DESCRIPTOR_SET BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferSampledImageMissingDescriptorSet) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS sampled_image BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferSampledImageMissingBindingValue) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS sampled_image DESCRIPTOR_SET 0 BINDING
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: invalid value for BINDING in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferSampledImageMissingBinding) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS sampled_image DESCRIPTOR_SET 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: missing BINDING for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferCombinedImageSampler) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
BUFFER framebuffer FORMAT R8G8B8A8_UNORM
SAMPLER sampler
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET 0 BINDING 0
BIND BUFFER framebuffer AS color LOCATION 0
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(1U, bufs.size());
EXPECT_EQ(BufferType::kCombinedImageSampler, bufs[0].type);
}
TEST_F(AmberScriptParserTest,
BindBufferCombinedImageSamplerMissingDescriptorSetValue) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
SAMPLER sampler
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest,
BindBufferCombinedImageSamplerMissingDescriptorSet) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
SAMPLER sampler
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS combined_image_sampler SAMPLER sampler BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest,
BindBufferCombinedImageSamplerMissingBindingValue) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
SAMPLER sampler
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET 0 BINDING
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("14: invalid value for BINDING in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferCombinedImageSamplerMissingBinding) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
SAMPLER sampler
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("14: missing BINDING for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferCombinedImageSamplerMissingSampler) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS combined_image_sampler DESCRIPTOR_SET 0 BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: expecting SAMPLER for combined image sampler", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferCombinedImageSamplerUnknownSampler) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS combined_image_sampler SAMPLER foo DESCRIPTOR_SET 0 BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: unknown sampler: foo", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferCombinedImageSamplerBaseMipLevel) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM MIP_LEVELS 4
BUFFER framebuffer FORMAT R8G8B8A8_UNORM
SAMPLER sampler MAX_LOD 4.0
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET 0 BINDING 0 BASE_MIP_LEVEL 2
BIND BUFFER framebuffer AS color LOCATION 0
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(1U, bufs.size());
EXPECT_EQ(2U, bufs[0].base_mip_level);
}
TEST_F(AmberScriptParserTest,
BindBufferCombinedImageSamplerMissingBaseMipLevel) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM MIP_LEVELS 4
BUFFER framebuffer FORMAT R8G8B8A8_UNORM
SAMPLER sampler MAX_LOD 4.0
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET 0 BINDING 0 BASE_MIP_LEVEL
BIND BUFFER framebuffer AS color LOCATION 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("15: invalid value for BASE_MIP_LEVEL", r.Error());
}
TEST_F(AmberScriptParserTest,
BindBufferCombinedImageSamplerBaseMipLevelTooLarge) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM MIP_LEVELS 2
BUFFER framebuffer FORMAT R8G8B8A8_UNORM
SAMPLER sampler MAX_LOD 2.0
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET 0 BINDING 0 BASE_MIP_LEVEL 3
BIND BUFFER framebuffer AS color LOCATION 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ(
"14: base mip level (now 3) needs to be larger than the number of buffer "
"mip maps (2)",
r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferUniformTexelBufferCompute) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS uniform_texel_buffer DESCRIPTOR_SET 0 BINDING 0
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(1U, bufs.size());
EXPECT_EQ(BufferType::kUniformTexelBuffer, bufs[0].type);
}
TEST_F(AmberScriptParserTest, BindBufferUniformTexelBufferGraphics) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
BUFFER framebuffer FORMAT R8G8B8A8_UNORM
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS uniform_texel_buffer DESCRIPTOR_SET 0 BINDING 0
BIND BUFFER framebuffer AS color LOCATION 0
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(1U, bufs.size());
EXPECT_EQ(BufferType::kUniformTexelBuffer, bufs[0].type);
}
TEST_F(AmberScriptParserTest,
BindBufferUniformTexelBufferMissingDescriptorSetValue) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS uniform_texel_buffer DESCRIPTOR_SET BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("10: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest,
BindBufferUniformTexelBufferMissingDescriptorSet) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS uniform_texel_buffer BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("10: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferUniformTexelBufferMissingBindingValue) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS uniform_texel_buffer DESCRIPTOR_SET 0 BINDING
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("11: invalid value for BINDING in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferUniformTexelBufferMissingBinding) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS uniform_texel_buffer DESCRIPTOR_SET 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("11: missing BINDING for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferStorageTexelBufferCompute) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS storage_texel_buffer DESCRIPTOR_SET 0 BINDING 0
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(1U, bufs.size());
EXPECT_EQ(BufferType::kStorageTexelBuffer, bufs[0].type);
}
TEST_F(AmberScriptParserTest, BindBufferStorageTexelBufferGraphics) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
BUFFER framebuffer FORMAT R8G8B8A8_UNORM
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND BUFFER texture AS storage_texel_buffer DESCRIPTOR_SET 0 BINDING 0
BIND BUFFER framebuffer AS color LOCATION 0
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(1U, bufs.size());
EXPECT_EQ(BufferType::kStorageTexelBuffer, bufs[0].type);
}
TEST_F(AmberScriptParserTest,
BindBufferStorageTexelBufferMissingDescriptorSetValue) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS storage_texel_buffer DESCRIPTOR_SET BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("10: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest,
BindBufferStorageTexelBufferMissingDescriptorSet) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS storage_texel_buffer BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("10: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferStorageTexelBufferMissingBindingValue) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS storage_texel_buffer DESCRIPTOR_SET 0 BINDING
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("11: invalid value for BINDING in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferStorageTexelBufferMissingBinding) {
std::string in = R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS storage_texel_buffer DESCRIPTOR_SET 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("11: missing BINDING for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindSampler) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
SAMPLER sampler
BUFFER framebuffer FORMAT R8G8B8A8_UNORM
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND SAMPLER sampler DESCRIPTOR_SET 0 BINDING 0
BIND BUFFER framebuffer AS color LOCATION 0
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& samplers = pipeline->GetSamplers();
ASSERT_EQ(1U, samplers.size());
}
TEST_F(AmberScriptParserTest, BindSamplerMissingDescriptorSetValue) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
SAMPLER sampler
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND SAMPLER sampler DESCRIPTOR_SET BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindSamplerMissingDescriptorSet) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
SAMPLER sampler
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND SAMPLER sampler BINDING 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindSamplerMissingBindingValue) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
SAMPLER sampler
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND SAMPLER sampler DESCRIPTOR_SET 0 BINDING
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: invalid value for BINDING in BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindSamplerMissingBinding) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
SAMPLER sampler
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND SAMPLER sampler DESCRIPTOR_SET 0
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("13: missing BINDING for BIND command", r.Error());
}
TEST_F(AmberScriptParserTest, BindDescriptorOffsetWithUnsupportedBufferType) {
std::string unsupported_buffer_types[] = {"uniform_texel_buffer",
"storage_texel_buffer",
"sampled_image", "storage_image"};
for (const auto& buffer_type : unsupported_buffer_types) {
std::ostringstream in;
in << R"(
SHADER compute compute_shader GLSL
# GLSL Shader
END
BUFFER texture FORMAT R8G8B8A8_UNORM
PIPELINE compute pipeline
ATTACH compute_shader
BIND BUFFER texture AS )"
<< buffer_type << R"( DESCRIPTOR_SET 0 BINDING 0 DESCRIPTOR_OFFSET 0
END)";
Parser parser;
Result r = parser.Parse(in.str());
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("10: extra parameters after BIND command: DESCRIPTOR_OFFSET",
r.Error());
}
}
TEST_F(AmberScriptParserTest, BindBufferArray) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf1 FORMAT R32G32B32A32_SFLOAT
BUFFER my_buf2 FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER_ARRAY my_buf1 my_buf2 AS uniform DESCRIPTOR_SET 1 BINDING 2
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(2U, bufs.size());
for (size_t i = 0; i < 2; i++) {
EXPECT_EQ(BufferType::kUniform, bufs[i].type);
EXPECT_EQ(1U, bufs[i].descriptor_set);
EXPECT_EQ(2U, bufs[i].binding);
EXPECT_EQ(0U, bufs[i].descriptor_offset);
EXPECT_EQ(~0ULL, bufs[i].descriptor_range);
EXPECT_EQ(static_cast<uint32_t>(0), bufs[i].location);
EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
bufs[i].buffer->GetFormat()->GetFormatType());
}
}
TEST_F(AmberScriptParserTest, BindBufferArrayWithDescriptorOffsetAndRange) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf1 FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER_ARRAY my_buf1 my_buf1 AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_OFFSET 256 512 DESCRIPTOR_RANGE 1024 2048
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(2U, bufs.size());
for (size_t i = 0; i < 2; i++) {
EXPECT_EQ(BufferType::kUniform, bufs[i].type);
EXPECT_EQ(1U, bufs[i].descriptor_set);
EXPECT_EQ(2U, bufs[i].binding);
EXPECT_EQ(256U * (i + 1), bufs[i].descriptor_offset);
EXPECT_EQ(1024U * (i + 1), bufs[i].descriptor_range);
EXPECT_EQ(static_cast<uint32_t>(0), bufs[i].location);
EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
bufs[i].buffer->GetFormat()->GetFormatType());
}
}
TEST_F(AmberScriptParserTest,
BindDynamicBufferArrayWithDescriptorOffsetAndRange) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf1 FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER_ARRAY my_buf1 my_buf1 AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 16 32 DESCRIPTOR_OFFSET 256 512 DESCRIPTOR_RANGE 1024 2048
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(2U, bufs.size());
for (size_t i = 0; i < 2; i++) {
EXPECT_EQ(BufferType::kUniformDynamic, bufs[i].type);
EXPECT_EQ(1U, bufs[i].descriptor_set);
EXPECT_EQ(2U, bufs[i].binding);
EXPECT_EQ(16U * (i + 1), bufs[i].dynamic_offset);
EXPECT_EQ(256U * (i + 1), bufs[i].descriptor_offset);
EXPECT_EQ(1024U * (i + 1), bufs[i].descriptor_range);
EXPECT_EQ(static_cast<uint32_t>(0), bufs[i].location);
EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
bufs[i].buffer->GetFormat()->GetFormatType());
}
}
TEST_F(AmberScriptParserTest, BindBufferArrayOnlyOneDescriptorOffset) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER_ARRAY my_buf my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_OFFSET 256
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ(
"13: expecting a DESCRIPTOR_OFFSET value for each buffer in the array",
r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferArrayOnlyOneDescriptorRange) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER_ARRAY my_buf my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_RANGE 256
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ(
"13: expecting a DESCRIPTOR_RANGE value for each buffer in the array",
r.Error());
}
TEST_F(AmberScriptParserTest, BindUniformBufferEmptyDescriptorOffset) {
std::string in = R"(
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_OFFSET
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("5: expecting an integer value for DESCRIPTOR_OFFSET", r.Error());
}
TEST_F(AmberScriptParserTest, BindUniformBufferInvalidDescriptorOffset) {
std::string in = R"(
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_OFFSET foo
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("4: expecting an integer value for DESCRIPTOR_OFFSET", r.Error());
}
TEST_F(AmberScriptParserTest, BindUniformBufferEmptyDescriptorRange) {
std::string in = R"(
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_RANGE
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("5: expecting an integer value for DESCRIPTOR_RANGE", r.Error());
}
TEST_F(AmberScriptParserTest, BindUniformBufferInvalidDescriptorRange) {
std::string in = R"(
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_RANGE foo
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("4: expecting an integer value for DESCRIPTOR_RANGE", r.Error());
}
TEST_F(AmberScriptParserTest, BindBufferArrayOnlyOneBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER_ARRAY my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: expecting multiple buffer names for BUFFER_ARRAY", r.Error());
}
TEST_F(AmberScriptParserTest, BindSamplerArray) {
std::string in = R"(
SHADER vertex vert_shader PASSTHROUGH
SHADER fragment frag_shader GLSL
# GLSL Shader
END
SAMPLER sampler1
SAMPLER sampler2
BUFFER framebuffer FORMAT R8G8B8A8_UNORM
PIPELINE graphics pipeline
ATTACH vert_shader
ATTACH frag_shader
BIND SAMPLER_ARRAY sampler1 sampler2 DESCRIPTOR_SET 0 BINDING 0
BIND BUFFER framebuffer AS color LOCATION 0
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& samplers = pipeline->GetSamplers();
ASSERT_EQ(2U, samplers.size());
}
TEST_F(AmberScriptParserTest, BindSamplerArrayOnlyOneSampler) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
SAMPLER sampler
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND SAMPLER_ARRAY sampler DESCRIPTOR_SET 1 BINDING 2
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: expecting multiple sampler names for SAMPLER_ARRAY",
r.Error());
}
TEST_F(AmberScriptParserTest, BindUniformBufferDynamic) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 8
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(1U, bufs.size());
EXPECT_EQ(BufferType::kUniformDynamic, bufs[0].type);
EXPECT_EQ(1U, bufs[0].descriptor_set);
EXPECT_EQ(2U, bufs[0].binding);
EXPECT_EQ(8u, bufs[0].dynamic_offset);
EXPECT_EQ(static_cast<uint32_t>(0), bufs[0].location);
EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
bufs[0].buffer->GetFormat()->GetFormatType());
}
TEST_F(AmberScriptParserTest, BindUniformBufferArrayDynamic) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER buf0 FORMAT R32G32B32A32_SFLOAT
BUFFER buf1 FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER_ARRAY buf0 buf1 AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 8 16
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(2U, bufs.size());
EXPECT_EQ(BufferType::kUniformDynamic, bufs[0].type);
EXPECT_EQ(1U, bufs[0].descriptor_set);
EXPECT_EQ(2U, bufs[0].binding);
EXPECT_EQ(8u, bufs[0].dynamic_offset);
EXPECT_EQ(static_cast<uint32_t>(0), bufs[0].location);
EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
bufs[0].buffer->GetFormat()->GetFormatType());
EXPECT_EQ(1U, bufs[1].descriptor_set);
EXPECT_EQ(2U, bufs[1].binding);
EXPECT_EQ(16u, bufs[1].dynamic_offset);
EXPECT_EQ(static_cast<uint32_t>(0), bufs[1].location);
EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
bufs[1].buffer->GetFormat()->GetFormatType());
}
TEST_F(AmberScriptParserTest, BindUniformBufferDynamicMissingOffset) {
std::string in = R"(
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
BIND BUFFER my_buf AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("5: expecting an OFFSET for dynamic buffer type", r.Error());
}
TEST_F(AmberScriptParserTest, BindUniformBufferDynamicEmptyOffset) {
std::string in = R"(
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
BIND BUFFER my_buf AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("5: expecting an integer value for OFFSET", r.Error());
}
TEST_F(AmberScriptParserTest, BindUniformBufferDynamicInvalidOffset) {
std::string in = R"(
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
BIND BUFFER my_buf AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET foo
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("4: expecting an integer value for OFFSET", r.Error());
}
TEST_F(AmberScriptParserTest, BindUniformBufferArrayDynamicNotEnoughOffsets) {
std::string in = R"(
BUFFER buf0 FORMAT R32G32B32A32_SFLOAT
BUFFER buf1 FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
BIND BUFFER_ARRAY buf0 buf1 AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 8
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("7: expecting an OFFSET value for each buffer in the array",
r.Error());
}
TEST_F(AmberScriptParserTest, BindStorageBufferDynamic) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER my_buf AS storage_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 8
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(1U, bufs.size());
EXPECT_EQ(BufferType::kStorageDynamic, bufs[0].type);
EXPECT_EQ(1U, bufs[0].descriptor_set);
EXPECT_EQ(2U, bufs[0].binding);
EXPECT_EQ(8u, bufs[0].dynamic_offset);
EXPECT_EQ(static_cast<uint32_t>(0), bufs[0].location);
EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
bufs[0].buffer->GetFormat()->GetFormatType());
}
TEST_F(AmberScriptParserTest, BindStorageBufferArrayDynamic) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER buf0 FORMAT R32G32B32A32_SFLOAT
BUFFER buf1 FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER_ARRAY buf0 buf1 AS storage_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 8 16
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& bufs = pipeline->GetBuffers();
ASSERT_EQ(2U, bufs.size());
EXPECT_EQ(BufferType::kStorageDynamic, bufs[0].type);
EXPECT_EQ(1U, bufs[0].descriptor_set);
EXPECT_EQ(2U, bufs[0].binding);
EXPECT_EQ(8u, bufs[0].dynamic_offset);
EXPECT_EQ(static_cast<uint32_t>(0), bufs[0].location);
EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
bufs[0].buffer->GetFormat()->GetFormatType());
EXPECT_EQ(1U, bufs[1].descriptor_set);
EXPECT_EQ(2U, bufs[1].binding);
EXPECT_EQ(16u, bufs[1].dynamic_offset);
EXPECT_EQ(static_cast<uint32_t>(0), bufs[1].location);
EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
bufs[1].buffer->GetFormat()->GetFormatType());
}
TEST_F(AmberScriptParserTest, BindStorageBufferDynamicMissingOffset) {
std::string in = R"(
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
BIND BUFFER my_buf AS storage_dynamic DESCRIPTOR_SET 1 BINDING 2
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("5: expecting an OFFSET for dynamic buffer type", r.Error());
}
TEST_F(AmberScriptParserTest, BindStorageBufferDynamicEmptyOffset) {
std::string in = R"(
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
BIND BUFFER my_buf AS storage_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("5: expecting an integer value for OFFSET", r.Error());
}
TEST_F(AmberScriptParserTest, BindStorageBufferDynamicInvalidOffset) {
std::string in = R"(
BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
BIND BUFFER my_buf AS storage_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET foo
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("4: expecting an integer value for OFFSET", r.Error());
}
TEST_F(AmberScriptParserTest, BindStorageBufferArrayDynamicNotEnoughOffsets) {
std::string in = R"(
BUFFER buf0 FORMAT R32G32B32A32_SFLOAT
BUFFER buf1 FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
BIND BUFFER_ARRAY buf0 buf1 AS storage_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 8
END
)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("7: expecting an OFFSET value for each buffer in the array",
r.Error());
}
TEST_F(AmberScriptParserTest, BindResolveTarget) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
IMAGE my_fb_ms DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
IMAGE my_fb DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
FRAMEBUFFER_SIZE 64 64
BIND BUFFER my_fb_ms AS color LOCATION 0
BIND BUFFER my_fb AS resolve
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& resolve_targets = pipeline->GetResolveTargets();
ASSERT_EQ(1U, resolve_targets.size());
const auto& buf_info = resolve_targets[0];
ASSERT_TRUE(buf_info.buffer != nullptr);
EXPECT_EQ(64u * 64u, buf_info.buffer->ElementCount());
EXPECT_EQ(64u * 64u * 4u, buf_info.buffer->ValueCount());
EXPECT_EQ(64u * 64u * 4u * sizeof(float), buf_info.buffer->GetSizeInBytes());
}
TEST_F(AmberScriptParserTest, BindResolveTargetMissingBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
BIND BUFFER AS resolve
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("12: unknown buffer: AS", r.Error());
}
TEST_F(AmberScriptParserTest, BindResolveTargetNonDeclaredBuffer) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
IMAGE my_fb_ms DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
FRAMEBUFFER_SIZE 64 64
BIND BUFFER my_fb_ms AS color LOCATION 0
BIND BUFFER my_fb AS resolve
END)";
Parser parser;
Result r = parser.Parse(in);
ASSERT_FALSE(r.IsSuccess());
EXPECT_EQ("14: unknown buffer: my_fb", r.Error());
}
TEST_F(AmberScriptParserTest, BindMultipleResolveTargets) {
std::string in = R"(
SHADER vertex my_shader PASSTHROUGH
SHADER fragment my_fragment GLSL
# GLSL Shader
END
IMAGE my_fb_ms0 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
IMAGE my_fb_ms1 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
IMAGE my_fb_ms2 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
IMAGE my_fb0 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT
IMAGE my_fb1 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT
IMAGE my_fb2 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT
PIPELINE graphics my_pipeline
ATTACH my_shader
ATTACH my_fragment
FRAMEBUFFER_SIZE 64 64
BIND BUFFER my_fb_ms0 AS color LOCATION 0
BIND BUFFER my_fb_ms1 AS color LOCATION 1
BIND BUFFER my_fb_ms2 AS color LOCATION 2
BIND BUFFER my_fb0 AS resolve
BIND BUFFER my_fb1 AS resolve
BIND BUFFER my_fb2 AS resolve
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& resolve_targets = pipeline->GetResolveTargets();
ASSERT_EQ(3U, resolve_targets.size());
for (const auto& buf_info : resolve_targets) {
ASSERT_TRUE(buf_info.buffer != nullptr);
EXPECT_EQ(64u * 64u, buf_info.buffer->ElementCount());
EXPECT_EQ(64u * 64u * 4u, buf_info.buffer->ValueCount());
EXPECT_EQ(64u * 64u * 4u * sizeof(float),
buf_info.buffer->GetSizeInBytes());
}
}
} // namespace amberscript
} // namespace amber