Snap for 9728260 from 7c0d959d201b13b1143a258a859eab384f7321bb to udc-release

Change-Id: Iad2ba44296b4f267bab414455de1a75a5a985641
diff --git a/docs/amber_script.md b/docs/amber_script.md
index 7c78d82..9bd58d7 100644
--- a/docs/amber_script.md
+++ b/docs/amber_script.md
@@ -350,9 +350,19 @@
  * `float_opaque_white`
  * `int_opaque_white`
 
+#### Compare operations
+* `never`
+* `less`
+* `equal`
+* `less_or_equal`
+* `greater`
+* `not_equal`
+* `greater_or_equal`
+* `always`
+
 ```groovy
 
-# Creates a sampler with |name|.
+# Creates a sampler with |name|. |compare_enable| is either on or off.
 SAMPLER {name} \
     [ MAG_FILTER {filter_type} (default nearest) ] \
     [ MIN_FILTER {filter_type} (default nearest) ] \
@@ -362,7 +372,9 @@
     [ BORDER_COLOR {border_color} (default float_transparent_black) ] \
     [ MIN_LOD _val_ (default 0.0) ] \
     [ MAX_LOD _val_ (default 1.0) ] \
-    [ NORMALIZED_COORDS | UNNORMALIZED_COORDS (default NORMALIZED_COORDS) ]
+    [ NORMALIZED_COORDS | UNNORMALIZED_COORDS (default NORMALIZED_COORDS) ] \
+    [ COMPARE _compare_enable_ (default off) ] \
+    [ COMPARE_OP _compare_op_ (default never) ]
 ```
 
 Note: unnormalized coordinates will override MIN\_LOD and MAX\_LOD to 0.0.
diff --git a/src/amberscript/parser.cc b/src/amberscript/parser.cc
index d3e0eb6..8cd6e19 100644
--- a/src/amberscript/parser.cc
+++ b/src/amberscript/parser.cc
@@ -3893,6 +3893,30 @@
       sampler->SetNormalizedCoords(false);
       sampler->SetMinLOD(0.0f);
       sampler->SetMaxLOD(0.0f);
+    } else if (param == "COMPARE") {
+      token = tokenizer_->NextToken();
+
+      if (!token->IsIdentifier())
+        return Result("invalid value for COMPARE");
+
+      if (token->AsString() == "on")
+        sampler->SetCompareEnable(true);
+      else if (token->AsString() == "off")
+        sampler->SetCompareEnable(false);
+      else
+        return Result("invalid value for COMPARE: " + token->AsString());
+    } else if (param == "COMPARE_OP") {
+      token = tokenizer_->NextToken();
+
+      if (!token->IsIdentifier())
+        return Result("invalid value for COMPARE_OP");
+
+      CompareOp compare_op = StrToCompareOp(token->AsString());
+      if (compare_op != CompareOp::kUnknown) {
+        sampler->SetCompareOp(compare_op);
+      } else {
+        return Result("invalid value for COMPARE_OP: " + token->AsString());
+      }
     } else {
       return Result("unexpected sampler parameter " + param);
     }
diff --git a/src/amberscript/parser_sampler_test.cc b/src/amberscript/parser_sampler_test.cc
index 6cba69d..d4b0dd1 100644
--- a/src/amberscript/parser_sampler_test.cc
+++ b/src/amberscript/parser_sampler_test.cc
@@ -45,6 +45,8 @@
   EXPECT_EQ(0.0, sampler->GetMinLOD());
   EXPECT_EQ(1.0, sampler->GetMaxLOD());
   EXPECT_EQ(true, sampler->GetNormalizedCoords());
+  EXPECT_EQ(false, sampler->GetCompareEnable());
+  EXPECT_EQ(CompareOp::kNever, sampler->GetCompareOp());
 }
 
 TEST_F(AmberScriptParserTest, SamplerCustomValues) {
@@ -57,7 +59,9 @@
   BORDER_COLOR float_opaque_white \
   MIN_LOD 2.5 \
   MAX_LOD 5.0 \
-  NORMALIZED_COORDS)";
+  NORMALIZED_COORDS \
+  COMPARE on \
+  COMPARE_OP greater)";
 
   Parser parser;
   Result r = parser.Parse(in);
@@ -81,6 +85,8 @@
   EXPECT_EQ(2.5, sampler->GetMinLOD());
   EXPECT_EQ(5.0, sampler->GetMaxLOD());
   EXPECT_EQ(true, sampler->GetNormalizedCoords());
+  EXPECT_EQ(true, sampler->GetCompareEnable());
+  EXPECT_EQ(CompareOp::kGreater, sampler->GetCompareOp());
 }
 
 TEST_F(AmberScriptParserTest, SamplerUnexpectedParameter) {
diff --git a/src/clspv_helper.cc b/src/clspv_helper.cc
index 59b8737..4be5bfa 100644
--- a/src/clspv_helper.cc
+++ b/src/clspv_helper.cc
@@ -258,9 +258,10 @@
   for (const auto& option : shader_info->GetCompileOptions()) {
     options += option + " ";
   }
+  std::string error_log;
   if (clspv::CompileFromSourceString(src_str, /* sampler map */ "", options,
-                                     generated_binary)) {
-    return Result("Clspv compile failed");
+                                     generated_binary, &error_log)) {
+    return Result("Clspv compile error: " + error_log);
   }
 
   // Parse the reflection instructions.
diff --git a/src/sampler.h b/src/sampler.h
index c44316a..f16e4cd 100644
--- a/src/sampler.h
+++ b/src/sampler.h
@@ -23,6 +23,7 @@
 
 #include "amber/result.h"
 #include "amber/value.h"
+#include "src/command_data.h"
 #include "src/format.h"
 
 namespace amber {
@@ -86,6 +87,14 @@
   void SetNormalizedCoords(bool norm) { normalized_coords_ = norm; }
   bool GetNormalizedCoords() const { return normalized_coords_; }
 
+  void SetCompareEnable(bool compare_enable) {
+    compare_enable_ = compare_enable;
+  }
+  bool GetCompareEnable() const { return compare_enable_; }
+
+  void SetCompareOp(CompareOp compare_op) { compare_op_ = compare_op; }
+  CompareOp GetCompareOp() const { return compare_op_; }
+
  private:
   std::string name_;
   FilterType min_filter_ = FilterType::kNearest;
@@ -98,6 +107,8 @@
   float min_lod_ = 0.0f;
   float max_lod_ = 1.0f;
   bool normalized_coords_ = true;
+  bool compare_enable_ = false;
+  CompareOp compare_op_ = CompareOp::kNever;
 };
 
 }  // namespace amber
diff --git a/src/vkscript/command_parser.cc b/src/vkscript/command_parser.cc
index 610c7e6..3429d4d 100644
--- a/src/vkscript/command_parser.cc
+++ b/src/vkscript/command_parser.cc
@@ -486,7 +486,6 @@
                                   std::vector<Value>* values) {
   assert(values);
 
-  uint32_t row_index = 0;
   auto token = tokenizer_->NextToken();
   size_t seen = 0;
   while (!token->IsEOL() && !token->IsEOS()) {
@@ -515,7 +514,6 @@
     values->push_back(v);
     token = tokenizer_->NextToken();
 
-    ++row_index;
     ++seen;
   }
 
diff --git a/src/vulkan/index_buffer.cc b/src/vulkan/index_buffer.cc
index b651427..30b223d 100644
--- a/src/vulkan/index_buffer.cc
+++ b/src/vulkan/index_buffer.cc
@@ -36,6 +36,15 @@
   if (buffer->ElementCount() == 0)
     return Result("IndexBuffer::SendIndexData |buffer| is empty");
 
+  if (buffer->GetFormat()->IsUint32())
+    index_type_ = VK_INDEX_TYPE_UINT32;
+  else if (buffer->GetFormat()->IsUint16())
+    index_type_ = VK_INDEX_TYPE_UINT16;
+  else if (buffer->GetFormat()->IsUint8())
+    index_type_ = VK_INDEX_TYPE_UINT8_EXT;
+  else
+    return Result("IndexBuffer::SendIndexData unexpected index buffer format");
+
   transfer_buffer_ =
       MakeUnique<TransferBuffer>(device_, buffer->GetSizeInBytes(), nullptr);
   Result r = transfer_buffer_->AddUsageFlags(VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
@@ -62,7 +71,7 @@
 
   device_->GetPtrs()->vkCmdBindIndexBuffer(command->GetVkCommandBuffer(),
                                            transfer_buffer_->GetVkBuffer(), 0,
-                                           VK_INDEX_TYPE_UINT32);
+                                           index_type_);
   return {};
 }
 
diff --git a/src/vulkan/index_buffer.h b/src/vulkan/index_buffer.h
index 2d21330..4b22ebe 100644
--- a/src/vulkan/index_buffer.h
+++ b/src/vulkan/index_buffer.h
@@ -46,6 +46,7 @@
  private:
   Device* device_ = nullptr;
   std::unique_ptr<TransferBuffer> transfer_buffer_;
+  VkIndexType index_type_;
 };
 
 }  // namespace vulkan
diff --git a/src/vulkan/pipeline.cc b/src/vulkan/pipeline.cc
index df301e4..8cd4995 100644
--- a/src/vulkan/pipeline.cc
+++ b/src/vulkan/pipeline.cc
@@ -430,7 +430,9 @@
             "Vulkan: Pipeline::SendDescriptorDataToDeviceIfNeeded() "
             "descriptor's transfer resource is not found");
       }
-      descriptor_transfer_resources_[buffer]->Initialize();
+      Result r = descriptor_transfer_resources_[buffer]->Initialize();
+      if (!r.IsSuccess())
+         return r;
     }
 
     // Note that if a buffer for a descriptor is host accessible and
diff --git a/src/vulkan/sampler.cc b/src/vulkan/sampler.cc
index 979c098..c8995e8 100644
--- a/src/vulkan/sampler.cc
+++ b/src/vulkan/sampler.cc
@@ -52,6 +52,31 @@
   }
 }
 
+VkCompareOp ToVkCompareOp(CompareOp op) {
+  switch (op) {
+    case CompareOp::kNever:
+      return VK_COMPARE_OP_NEVER;
+    case CompareOp::kLess:
+      return VK_COMPARE_OP_LESS;
+    case CompareOp::kEqual:
+      return VK_COMPARE_OP_EQUAL;
+    case CompareOp::kLessOrEqual:
+      return VK_COMPARE_OP_LESS_OR_EQUAL;
+    case CompareOp::kGreater:
+      return VK_COMPARE_OP_GREATER;
+    case CompareOp::kNotEqual:
+      return VK_COMPARE_OP_NOT_EQUAL;
+    case CompareOp::kGreaterOrEqual:
+      return VK_COMPARE_OP_GREATER_OR_EQUAL;
+    case CompareOp::kAlways:
+      return VK_COMPARE_OP_ALWAYS;
+    case CompareOp::kUnknown:
+      break;
+  }
+  assert(false && "Vulkan::Unknown CompareOp");
+  return VK_COMPARE_OP_NEVER;
+}
+
 }  // namespace
 
 Sampler::Sampler(Device* device) : device_(device) {}
@@ -76,6 +101,9 @@
   sampler_info.maxLod = sampler->GetMaxLOD();
   sampler_info.unnormalizedCoordinates =
       (sampler->GetNormalizedCoords() ? VK_FALSE : VK_TRUE);
+  sampler_info.compareEnable =
+      (sampler->GetCompareEnable() ? VK_TRUE : VK_FALSE);
+  sampler_info.compareOp = ToVkCompareOp(sampler->GetCompareOp());
 
   if (device_->GetPtrs()->vkCreateSampler(device_->GetVkDevice(), &sampler_info,
                                           nullptr, &sampler_) != VK_SUCCESS) {
diff --git a/tests/cases/draw_indexed_uint16.amber b/tests/cases/draw_indexed_uint16.amber
new file mode 100644
index 0000000..f42e2b5
--- /dev/null
+++ b/tests/cases/draw_indexed_uint16.amber
@@ -0,0 +1,48 @@
+#!amber
+# Copyright 2022 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 vert_shader PASSTHROUGH
+SHADER fragment frag_shader GLSL
+#version 430
+layout(location = 0) out vec4 color_out;
+void main() {
+  color_out = vec4(0.0, 1.0, 0.0, 1.0);
+}
+END
+
+BUFFER position DATA_TYPE vec4<float> DATA
+-1.0  1.0 0.0 1.0
+ 1.0  1.0 0.0 1.0
+ 1.0 -1.0 0.0 1.0
+-1.0 -1.0 0.0 1.0
+END
+
+BUFFER indices DATA_TYPE uint16 DATA
+3 2 1 0
+END
+
+IMAGE framebuffer FORMAT B8G8R8A8_UNORM DIM_2D WIDTH 64 HEIGHT 64
+
+PIPELINE graphics pipeline
+  ATTACH vert_shader
+  ATTACH frag_shader
+  VERTEX_DATA position LOCATION 0
+  INDEX_DATA indices
+  FRAMEBUFFER_SIZE 64 64
+  BIND BUFFER framebuffer AS color LOCATION 0
+END
+
+RUN pipeline DRAW_ARRAY AS TRIANGLE_FAN INDEXED START_IDX 0 COUNT 4
+EXPECT framebuffer IDX 0 0 SIZE 64 64 EQ_RGBA 0 255 0 255
diff --git a/tests/cases/draw_indexed_uint32.amber b/tests/cases/draw_indexed_uint32.amber
new file mode 100644
index 0000000..3a2eac2
--- /dev/null
+++ b/tests/cases/draw_indexed_uint32.amber
@@ -0,0 +1,48 @@
+#!amber
+# Copyright 2022 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 vert_shader PASSTHROUGH
+SHADER fragment frag_shader GLSL
+#version 430
+layout(location = 0) out vec4 color_out;
+void main() {
+  color_out = vec4(0.0, 1.0, 0.0, 1.0);
+}
+END
+
+BUFFER position DATA_TYPE vec4<float> DATA
+-1.0  1.0 0.0 1.0
+ 1.0  1.0 0.0 1.0
+ 1.0 -1.0 0.0 1.0
+-1.0 -1.0 0.0 1.0
+END
+
+BUFFER indices DATA_TYPE uint32 DATA
+3 2 1 0
+END
+
+IMAGE framebuffer FORMAT B8G8R8A8_UNORM DIM_2D WIDTH 64 HEIGHT 64
+
+PIPELINE graphics pipeline
+  ATTACH vert_shader
+  ATTACH frag_shader
+  VERTEX_DATA position LOCATION 0
+  INDEX_DATA indices
+  FRAMEBUFFER_SIZE 64 64
+  BIND BUFFER framebuffer AS color LOCATION 0
+END
+
+RUN pipeline DRAW_ARRAY AS TRIANGLE_FAN INDEXED START_IDX 0 COUNT 4
+EXPECT framebuffer IDX 0 0 SIZE 64 64 EQ_RGBA 0 255 0 255
diff --git a/tests/cases/draw_indexed_uint8.amber b/tests/cases/draw_indexed_uint8.amber
new file mode 100644
index 0000000..a038233
--- /dev/null
+++ b/tests/cases/draw_indexed_uint8.amber
@@ -0,0 +1,50 @@
+#!amber
+# Copyright 2022 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.
+
+DEVICE_EXTENSION VK_EXT_index_type_uint8
+
+SHADER vertex vert_shader PASSTHROUGH
+SHADER fragment frag_shader GLSL
+#version 430
+layout(location = 0) out vec4 color_out;
+void main() {
+  color_out = vec4(0.0, 1.0, 0.0, 1.0);
+}
+END
+
+BUFFER position DATA_TYPE vec4<float> DATA
+-1.0  1.0 0.0 1.0
+ 1.0  1.0 0.0 1.0
+ 1.0 -1.0 0.0 1.0
+-1.0 -1.0 0.0 1.0
+END
+
+BUFFER indices DATA_TYPE uint8 DATA
+3 2 1 0
+END
+
+IMAGE framebuffer FORMAT B8G8R8A8_UNORM DIM_2D WIDTH 64 HEIGHT 64
+
+PIPELINE graphics pipeline
+  ATTACH vert_shader
+  ATTACH frag_shader
+  VERTEX_DATA position LOCATION 0
+  INDEX_DATA indices
+  FRAMEBUFFER_SIZE 64 64
+  BIND BUFFER framebuffer AS color LOCATION 0
+END
+
+RUN pipeline DRAW_ARRAY AS TRIANGLE_FAN INDEXED START_IDX 0 COUNT 4
+EXPECT framebuffer IDX 0 0 SIZE 64 64 EQ_RGBA 0 255 0 255
diff --git a/tests/run_tests.py b/tests/run_tests.py
index 6cd8fc3..23789f6 100755
--- a/tests/run_tests.py
+++ b/tests/run_tests.py
@@ -98,6 +98,8 @@
   "draw_rectangles_depth_test_x8d24.amber",
   # Tessellation not supported
   "tessellation_isolines.amber",
+  # 8 bit indices not supported
+  "draw_indexed_uint8.amber",
 ]
 
 OPENCL_CASES = [