Merge vk-gl-cts/master into vk-gl-cts/vulkan-cts-next-dev

Change-Id: If018dc6d1a4134e6890419870b28dead7b7f895c
diff --git a/AndroidGen.mk b/AndroidGen.mk
index 8625c06..2a85b45 100644
--- a/AndroidGen.mk
+++ b/AndroidGen.mk
@@ -214,7 +214,9 @@
 	external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsm16bitStorageTests.cpp \
 	external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp \
 	external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp \
+	external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmConditionalBranchTests.cpp \
 	external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp \
+	external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmIndexingTests.cpp \
 	external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp \
 	external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmTests.cpp \
 	external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUboMatrixPaddingTests.cpp \
diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt
index 9006114..d11d64c 100644
--- a/android/cts/master/vk-master.txt
+++ b/android/cts/master/vk-master.txt
@@ -162682,6 +162682,26 @@
 dEQP-VK.spirv_assembly.instruction.compute.16bit_storage.push_constant_16_to_32.vector_sint
 dEQP-VK.spirv_assembly.instruction.compute.16bit_storage.push_constant_16_to_32.vector_uint
 dEQP-VK.spirv_assembly.instruction.compute.ubo_padding.mat2x2
+dEQP-VK.spirv_assembly.instruction.compute.conditional_branch.same_labels_true
+dEQP-VK.spirv_assembly.instruction.compute.conditional_branch.same_labels_false
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opaccesschain_u16
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opaccesschain_s16
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opaccesschain_u32
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opaccesschain_s32
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opaccesschain_u64
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opaccesschain_s64
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opinboundsaccesschain_u16
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opinboundsaccesschain_s16
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opinboundsaccesschain_u32
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opinboundsaccesschain_s32
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opinboundsaccesschain_u64
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opinboundsaccesschain_s64
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opptraccesschain_u16
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opptraccesschain_s16
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opptraccesschain_u32
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opptraccesschain_s32
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opptraccesschain_u64
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opptraccesschain_s64
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opselect_single_buffer
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opfunctioncall_single_buffer
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opphi_single_buffer
@@ -164724,6 +164744,106 @@
 dEQP-VK.spirv_assembly.instruction.graphics.ubo_padding.mat2x2_tesse
 dEQP-VK.spirv_assembly.instruction.graphics.ubo_padding.mat2x2_geom
 dEQP-VK.spirv_assembly.instruction.graphics.ubo_padding.mat2x2_frag
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_true_vert
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_true_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_true_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_true_geom
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_true_frag
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_false_vert
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_false_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_false_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_false_geom
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_false_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u16_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u16_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u16_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u16_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u16_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s16_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s16_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s16_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s16_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s16_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u32_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u32_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u32_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u32_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u32_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s32_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s32_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s32_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s32_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s32_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u64_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u64_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u64_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u64_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u64_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s64_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s64_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s64_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s64_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s64_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u16_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u16_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u16_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u16_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u16_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s16_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s16_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s16_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s16_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s16_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u32_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u32_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u32_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u32_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u32_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s32_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s32_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s32_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s32_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s32_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u64_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u64_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u64_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u64_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u64_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s64_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s64_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s64_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s64_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s64_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u16_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u16_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u16_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u16_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u16_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s16_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s16_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s16_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s16_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s16_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u32_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u32_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u32_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u32_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u32_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s32_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s32_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s32_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s32_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s32_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u64_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u64_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u64_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u64_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u64_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s64_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s64_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s64_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s64_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s64_frag
 dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_vert
 dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_tessc
 dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_tesse
diff --git a/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl44-master.txt b/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl44-master.txt
index 51e7861..bbf1667 100644
--- a/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl44-master.txt
+++ b/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl44-master.txt
@@ -5912,6 +5912,10 @@
 KHR-GL44.tessellation_shader.tessellation_invariance.invariance_rule5
 KHR-GL44.tessellation_shader.tessellation_invariance.invariance_rule6
 KHR-GL44.tessellation_shader.tessellation_invariance.invariance_rule7
+KHR-GL44.tessellation_shader.winding.triangles_ccw
+KHR-GL44.tessellation_shader.winding.triangles_cw
+KHR-GL44.tessellation_shader.winding.quads_ccw
+KHR-GL44.tessellation_shader.winding.quads_cw
 KHR-GL44.texture_cube_map_array.sampling
 KHR-GL44.texture_cube_map_array.color_depth_attachments
 KHR-GL44.texture_cube_map_array.stencil_attachments_mutable_nonlayered
diff --git a/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl45-master.txt b/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl45-master.txt
index 3b3b0d5..c2f050e 100644
--- a/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl45-master.txt
+++ b/external/openglcts/data/mustpass/gl/khronos_mustpass/4.5.5.x/gl45-master.txt
@@ -5913,6 +5913,10 @@
 KHR-GL45.tessellation_shader.tessellation_invariance.invariance_rule5
 KHR-GL45.tessellation_shader.tessellation_invariance.invariance_rule6
 KHR-GL45.tessellation_shader.tessellation_invariance.invariance_rule7
+KHR-GL45.tessellation_shader.winding.triangles_ccw
+KHR-GL45.tessellation_shader.winding.triangles_cw
+KHR-GL45.tessellation_shader.winding.quads_ccw
+KHR-GL45.tessellation_shader.winding.quads_cw
 KHR-GL45.texture_cube_map_array.sampling
 KHR-GL45.texture_cube_map_array.color_depth_attachments
 KHR-GL45.texture_cube_map_array.stencil_attachments_mutable_nonlayered
diff --git a/external/openglcts/data/mustpass/gles/khronos_mustpass/3.2.4.x/gles31-khr-master.txt b/external/openglcts/data/mustpass/gles/khronos_mustpass/3.2.4.x/gles31-khr-master.txt
index d9df703..7109665 100644
--- a/external/openglcts/data/mustpass/gles/khronos_mustpass/3.2.4.x/gles31-khr-master.txt
+++ b/external/openglcts/data/mustpass/gles/khronos_mustpass/3.2.4.x/gles31-khr-master.txt
@@ -2459,6 +2459,10 @@
 KHR-GLES31.core.tessellation_shader.tessellation_invariance.invariance_rule5
 KHR-GLES31.core.tessellation_shader.tessellation_invariance.invariance_rule6
 KHR-GLES31.core.tessellation_shader.tessellation_invariance.invariance_rule7
+KHR-GLES31.core.tessellation_shader.winding.triangles_ccw
+KHR-GLES31.core.tessellation_shader.winding.triangles_cw
+KHR-GLES31.core.tessellation_shader.winding.quads_ccw
+KHR-GLES31.core.tessellation_shader.winding.quads_cw
 KHR-GLES31.core.texture_cube_map_array.sampling
 KHR-GLES31.core.texture_cube_map_array.color_depth_attachments
 KHR-GLES31.core.texture_cube_map_array.stencil_attachments_mutable_nonlayered
diff --git a/external/openglcts/data/mustpass/gles/khronos_mustpass/3.2.4.x/gles32-khr-master.txt b/external/openglcts/data/mustpass/gles/khronos_mustpass/3.2.4.x/gles32-khr-master.txt
index b548528..1fc660d 100644
--- a/external/openglcts/data/mustpass/gles/khronos_mustpass/3.2.4.x/gles32-khr-master.txt
+++ b/external/openglcts/data/mustpass/gles/khronos_mustpass/3.2.4.x/gles32-khr-master.txt
@@ -225,6 +225,10 @@
 KHR-GLES32.core.tessellation_shader.tessellation_invariance.invariance_rule5
 KHR-GLES32.core.tessellation_shader.tessellation_invariance.invariance_rule6
 KHR-GLES32.core.tessellation_shader.tessellation_invariance.invariance_rule7
+KHR-GLES32.core.tessellation_shader.winding.triangles_ccw
+KHR-GLES32.core.tessellation_shader.winding.triangles_cw
+KHR-GLES32.core.tessellation_shader.winding.quads_ccw
+KHR-GLES32.core.tessellation_shader.winding.quads_cw
 KHR-GLES32.core.texture_cube_map_array.sampling
 KHR-GLES32.core.texture_cube_map_array.color_depth_attachments
 KHR-GLES32.core.texture_cube_map_array.stencil_attachments_mutable_nonlayered
diff --git a/external/openglcts/data/mustpass/gles/khronos_mustpass/master/gles31-khr-master.txt b/external/openglcts/data/mustpass/gles/khronos_mustpass/master/gles31-khr-master.txt
index d9df703..7109665 100644
--- a/external/openglcts/data/mustpass/gles/khronos_mustpass/master/gles31-khr-master.txt
+++ b/external/openglcts/data/mustpass/gles/khronos_mustpass/master/gles31-khr-master.txt
@@ -2459,6 +2459,10 @@
 KHR-GLES31.core.tessellation_shader.tessellation_invariance.invariance_rule5
 KHR-GLES31.core.tessellation_shader.tessellation_invariance.invariance_rule6
 KHR-GLES31.core.tessellation_shader.tessellation_invariance.invariance_rule7
+KHR-GLES31.core.tessellation_shader.winding.triangles_ccw
+KHR-GLES31.core.tessellation_shader.winding.triangles_cw
+KHR-GLES31.core.tessellation_shader.winding.quads_ccw
+KHR-GLES31.core.tessellation_shader.winding.quads_cw
 KHR-GLES31.core.texture_cube_map_array.sampling
 KHR-GLES31.core.texture_cube_map_array.color_depth_attachments
 KHR-GLES31.core.texture_cube_map_array.stencil_attachments_mutable_nonlayered
diff --git a/external/openglcts/data/mustpass/gles/khronos_mustpass/master/gles32-khr-master.txt b/external/openglcts/data/mustpass/gles/khronos_mustpass/master/gles32-khr-master.txt
index e60ab82..faaabc9 100644
--- a/external/openglcts/data/mustpass/gles/khronos_mustpass/master/gles32-khr-master.txt
+++ b/external/openglcts/data/mustpass/gles/khronos_mustpass/master/gles32-khr-master.txt
@@ -226,6 +226,10 @@
 KHR-GLES32.core.tessellation_shader.tessellation_invariance.invariance_rule5
 KHR-GLES32.core.tessellation_shader.tessellation_invariance.invariance_rule6
 KHR-GLES32.core.tessellation_shader.tessellation_invariance.invariance_rule7
+KHR-GLES32.core.tessellation_shader.winding.triangles_ccw
+KHR-GLES32.core.tessellation_shader.winding.triangles_cw
+KHR-GLES32.core.tessellation_shader.winding.quads_ccw
+KHR-GLES32.core.tessellation_shader.winding.quads_cw
 KHR-GLES32.core.texture_cube_map_array.sampling
 KHR-GLES32.core.texture_cube_map_array.color_depth_attachments
 KHR-GLES32.core.texture_cube_map_array.stencil_attachments_mutable_nonlayered
diff --git a/external/openglcts/modules/glesext/CMakeLists.txt b/external/openglcts/modules/glesext/CMakeLists.txt
index 6a14c24..821e4a8 100644
--- a/external/openglcts/modules/glesext/CMakeLists.txt
+++ b/external/openglcts/modules/glesext/CMakeLists.txt
@@ -121,6 +121,8 @@
     tessellation_shader/esextcTessellationShaderTriangles.hpp
     tessellation_shader/esextcTessellationShaderUtils.cpp
     tessellation_shader/esextcTessellationShaderUtils.hpp
+    tessellation_shader/esextcTessellationShaderWinding.cpp
+    tessellation_shader/esextcTessellationShaderWinding.hpp
     tessellation_shader/esextcTessellationShaderVertexOrdering.cpp
     tessellation_shader/esextcTessellationShaderVertexOrdering.hpp
     tessellation_shader/esextcTessellationShaderVertexSpacing.cpp
diff --git a/external/openglcts/modules/glesext/tessellation_shader/esextcTessellationShaderTests.cpp b/external/openglcts/modules/glesext/tessellation_shader/esextcTessellationShaderTests.cpp
index 123ef01..c98a77e 100644
--- a/external/openglcts/modules/glesext/tessellation_shader/esextcTessellationShaderTests.cpp
+++ b/external/openglcts/modules/glesext/tessellation_shader/esextcTessellationShaderTests.cpp
@@ -37,6 +37,7 @@
 #include "esextcTessellationShaderTriangles.hpp"
 #include "esextcTessellationShaderVertexOrdering.hpp"
 #include "esextcTessellationShaderVertexSpacing.hpp"
+#include "esextcTessellationShaderWinding.hpp"
 #include "esextcTessellationShaderXFB.hpp"
 
 namespace glcts
@@ -85,6 +86,7 @@
 	addChild(new TessellationShaderBarrierTests(m_context, m_extParams));
 	addChild(new TessellationShaderErrors(m_context, m_extParams));
 	addChild(new TessellationShaderInvarianceTests(m_context, m_extParams));
+	addChild(new TesselationShaderWindingTests(m_context, m_extParams));
 }
 
 } // namespace glcts
diff --git a/external/openglcts/modules/glesext/tessellation_shader/esextcTessellationShaderWinding.cpp b/external/openglcts/modules/glesext/tessellation_shader/esextcTessellationShaderWinding.cpp
new file mode 100644
index 0000000..0a5792f
--- /dev/null
+++ b/external/openglcts/modules/glesext/tessellation_shader/esextcTessellationShaderWinding.cpp
@@ -0,0 +1,267 @@
+/*-------------------------------------------------------------------------
+ * OpenGL Conformance Test Suite
+ * -----------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * 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 implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */ /*!
+ * \file esextcTessellationShaderWinding.cpp
+ * \brief Test winding order with tessellation shaders
+ */ /*-------------------------------------------------------------------*/
+
+#include "esextcTessellationShaderWinding.hpp"
+#include "deSharedPtr.hpp"
+#include "esextcTessellationShaderUtils.hpp"
+#include "gluContextInfo.hpp"
+#include "gluDefs.hpp"
+#include "gluPixelTransfer.hpp"
+#include "gluShaderProgram.hpp"
+#include "glwEnums.hpp"
+#include "glwFunctions.hpp"
+#include "tcuRGBA.hpp"
+#include "tcuSurface.hpp"
+#include "tcuTestLog.hpp"
+#include <string>
+
+namespace glcts
+{
+
+class WindingCase : public TestCaseBase
+{
+public:
+	WindingCase(glcts::Context& context, const ExtParameters& extParams, std::string name, std::string primitiveType,
+				std::string winding);
+
+	void		  init(void);
+	void		  deinit(void);
+	IterateResult iterate(void);
+
+private:
+	static const int RENDER_SIZE = 64;
+
+	de::SharedPtr<const glu::ShaderProgram> m_program;
+};
+
+WindingCase::WindingCase(glcts::Context& context, const ExtParameters& extParams, std::string name,
+						 std::string primitiveType, std::string winding)
+	: TestCaseBase(context, extParams, name.c_str(), "")
+{
+	DE_ASSERT((primitiveType.compare("triangles") == 0) || (primitiveType.compare("quads") == 0));
+	DE_ASSERT((winding.compare("cw") == 0) || (winding.compare("ccw") == 0));
+
+	m_specializationMap["PRIMITIVE_TYPE"] = primitiveType;
+	m_specializationMap["WINDING"]		  = winding;
+}
+
+void WindingCase::init(void)
+{
+	TestCaseBase::init();
+	if (!m_is_tessellation_shader_supported)
+	{
+		TCU_THROW(NotSupportedError, TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
+	}
+
+	TestCaseBase::init();
+
+	const char* vs("${VERSION}\n"
+				   "void main (void)\n"
+				   "{\n"
+				   "}\n");
+	const char* tcs("${VERSION}\n"
+					"${TESSELLATION_SHADER_REQUIRE}\n"
+					"layout (vertices = 1) out;\n"
+					"void main (void)\n"
+					"{\n"
+					"	gl_TessLevelInner[0] = 5.0;\n"
+					"	gl_TessLevelInner[1] = 5.0;\n"
+					"\n"
+					"	gl_TessLevelOuter[0] = 5.0;\n"
+					"	gl_TessLevelOuter[1] = 5.0;\n"
+					"	gl_TessLevelOuter[2] = 5.0;\n"
+					"	gl_TessLevelOuter[3] = 5.0;\n"
+					"}\n");
+	const char* tes("${VERSION}\n"
+					"${TESSELLATION_SHADER_REQUIRE}\n"
+					"layout (${PRIMITIVE_TYPE}, ${WINDING}) in;\n"
+					"void main (void)\n"
+					"{\n"
+					"	gl_Position = vec4(gl_TessCoord.xy*2.0 - 1.0, 0.0, 1.0);\n"
+					"}\n");
+	const char* fs("${VERSION}\n"
+				   "layout (location = 0) out mediump vec4 o_color;\n"
+				   "void main (void)\n"
+				   "{\n"
+				   "	o_color = vec4(1.0);\n"
+				   "}\n");
+
+	m_program = de::SharedPtr<const glu::ShaderProgram>(
+		new glu::ShaderProgram(m_context.getRenderContext(),
+							   glu::ProgramSources() << glu::VertexSource(specializeShader(1, &vs))
+													 << glu::TessellationControlSource(specializeShader(1, &tcs))
+													 << glu::TessellationEvaluationSource(specializeShader(1, &tes))
+													 << glu::FragmentSource(specializeShader(1, &fs))));
+
+	m_testCtx.getLog() << *m_program;
+	if (!m_program->isOk())
+		TCU_FAIL("Program compilation failed");
+}
+
+void WindingCase::deinit(void)
+{
+	m_program.clear();
+}
+
+WindingCase::IterateResult WindingCase::iterate(void)
+{
+	const glu::RenderContext& renderCtx = m_context.getRenderContext();
+	const deUint32			  programGL = m_program->getProgram();
+	const glw::Functions&	 gl		= renderCtx.getFunctions();
+
+	const unsigned int windingTaken[2]	 = { GL_CW, GL_CCW };
+	const char*		   windingTakenName[2] = { "GL_CW", "GL_CCW" };
+
+	const bool testPrimitiveTypeIsTriangles = (m_specializationMap["PRIMITIVE_TYPE"].compare("triangles") == 0);
+	const bool testWindingIsCW				= (m_specializationMap["WINDING"].compare("cw") == 0);
+	bool	   success						= true;
+
+	gl.viewport(0, 0, RENDER_SIZE, RENDER_SIZE);
+	gl.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
+	gl.useProgram(programGL);
+
+	gl.patchParameteri(GL_PATCH_VERTICES, 1);
+
+	gl.enable(GL_CULL_FACE);
+
+	deUint32 vaoGL;
+	gl.genVertexArrays(1, &vaoGL);
+	gl.bindVertexArray(vaoGL);
+
+	m_testCtx.getLog() << tcu::TestLog::Message << "Face culling enabled" << tcu::TestLog::EndMessage;
+
+	for (int windingIndex = 0; windingIndex < 2; windingIndex++)
+	{
+		m_testCtx.getLog() << tcu::TestLog::Message << "Setting glFrontFace(" << windingTakenName[windingIndex] << ")"
+						   << tcu::TestLog::EndMessage;
+
+		gl.frontFace(windingTaken[windingIndex]);
+
+		gl.clear(GL_COLOR_BUFFER_BIT);
+		gl.drawArrays(GL_PATCHES, 0, 1);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
+
+		{
+			tcu::Surface rendered(RENDER_SIZE, RENDER_SIZE);
+			glu::readPixels(renderCtx, 0, 0, rendered.getAccess());
+			m_testCtx.getLog() << tcu::TestLog::Image("RenderedImage", "Rendered Image", rendered);
+
+			{
+				const int badPixelTolerance =
+					testPrimitiveTypeIsTriangles ? 5 * de::max(rendered.getWidth(), rendered.getHeight()) : 0;
+				const int totalNumPixels = rendered.getWidth() * rendered.getHeight();
+
+				int numWhitePixels = 0;
+				int numRedPixels   = 0;
+				for (int y = 0; y < rendered.getHeight(); y++)
+					for (int x = 0; x < rendered.getWidth(); x++)
+					{
+						numWhitePixels += rendered.getPixel(x, y) == tcu::RGBA::white() ? 1 : 0;
+						numRedPixels += rendered.getPixel(x, y) == tcu::RGBA::red() ? 1 : 0;
+					}
+
+				DE_ASSERT(numWhitePixels + numRedPixels <= totalNumPixels);
+
+				m_testCtx.getLog() << tcu::TestLog::Message << "Note: got " << numWhitePixels << " white and "
+								   << numRedPixels << " red pixels" << tcu::TestLog::EndMessage;
+
+				if (totalNumPixels - numWhitePixels - numRedPixels > badPixelTolerance)
+				{
+					m_testCtx.getLog() << tcu::TestLog::Message << "Failure: Got "
+									   << totalNumPixels - numWhitePixels - numRedPixels
+									   << " other than white or red pixels (maximum tolerance " << badPixelTolerance
+									   << ")" << tcu::TestLog::EndMessage;
+					success = false;
+					break;
+				}
+
+				bool frontFaceWindingIsCW = (windingIndex == 0);
+				if (frontFaceWindingIsCW == testWindingIsCW)
+				{
+					if (testPrimitiveTypeIsTriangles)
+					{
+						if (de::abs(numWhitePixels - totalNumPixels / 2) > badPixelTolerance)
+						{
+							m_testCtx.getLog() << tcu::TestLog::Message
+											   << "Failure: wrong number of white pixels; expected approximately "
+											   << totalNumPixels / 2 << tcu::TestLog::EndMessage;
+							success = false;
+							break;
+						}
+					}
+					else // test primitive type is quads
+					{
+						if (numWhitePixels != totalNumPixels)
+						{
+							m_testCtx.getLog()
+								<< tcu::TestLog::Message << "Failure: expected only white pixels (full-viewport quad)"
+								<< tcu::TestLog::EndMessage;
+							success = false;
+							break;
+						}
+					}
+				}
+				else
+				{
+					if (numWhitePixels != 0)
+					{
+						m_testCtx.getLog()
+							<< tcu::TestLog::Message << "Failure: expected only red pixels (everything culled)"
+							<< tcu::TestLog::EndMessage;
+						success = false;
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	gl.bindVertexArray(0);
+	gl.deleteVertexArrays(1, &vaoGL);
+
+	m_testCtx.setTestResult(success ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
+							success ? "Pass" : "Image verification failed");
+	return STOP;
+}
+
+/** Constructor
+ *
+ * @param context Test context
+ **/
+TesselationShaderWindingTests::TesselationShaderWindingTests(glcts::Context& context, const ExtParameters& extParams)
+	: TestCaseGroupBase(context, extParams, "winding", "Verifies winding order with tessellation shaders")
+{
+}
+
+/**
+ * Initializes test groups for winding tests
+ **/
+void TesselationShaderWindingTests::init(void)
+{
+	addChild(new WindingCase(m_context, m_extParams, "triangles_ccw", "triangles", "ccw"));
+	addChild(new WindingCase(m_context, m_extParams, "triangles_cw", "triangles", "cw"));
+	addChild(new WindingCase(m_context, m_extParams, "quads_ccw", "quads", "ccw"));
+	addChild(new WindingCase(m_context, m_extParams, "quads_cw", "quads", "cw"));
+}
+
+} /* namespace glcts */
diff --git a/external/openglcts/modules/glesext/tessellation_shader/esextcTessellationShaderWinding.hpp b/external/openglcts/modules/glesext/tessellation_shader/esextcTessellationShaderWinding.hpp
new file mode 100644
index 0000000..b34151c
--- /dev/null
+++ b/external/openglcts/modules/glesext/tessellation_shader/esextcTessellationShaderWinding.hpp
@@ -0,0 +1,54 @@
+#ifndef _ESEXTCTESSELLATIONSHADERWINDING_HPP
+#define _ESEXTCTESSELLATIONSHADERWINDING_HPP
+/*-------------------------------------------------------------------------
+ * OpenGL Conformance Test Suite
+ * -----------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * 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 implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */ /*!
+ * \file esextcTessellationShaderWinding.hpp
+ * \brief Test winding order with tessellation shaders
+ */ /*-------------------------------------------------------------------*/
+
+#include "../esextcTestCaseBase.hpp"
+#include "esextcTessellationShaderUtils.hpp"
+#include "gluShaderUtil.hpp"
+#include "tcuDefs.hpp"
+
+namespace glcts
+{
+
+class TesselationShaderWindingTests : public glcts::TestCaseGroupBase
+{
+public:
+	/* Public methods */
+	TesselationShaderWindingTests(glcts::Context& context, const ExtParameters& extParams);
+
+	virtual ~TesselationShaderWindingTests(void)
+	{
+	}
+
+	void init(void);
+
+private:
+	/* Private methods */
+	TesselationShaderWindingTests(const TesselationShaderWindingTests& other);
+	TesselationShaderWindingTests& operator=(const TesselationShaderWindingTests& other);
+};
+
+} // namespace glcts
+
+#endif // _ESEXTCTESSELLATIONSHADERWINDING_HPP
diff --git a/external/vulkancts/modules/vulkan/api/vktApiBufferTests.cpp b/external/vulkancts/modules/vulkan/api/vktApiBufferTests.cpp
index 2e960cb..fa4e3a7 100644
--- a/external/vulkancts/modules/vulkan/api/vktApiBufferTests.cpp
+++ b/external/vulkancts/modules/vulkan/api/vktApiBufferTests.cpp
@@ -31,6 +31,7 @@
 #include "vkQueryUtil.hpp"
 #include "vkRefUtil.hpp"
 #include "vktTestCase.hpp"
+#include "tcuPlatform.hpp"
 
 #include <algorithm>
 
@@ -50,6 +51,35 @@
 	ALLOCATION_KIND_LAST,
 };
 
+PlatformMemoryLimits getPlatformMemoryLimits (Context& context)
+{
+	PlatformMemoryLimits	memoryLimits;
+
+	context.getTestContext().getPlatform().getVulkanPlatform().getMemoryLimits(memoryLimits);
+
+	return memoryLimits;
+}
+
+VkDeviceSize getMaxBufferSize(const VkDeviceSize& bufferSize,
+							  const VkDeviceSize& alignment,
+							  const PlatformMemoryLimits& limits)
+{
+	VkDeviceSize size = bufferSize;
+
+	if (limits.totalDeviceLocalMemory == 0)
+	{
+		// 'UMA' systems where device memory counts against system memory
+		size = std::min(bufferSize, limits.totalSystemMemory - alignment);
+	}
+	else
+	{
+		// 'LMA' systems where device memory is local to the GPU
+		size = std::min(bufferSize, limits.totalDeviceLocalMemory - alignment);
+	}
+
+	return size;
+}
+
 struct BufferCaseParameters
 {
 	VkBufferUsageFlags	usage;
@@ -310,9 +340,21 @@
 		const deUint32					heapTypeIndex					= (deUint32)deCtz32(memReqs.memoryTypeBits);
 		const VkMemoryType				memoryType						= memoryProperties.memoryTypes[heapTypeIndex];
 		const VkMemoryHeap				memoryHeap						= memoryProperties.memoryHeaps[memoryType.heapIndex];
-		const VkDeviceSize				maxBufferSize					= deAlign64(memoryHeap.size >> 1u, memReqs.alignment);
 		const deUint32					shrinkBits						= 4u;	// number of bits to shift when reducing the size with each iteration
 
+		// Buffer size - Choose half of the reported heap size for the maximum buffer size, we
+		// should attempt to test as large a portion as possible.
+		//
+		// However on a system where device memory is shared with the system, the maximum size
+		// should be tested against the platform memory limits as significant portion of the heap
+		// may already be in use by the operating system and other running processes.
+		const VkDeviceSize  availableBufferSize	= getMaxBufferSize(memoryHeap.size,
+																   memReqs.alignment,
+																   getPlatformMemoryLimits(m_context));
+
+		// For our test buffer size, halve the maximum available size and align
+		const VkDeviceSize maxBufferSize = deAlign64(availableBufferSize >> 1, memReqs.alignment);
+
 		size = std::min(size, maxBufferSize);
 
 		while (*memory == DE_NULL)
diff --git a/external/vulkancts/modules/vulkan/clipping/vktClippingTests.cpp b/external/vulkancts/modules/vulkan/clipping/vktClippingTests.cpp
index 0252c1c..9b82e43 100644
--- a/external/vulkancts/modules/vulkan/clipping/vktClippingTests.cpp
+++ b/external/vulkancts/modules/vulkan/clipping/vktClippingTests.cpp
@@ -586,11 +586,6 @@
 			}
 		}
 	}
-	else
-	{
-		//TODO: Now we have 2 cases {some-points-drawn|nothing}, we should have {all-points-drawn|some-points-drawn|nothing}
-		return tcu::TestStatus::pass("OK");
-	}
 
 	std::vector<VulkanShader> shaders;
 	shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT,		context.getBinaryCollection().get("vert")));
@@ -606,14 +601,14 @@
 		vertices.push_back(Vec4(   p,    p, 0.4f, 1.0f));
 		vertices.push_back(Vec4(   p,   -p, 0.6f, 1.0f));
 		vertices.push_back(Vec4(0.0f,   -p, 0.8f, 1.0f));
-		vertices.push_back(Vec4(   p, 0.0f, 0.9f, 1.0f));
-		vertices.push_back(Vec4(0.0f,    p, 0.1f, 1.0f));
-		vertices.push_back(Vec4(  -p, 0.0f, 0.2f, 1.0f));
+		vertices.push_back(Vec4(   p, 0.0f, 0.7f, 1.0f));
+		vertices.push_back(Vec4(0.0f,    p, 0.5f, 1.0f));
+		vertices.push_back(Vec4(  -p, 0.0f, 0.3f, 1.0f));
 	}
 
 	tcu::TestLog&	log	= context.getTestContext().getLog();
 
-	log << tcu::TestLog::Message << "Drawing several large points just outside the clip volume. Expecting an empty image." << tcu::TestLog::EndMessage;
+	log << tcu::TestLog::Message << "Drawing several large points just outside the clip volume. Expecting an empty image or all points rendered." << tcu::TestLog::EndMessage;
 
 	DrawState			drawState		(VK_PRIMITIVE_TOPOLOGY_POINT_LIST, RENDER_SIZE, RENDER_SIZE);
 	DrawCallData		drawCallData	(vertices);
@@ -622,18 +617,26 @@
 	VulkanDrawContext	drawContext(context, drawState, drawCallData, vulkanProgram);
 	drawContext.draw();
 
+	// Popful case: All pixels must be black -- nothing is drawn.
 	const int	numBlackPixels	= countPixels(drawContext.getColorPixels(), Vec4(0.0f, 0.0f, 0.0f, 1.0f), Vec4());
 	bool		result			= false;
 
+	// Pop-free case: All points must be rendered.
+	bool allPointsRendered = true;
+	for (std::vector<Vec4>::iterator i = vertices.begin(); i != vertices.end(); ++i)
+	{
+		if (countPixels(drawContext.getColorPixels(), Vec4(1.0f, i->z(), 0.0f, 1.0f), Vec4(0.01f)) == 0)
+			allPointsRendered = false;
+	}
+
 	if (pointClippingOutside)
 	{
-		// All pixels must be black -- nothing is drawn.
-		result = (numBlackPixels == NUM_RENDER_PIXELS);
+		result = (numBlackPixels == NUM_RENDER_PIXELS || allPointsRendered);
 	}
 	else
 	{
-		// Rendering pixels without clipping: some pixels should not be black -- something is drawn.
-		result = (numBlackPixels < NUM_RENDER_PIXELS);
+		// Rendering pixels without clipping: all points should be drawn.
+		result = (allPointsRendered == true);
 	}
 
 	return (result ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Rendered image(s) are incorrect"));
diff --git a/external/vulkancts/modules/vulkan/draw/vktDrawInstancedTests.cpp b/external/vulkancts/modules/vulkan/draw/vktDrawInstancedTests.cpp
index 13b80e3..d446468 100644
--- a/external/vulkancts/modules/vulkan/draw/vktDrawInstancedTests.cpp
+++ b/external/vulkancts/modules/vulkan/draw/vktDrawInstancedTests.cpp
@@ -434,7 +434,7 @@
 tcu::TestStatus InstancedDrawInstance::iterate()
 {
 	const vk::VkQueue		queue					= m_context.getUniversalQueue();
-	static const deUint32	instanceCounts[]		= { 1, 2, 4, 20 };
+	static const deUint32	instanceCounts[]		= { 0, 1, 2, 4, 20 };
 	static const deUint32	firstInstanceIndices[]	= { 0, 1, 3, 4, 20 };
 
 	qpTestResult			res						= QP_TEST_RESULT_PASS;
@@ -452,9 +452,11 @@
 		const deUint32 instanceCount = instanceCounts[instanceCountNdx];
 		for (int firstInstanceIndexNdx = 0; firstInstanceIndexNdx < firstInstanceIndicesCount; firstInstanceIndexNdx++)
 		{
-			const deUint32 firstInstance = firstInstanceIndices[firstInstanceIndexNdx];
+			// Prepare vertex data for at least one instance
+			const deUint32				prepareCount			= de::max(instanceCount, 1u);
+			const deUint32				firstInstance			= firstInstanceIndices[firstInstanceIndexNdx];
 
-			prepareVertexData(instanceCount, firstInstance);
+			prepareVertexData(prepareCount, firstInstance);
 			const de::SharedPtr<Buffer>	vertexBuffer			= createAndUploadBuffer(m_data, m_vk, m_context);
 			const de::SharedPtr<Buffer>	instancedVertexBuffer	= createAndUploadBuffer(m_instancedColor, m_vk, m_context);
 			de::SharedPtr<Buffer>		indexBuffer;
diff --git a/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.cpp b/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.cpp
index afbb786..4508bb9 100644
--- a/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.cpp
+++ b/external/vulkancts/modules/vulkan/geometry/vktGeometryBasicGeometryShaderTests.cpp
@@ -490,7 +490,7 @@
 															},											// VkImageSubresourceRange	subresourceRange;
 														};
 		m_imageView										= createImageView(vk, device, &viewParams);
-		const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo (*m_sampler, *m_imageView, VK_IMAGE_LAYOUT_GENERAL);
+		const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo (*m_sampler, *m_imageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
 		DescriptorSetUpdateBuilder()
 			.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfo)
 			.update(vk, device);
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTests.cpp
index 7a0e980..194e62e 100644
--- a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTests.cpp
+++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTests.cpp
@@ -76,6 +76,15 @@
 };
 typedef deUint32 TestModeFlags;
 
+enum RenderType
+{
+	// resolve multisample rendering to single sampled image
+	RENDER_TYPE_RESOLVE		= 0u,
+
+	// copy samples to an array of single sampled images
+	RENDER_TYPE_COPY_SAMPLES
+};
+
 void									initMultisamplePrograms				(SourceCollections& sources, GeometryType geometryType);
 bool									isSupportedSampleCount				(const InstanceInterface& instanceInterface, VkPhysicalDevice physicalDevice, VkSampleCountFlagBits rasterizationSamples);
 bool									isSupportedDepthStencilFormat		(const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format);
@@ -148,6 +157,7 @@
 	virtual										~MinSampleShadingTest				(void) {}
 
 protected:
+	virtual void								initPrograms						(SourceCollections& programCollection) const;
 	virtual TestInstance*						createMultisampleTestInstance		(Context&										context,
 																					 VkPrimitiveTopology							topology,
 																					 const std::vector<Vertex4RGBA>&				vertices,
@@ -234,7 +244,8 @@
 																			 const VkPrimitiveTopology						topology,
 																			 const std::vector<Vertex4RGBA>&				vertices,
 																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
-																			 const VkPipelineColorBlendAttachmentState&		blendState);
+																			 const VkPipelineColorBlendAttachmentState&		blendState,
+																			 const RenderType								renderType);
 
 												MultisampleRenderer			(Context&										context,
 																			 const VkFormat									colorFormat,
@@ -246,11 +257,13 @@
 																			 const VkPrimitiveTopology*						pTopology,
 																			 const std::vector<Vertex4RGBA>*				pVertices,
 																			 const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
-																			 const VkPipelineColorBlendAttachmentState&		blendState);
+																			 const VkPipelineColorBlendAttachmentState&		blendState,
+																		     const RenderType								renderType);
 
 	virtual										~MultisampleRenderer		(void);
 
 	de::MovePtr<tcu::TextureLevel>				render						(void);
+	de::MovePtr<tcu::TextureLevel>				getSingleSampledImage		(deUint32 sampleId);
 
 protected:
 	void										initialize					(Context&										context,
@@ -269,6 +282,8 @@
 	const VkPipelineMultisampleStateCreateInfo	m_multisampleStateParams;
 	const VkPipelineColorBlendAttachmentState	m_colorBlendState;
 
+	const RenderType							m_renderType;
+
 	Move<VkImage>								m_colorImage;
 	de::MovePtr<Allocation>						m_colorImageAlloc;
 	Move<VkImageView>							m_colorAttachmentView;
@@ -277,6 +292,14 @@
 	de::MovePtr<Allocation>						m_resolveImageAlloc;
 	Move<VkImageView>							m_resolveAttachmentView;
 
+	struct PerSampleImage
+	{
+		Move<VkImage>								m_image;
+		de::MovePtr<Allocation>						m_imageAlloc;
+		Move<VkImageView>							m_attachmentView;
+	};
+	std::vector<de::SharedPtr<PerSampleImage> >	m_perSampleImages;
+
 	Move<VkImage>								m_depthStencilImage;
 	de::MovePtr<Allocation>						m_depthStencilImageAlloc;
 	Move<VkImageView>							m_depthStencilAttachmentView;
@@ -287,12 +310,22 @@
 	Move<VkShaderModule>						m_vertexShaderModule;
 	Move<VkShaderModule>						m_fragmentShaderModule;
 
+	Move<VkShaderModule>						m_copySampleVertexShaderModule;
+	Move<VkShaderModule>						m_copySampleFragmentShaderModule;
+
 	Move<VkBuffer>								m_vertexBuffer;
 	de::MovePtr<Allocation>						m_vertexBufferAlloc;
 
 	Move<VkPipelineLayout>						m_pipelineLayout;
 	std::vector<VkPipelineSp>					m_graphicsPipelines;
 
+	Move<VkDescriptorSetLayout>					m_copySampleDesciptorLayout;
+	Move<VkDescriptorPool>						m_copySampleDesciptorPool;
+	Move<VkDescriptorSet>						m_copySampleDesciptorSet;
+
+	Move<VkPipelineLayout>						m_copySamplePipelineLayout;
+	std::vector<VkPipelineSp>					m_copySamplePipelines;
+
 	Move<VkCommandPool>							m_cmdPool;
 	Move<VkCommandBuffer>						m_cmdBuffer;
 
@@ -337,9 +370,9 @@
 	virtual tcu::TestStatus						iterate						(void);
 
 protected:
-	virtual tcu::TestStatus						verifyImage					(const tcu::ConstPixelBufferAccess& testShadingImage,
-																			 const tcu::ConstPixelBufferAccess& minShadingImage,
-																			 const tcu::ConstPixelBufferAccess& maxShadingImage);
+	virtual tcu::TestStatus						verifySampleShadedImage		(const std::vector<tcu::TextureLevel>& testShadingImages,
+																			 const tcu::ConstPixelBufferAccess& noSampleshadingImage);
+
 	const VkFormat								m_colorFormat;
 	const tcu::IVec2							m_renderSize;
 	const VkPrimitiveTopology					m_primitiveTopology;
@@ -436,7 +469,7 @@
 		"	gl_Position = position;\n"
 		"	vtxColor = color;\n"
 		<< (geometryType == GEOMETRY_TYPE_OPAQUE_POINT ? "	gl_PointSize = 3.0f;\n"
-														 : "" )
+			: "")
 		<< "}\n";
 
 	static const char* fragmentSource =
@@ -452,6 +485,67 @@
 	sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource);
 }
 
+void initSampleShadingPrograms (SourceCollections& sources, GeometryType geometryType)
+{
+	{
+		std::ostringstream vertexSource;
+
+		vertexSource <<
+			"#version 440\n"
+			"layout(location = 0) in vec4 position;\n"
+			"layout(location = 1) in vec4 color;\n"
+			"void main (void)\n"
+			"{\n"
+			"	gl_Position = position;\n"
+			<< (geometryType == GEOMETRY_TYPE_OPAQUE_POINT ? "	gl_PointSize = 3.0f;\n"
+				: "")
+			<< "}\n";
+
+		static const char* fragmentSource =
+			"#version 440\n"
+			"layout(location = 0) out highp vec4 fragColor;\n"
+			"void main (void)\n"
+			"{\n"
+			"	fragColor = vec4(fract(gl_FragCoord.xy), 0.0, 1.0);\n"
+			"}\n";
+
+		sources.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
+		sources.glslSources.add("color_frag") << glu::FragmentSource(fragmentSource);
+	}
+
+	{
+		static const char*  vertexSource =
+			"#version 440\n"
+			"void main (void)\n"
+			"{\n"
+			"	const vec4 positions[4] = vec4[4](\n"
+			"		vec4(-1.0, -1.0, 0.0, 1.0),\n"
+			"		vec4(-1.0,  1.0, 0.0, 1.0),\n"
+			"		vec4( 1.0, -1.0, 0.0, 1.0),\n"
+			"		vec4( 1.0,  1.0, 0.0, 1.0)\n"
+			"	);\n"
+			"	gl_Position = positions[gl_VertexIndex];\n"
+			"}\n";
+
+		static const char* fragmentSource =
+			"#version 440\n"
+			"precision highp float;\n"
+			"layout(location = 0) out highp vec4 fragColor;\n"
+			"layout(set = 0, binding = 0, input_attachment_index = 0) uniform subpassInputMS imageMS;\n"
+			"layout(push_constant) uniform PushConstantsBlock\n"
+			"{\n"
+			"	int sampleId;\n"
+			"} pushConstants;\n"
+			"void main (void)\n"
+			"{\n"
+			"	fragColor = subpassLoad(imageMS, pushConstants.sampleId);\n"
+			"}\n";
+
+		sources.glslSources.add("quad_vert") << glu::VertexSource(vertexSource);
+		sources.glslSources.add("copy_sample_frag") << glu::FragmentSource(fragmentSource);
+	}
+}
+
 bool isSupportedSampleCount (const InstanceInterface& instanceInterface, VkPhysicalDevice physicalDevice, VkSampleCountFlagBits rasterizationSamples)
 {
 	VkPhysicalDeviceProperties deviceProperties;
@@ -772,6 +866,11 @@
 {
 }
 
+void MinSampleShadingTest::initPrograms (SourceCollections& programCollection) const
+{
+	initSampleShadingPrograms(programCollection, m_geometryType);
+}
+
 TestInstance* MinSampleShadingTest::createMultisampleTestInstance (Context&										context,
 																   VkPrimitiveTopology							topology,
 																   const std::vector<Vertex4RGBA>&				vertices,
@@ -965,12 +1064,12 @@
 
 		m_multisampleRenderer = de::MovePtr<MultisampleRenderer>(
 			new MultisampleRenderer(
-				context, m_colorFormat, depthStencilFormat, m_renderSize, useDepth, useStencil, 2u, pTopology, pVertices, multisampleStateParams, blendState));
+				context, m_colorFormat, depthStencilFormat, m_renderSize, useDepth, useStencil, 2u, pTopology, pVertices, multisampleStateParams, blendState, RENDER_TYPE_RESOLVE));
 	}
 	else
 	{
 		m_multisampleRenderer = de::MovePtr<MultisampleRenderer>(
-			new MultisampleRenderer(context, m_colorFormat, m_renderSize, topology, vertices, multisampleStateParams, blendState));
+			new MultisampleRenderer(context, m_colorFormat, m_renderSize, topology, vertices, multisampleStateParams, blendState, RENDER_TYPE_RESOLVE));
 	}
 }
 
@@ -1063,55 +1162,109 @@
 
 tcu::TestStatus MinSampleShadingInstance::iterate (void)
 {
-	de::MovePtr<tcu::TextureLevel>				testShadingImage;
-	de::MovePtr<tcu::TextureLevel>				minShadingImage;
-	de::MovePtr<tcu::TextureLevel>				maxShadingImage;
+	de::MovePtr<tcu::TextureLevel>	noSampleshadingImage;
+	std::vector<tcu::TextureLevel>	sampleShadedImages;
 
-	// Render with test minSampleShading
+	// Render and resolve without sample shading
 	{
-		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
-		testShadingImage = renderer.render();
+		VkPipelineMultisampleStateCreateInfo multisampleStateParms = m_multisampleStateParams;
+		multisampleStateParms.sampleShadingEnable	= VK_FALSE;
+		multisampleStateParms.minSampleShading		= 0.0;
+
+		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleStateParms, m_colorBlendState, RENDER_TYPE_RESOLVE);
+		noSampleshadingImage  = renderer.render();
 	}
 
-	// Render with minSampleShading = 0.0f
+	// Render with test minSampleShading and collect per-sample images
 	{
-		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
-		multisampleParams.minSampleShading = 0.0f;
+		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_COPY_SAMPLES);
+		renderer.render();
 
-		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
-		minShadingImage = renderer.render();
+		sampleShadedImages.resize(m_multisampleStateParams.rasterizationSamples);
+		for (deUint32 sampleId = 0; sampleId < sampleShadedImages.size(); sampleId++)
+		{
+			sampleShadedImages[sampleId] = *renderer.getSingleSampledImage(sampleId);
+		}
 	}
 
-	// Render with minSampleShading = 1.0f
+	// Log images
 	{
-		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
-		multisampleParams.minSampleShading = 1.0f;
+		tcu::TestLog& testLog	= m_context.getTestContext().getLog();
 
-		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
-		maxShadingImage = renderer.render();
+		testLog << tcu::TestLog::ImageSet("Images", "Images")
+				<< tcu::TestLog::Image("noSampleshadingImage", "Image rendered without sample shading", noSampleshadingImage->getAccess());
+
+		for (deUint32 sampleId = 0; sampleId < sampleShadedImages.size(); sampleId++)
+		{
+			testLog << tcu::TestLog::Image("sampleShadedImage", "One sample of sample shaded image", sampleShadedImages[sampleId].getAccess());
+		}
+		testLog << tcu::TestLog::EndImageSet;
 	}
 
-	return verifyImage(testShadingImage->getAccess(), minShadingImage->getAccess(), maxShadingImage->getAccess());
+	return verifySampleShadedImage(sampleShadedImages, noSampleshadingImage->getAccess());
 }
 
-tcu::TestStatus MinSampleShadingInstance::verifyImage (const tcu::ConstPixelBufferAccess& testShadingImage, const tcu::ConstPixelBufferAccess& minShadingImage, const tcu::ConstPixelBufferAccess& maxShadingImage)
+tcu::TestStatus MinSampleShadingInstance::verifySampleShadedImage (const std::vector<tcu::TextureLevel>& sampleShadedImages, const tcu::ConstPixelBufferAccess& noSampleshadingImage)
 {
-	const deUint32	testColorCount	= getUniqueColorsCount(testShadingImage);
-	const deUint32	minColorCount	= getUniqueColorsCount(minShadingImage);
-	const deUint32	maxColorCount	= getUniqueColorsCount(maxShadingImage);
+	const deUint32	pixelCount	= noSampleshadingImage.getWidth() * noSampleshadingImage.getHeight() * noSampleshadingImage.getDepth();
 
-	tcu::TestLog& log = m_context.getTestContext().getLog();
+	bool anyPixelCovered		= false;
 
-	log << tcu::TestLog::Message
-		<< "\nColors found: " << testColorCount << "\n"
-		<< "Min. colors expected: " << minColorCount << "\n"
-		<< "Max. colors expected: " << maxColorCount << "\n"
-		<< tcu::TestLog::EndMessage;
+	for (deUint32 pixelNdx = 0; pixelNdx < pixelCount; pixelNdx++)
+	{
+		const deUint32 noSampleShadingValue = *((const deUint32*)noSampleshadingImage.getDataPtr() + pixelNdx);
 
-	if (minColorCount > testColorCount || testColorCount > maxColorCount)
-		return tcu::TestStatus::fail("Unique colors out of expected bounds");
-	else
-		return tcu::TestStatus::pass("Unique colors within expected bounds");
+		if (noSampleShadingValue == 0)
+		{
+			// non-covered pixel, continue
+			continue;
+		}
+		else
+		{
+			anyPixelCovered = true;
+		}
+
+		int numNotCoveredSamples = 0;
+
+		std::map<deUint32, deUint32>	histogram; // map<pixel value, number of occurrences>
+
+		// Collect histogram of occurrences or each pixel across all samples
+		for (size_t i = 0; i < sampleShadedImages.size(); ++i)
+		{
+			const deUint32 sampleShadedValue = *((const deUint32*)sampleShadedImages[i].getAccess().getDataPtr() + pixelNdx);
+
+			if (sampleShadedValue == 0)
+			{
+				numNotCoveredSamples++;
+				continue;
+			}
+
+			if (histogram.find(sampleShadedValue) != histogram.end())
+				histogram[sampleShadedValue]++;
+			else
+				histogram[sampleShadedValue] = 1;
+		}
+
+		if (numNotCoveredSamples == static_cast<int>(sampleShadedImages.size()))
+		{
+			return tcu::TestStatus::fail("Got uncovered pixel, where covered samples were expected");
+		}
+
+		const int uniqueColorsCount				= (int)histogram.size();
+		const int expectedUniqueSamplesCount	= static_cast<int>(m_multisampleStateParams.minSampleShading * static_cast<float>(sampleShadedImages.size()) + 0.5f);
+
+		if (uniqueColorsCount + numNotCoveredSamples < expectedUniqueSamplesCount)
+		{
+			return tcu::TestStatus::fail("Got less unique colors than requested through minSampleShading");
+		}
+	}
+
+	if (!anyPixelCovered)
+	{
+		return tcu::TestStatus::fail("Did not get any covered pixel, cannot test minSampleShading");
+	}
+
+	return tcu::TestStatus::pass("Got proper count of unique colors");
 }
 
 SampleMaskInstance::SampleMaskInstance (Context&										context,
@@ -1137,7 +1290,7 @@
 
 	// Render with test flags
 	{
-		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
+		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_COPY_SAMPLES);
 		testSampleMaskImage = renderer.render();
 	}
 
@@ -1148,7 +1301,7 @@
 
 		multisampleParams.pSampleMask = sampleMask.data();
 
-		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
+		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState, RENDER_TYPE_COPY_SAMPLES);
 		minSampleMaskImage = renderer.render();
 	}
 
@@ -1159,7 +1312,7 @@
 
 		multisampleParams.pSampleMask = sampleMask.data();
 
-		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
+		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState, RENDER_TYPE_COPY_SAMPLES);
 		maxSampleMaskImage = renderer.render();
 	}
 
@@ -1243,7 +1396,7 @@
 			false														// VkBool32									alphaToOneEnable;
 		};
 
-		MultisampleRenderer				renderer		(context, VK_FORMAT_R8G8B8A8_UNORM, tcu::IVec2(32, 32), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vertices, multisampleStateParams, getDefaultColorBlendAttachmentState());
+		MultisampleRenderer				renderer		(context, VK_FORMAT_R8G8B8A8_UNORM, tcu::IVec2(32, 32), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vertices, multisampleStateParams, getDefaultColorBlendAttachmentState(), RENDER_TYPE_RESOLVE);
 		de::MovePtr<tcu::TextureLevel>	result			= renderer.render();
 		const deUint32					uniqueColors	= getUniqueColorsCount(result->getAccess());
 
@@ -1300,7 +1453,7 @@
 
 	// Render with blend enabled and alpha to one on
 	{
-		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
+		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_RESOLVE);
 		alphaOneImage = renderer.render();
 	}
 
@@ -1309,7 +1462,7 @@
 		VkPipelineMultisampleStateCreateInfo	multisampleParams	= m_multisampleStateParams;
 		multisampleParams.alphaToOneEnable = false;
 
-		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState);
+		MultisampleRenderer renderer (m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, multisampleParams, m_colorBlendState, RENDER_TYPE_RESOLVE);
 		noAlphaOneImage = renderer.render();
 	}
 
@@ -1360,7 +1513,7 @@
 	DE_ASSERT(m_multisampleStateParams.alphaToCoverageEnable);
 
 	de::MovePtr<tcu::TextureLevel>	result;
-	MultisampleRenderer				renderer	(m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState);
+	MultisampleRenderer				renderer	(m_context, m_colorFormat, m_renderSize, m_primitiveTopology, m_vertices, m_multisampleStateParams, m_colorBlendState, RENDER_TYPE_RESOLVE);
 
 	result = renderer.render();
 
@@ -1415,7 +1568,8 @@
 										  const VkPrimitiveTopology						topology,
 										  const std::vector<Vertex4RGBA>&				vertices,
 										  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
-										  const VkPipelineColorBlendAttachmentState&	blendState)
+										  const VkPipelineColorBlendAttachmentState&	blendState,
+										  const RenderType								renderType)
 	: m_context					(context)
 	, m_colorFormat				(colorFormat)
 	, m_depthStencilFormat		(VK_FORMAT_UNDEFINED)
@@ -1424,6 +1578,7 @@
 	, m_useStencil				(false)
 	, m_multisampleStateParams	(multisampleStateParams)
 	, m_colorBlendState			(blendState)
+	, m_renderType				(renderType)
 {
 	initialize(context, 1u, &topology, &vertices);
 }
@@ -1438,7 +1593,8 @@
 										  const VkPrimitiveTopology*					pTopology,
 										  const std::vector<Vertex4RGBA>*				pVertices,
 										  const VkPipelineMultisampleStateCreateInfo&	multisampleStateParams,
-										  const VkPipelineColorBlendAttachmentState&	blendState)
+										  const VkPipelineColorBlendAttachmentState&	blendState,
+										  const RenderType								renderType)
 	: m_context					(context)
 	, m_colorFormat				(colorFormat)
 	, m_depthStencilFormat		(depthStencilFormat)
@@ -1447,6 +1603,7 @@
 	, m_useStencil				(useStencil)
 	, m_multisampleStateParams	(multisampleStateParams)
 	, m_colorBlendState			(blendState)
+	, m_renderType				(renderType)
 {
 	initialize(context, numTopologies, pTopology, pVertices);
 }
@@ -1467,6 +1624,10 @@
 
 	// Create color image
 	{
+
+		const VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+			(m_renderType == RENDER_TYPE_COPY_SAMPLES ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0u);
+
 		const VkImageCreateInfo colorImageParams =
 		{
 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
@@ -1479,7 +1640,7 @@
 			1u,																			// deUint32					arrayLayers;
 			m_multisampleStateParams.rasterizationSamples,								// VkSampleCountFlagBits	samples;
 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
-			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
+			imageUsageFlags,															// VkImageUsageFlags		usage;
 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
 			1u,																			// deUint32					queueFamilyIndexCount;
 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
@@ -1494,6 +1655,7 @@
 	}
 
 	// Create resolve image
+	if (m_renderType == RENDER_TYPE_RESOLVE)
 	{
 		const VkImageCreateInfo resolveImageParams =
 		{
@@ -1520,6 +1682,78 @@
 		// Allocate and bind resolve image memory
 		m_resolveImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_resolveImage), MemoryRequirement::Any);
 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_resolveImage, m_resolveImageAlloc->getMemory(), m_resolveImageAlloc->getOffset()));
+
+		// Create resolve attachment view
+		{
+			const VkImageViewCreateInfo resolveAttachmentViewParams =
+			{
+				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
+				DE_NULL,										// const void*				pNext;
+				0u,												// VkImageViewCreateFlags	flags;
+				*m_resolveImage,								// VkImage					image;
+				VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
+				m_colorFormat,									// VkFormat					format;
+				componentMappingRGBA,							// VkComponentMapping		components;
+				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
+			};
+
+			m_resolveAttachmentView = createImageView(vk, vkDevice, &resolveAttachmentViewParams);
+		}
+	}
+
+	// Create per-sample output images
+	if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+	{
+		const VkImageCreateInfo perSampleImageParams =
+		{
+			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,											// VkStructureType			sType;
+			DE_NULL,																		// const void*				pNext;
+			0u,																				// VkImageCreateFlags		flags;
+			VK_IMAGE_TYPE_2D,																// VkImageType				imageType;
+			m_colorFormat,																	// VkFormat					format;
+			{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u },					// VkExtent3D				extent;
+			1u,																				// deUint32					mipLevels;
+			1u,																				// deUint32					arrayLayers;
+			VK_SAMPLE_COUNT_1_BIT,															// VkSampleCountFlagBits	samples;
+			VK_IMAGE_TILING_OPTIMAL,														// VkImageTiling			tiling;
+			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |			// VkImageUsageFlags		usage;
+			VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+			VK_SHARING_MODE_EXCLUSIVE,														// VkSharingMode			sharingMode;
+			1u,																				// deUint32					queueFamilyIndexCount;
+			&queueFamilyIndex,																// const deUint32*			pQueueFamilyIndices;
+			VK_IMAGE_LAYOUT_UNDEFINED														// VkImageLayout			initialLayout;
+		};
+
+		m_perSampleImages.resize(static_cast<size_t>(m_multisampleStateParams.rasterizationSamples));
+
+		for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+		{
+			m_perSampleImages[i]	= de::SharedPtr<PerSampleImage>(new PerSampleImage);
+			PerSampleImage& image	= *m_perSampleImages[i];
+
+			image.m_image			= createImage(vk, vkDevice, &perSampleImageParams);
+
+			// Allocate and bind image memory
+			image.m_imageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *image.m_image), MemoryRequirement::Any);
+			VK_CHECK(vk.bindImageMemory(vkDevice, *image.m_image, image.m_imageAlloc->getMemory(), image.m_imageAlloc->getOffset()));
+
+			// Create per-sample attachment view
+			{
+				const VkImageViewCreateInfo perSampleAttachmentViewParams =
+				{
+					VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
+					DE_NULL,										// const void*				pNext;
+					0u,												// VkImageViewCreateFlags	flags;
+					*image.m_image,									// VkImage					image;
+					VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
+					m_colorFormat,									// VkFormat					format;
+					componentMappingRGBA,							// VkComponentMapping		components;
+					{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
+				};
+
+				image.m_attachmentView = createImageView(vk, vkDevice, &perSampleAttachmentViewParams);
+			}
+		}
 	}
 
 	// Create a depth/stencil image
@@ -1568,25 +1802,7 @@
 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
 	}
 
-	// Create resolve attachment view
-	{
-		const VkImageViewCreateInfo resolveAttachmentViewParams =
-		{
-			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
-			DE_NULL,										// const void*				pNext;
-			0u,												// VkImageViewCreateFlags	flags;
-			*m_resolveImage,								// VkImage					image;
-			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
-			m_colorFormat,									// VkFormat					format;
-			componentMappingRGBA,							// VkComponentMapping		components;
-			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }	// VkImageSubresourceRange	subresourceRange;
-		};
-
-		m_resolveAttachmentView = createImageView(vk, vkDevice, &resolveAttachmentViewParams);
-	}
-
 	VkImageAspectFlags	depthStencilAttachmentAspect	= (VkImageAspectFlagBits)0;
-	const deUint32		numUsedAttachments				= (m_useDepth || m_useStencil ? 3u : 2u);
 
 	// Create depth/stencil attachment view
 	if (m_useDepth || m_useStencil)
@@ -1610,8 +1826,9 @@
 
 	// Create render pass
 	{
-		const VkAttachmentDescription attachmentDescriptions[3] =
+		std::vector<VkAttachmentDescription> attachmentDescriptions;
 		{
+			const VkAttachmentDescription colorAttachmentDescription =
 			{
 				0u,													// VkAttachmentDescriptionFlags		flags;
 				m_colorFormat,										// VkFormat							format;
@@ -1622,7 +1839,17 @@
 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
-			},
+			};
+			attachmentDescriptions.push_back(colorAttachmentDescription);
+		}
+
+		deUint32 resolveAttachmentIndex = VK_ATTACHMENT_UNUSED;
+
+		if (m_renderType == RENDER_TYPE_RESOLVE)
+		{
+			resolveAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
+
+			const VkAttachmentDescription resolveAttachmentDescription =
 			{
 				0u,													// VkAttachmentDescriptionFlags		flags;
 				m_colorFormat,										// VkFormat							format;
@@ -1633,7 +1860,42 @@
 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
-			},
+			};
+			attachmentDescriptions.push_back(resolveAttachmentDescription);
+		}
+
+		deUint32 perSampleAttachmentIndex = VK_ATTACHMENT_UNUSED;
+
+		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+		{
+			perSampleAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
+
+			const VkAttachmentDescription perSampleAttachmentDescription =
+			{
+				0u,													// VkAttachmentDescriptionFlags		flags;
+				m_colorFormat,										// VkFormat							format;
+				VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
+				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
+				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
+				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
+				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
+				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
+				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
+			};
+
+			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+			{
+				attachmentDescriptions.push_back(perSampleAttachmentDescription);
+			}
+		}
+
+		deUint32 depthStencilAttachmentIndex = VK_ATTACHMENT_UNUSED;
+
+		if (m_useDepth || m_useStencil)
+		{
+			depthStencilAttachmentIndex = static_cast<deUint32>(attachmentDescriptions.size());
+
+			const VkAttachmentDescription depthStencilAttachmentDescription =
 			{
 				0u,																					// VkAttachmentDescriptionFlags		flags;
 				m_depthStencilFormat,																// VkFormat							format;
@@ -1644,7 +1906,8 @@
 				(m_useStencil ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE),	// VkAttachmentStoreOp				stencilStoreOp;
 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,									// VkImageLayout					initialLayout;
 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL									// VkImageLayout					finalLayout;
-			},
+			};
+			attachmentDescriptions.push_back(depthStencilAttachmentDescription);
 		};
 
 		const VkAttachmentReference colorAttachmentReference =
@@ -1653,43 +1916,103 @@
 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
 		};
 
+		const VkAttachmentReference inputAttachmentReference =
+		{
+			0u,													// deUint32			attachment;
+			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL			// VkImageLayout	layout;
+		};
+
 		const VkAttachmentReference resolveAttachmentReference =
 		{
-			1u,													// deUint32			attachment;
+			resolveAttachmentIndex,								// deUint32			attachment;
 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
 		};
 
+		std::vector<VkAttachmentReference> perSampleAttachmentReferences(m_perSampleImages.size());
+		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+		{
+			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+			{
+				const VkAttachmentReference perSampleAttachmentReference =
+				{
+					perSampleAttachmentIndex + static_cast<deUint32>(i),	// deUint32			attachment;
+					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL				// VkImageLayout	layout;
+				};
+				perSampleAttachmentReferences[i] = perSampleAttachmentReference;
+			}
+		}
+
 		const VkAttachmentReference depthStencilAttachmentReference =
 		{
-			2u,													// deUint32			attachment;
+			depthStencilAttachmentIndex,						// deUint32			attachment;
 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
 		};
 
-		const VkSubpassDescription subpassDescription =
+		std::vector<VkSubpassDescription>	subpassDescriptions;
+		std::vector<VkSubpassDependency>	subpassDependencies;
+
 		{
-			0u,																			// VkSubpassDescriptionFlags	flags;
-			VK_PIPELINE_BIND_POINT_GRAPHICS,											// VkPipelineBindPoint			pipelineBindPoint;
-			0u,																			// deUint32						inputAttachmentCount;
-			DE_NULL,																	// const VkAttachmentReference*	pInputAttachments;
-			1u,																			// deUint32						colorAttachmentCount;
-			&colorAttachmentReference,													// const VkAttachmentReference*	pColorAttachments;
-			&resolveAttachmentReference,												// const VkAttachmentReference*	pResolveAttachments;
-			(m_useDepth || m_useStencil ? &depthStencilAttachmentReference : DE_NULL),	// const VkAttachmentReference*	pDepthStencilAttachment;
-			0u,																			// deUint32						preserveAttachmentCount;
-			DE_NULL																		// const VkAttachmentReference*	pPreserveAttachments;
-		};
+			const VkSubpassDescription renderSubpassDescription =
+			{
+				0u,																				// VkSubpassDescriptionFlags	flags;
+				VK_PIPELINE_BIND_POINT_GRAPHICS,												// VkPipelineBindPoint			pipelineBindPoint;
+				0u,																				// deUint32						inputAttachmentCount;
+				DE_NULL,																		// const VkAttachmentReference*	pInputAttachments;
+				1u,																				// deUint32						colorAttachmentCount;
+				&colorAttachmentReference,														// const VkAttachmentReference*	pColorAttachments;
+				(m_renderType == RENDER_TYPE_RESOLVE) ? &resolveAttachmentReference : DE_NULL,	// const VkAttachmentReference*	pResolveAttachments;
+				(m_useDepth || m_useStencil ? &depthStencilAttachmentReference : DE_NULL),		// const VkAttachmentReference*	pDepthStencilAttachment;
+				0u,																				// deUint32						preserveAttachmentCount;
+				DE_NULL																			// const VkAttachmentReference*	pPreserveAttachments;
+			};
+			subpassDescriptions.push_back(renderSubpassDescription);
+		}
+
+		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+		{
+
+			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+			{
+				const VkSubpassDescription copySampleSubpassDescription =
+				{
+					0u,													// VkSubpassDescriptionFlags		flags;
+					VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
+					1u,													// deUint32							inputAttachmentCount;
+					&inputAttachmentReference,							// const VkAttachmentReference*		pInputAttachments;
+					1u,													// deUint32							colorAttachmentCount;
+					&perSampleAttachmentReferences[i],					// const VkAttachmentReference*		pColorAttachments;
+					DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
+					DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment;
+					0u,													// deUint32							preserveAttachmentCount;
+					DE_NULL												// const VkAttachmentReference*		pPreserveAttachments;
+				};
+				subpassDescriptions.push_back(copySampleSubpassDescription);
+
+				const VkSubpassDependency copySampleSubpassDependency =
+				{
+					0u,													// deUint32							srcSubpass
+					1u + static_cast<deUint32>(i),						// deUint32							dstSubpass
+					VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,					// VkPipelineStageFlags				srcStageMask
+					VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,				// VkPipelineStageFlags				dstStageMask
+					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags					srcAccessMask
+					VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,				// VkAccessFlags					dstAccessMask
+					0u,													// VkDependencyFlags				dependencyFlags
+				};
+				subpassDependencies.push_back(copySampleSubpassDependency);
+			}
+		}
 
 		const VkRenderPassCreateInfo renderPassParams =
 		{
-			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
-			DE_NULL,											// const void*						pNext;
-			0u,													// VkRenderPassCreateFlags			flags;
-			numUsedAttachments,									// deUint32							attachmentCount;
-			attachmentDescriptions,								// const VkAttachmentDescription*	pAttachments;
-			1u,													// deUint32							subpassCount;
-			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
-			0u,													// deUint32							dependencyCount;
-			DE_NULL												// const VkSubpassDependency*		pDependencies;
+			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,					// VkStructureType					sType;
+			DE_NULL,													// const void*						pNext;
+			0u,															// VkRenderPassCreateFlags			flags;
+			(deUint32)attachmentDescriptions.size(),					// deUint32							attachmentCount;
+			&attachmentDescriptions[0],									// const VkAttachmentDescription*	pAttachments;
+			(deUint32)subpassDescriptions.size(),						// deUint32							subpassCount;
+			&subpassDescriptions[0],									// const VkSubpassDescription*		pSubpasses;
+			(deUint32)subpassDependencies.size(),						// deUint32							dependencyCount;
+			subpassDependencies.size() != 0 ? &subpassDependencies[0] : DE_NULL
 		};
 
 		m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
@@ -1697,24 +2020,36 @@
 
 	// Create framebuffer
 	{
-		const VkImageView attachments[3] =
+		std::vector<VkImageView> attachments;
+		attachments.push_back(*m_colorAttachmentView);
+		if (m_renderType == RENDER_TYPE_RESOLVE)
 		{
-			*m_colorAttachmentView,
-			*m_resolveAttachmentView,
-			*m_depthStencilAttachmentView
-		};
+			attachments.push_back(*m_resolveAttachmentView);
+		}
+		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+		{
+			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+			{
+				attachments.push_back(*m_perSampleImages[i]->m_attachmentView);
+			}
+		}
+
+		if (m_useDepth || m_useStencil)
+		{
+			attachments.push_back(*m_depthStencilAttachmentView);
+		}
 
 		const VkFramebufferCreateInfo framebufferParams =
 		{
-			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
-			DE_NULL,											// const void*					pNext;
-			0u,													// VkFramebufferCreateFlags		flags;
-			*m_renderPass,										// VkRenderPass					renderPass;
-			numUsedAttachments,									// deUint32						attachmentCount;
-			attachments,										// const VkImageView*			pAttachments;
-			(deUint32)m_renderSize.x(),							// deUint32						width;
-			(deUint32)m_renderSize.y(),							// deUint32						height;
-			1u													// deUint32						layers;
+			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType					sType;
+			DE_NULL,											// const void*						pNext;
+			0u,													// VkFramebufferCreateFlags			flags;
+			*m_renderPass,										// VkRenderPass						renderPass;
+			(deUint32)attachments.size(),						// deUint32							attachmentCount;
+			&attachments[0],									// const VkImageView*				pAttachments;
+			(deUint32)m_renderSize.x(),							// deUint32							width;
+			(deUint32)m_renderSize.y(),							// deUint32							height;
+			1u													// deUint32							layers;
 		};
 
 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
@@ -1734,14 +2069,64 @@
 		};
 
 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
+
+		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+		{
+
+			// Create descriptor set layout
+			const VkDescriptorSetLayoutBinding		layoutBinding					=
+			{
+				0u,															// deUint32								binding;
+				VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,						// VkDescriptorType						descriptorType;
+				1u,															// deUint32								descriptorCount;
+				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlags					stageFlags;
+				DE_NULL,													// const VkSampler*						pImmutableSamplers;
+			};
+
+			const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutParams		=
+			{
+				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType						sType
+				DE_NULL,													// const void*							pNext
+				0u,															// VkDescriptorSetLayoutCreateFlags		flags
+				1u,															// deUint32								bindingCount
+				&layoutBinding												// const VkDescriptorSetLayoutBinding*	pBindings
+			};
+			m_copySampleDesciptorLayout	= createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
+
+			// Create pipeline layout
+
+			const VkPushConstantRange				pushConstantRange				=
+			{
+				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlags					stageFlags;
+				0u,															// deUint32								offset;
+				sizeof(deInt32)												// deUint32								size;
+			};
+			const VkPipelineLayoutCreateInfo		copySamplePipelineLayoutParams	=
+			{
+				VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,				// VkStructureType						sType;
+				DE_NULL,													// const void*							pNext;
+				0u,															// VkPipelineLayoutCreateFlags			flags;
+				1u,															// deUint32								setLayoutCount;
+				&m_copySampleDesciptorLayout.get(),							// const VkDescriptorSetLayout*			pSetLayouts;
+				1u,															// deUint32								pushConstantRangeCount;
+				&pushConstantRange											// const VkPushConstantRange*			pPushConstantRanges;
+			};
+			m_copySamplePipelineLayout		= createPipelineLayout(vk, vkDevice, &copySamplePipelineLayoutParams);
+		}
 	}
 
 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
 	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
 
+	if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+	{
+		m_copySampleVertexShaderModule		= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("quad_vert"), 0);
+		m_copySampleFragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("copy_sample_frag"), 0);
+	}
+
 	// Create pipeline
 	{
-		const VkPipelineShaderStageCreateInfo shaderStageParams[2] =
+		const VkPipelineShaderStageCreateInfo	shaderStageParams[2] =
 		{
 			{
 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
@@ -1763,7 +2148,7 @@
 			}
 		};
 
-		const VkVertexInputBindingDescription vertexInputBindingDescription =
+		const VkVertexInputBindingDescription	vertexInputBindingDescription =
 		{
 			0u,									// deUint32				binding;
 			sizeof(Vertex4RGBA),				// deUint32				stride;
@@ -1920,6 +2305,208 @@
 		}
 	}
 
+	if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+	{
+		// Create pipelines for copying samples to single sampled images
+		{
+			const VkPipelineShaderStageCreateInfo shaderStageParams[2] =
+			{
+				{
+					VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType							sType;
+					DE_NULL,													// const void*								pNext;
+					0u,															// VkPipelineShaderStageCreateFlags			flags;
+					VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits					stage;
+					*m_copySampleVertexShaderModule,							// VkShaderModule							module;
+					"main",														// const char*								pName;
+					DE_NULL														// const VkSpecializationInfo*				pSpecializationInfo;
+				},
+				{
+					VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType							sType;
+					DE_NULL,													// const void*								pNext;
+					0u,															// VkPipelineShaderStageCreateFlags			flags;
+					VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits					stage;
+					*m_copySampleFragmentShaderModule,							// VkShaderModule							module;
+					"main",														// const char*								pName;
+					DE_NULL														// const VkSpecializationInfo*				pSpecializationInfo;
+				}
+			};
+
+			const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+			{
+				VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
+				DE_NULL,														// const void*								pNext;
+				0u,																// VkPipelineVertexInputStateCreateFlags	flags;
+				0u,																// deUint32									vertexBindingDescriptionCount;
+				DE_NULL,														// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
+				0u,																// deUint32									vertexAttributeDescriptionCount;
+				DE_NULL															// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
+			};
+
+			// Topology is set before the pipeline creation.
+			VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
+			{
+				VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
+				DE_NULL,														// const void*								pNext;
+				0u,																// VkPipelineInputAssemblyStateCreateFlags	flags;
+				VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,							// VkPrimitiveTopology						topology;
+				false															// VkBool32									primitiveRestartEnable;
+			};
+
+			const VkViewport viewport =
+			{
+				0.0f,						// float	x;
+				0.0f,						// float	y;
+				(float)m_renderSize.x(),	// float	width;
+				(float)m_renderSize.y(),	// float	height;
+				0.0f,						// float	minDepth;
+				1.0f						// float	maxDepth;
+			};
+
+			const VkRect2D scissor =
+			{
+				{ 0, 0 },													// VkOffset2D  offset;
+				{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }	// VkExtent2D  extent;
+			};
+
+			const VkPipelineViewportStateCreateInfo viewportStateParams =
+			{
+				VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType							sType;
+				DE_NULL,														// const void*								pNext;
+				0u,																// VkPipelineViewportStateCreateFlags		flags;
+				1u,																// deUint32									viewportCount;
+				&viewport,														// const VkViewport*						pViewports;
+				1u,																// deUint32									scissorCount;
+				&scissor														// const VkRect2D*							pScissors;
+			};
+
+			const VkPipelineRasterizationStateCreateInfo rasterStateParams =
+			{
+				VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
+				DE_NULL,														// const void*								pNext;
+				0u,																// VkPipelineRasterizationStateCreateFlags	flags;
+				false,															// VkBool32									depthClampEnable;
+				false,															// VkBool32									rasterizerDiscardEnable;
+				VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
+				VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
+				VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
+				VK_FALSE,														// VkBool32									depthBiasEnable;
+				0.0f,															// float									depthBiasConstantFactor;
+				0.0f,															// float									depthBiasClamp;
+				0.0f,															// float									depthBiasSlopeFactor;
+				1.0f															// float									lineWidth;
+			};
+
+			const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
+			{
+				VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
+				DE_NULL,													// const void*									pNext;
+				0u,															// VkPipelineColorBlendStateCreateFlags			flags;
+				false,														// VkBool32										logicOpEnable;
+				VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
+				1u,															// deUint32										attachmentCount;
+				&m_colorBlendState,											// const VkPipelineColorBlendAttachmentState*	pAttachments;
+				{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
+			};
+
+			const  VkPipelineMultisampleStateCreateInfo multisampleStateParams =
+			{
+				VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType
+				DE_NULL,													// const void*								pNext
+				0u,															// VkPipelineMultisampleStateCreateFlags	flags
+				VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples
+				VK_FALSE,													// VkBool32									sampleShadingEnable
+				0.0f,														// float									minSampleShading
+				DE_NULL,													// const VkSampleMask*						pSampleMask
+				VK_FALSE,													// VkBool32									alphaToCoverageEnable
+				VK_FALSE,													// VkBool32									alphaToOneEnable
+			};
+
+			const VkGraphicsPipelineCreateInfo graphicsPipelineTemplate =
+			{
+				VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
+				DE_NULL,											// const void*										pNext;
+				0u,													// VkPipelineCreateFlags							flags;
+				2u,													// deUint32											stageCount;
+				shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
+				&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
+				&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
+				DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
+				&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
+				&rasterStateParams,									// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
+				&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
+				DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
+				&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
+				(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
+				*m_copySamplePipelineLayout,						// VkPipelineLayout									layout;
+				*m_renderPass,										// VkRenderPass										renderPass;
+				0u,													// deUint32											subpass;
+				0u,													// VkPipeline										basePipelineHandle;
+				0u													// deInt32											basePipelineIndex;
+			};
+
+			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+			{
+				VkGraphicsPipelineCreateInfo graphicsPipelineParams = graphicsPipelineTemplate;
+
+				// Pipeline is to be used in subpasses subsequent to sample-shading subpass
+				graphicsPipelineParams.subpass = 1u + (deUint32)i;
+
+				m_copySamplePipelines.push_back(VkPipelineSp(new Unique<VkPipeline>(createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams))));
+			}
+		}
+
+
+		const VkDescriptorPoolSize			descriptorPoolSize			=
+		{
+			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,					// VkDescriptorType					type;
+			1u														// deUint32							descriptorCount;
+		};
+
+		const VkDescriptorPoolCreateInfo	descriptorPoolCreateInfo	=
+		{
+			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,			// VkStructureType					sType
+			DE_NULL,												// const void*						pNext
+			VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,		// VkDescriptorPoolCreateFlags		flags
+			1u,													// deUint32							maxSets
+			1u,														// deUint32							poolSizeCount
+			&descriptorPoolSize										// const VkDescriptorPoolSize*		pPoolSizes
+		};
+
+		m_copySampleDesciptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo);
+
+		const VkDescriptorSetAllocateInfo	descriptorSetAllocateInfo	=
+		{
+			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,			// VkStructureType					sType
+			DE_NULL,												// const void*						pNext
+			*m_copySampleDesciptorPool,								// VkDescriptorPool					descriptorPool
+			1u,														// deUint32							descriptorSetCount
+			&m_copySampleDesciptorLayout.get(),						// const VkDescriptorSetLayout*		pSetLayouts
+		};
+
+		m_copySampleDesciptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
+
+		const VkDescriptorImageInfo			imageInfo					=
+		{
+			DE_NULL,
+			*m_colorAttachmentView,
+			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+		};
+		const VkWriteDescriptorSet			descriptorWrite				=
+		{
+			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,			// VkStructureType					sType;
+			DE_NULL,										// const void*						pNext;
+			*m_copySampleDesciptorSet,						// VkDescriptorSet					dstSet;
+			0u,												// deUint32							dstBinding;
+			0u,												// deUint32							dstArrayElement;
+			1u,												// deUint32							descriptorCount;
+			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,			// VkDescriptorType					descriptorType;
+			&imageInfo,										// const VkDescriptorImageInfo*		pImageInfo;
+			DE_NULL,										// const VkDescriptorBufferInfo*	pBufferInfo;
+			DE_NULL,										// const VkBufferView*				pTexelBufferView;
+		};
+		vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL);
+	}
+
 	// Create vertex buffer
 	{
 		const VkBufferCreateInfo vertexBufferParams =
@@ -1974,12 +2561,23 @@
 		depthStencilClearValue.depthStencil.depth = 1.0f;
 		depthStencilClearValue.depthStencil.stencil = 0u;
 
-		const VkClearValue clearValues[3] =
+		std::vector<VkClearValue> clearValues;
+		clearValues.push_back(colorClearValue);
+		if (m_renderType == RENDER_TYPE_RESOLVE)
 		{
-			colorClearValue,
-			colorClearValue,
-			depthStencilClearValue
-		};
+			clearValues.push_back(colorClearValue);
+		}
+		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+		{
+			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+			{
+				clearValues.push_back(colorClearValue);
+			}
+		}
+		if (m_useDepth || m_useStencil)
+		{
+			clearValues.push_back(depthStencilClearValue);
+		}
 
 		const VkRenderPassBeginInfo renderPassBeginInfo =
 		{
@@ -1991,13 +2589,15 @@
 				{ 0, 0 },
 				{ (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }
 			},														// VkRect2D				renderArea;
-			numUsedAttachments,										// deUint32				clearValueCount;
-			clearValues												// const VkClearValue*	pClearValues;
+			(deUint32)clearValues.size(),							// deUint32				clearValueCount;
+			&clearValues[0]											// const VkClearValue*	pClearValues;
 		};
 
-		const VkImageMemoryBarrier imageLayoutBarriers[] =
+		std::vector<VkImageMemoryBarrier> imageLayoutBarriers;
+
 		{
-			// color attachment image
+			const VkImageMemoryBarrier colorImageBarrier =
+				// color attachment image
 			{
 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
 				DE_NULL,										// const void*				pNext;
@@ -2009,7 +2609,12 @@
 				VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
 				*m_colorImage,									// VkImage					image;
 				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
-			},
+			};
+			imageLayoutBarriers.push_back(colorImageBarrier);
+		}
+		if (m_renderType == RENDER_TYPE_RESOLVE)
+		{
+			const VkImageMemoryBarrier resolveImageBarrier =
 			// resolve attachment image
 			{
 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
@@ -2022,7 +2627,33 @@
 				VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
 				*m_resolveImage,								// VkImage					image;
 				{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
-			},
+			};
+			imageLayoutBarriers.push_back(resolveImageBarrier);
+		}
+		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+		{
+			for (size_t i = 0; i < m_perSampleImages.size(); ++i)
+			{
+				const VkImageMemoryBarrier perSampleImageBarrier =
+				// resolve attachment image
+				{
+					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
+					DE_NULL,										// const void*				pNext;
+					0u,												// VkAccessFlags			srcAccessMask;
+					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
+					VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
+					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
+					VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
+					VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
+					*m_perSampleImages[i]->m_image,					// VkImage					image;
+					{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
+				};
+				imageLayoutBarriers.push_back(perSampleImageBarrier);
+			}
+		}
+		if (m_useDepth || m_useStencil)
+		{
+			const VkImageMemoryBarrier depthStencilImageBarrier =
 			// depth/stencil attachment image
 			{
 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
@@ -2035,7 +2666,8 @@
 				VK_QUEUE_FAMILY_IGNORED,							// deUint32					dstQueueFamilyIndex;
 				*m_depthStencilImage,								// VkImage					image;
 				{ depthStencilAttachmentAspect, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
-			},
+			};
+			imageLayoutBarriers.push_back(depthStencilImageBarrier);
 		};
 
 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
@@ -2043,7 +2675,7 @@
 		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
 
 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
-			0u, DE_NULL, 0u, DE_NULL, numUsedAttachments, imageLayoutBarriers);
+			0u, DE_NULL, 0u, DE_NULL, (deUint32)imageLayoutBarriers.size(), &imageLayoutBarriers[0]);
 
 		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
 
@@ -2058,6 +2690,19 @@
 			vertexBufferOffset += static_cast<VkDeviceSize>(pVertices[i].size() * sizeof(Vertex4RGBA));
 		}
 
+		if (m_renderType == RENDER_TYPE_COPY_SAMPLES)
+		{
+			// Copy each sample id to single sampled image
+			for (deInt32 sampleId = 0; sampleId < (deInt32)m_perSampleImages.size(); ++sampleId)
+			{
+				vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
+				vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_copySamplePipelines[sampleId]);
+				vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_copySamplePipelineLayout, 0u, 1u, &m_copySampleDesciptorSet.get(), 0u, DE_NULL);
+				vk.cmdPushConstants(*m_cmdBuffer, *m_copySamplePipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(deInt32), &sampleId);
+				vk.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
+			}
+		}
+
 		vk.cmdEndRenderPass(*m_cmdBuffer);
 
 		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
@@ -2095,7 +2740,25 @@
 	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
 	VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
 
-	return readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_resolveImage, m_colorFormat, m_renderSize.cast<deUint32>());
+	if (m_renderType == RENDER_TYPE_RESOLVE)
+	{
+		return readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_resolveImage, m_colorFormat, m_renderSize.cast<deUint32>());
+	}
+	else
+	{
+		return de::MovePtr<tcu::TextureLevel>();
+	}
+}
+
+de::MovePtr<tcu::TextureLevel> MultisampleRenderer::getSingleSampledImage (deUint32 sampleId)
+{
+	const DeviceInterface&		vk					= m_context.getDeviceInterface();
+	const VkDevice				vkDevice			= m_context.getDevice();
+	const VkQueue				queue				= m_context.getUniversalQueue();
+	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
+	SimpleAllocator				allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
+
+	return readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_perSampleImages[sampleId]->m_image, m_colorFormat, m_renderSize.cast<deUint32>());
 }
 
 } // anonymous
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt b/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt
index 5717740..00e9cc3 100644
--- a/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt
+++ b/external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt
@@ -7,6 +7,10 @@
 	vktSpvAsm16bitStorageTests.hpp
 	vktSpvAsmUboMatrixPaddingTests.cpp
 	vktSpvAsmUboMatrixPaddingTests.hpp
+	vktSpvAsmConditionalBranchTests.cpp
+	vktSpvAsmConditionalBranchTests.hpp
+	vktSpvAsmIndexingTests.cpp
+	vktSpvAsmIndexingTests.hpp
 	vktSpvAsmComputeShaderCase.cpp
 	vktSpvAsmComputeShaderCase.hpp
 	vktSpvAsmComputeShaderTestUtil.cpp
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmConditionalBranchTests.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmConditionalBranchTests.cpp
new file mode 100644
index 0000000..320d53d
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmConditionalBranchTests.cpp
@@ -0,0 +1,236 @@
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 Google Inc.
+ *
+ * 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 implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Assembly Tests for OpBranchConditional instruction.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktSpvAsmConditionalBranchTests.hpp"
+#include "vktSpvAsmComputeShaderCase.hpp"
+#include "vktSpvAsmComputeShaderTestUtil.hpp"
+#include "vktSpvAsmGraphicsShaderTestUtil.hpp"
+
+#include "tcuStringTemplate.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+using namespace vk;
+using std::map;
+using std::string;
+using std::vector;
+using tcu::RGBA;
+using tcu::IVec3;
+using tcu::StringTemplate;
+
+namespace
+{
+
+static const string conditions[] = { "true", "false" };
+
+void addComputeSameLabelsTest (tcu::TestCaseGroup* group)
+{
+	tcu::TestContext&		testCtx			= group->getTestContext();
+	const int				numItems		= 128;
+	vector<deUint32>		outputData;
+
+	outputData.reserve(numItems);
+	for (deUint32 numIdx = 0; numIdx < numItems; ++numIdx)
+		outputData.push_back(numIdx);
+
+	for (int conditionIdx = 0; conditionIdx < DE_LENGTH_OF_ARRAY(conditions); ++conditionIdx)
+	{
+		ComputeShaderSpec		spec;
+		map<string, string>		specs;
+		string					testName		= string("same_labels_") + conditions[conditionIdx];
+
+		const StringTemplate	shaderSource	(
+			"                         OpCapability Shader\n"
+			"                    %1 = OpExtInstImport \"GLSL.std.450\"\n"
+			"                         OpMemoryModel Logical GLSL450\n"
+			"                         OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n"
+			"                         OpExecutionMode %main LocalSize 1 1 1\n"
+			"                         OpSource GLSL 430\n"
+			"                         OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n"
+			"                         OpDecorate %_arr_uint_uint_128 ArrayStride 4\n"
+			"                         OpMemberDecorate %Output 0 Offset 0\n"
+			"                         OpDecorate %Output BufferBlock\n"
+			"                         OpDecorate %dataOutput DescriptorSet 0\n"
+			"                         OpDecorate %dataOutput Binding 0\n"
+			"                 %void = OpTypeVoid\n"
+			"                    %3 = OpTypeFunction %void\n"
+			"                 %uint = OpTypeInt 32 0\n"
+			"   %_ptr_Function_uint = OpTypePointer Function %uint\n"
+			"               %v3uint = OpTypeVector %uint 3\n"
+			"    %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
+			"%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n"
+			"               %uint_0 = OpConstant %uint 0\n"
+			"      %_ptr_Input_uint = OpTypePointer Input %uint\n"
+			"                 %bool = OpTypeBool\n"
+			"                 %true = OpConstantTrue %bool\n"
+			"                %false = OpConstantFalse %bool\n"
+			"             %uint_128 = OpConstant %uint 128\n"
+			"   %_arr_uint_uint_128 = OpTypeArray %uint %uint_128\n"
+			"               %Output = OpTypeStruct %_arr_uint_uint_128\n"
+			"  %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
+			"           %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
+			"    %_ptr_Uniform_uint = OpTypePointer Uniform %uint\n"
+			"           %uint_dummy = OpConstant %uint 2863311530\n"
+			"                 %main = OpFunction %void None %3\n"
+			"                    %5 = OpLabel\n"
+			"                    %i = OpVariable %_ptr_Function_uint Function\n"
+			"                   %14 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0\n"
+			"                   %15 = OpLoad %uint %14\n"
+			"                         OpStore %i %15\n"
+			"               %uint_i = OpLoad %uint %i\n"
+			"                         OpSelectionMerge %merge None\n"
+			"                         OpBranchConditional %${condition} %live %live\n"
+			"                 %live = OpLabel\n"
+			"                   %31 = OpAccessChain %_ptr_Uniform_uint %dataOutput %uint_0 %uint_i\n"
+			"                         OpStore %31 %uint_i\n"
+			"                         OpBranch %merge\n"
+			"                 %dead = OpLabel\n"
+			"                   %35 = OpAccessChain %_ptr_Uniform_uint %dataOutput %uint_0 %uint_i\n"
+			"                         OpStore %35 %uint_dummy\n"
+			"                         OpBranch %merge\n"
+			"                %merge = OpLabel\n"
+			"                         OpReturn\n"
+			"                         OpFunctionEnd\n");
+
+		specs["condition"]		= conditions[conditionIdx];
+		spec.assembly			= shaderSource.specialize(specs);
+		spec.numWorkGroups		= IVec3(numItems, 1, 1);
+
+		spec.outputs.push_back(BufferSp(new Buffer<deUint32>(outputData)));
+
+		group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), "Tests both labels pointing to a same branch.", spec));
+	}
+}
+
+void addGraphicsSameLabelsTest (tcu::TestCaseGroup* group)
+{
+	const deUint32			numItems			= 128;
+	RGBA					defaultColors[4];
+	GraphicsResources		resources;
+	vector<deUint32>		outputData;
+
+	outputData.reserve(numItems);
+	for (deUint32 numIdx = 0; numIdx < numItems; ++numIdx)
+		outputData.push_back(numIdx);
+
+	resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Buffer<deUint32>(outputData))));
+
+	getDefaultColors(defaultColors);
+
+	for (int conditionIdx = 0; conditionIdx < DE_LENGTH_OF_ARRAY(conditions); ++conditionIdx)
+	{
+		map<string, string>		fragments;
+		map<string, string>		specs;
+		string					testName	= string("same_labels_") + conditions[conditionIdx];
+
+		fragments["pre_main"]				=
+			"          %c_u32_128 = OpConstant %u32 128\n"
+			"                  %3 = OpTypeFunction %void\n"
+			"               %true = OpConstantTrue %bool\n"
+			"              %false = OpConstantFalse %bool\n"
+			" %_arr_uint_uint_128 = OpTypeArray %u32 %c_u32_128\n"
+			"             %Output = OpTypeStruct %_arr_uint_uint_128\n"
+			"%_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
+			"         %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
+			"  %_ptr_Uniform_uint = OpTypePointer Uniform %u32\n"
+			"             %fp_u32 = OpTypePointer Function %u32\n"
+			"         %uint_dummy = OpConstant %u32 2863311530\n";
+
+		fragments["decoration"]				=
+			"                       OpDecorate %_arr_uint_uint_128 ArrayStride 4\n"
+			"                       OpMemberDecorate %Output 0 Offset 0\n"
+			"                       OpDecorate %Output BufferBlock\n"
+			"                       OpDecorate %dataOutput DescriptorSet 0\n"
+			"                       OpDecorate %dataOutput Binding 0\n";
+
+		const StringTemplate	testFun		(
+			"          %test_code = OpFunction %v4f32 None %v4f32_function\n"
+			"              %param = OpFunctionParameter %v4f32\n"
+
+			"              %entry = OpLabel\n"
+			"                  %i = OpVariable %fp_u32 Function\n"
+			"                       OpStore %i %c_u32_0\n"
+			"                       OpBranch %loop\n"
+
+			"               %loop = OpLabel\n"
+			"                 %15 = OpLoad %u32 %i\n"
+			"                 %lt = OpSLessThan %bool %15 %c_u32_128\n"
+			"                       OpLoopMerge %merge %inc None\n"
+			"                       OpBranchConditional %lt %write %merge\n"
+
+			"              %write = OpLabel\n"
+			"             %uint_i = OpLoad %u32 %i\n"
+			"                       OpSelectionMerge %condmerge None\n"
+			"                       OpBranchConditional %${condition} %live %live\n"
+			"               %live = OpLabel\n"
+			"                 %31 = OpAccessChain %_ptr_Uniform_uint %dataOutput %c_u32_0 %uint_i\n"
+			"                       OpStore %31 %uint_i\n"
+			"                       OpBranch %condmerge\n"
+			"               %dead = OpLabel\n"
+			"                 %35 = OpAccessChain %_ptr_Uniform_uint %dataOutput %c_u32_0 %uint_i\n"
+			"                       OpStore %35 %uint_dummy\n"
+			"                       OpBranch %condmerge\n"
+			"          %condmerge = OpLabel\n"
+			"                       OpBranch %inc\n"
+
+			"                %inc = OpLabel\n"
+			"                 %37 = OpLoad %u32 %i\n"
+			"                 %39 = OpIAdd %u32 %37 %c_u32_1\n"
+			"                       OpStore %i %39\n"
+			"                       OpBranch %loop\n"
+
+			"              %merge = OpLabel\n"
+			"                       OpReturnValue %param\n"
+
+			"                       OpFunctionEnd\n");
+
+		specs["condition"]		= conditions[conditionIdx];
+		fragments["testfun"]	= testFun.specialize(specs);
+
+		createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, resources, vector<string>(), group);
+	}
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createConditionalBranchComputeGroup (tcu::TestContext& testCtx)
+{
+	de::MovePtr<tcu::TestCaseGroup> group		(new tcu::TestCaseGroup(testCtx, "conditional_branch", "Compute tests for OpBranchConditional."));
+	addComputeSameLabelsTest(group.get());
+
+	return group.release();
+}
+
+tcu::TestCaseGroup* createConditionalBranchGraphicsGroup (tcu::TestContext& testCtx)
+{
+	de::MovePtr<tcu::TestCaseGroup> group		(new tcu::TestCaseGroup(testCtx, "conditional_branch", "Graphics tests for OpBranchConditional."));
+	addGraphicsSameLabelsTest(group.get());
+
+	return group.release();
+}
+
+} // SpirVAssembly
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmConditionalBranchTests.hpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmConditionalBranchTests.hpp
new file mode 100644
index 0000000..4a1efe8
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmConditionalBranchTests.hpp
@@ -0,0 +1,40 @@
+#ifndef _VKTSPVASMCONDITIONALBRANCHTESTS_HPP
+#define _VKTSPVASMCONDITIONALBRANCHTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 Google Inc.
+ *
+ * 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 implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Assembly Tests for OpBranchConditional instruction.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+tcu::TestCaseGroup*	createConditionalBranchComputeGroup		(tcu::TestContext& testCtx);
+tcu::TestCaseGroup*	createConditionalBranchGraphicsGroup	(tcu::TestContext& testCtx);
+
+} // SpirVAssembly
+} // vkt
+
+#endif // _VKTSPVASMCONDITIONALBRANCHTESTS_HPP
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp
index cd36dd7..f039e4a 100644
--- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp
+++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp
@@ -2194,13 +2194,13 @@
 
 	if (hasTessellation && !supportsTessellation)
 	{
-		throw tcu::NotSupportedError(std::string("Tessellation not supported"));
+		TCU_THROW(NotSupportedError, "Tessellation not supported");
 	}
 
 	if ((instance.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT) &&
 		!supportsGeometry)
 	{
-		throw tcu::NotSupportedError(std::string("Geometry not supported"));
+		TCU_THROW(NotSupportedError, "Geometry not supported");
 	}
 
 	{
@@ -2211,11 +2211,16 @@
 			if (feature == "shaderInt16")
 			{
 				if (features.shaderInt16 != VK_TRUE)
-					throw tcu::NotSupportedError(std::string("Device feature not supported: ") + feature);
+					TCU_THROW(NotSupportedError, "Device feature not supported: shaderInt16");
+			}
+			else if (feature == "shaderInt64")
+			{
+				if (features.shaderInt64 != VK_TRUE)
+					TCU_THROW(NotSupportedError, "Device feature not supported: shaderInt64");
 			}
 			else
 			{
-				throw tcu::InternalError(std::string("Unimplemented physical device feature: ") + feature);
+				TCU_THROW(InternalError, (std::string("Unimplemented physical device feature: ") + feature).c_str());
 			}
 		}
 	}
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmIndexingTests.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmIndexingTests.cpp
new file mode 100644
index 0000000..995c6f3
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmIndexingTests.cpp
@@ -0,0 +1,483 @@
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 Google Inc.
+ *
+ * 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 implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Assembly Tests for indexing with different bit sizes.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktSpvAsmIndexingTests.hpp"
+#include "vktSpvAsmComputeShaderCase.hpp"
+#include "vktSpvAsmComputeShaderTestUtil.hpp"
+#include "vktSpvAsmGraphicsShaderTestUtil.hpp"
+
+#include "tcuStringTemplate.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+using namespace vk;
+using std::map;
+using std::string;
+using std::vector;
+using std::pair;
+using tcu::IVec3;
+using tcu::RGBA;
+using tcu::UVec4;
+using tcu::Mat4;
+using tcu::StringTemplate;
+
+namespace
+{
+
+enum ChainOp
+{
+	CHAIN_OP_ACCESS_CHAIN = 0,
+	CHAIN_OP_IN_BOUNDS_ACCESS_CHAIN,
+	CHAIN_OP_PTR_ACCESS_CHAIN,
+
+	CHAIN_OP_LAST
+};
+static const int					idxSizes[]				= { 16, 32, 64 };
+static const ComputeTestFeatures	computeTestFeatures[]	= { COMPUTE_TEST_USES_INT16, COMPUTE_TEST_USES_NONE, COMPUTE_TEST_USES_INT64 };
+static const string					chainOpTestNames[]		= { "opaccesschain", "opinboundsaccesschain", "opptraccesschain" };
+
+struct InputData
+{
+	Mat4	matrix[32][32];
+};
+
+void addComputeIndexingTests (tcu::TestCaseGroup* group)
+{
+	tcu::TestContext&	testCtx			= group->getTestContext();
+	de::Random			rnd				(deStringHash(group->getName()));
+	const int			numItems		= 128;
+	const int			numStructs		= 2;
+	const int			numInputFloats	= (int)sizeof(InputData) / 4 * numStructs;
+	vector<float>		inputData;
+	vector<UVec4>		indexSelectorData;
+
+	inputData.reserve(numInputFloats);
+	for (deUint32 numIdx = 0; numIdx < numInputFloats; ++numIdx)
+		inputData.push_back(rnd.getFloat());
+
+	indexSelectorData.reserve(numItems);
+	for (deUint32 numIdx = 0; numIdx < numItems; ++numIdx)
+		indexSelectorData.push_back(UVec4(rnd.getUint32() % 32, rnd.getUint32() % 32, rnd.getUint32() % 4, rnd.getUint32() % 4));
+
+	for (int chainOpIdx = 0; chainOpIdx < CHAIN_OP_LAST; ++chainOpIdx)
+	{
+		for (int idxSizeIdx = 0; idxSizeIdx < DE_LENGTH_OF_ARRAY(idxSizes); ++idxSizeIdx)
+		{
+			for (int sign = 0; sign < 2; ++sign)
+			{
+				const int					idxSize			= idxSizes[idxSizeIdx];
+				const string				testName		= chainOpTestNames[chainOpIdx] + string(sign == 0 ? "_u" : "_s") + de::toString(idxSize);
+				VulkanFeatures				vulkanFeatures;
+				map<string, string>			specs;
+				vector<float>				outputData;
+				ComputeShaderSpec			spec;
+				const ComputeTestFeatures	features		= computeTestFeatures[idxSizeIdx];
+				int							element			= 0;
+
+				// Index an input buffer containing 2D array of 4x4 matrices. The indices are read from another
+				// input and converted to the desired bit size and sign.
+				const StringTemplate		shaderSource(
+					"                             OpCapability Shader\n"
+					"                             ${intcaps:opt}\n"
+					"                             ${variablepointercaps:opt}\n"
+					"                             ${extensions:opt}\n"
+					"                        %1 = OpExtInstImport \"GLSL.std.450\"\n"
+					"                             OpMemoryModel Logical GLSL450\n"
+					"                             OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n"
+					"                             OpExecutionMode %main LocalSize 1 1 1\n"
+					"                             OpSource GLSL 430\n"
+					"                             OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n"
+					"                             OpDecorate %_arr_float_uint_128 ArrayStride 4\n"
+					"                             OpMemberDecorate %Output 0 Offset 0\n"
+					"                             OpDecorate %Output BufferBlock\n"
+					"                             OpDecorate %dataOutput DescriptorSet 0\n"
+					"                             OpDecorate %dataOutput Binding 2\n"
+					"                             OpDecorate %_arr_mat4v4float_uint_32 ArrayStride 64\n"
+					"                             OpDecorate %_arr__arr_mat4v4float_uint_32_uint_32 ArrayStride 2048\n"
+					"                             OpMemberDecorate %Input 0 ColMajor\n"
+					"                             OpMemberDecorate %Input 0 Offset 0\n"
+					"                             OpMemberDecorate %Input 0 MatrixStride 16\n"
+					"                             OpDecorate %Input ${inputdecoration}\n"
+					"                             OpDecorate %dataInput DescriptorSet 0\n"
+					"                             OpDecorate %dataInput Binding 0\n"
+					"                             OpDecorate %_ptr_buffer_Input ArrayStride 65536\n"
+					"                             OpDecorate %_arr_v4uint_uint_128 ArrayStride 16\n"
+					"                             OpMemberDecorate %DataSelector 0 Offset 0\n"
+					"                             OpDecorate %DataSelector BufferBlock\n"
+					"                             OpDecorate %selector DescriptorSet 0\n"
+					"                             OpDecorate %selector Binding 1\n"
+					"                     %void = OpTypeVoid\n"
+					"                        %3 = OpTypeFunction %void\n"
+					"                      %idx = OpTypeInt ${idxsize} ${idxsign}\n"
+					"                    %idx_0 = OpConstant %idx 0\n"
+					"                    %idx_1 = OpConstant %idx 1\n"
+					"                    %idx_2 = OpConstant %idx 2\n"
+					"                    %idx_3 = OpConstant %idx 3\n"
+					"                   %uint32 = OpTypeInt 32 0\n"
+					"     %_ptr_Function_uint32 = OpTypePointer Function %uint32\n"
+					"                 %v3uint32 = OpTypeVector %uint32 3\n"
+					"      %_ptr_Input_v3uint32 = OpTypePointer Input %v3uint32\n"
+					"    %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint32 Input\n"
+					"        %_ptr_Input_uint32 = OpTypePointer Input %uint32\n"
+					"                    %float = OpTypeFloat 32\n"
+					"                 %uint_128 = OpConstant %uint32 128\n"
+					"                  %uint_32 = OpConstant %uint32 32\n"
+					"      %_arr_float_uint_128 = OpTypeArray %float %uint_128\n"
+					"                   %Output = OpTypeStruct %_arr_float_uint_128\n"
+					"      %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
+					"               %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
+					"                  %v4float = OpTypeVector %float 4\n"
+					"              %mat4v4float = OpTypeMatrix %v4float 4\n"
+					" %_arr_mat4v4float_uint_32 = OpTypeArray %mat4v4float %uint_32\n"
+					" %_arr__arr_mat4v4float_uint_32_uint_32 = OpTypeArray %_arr_mat4v4float_uint_32 %uint_32\n"
+					"                    %Input = OpTypeStruct %_arr__arr_mat4v4float_uint_32_uint_32\n"
+					"        %_ptr_buffer_Input = OpTypePointer ${inputstorageclass} %Input\n"
+					"                %dataInput = OpVariable %_ptr_buffer_Input ${inputstorageclass}\n"
+					"                 %v4uint32 = OpTypeVector %uint32 4\n"
+					"     %_arr_v4uint_uint_128 = OpTypeArray %v4uint32 %uint_128\n"
+					"             %DataSelector = OpTypeStruct %_arr_v4uint_uint_128\n"
+					"%_ptr_Uniform_DataSelector = OpTypePointer Uniform %DataSelector\n"
+					"                 %selector = OpVariable %_ptr_Uniform_DataSelector Uniform\n"
+					"      %_ptr_Uniform_uint32 = OpTypePointer Uniform %uint32\n"
+					"       %_ptr_Uniform_float = OpTypePointer Uniform %float\n"
+					"       %_ptr_buffer_float  = OpTypePointer ${inputstorageclass} %float\n"
+
+					"                     %main = OpFunction %void None %3\n"
+					"                        %5 = OpLabel\n"
+					"                        %i = OpVariable %_ptr_Function_uint32 Function\n"
+					"                       %14 = OpAccessChain %_ptr_Input_uint32 %gl_GlobalInvocationID %idx_0\n"
+					"                       %15 = OpLoad %uint32 %14\n"
+					"                             OpStore %i %15\n"
+					"                   %uint_i = OpLoad %uint32 %i\n"
+					"                       %39 = OpAccessChain %_ptr_Uniform_uint32 %selector %idx_0 %uint_i %idx_0\n"
+					"                       %40 = OpLoad %uint32 %39\n"
+					"                       %43 = OpAccessChain %_ptr_Uniform_uint32 %selector %idx_0 %uint_i %idx_1\n"
+					"                       %44 = OpLoad %uint32 %43\n"
+					"                       %47 = OpAccessChain %_ptr_Uniform_uint32 %selector %idx_0 %uint_i %idx_2\n"
+					"                       %48 = OpLoad %uint32 %47\n"
+					"                       %51 = OpAccessChain %_ptr_Uniform_uint32 %selector %idx_0 %uint_i %idx_3\n"
+					"                       %52 = OpLoad %uint32 %51\n"
+					"                       %i0 = OpUConvert %idx %40\n"
+					"                       %i1 = OpUConvert %idx %44\n"
+					"                       %i2 = OpUConvert %idx %48\n"
+					"                       %i3 = OpUConvert %idx %52\n"
+					"                       %54 = ${accesschain}\n"
+					"                       %55 = OpLoad %float %54\n"
+					"                       %56 = OpAccessChain %_ptr_Uniform_float %dataOutput %idx_0 %uint_i\n"
+					"                             OpStore %56 %55\n"
+					"                             OpReturn\n"
+					"                             OpFunctionEnd\n");
+
+
+				switch (chainOpIdx)
+				{
+					case CHAIN_OP_ACCESS_CHAIN:
+						specs["accesschain"]			= "OpAccessChain %_ptr_buffer_float %dataInput %idx_0 %i0 %i1 %i2 %i3\n";
+						specs["inputdecoration"]		= "BufferBlock";
+						specs["inputstorageclass"]		= "Uniform";
+						break;
+					case CHAIN_OP_IN_BOUNDS_ACCESS_CHAIN:
+						specs["accesschain"]			= "OpInBoundsAccessChain %_ptr_buffer_float %dataInput %idx_0 %i0 %i1 %i2 %i3\n";
+						specs["inputdecoration"]		= "BufferBlock";
+						specs["inputstorageclass"]		= "Uniform";
+						break;
+					default:
+						DE_ASSERT(chainOpIdx == CHAIN_OP_PTR_ACCESS_CHAIN);
+						specs["accesschain"]			= "OpPtrAccessChain %_ptr_buffer_float %dataInput %idx_1 %idx_0 %i0 %i1 %i2 %i3\n";
+						specs["inputdecoration"]		= "Block";
+						specs["inputstorageclass"]		= "StorageBuffer";
+						specs["variablepointercaps"]	= "OpCapability VariablePointersStorageBuffer";
+						specs["extensions"]				= "OpExtension \"SPV_KHR_variable_pointers\"\n                             "
+														  "OpExtension \"SPV_KHR_storage_buffer_storage_class\"";
+						element = 1;
+						vulkanFeatures.extVariablePointers = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER;
+						spec.extensions.push_back("VK_KHR_variable_pointers");
+						break;
+				};
+
+				spec.inputs.push_back(BufferSp(new Float32Buffer(inputData)));
+				spec.inputs.push_back(BufferSp(new Buffer<UVec4>(indexSelectorData)));
+
+				outputData.reserve(numItems);
+				for (deUint32 numIdx = 0; numIdx < numItems; ++numIdx)
+				{
+					// Determine the selected output float for the selected indices.
+					const UVec4 vec = indexSelectorData[numIdx];
+					outputData.push_back(inputData[element * sizeof(InputData) / 4 + vec.x() * (32 * 4 * 4) + vec.y() * 4 * 4 + vec.z() * 4 + vec.w()]);
+				}
+
+				if (idxSize == 16)
+					specs["intcaps"] = "OpCapability Int16";
+				else if (idxSize == 64)
+					specs["intcaps"] = "OpCapability Int64";
+
+				specs["idxsize"]				= de::toString(idxSize);
+				specs["idxsign"]				= de::toString(sign);
+				spec.assembly					= shaderSource.specialize(specs);
+				spec.numWorkGroups				= IVec3(numItems, 1, 1);
+				spec.requestedVulkanFeatures	= vulkanFeatures;
+				spec.inputTypes[0]				= VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+				spec.inputTypes[1]				= VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+
+				spec.outputs.push_back(BufferSp(new Float32Buffer(outputData)));
+
+				group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec, features));
+			}
+		}
+	}
+}
+
+void addGraphicsIndexingTests (tcu::TestCaseGroup* group)
+{
+	de::Random			rnd				(deStringHash(group->getName()));
+	const int			numItems		= 128;
+	const int			numStructs		= 2;
+	const int			numInputFloats	= (int)sizeof(InputData) / 4 * numStructs;
+	RGBA				defaultColors[4];
+	vector<float>		inputData;
+	vector<UVec4>		indexSelectorData;
+
+	inputData.reserve(numInputFloats);
+	for (deUint32 numIdx = 0; numIdx < numInputFloats; ++numIdx)
+		inputData.push_back(rnd.getFloat());
+
+	indexSelectorData.reserve(numItems);
+	for (deUint32 numIdx = 0; numIdx < numItems; ++numIdx)
+		indexSelectorData.push_back(UVec4(rnd.getUint32() % 32, rnd.getUint32() % 32, rnd.getUint32() % 4, rnd.getUint32() % 4));
+
+	getDefaultColors(defaultColors);
+
+	for (int chainOpIdx = 0; chainOpIdx < CHAIN_OP_LAST; ++chainOpIdx)
+	{
+		for (int idxSizeIdx = 0; idxSizeIdx < DE_LENGTH_OF_ARRAY(idxSizes); ++idxSizeIdx)
+		{
+			for (int sign = 0; sign < 2; sign++)
+			{
+				const int					idxSize			= idxSizes[idxSizeIdx];
+				const string				testName		= chainOpTestNames[chainOpIdx] + string(sign == 0 ? "_u" : "_s") + de::toString(idxSize);
+				VulkanFeatures				vulkanFeatures;
+				vector<string>				extensions;
+				vector<string>				features;
+				vector<deInt32>				noSpecConstants;
+				PushConstants				noPushConstants;
+				GraphicsInterfaces			noInterfaces;
+				map<string, string>			specs;
+				map<string, string>			fragments;
+				vector<float>				outputData;
+				ComputeShaderSpec			spec;
+				int							element			= 0;
+				GraphicsResources			resources;
+
+				const StringTemplate		preMain(
+					"                %c_i32_128 = OpConstant %i32 128\n"
+					"                     %uint = OpTypeInt ${idxsize} 0\n"
+					"     %_ptr_Function_uint32 = OpTypePointer Function %u32\n"
+					"                 %v3uint32 = OpTypeVector %u32 3\n"
+					"      %_ptr_Input_v3uint32 = OpTypePointer Input %v3uint32\n"
+					"                   %uint_0 = OpConstant %uint 0\n"
+					"        %_ptr_Input_uint32 = OpTypePointer Input %u32\n"
+					"                 %uint_128 = OpConstant %u32 128\n"
+					"                  %uint_32 = OpConstant %u32 32\n"
+					"      %_arr_float_uint_128 = OpTypeArray %f32 %uint_128\n"
+					"                   %Output = OpTypeStruct %_arr_float_uint_128\n"
+					"      %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
+					"               %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
+					"                      %int = OpTypeInt ${idxsize} ${idxsign}\n"
+					"                    %int_0 = OpConstant %int 0\n"
+					"                  %v4float = OpTypeVector %f32 4\n"
+					"              %mat4v4float = OpTypeMatrix %v4float 4\n"
+					" %_arr_mat4v4float_uint_32 = OpTypeArray %mat4v4float %uint_32\n"
+					" %_arr__arr_mat4v4float_uint_32_uint_32 = OpTypeArray %_arr_mat4v4float_uint_32 %uint_32\n"
+					"                    %Input = OpTypeStruct %_arr__arr_mat4v4float_uint_32_uint_32\n"
+					"        %_ptr_buffer_Input = OpTypePointer ${inputstorageclass} %Input\n"
+					"                %dataInput = OpVariable %_ptr_buffer_Input ${inputstorageclass}\n"
+					"                 %v4uint32 = OpTypeVector %u32 4\n"
+					"     %_arr_v4uint_uint_128 = OpTypeArray %v4uint32 %uint_128\n"
+					"             %DataSelector = OpTypeStruct %_arr_v4uint_uint_128\n"
+					"%_ptr_Uniform_DataSelector = OpTypePointer Uniform %DataSelector\n"
+					"                 %selector = OpVariable %_ptr_Uniform_DataSelector Uniform\n"
+					"      %_ptr_Uniform_uint32 = OpTypePointer Uniform %u32\n"
+					"                   %uint_1 = OpConstant %uint 1\n"
+					"                   %uint_2 = OpConstant %uint 2\n"
+					"                   %uint_3 = OpConstant %uint 3\n"
+					"       %_ptr_Uniform_float = OpTypePointer Uniform %f32\n"
+					"        %_ptr_buffer_float = OpTypePointer ${inputstorageclass} %f32\n");
+
+
+				const StringTemplate		decoration(
+					"OpDecorate %_arr_float_uint_128 ArrayStride 4\n"
+					"OpMemberDecorate %Output 0 Offset 0\n"
+					"OpDecorate %Output BufferBlock\n"
+					"OpDecorate %dataOutput DescriptorSet 0\n"
+					"OpDecorate %dataOutput Binding 2\n"
+					"OpDecorate %_arr_mat4v4float_uint_32 ArrayStride 64\n"
+					"OpDecorate %_arr__arr_mat4v4float_uint_32_uint_32 ArrayStride 2048\n"
+					"OpMemberDecorate %Input 0 ColMajor\n"
+					"OpMemberDecorate %Input 0 Offset 0\n"
+					"OpMemberDecorate %Input 0 MatrixStride 16\n"
+					"OpDecorate %Input ${inputdecoration}\n"
+					"OpDecorate %dataInput DescriptorSet 0\n"
+					"OpDecorate %dataInput Binding 0\n"
+					"OpDecorate %_ptr_buffer_Input ArrayStride 65536\n"
+					"OpDecorate %_arr_v4uint_uint_128 ArrayStride 16\n"
+					"OpMemberDecorate %DataSelector 0 Offset 0\n"
+					"OpDecorate %DataSelector BufferBlock\n"
+					"OpDecorate %selector DescriptorSet 0\n"
+					"OpDecorate %selector Binding 1\n");
+
+				// Index an input buffer containing 2D array of 4x4 matrices. The indices are read from another
+				// input and converted to the desired bit size and sign.
+				const StringTemplate		testFun(
+					"%test_code = OpFunction %v4f32 None %v4f32_function\n"
+					"    %param = OpFunctionParameter %v4f32\n"
+
+					"    %entry = OpLabel\n"
+					"        %i = OpVariable %fp_i32 Function\n"
+					"             OpStore %i %c_i32_0\n"
+					"             OpBranch %loop\n"
+
+					"     %loop = OpLabel\n"
+					"       %15 = OpLoad %i32 %i\n"
+					"       %lt = OpSLessThan %bool %15 %c_i32_128\n"
+					"             OpLoopMerge %merge %inc None\n"
+					"             OpBranchConditional %lt %write %merge\n"
+
+					"    %write = OpLabel\n"
+					"    %int_i = OpLoad %i32 %i\n"
+					"       %39 = OpAccessChain %_ptr_Uniform_uint32 %selector %int_0 %int_i %uint_0\n"
+					"       %40 = OpLoad %u32 %39\n"
+					"       %43 = OpAccessChain %_ptr_Uniform_uint32 %selector %int_0 %int_i %uint_1\n"
+					"       %44 = OpLoad %u32 %43\n"
+					"       %47 = OpAccessChain %_ptr_Uniform_uint32 %selector %int_0 %int_i %uint_2\n"
+					"       %48 = OpLoad %u32 %47\n"
+					"       %51 = OpAccessChain %_ptr_Uniform_uint32 %selector %int_0 %int_i %uint_3\n"
+					"       %52 = OpLoad %u32 %51\n"
+					"       %i0 = OpUConvert %uint %40\n"
+					"       %i1 = OpUConvert %uint %44\n"
+					"       %i2 = OpUConvert %uint %48\n"
+					"       %i3 = OpUConvert %uint %52\n"
+					"       %54 = ${accesschain}\n"
+					"       %55 = OpLoad %f32 %54\n"
+					"       %56 = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %int_i\n"
+					"             OpStore %56 %55\n"
+					"             OpBranch %inc\n"
+
+					"      %inc = OpLabel\n"
+					"       %67 = OpLoad %i32 %i\n"
+					"       %69 = OpIAdd %i32 %67 %c_i32_1\n"
+					"             OpStore %i %69\n"
+					"             OpBranch %loop\n"
+
+					"    %merge = OpLabel\n"
+					"             OpReturnValue %param\n"
+
+					"             OpFunctionEnd\n");
+
+
+				resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputData))));
+				resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Buffer<UVec4>(indexSelectorData))));
+
+				if (idxSize == 16)
+				{
+					fragments["capability"] = "OpCapability Int16\n";
+					features.push_back("shaderInt16");
+				}
+				else if (idxSize == 64)
+				{
+					fragments["capability"] = "OpCapability Int64\n";
+					features.push_back("shaderInt64");
+				}
+
+				specs["idxsize"] = de::toString(idxSize);
+				specs["idxsign"] = de::toString(sign);
+
+				switch (chainOpIdx)
+				{
+					case CHAIN_OP_ACCESS_CHAIN:
+						specs["accesschain"]				= "OpAccessChain %_ptr_buffer_float %dataInput %int_0 %i0 %i1 %i2 %i3\n";
+						specs["inputdecoration"]			= "BufferBlock";
+						specs["inputstorageclass"]			= "Uniform";
+						break;
+					case CHAIN_OP_IN_BOUNDS_ACCESS_CHAIN:
+						specs["accesschain"]				= "OpInBoundsAccessChain %_ptr_buffer_float %dataInput %int_0 %i0 %i1 %i2 %i3\n";
+						specs["inputdecoration"]			= "BufferBlock";
+						specs["inputstorageclass"]			= "Uniform";
+						break;
+					default:
+						DE_ASSERT(chainOpIdx == CHAIN_OP_PTR_ACCESS_CHAIN);
+						specs["accesschain"]				= "OpPtrAccessChain %_ptr_buffer_float %dataInput %uint_1 %int_0 %i0 %i1 %i2 %i3\n";
+						specs["inputdecoration"]			= "Block";
+						specs["inputstorageclass"]			= "StorageBuffer";
+						fragments["capability"]				+= "OpCapability VariablePointersStorageBuffer";
+						fragments["extension"]				= "OpExtension \"SPV_KHR_variable_pointers\"\nOpExtension \"SPV_KHR_storage_buffer_storage_class\"";
+						extensions.push_back				("VK_KHR_variable_pointers");
+						vulkanFeatures.extVariablePointers	= EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER;
+						element = 1;
+						break;
+				};
+
+				outputData.reserve(numItems);
+				for (deUint32 numIdx = 0; numIdx < numItems; ++numIdx)
+				{
+					// Determine the selected output float for the selected indices.
+					const UVec4 vec = indexSelectorData[numIdx];
+					outputData.push_back(inputData[element * sizeof(InputData) / 4 + vec.x() * (32 * 4 * 4) + vec.y() * 4 * 4 + vec.z() * 4 + vec.w()]);
+				}
+
+				resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(outputData))));
+
+				fragments["pre_main"]	= preMain.specialize(specs);
+				fragments["decoration"]	= decoration.specialize(specs);
+				fragments["testfun"]	= testFun.specialize(specs);
+
+				createTestsForAllStages(
+						testName.c_str(), defaultColors, defaultColors, fragments, noSpecConstants,
+						noPushConstants, resources, noInterfaces, extensions, features, vulkanFeatures, group);
+			}
+		}
+	}
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createIndexingComputeGroup (tcu::TestContext& testCtx)
+{
+	de::MovePtr<tcu::TestCaseGroup> group		(new tcu::TestCaseGroup(testCtx, "indexing", "Compute tests for data indexing."));
+	addComputeIndexingTests(group.get());
+
+	return group.release();
+}
+
+tcu::TestCaseGroup* createIndexingGraphicsGroup (tcu::TestContext& testCtx)
+{
+	de::MovePtr<tcu::TestCaseGroup> group		(new tcu::TestCaseGroup(testCtx, "indexing", "Graphics tests for data indexing."));
+	addGraphicsIndexingTests(group.get());
+
+	return group.release();
+}
+
+} // SpirVAssembly
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmIndexingTests.hpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmIndexingTests.hpp
new file mode 100644
index 0000000..57bb3c8
--- /dev/null
+++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmIndexingTests.hpp
@@ -0,0 +1,40 @@
+#ifndef _VKTSPVASMINDEXINGTESTS_HPP
+#define _VKTSPVASMINDEXINGTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 Google Inc.
+ *
+ * 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 implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief SPIR-V Assembly Tests for indexing with different bit sizes.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+tcu::TestCaseGroup*	createIndexingComputeGroup	(tcu::TestContext& testCtx);
+tcu::TestCaseGroup*	createIndexingGraphicsGroup	(tcu::TestContext& testCtx);
+
+} // SpirVAssembly
+} // vkt
+
+#endif // _VKTSPVASMINDEXINGTESTS_HPP
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp
index eb32c24..b7b3f77 100644
--- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp
+++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp
@@ -52,6 +52,8 @@
 
 #include "vktSpvAsm16bitStorageTests.hpp"
 #include "vktSpvAsmUboMatrixPaddingTests.hpp"
+#include "vktSpvAsmConditionalBranchTests.hpp"
+#include "vktSpvAsmIndexingTests.hpp"
 #include "vktSpvAsmComputeShaderCase.hpp"
 #include "vktSpvAsmComputeShaderTestUtil.hpp"
 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
@@ -7842,6 +7844,8 @@
 
 	computeTests->addChild(create16BitStorageComputeGroup(testCtx));
 	computeTests->addChild(createUboMatrixPaddingComputeGroup(testCtx));
+	computeTests->addChild(createConditionalBranchComputeGroup(testCtx));
+	computeTests->addChild(createIndexingComputeGroup(testCtx));
 	computeTests->addChild(createVariablePointersComputeGroup(testCtx));
 	graphicsTests->addChild(createOpNopTests(testCtx));
 	graphicsTests->addChild(createOpSourceTests(testCtx));
@@ -7878,6 +7882,8 @@
 
 	graphicsTests->addChild(create16BitStorageGraphicsGroup(testCtx));
 	graphicsTests->addChild(createUboMatrixPaddingGraphicsGroup(testCtx));
+	graphicsTests->addChild(createConditionalBranchGraphicsGroup(testCtx));
+	graphicsTests->addChild(createIndexingGraphicsGroup(testCtx));
 	graphicsTests->addChild(createVariablePointersGraphicsGroup(testCtx));
 
 	instructionTests->addChild(computeTests.release());
diff --git a/external/vulkancts/mustpass/1.0.3/vk-default.txt b/external/vulkancts/mustpass/1.0.3/vk-default.txt
index 5ee3b59..edc6656 100644
--- a/external/vulkancts/mustpass/1.0.3/vk-default.txt
+++ b/external/vulkancts/mustpass/1.0.3/vk-default.txt
@@ -162683,6 +162683,26 @@
 dEQP-VK.spirv_assembly.instruction.compute.16bit_storage.push_constant_16_to_32.vector_sint
 dEQP-VK.spirv_assembly.instruction.compute.16bit_storage.push_constant_16_to_32.vector_uint
 dEQP-VK.spirv_assembly.instruction.compute.ubo_padding.mat2x2
+dEQP-VK.spirv_assembly.instruction.compute.conditional_branch.same_labels_true
+dEQP-VK.spirv_assembly.instruction.compute.conditional_branch.same_labels_false
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opaccesschain_u16
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opaccesschain_s16
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opaccesschain_u32
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opaccesschain_s32
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opaccesschain_u64
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opaccesschain_s64
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opinboundsaccesschain_u16
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opinboundsaccesschain_s16
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opinboundsaccesschain_u32
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opinboundsaccesschain_s32
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opinboundsaccesschain_u64
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opinboundsaccesschain_s64
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opptraccesschain_u16
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opptraccesschain_s16
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opptraccesschain_u32
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opptraccesschain_s32
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opptraccesschain_u64
+dEQP-VK.spirv_assembly.instruction.compute.indexing.opptraccesschain_s64
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opselect_single_buffer
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opfunctioncall_single_buffer
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opphi_single_buffer
@@ -164705,6 +164725,106 @@
 dEQP-VK.spirv_assembly.instruction.graphics.ubo_padding.mat2x2_tesse
 dEQP-VK.spirv_assembly.instruction.graphics.ubo_padding.mat2x2_geom
 dEQP-VK.spirv_assembly.instruction.graphics.ubo_padding.mat2x2_frag
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_true_vert
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_true_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_true_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_true_geom
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_true_frag
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_false_vert
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_false_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_false_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_false_geom
+dEQP-VK.spirv_assembly.instruction.graphics.conditional_branch.same_labels_false_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u16_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u16_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u16_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u16_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u16_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s16_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s16_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s16_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s16_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s16_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u32_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u32_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u32_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u32_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u32_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s32_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s32_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s32_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s32_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s32_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u64_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u64_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u64_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u64_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_u64_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s64_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s64_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s64_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s64_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opaccesschain_s64_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u16_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u16_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u16_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u16_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u16_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s16_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s16_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s16_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s16_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s16_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u32_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u32_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u32_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u32_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u32_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s32_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s32_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s32_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s32_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s32_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u64_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u64_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u64_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u64_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_u64_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s64_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s64_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s64_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s64_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opinboundsaccesschain_s64_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u16_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u16_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u16_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u16_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u16_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s16_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s16_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s16_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s16_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s16_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u32_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u32_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u32_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u32_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u32_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s32_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s32_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s32_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s32_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s32_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u64_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u64_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u64_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u64_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_u64_frag
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s64_vert
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s64_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s64_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s64_geom
+dEQP-VK.spirv_assembly.instruction.graphics.indexing.opptraccesschain_s64_frag
 dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_vert
 dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_tessc
 dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_tesse
diff --git a/framework/delibs/cmake/Defs.cmake b/framework/delibs/cmake/Defs.cmake
index d40bd73..e65015b 100644
--- a/framework/delibs/cmake/Defs.cmake
+++ b/framework/delibs/cmake/Defs.cmake
@@ -68,21 +68,19 @@
 DE_MAKE_ENV_BOOL("DE_OS" "IOS")
 
 # Prevent mixed compile with GCC and Clang
-if (NOT ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU") EQUAL ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU"))
+if (NOT (CMAKE_C_COMPILER_ID MATCHES "GNU") EQUAL (CMAKE_CXX_COMPILER_ID MATCHES "GNU"))
 	message(FATAL_ERROR "CMake C and CXX compilers do not match. Both or neither must be GNU.")
-elseif (NOT ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang") EQUAL ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
+elseif (NOT (CMAKE_C_COMPILER_ID MATCHES "Clang") EQUAL (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
 	message(FATAL_ERROR "CMake C and CXX compilers do not match. Both or neither must be Clang.")
 endif ()
 
 # Compiler detection
 if (NOT DEFINED DE_COMPILER)
-	# \note " x" postfix is to work around bug in CMake that causes
-	#       "MSVC" to translate to something completely different
-	if (("${CMAKE_C_COMPILER_ID} x" MATCHES "MSVC") OR MSVC)
+	if ((CMAKE_C_COMPILER_ID MATCHES "MSVC") OR MSVC)
 		set(DE_COMPILER "DE_COMPILER_MSC")
-	elseif ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU")
+	elseif (CMAKE_C_COMPILER_ID MATCHES "GNU")
 		set(DE_COMPILER "DE_COMPILER_GCC")
-	elseif ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")
+	elseif (CMAKE_C_COMPILER_ID MATCHES "Clang")
 		set(DE_COMPILER "DE_COMPILER_CLANG")
 
 	# Guess based on OS
diff --git a/framework/referencerenderer/rrRenderer.cpp b/framework/referencerenderer/rrRenderer.cpp
index 5dd13be..c46227b 100644
--- a/framework/referencerenderer/rrRenderer.cpp
+++ b/framework/referencerenderer/rrRenderer.cpp
@@ -1509,7 +1509,7 @@
 bool isValidCommand (const DrawCommand& command, int numInstances)
 {
 	// numInstances should be valid
-	if (numInstances < 1)
+	if (numInstances < 0)
 		return false;
 
 	// Shaders should have the same varyings