RESTRICT AUTOMERGE: Backport tests for VK_KHR_draw_indirect_count
authorOstrowski, Igor <igor.ostrowski@intel.com>
Fri, 9 Feb 2018 10:56:15 +0000 (11:56 +0100)
committerChris Forbes <chrisforbes@google.com>
Fri, 10 Aug 2018 16:54:48 +0000 (09:54 -0700)
This change add new tests for VK_KHR_draw_indirect_count
extension, and adds the extension to the whitelist.

New Tests:
dEQP-VK.draw.indirect_draw.*.indirect_draw_count.*
dEQP-VK.draw.indirect_draw.*.indirect_draw_first_instance.*
dEQP-VK.draw.indirect_draw.*.indirect_draw_count_first_instance.*
dEQP-VK.draw.indirect_draw.*.indirect_draw_count_instanced.*

Note: for Android CTS backport, adjusted excluded test list to not impact
previously-passing implementations that don't care about this extension.

Affected tests:
dEQP-VK.api.info.device.extensions

Components: Vulkan, Framework
VK-GL-CTS issue: 1004
Bug: b/111786155

Change-Id: I3d53806eb1a45293a77b940d9c2fa540a6d83d50
(cherry picked from Khronos commit 7b47cd53c6656b866e7c3a3c0a590da85f3b2de1)

14 files changed:
android/cts/master/src/vk-excluded-tests.txt
android/cts/master/vk-master.txt
external/vulkancts/data/vulkan/draw/VertexFetchInstanceIndex.vert [new file with mode: 0644]
external/vulkancts/framework/vulkan/vkConcreteDeviceInterface.inl
external/vulkancts/framework/vulkan/vkDeviceDriverImpl.inl
external/vulkancts/framework/vulkan/vkDeviceFunctionPointers.inl
external/vulkancts/framework/vulkan/vkFunctionPointerTypes.inl
external/vulkancts/framework/vulkan/vkInitDeviceFunctionPointers.inl
external/vulkancts/framework/vulkan/vkNullDriverImpl.inl
external/vulkancts/framework/vulkan/vkVirtualDeviceInterface.inl
external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
external/vulkancts/modules/vulkan/draw/vktDrawIndirectTest.cpp
external/vulkancts/mustpass/1.0.2/vk-default.txt
external/vulkancts/scripts/src/vulkan.h.in

index fee498d..557c114 100644 (file)
@@ -349,3 +349,9 @@ dEQP-VK.wsi.android.shared_presentable_image.scale_down.*
 
 # Issue: b/67022169
 dEQP-VK.wsi.android.incremental_present.scale_down.*
+
+# Issue: b/111786155 Backport of tests for KHR_draw_indirect_count, but change
+# includes some unrelated test refactoring. Exclude the tests that would affect
+# previously-passing implementations.
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_first_instance.*
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_first_instance.*
index ebe1dee..09578f4 100644 (file)
@@ -171608,16 +171608,32 @@ dEQP-VK.draw.indexed_draw.draw_instanced_indexed_triangle_list
 dEQP-VK.draw.indexed_draw.draw_instanced_indexed_triangle_strip
 dEQP-VK.draw.indirect_draw.sequential.indirect_draw.triangle_list
 dEQP-VK.draw.indirect_draw.sequential.indirect_draw.triangle_strip
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count.triangle_list
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count.triangle_strip
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count_first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count_first_instance.triangle_strip
 dEQP-VK.draw.indirect_draw.sequential.indirect_draw_instanced.no_first_instance.triangle_list
 dEQP-VK.draw.indirect_draw.sequential.indirect_draw_instanced.no_first_instance.triangle_strip
 dEQP-VK.draw.indirect_draw.sequential.indirect_draw_instanced.first_instance.triangle_list
 dEQP-VK.draw.indirect_draw.sequential.indirect_draw_instanced.first_instance.triangle_strip
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count_instanced.no_first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count_instanced.no_first_instance.triangle_strip
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count_instanced.first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count_instanced.first_instance.triangle_strip
 dEQP-VK.draw.indirect_draw.indexed.indirect_draw.triangle_list
 dEQP-VK.draw.indirect_draw.indexed.indirect_draw.triangle_strip
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count.triangle_list
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count.triangle_strip
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count_first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count_first_instance.triangle_strip
 dEQP-VK.draw.indirect_draw.indexed.indirect_draw_instanced.no_first_instance.triangle_list
 dEQP-VK.draw.indirect_draw.indexed.indirect_draw_instanced.no_first_instance.triangle_strip
 dEQP-VK.draw.indirect_draw.indexed.indirect_draw_instanced.first_instance.triangle_list
 dEQP-VK.draw.indirect_draw.indexed.indirect_draw_instanced.first_instance.triangle_strip
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count_instanced.no_first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count_instanced.no_first_instance.triangle_strip
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count_instanced.first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count_instanced.first_instance.triangle_strip
 dEQP-VK.draw.basic_draw.draw.point_list.1
 dEQP-VK.draw.basic_draw.draw.point_list.3
 dEQP-VK.draw.basic_draw.draw.point_list.17
diff --git a/external/vulkancts/data/vulkan/draw/VertexFetchInstanceIndex.vert b/external/vulkancts/data/vulkan/draw/VertexFetchInstanceIndex.vert
new file mode 100644 (file)
index 0000000..3ed625a
--- /dev/null
@@ -0,0 +1,19 @@
+#version 430
+
+layout(location = 0) in vec4 in_position;
+layout(location = 1) in vec4 in_color;
+layout(location = 2) in int in_refInstanceIndex;
+
+layout(location = 0) out vec4 out_color;
+
+out gl_PerVertex {
+    vec4 gl_Position;
+};
+
+void main() {
+       gl_Position = in_position;
+       if (gl_InstanceIndex == in_refInstanceIndex)
+               out_color = in_color;
+       else
+               out_color = vec4(1.0, 0.0, 0.0, 1.0);
+}
\ No newline at end of file
index 14221d5..3727f5a 100644 (file)
@@ -134,6 +134,8 @@ virtual void                destroyDescriptorUpdateTemplateKHR              (VkDevice device, VkDescriptor
 virtual void           updateDescriptorSetWithTemplateKHR              (VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, const void* pData) const;
 virtual void           cmdPushDescriptorSetWithTemplateKHR             (VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, VkPipelineLayout layout, deUint32 set, const void* pData) const;
 virtual VkResult       getSwapchainStatusKHR                                   (VkDevice device, VkSwapchainKHR swapchain) const;
+virtual void           cmdDrawIndirectCountKHR                                 (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, deUint32 maxDrawCount, deUint32 stride) const;
+virtual void           cmdDrawIndexedIndirectCountKHR                  (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, deUint32 maxDrawCount, deUint32 stride) const;
 virtual VkResult       importFenceWin32HandleKHR                               (VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo) const;
 virtual VkResult       getFenceWin32HandleKHR                                  (VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, pt::Win32Handle* pHandle) const;
 virtual VkResult       importFenceFdKHR                                                (VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo) const;
index 5d62b30..c82e0c2 100644 (file)
@@ -667,6 +667,16 @@ VkResult DeviceDriver::getSwapchainStatusKHR (VkDevice device, VkSwapchainKHR sw
        return m_vk.getSwapchainStatusKHR(device, swapchain);
 }
 
+void DeviceDriver::cmdDrawIndirectCountKHR (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, deUint32 maxDrawCount, deUint32 stride) const
+{
+       m_vk.cmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
+}
+
+void DeviceDriver::cmdDrawIndexedIndirectCountKHR (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, deUint32 maxDrawCount, deUint32 stride) const
+{
+       m_vk.cmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
+}
+
 VkResult DeviceDriver::importFenceWin32HandleKHR (VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo) const
 {
        return m_vk.importFenceWin32HandleKHR(device, pImportFenceWin32HandleInfo);
index e376610..13c4970 100644 (file)
@@ -134,6 +134,8 @@ DestroyDescriptorUpdateTemplateKHRFunc              destroyDescriptorUpdateTemplateKHR;
 UpdateDescriptorSetWithTemplateKHRFunc         updateDescriptorSetWithTemplateKHR;
 CmdPushDescriptorSetWithTemplateKHRFunc                cmdPushDescriptorSetWithTemplateKHR;
 GetSwapchainStatusKHRFunc                                      getSwapchainStatusKHR;
+CmdDrawIndirectCountKHRFunc                                    cmdDrawIndirectCountKHR;
+CmdDrawIndexedIndirectCountKHRFunc                     cmdDrawIndexedIndirectCountKHR;
 ImportFenceWin32HandleKHRFunc                          importFenceWin32HandleKHR;
 GetFenceWin32HandleKHRFunc                                     getFenceWin32HandleKHR;
 ImportFenceFdKHRFunc                                           importFenceFdKHR;
index f187b2c..21f6247 100644 (file)
@@ -181,6 +181,8 @@ typedef VKAPI_ATTR void                                     (VKAPI_CALL* DestroyDescriptorUpdateTemplateKHRFunc)
 typedef VKAPI_ATTR void                                        (VKAPI_CALL* UpdateDescriptorSetWithTemplateKHRFunc)                            (VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, const void* pData);
 typedef VKAPI_ATTR void                                        (VKAPI_CALL* CmdPushDescriptorSetWithTemplateKHRFunc)                           (VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, VkPipelineLayout layout, deUint32 set, const void* pData);
 typedef VKAPI_ATTR VkResult                            (VKAPI_CALL* GetSwapchainStatusKHRFunc)                                                         (VkDevice device, VkSwapchainKHR swapchain);
+typedef VKAPI_ATTR void                                        (VKAPI_CALL* CmdDrawIndirectCountKHRFunc)                                                       (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, deUint32 maxDrawCount, deUint32 stride);
+typedef VKAPI_ATTR void                                        (VKAPI_CALL* CmdDrawIndexedIndirectCountKHRFunc)                                        (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, deUint32 maxDrawCount, deUint32 stride);
 typedef VKAPI_ATTR VkResult                            (VKAPI_CALL* GetPhysicalDeviceSurfaceCapabilities2KHRFunc)                      (VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities);
 typedef VKAPI_ATTR VkResult                            (VKAPI_CALL* GetPhysicalDeviceSurfaceFormats2KHRFunc)                           (VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, deUint32* pSurfaceFormatCount, VkSurfaceFormat2KHR* pSurfaceFormats);
 typedef VKAPI_ATTR void                                        (VKAPI_CALL* GetPhysicalDeviceExternalFencePropertiesKHRFunc)           (VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo, VkExternalFencePropertiesKHR* pExternalFenceProperties);
index 6c943c9..c726440 100644 (file)
@@ -134,6 +134,8 @@ m_vk.destroyDescriptorUpdateTemplateKHR             = (DestroyDescriptorUpdateTemplateKHRFu
 m_vk.updateDescriptorSetWithTemplateKHR                = (UpdateDescriptorSetWithTemplateKHRFunc)              GET_PROC_ADDR("vkUpdateDescriptorSetWithTemplateKHR");
 m_vk.cmdPushDescriptorSetWithTemplateKHR       = (CmdPushDescriptorSetWithTemplateKHRFunc)             GET_PROC_ADDR("vkCmdPushDescriptorSetWithTemplateKHR");
 m_vk.getSwapchainStatusKHR                                     = (GetSwapchainStatusKHRFunc)                                   GET_PROC_ADDR("vkGetSwapchainStatusKHR");
+m_vk.cmdDrawIndirectCountKHR                           = (CmdDrawIndirectCountKHRFunc)                                 GET_PROC_ADDR("vkCmdDrawIndirectCountKHR");
+m_vk.cmdDrawIndexedIndirectCountKHR                    = (CmdDrawIndexedIndirectCountKHRFunc)                  GET_PROC_ADDR("vkCmdDrawIndexedIndirectCountKHR");
 m_vk.importFenceWin32HandleKHR                         = (ImportFenceWin32HandleKHRFunc)                               GET_PROC_ADDR("vkImportFenceWin32HandleKHR");
 m_vk.getFenceWin32HandleKHR                                    = (GetFenceWin32HandleKHRFunc)                                  GET_PROC_ADDR("vkGetFenceWin32HandleKHR");
 m_vk.importFenceFdKHR                                          = (ImportFenceFdKHRFunc)                                                GET_PROC_ADDR("vkImportFenceFdKHR");
index 6f068ee..10ca721 100644 (file)
@@ -1188,6 +1188,28 @@ VKAPI_ATTR VkResult VKAPI_CALL getSwapchainStatusKHR (VkDevice device, VkSwapcha
        return VK_SUCCESS;
 }
 
+VKAPI_ATTR void VKAPI_CALL cmdDrawIndirectCountKHR (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, deUint32 maxDrawCount, deUint32 stride)
+{
+       DE_UNREF(commandBuffer);
+       DE_UNREF(buffer);
+       DE_UNREF(offset);
+       DE_UNREF(countBuffer);
+       DE_UNREF(countBufferOffset);
+       DE_UNREF(maxDrawCount);
+       DE_UNREF(stride);
+}
+
+VKAPI_ATTR void VKAPI_CALL cmdDrawIndexedIndirectCountKHR (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, deUint32 maxDrawCount, deUint32 stride)
+{
+       DE_UNREF(commandBuffer);
+       DE_UNREF(buffer);
+       DE_UNREF(offset);
+       DE_UNREF(countBuffer);
+       DE_UNREF(countBufferOffset);
+       DE_UNREF(maxDrawCount);
+       DE_UNREF(stride);
+}
+
 VKAPI_ATTR VkResult VKAPI_CALL getPhysicalDeviceSurfaceCapabilities2KHR (VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkSurfaceCapabilities2KHR* pSurfaceCapabilities)
 {
        DE_UNREF(physicalDevice);
@@ -1571,6 +1593,8 @@ static const tcu::StaticFunctionLibrary::Entry s_deviceFunctions[] =
        VK_NULL_FUNC_ENTRY(vkUpdateDescriptorSetWithTemplateKHR,        updateDescriptorSetWithTemplateKHR),
        VK_NULL_FUNC_ENTRY(vkCmdPushDescriptorSetWithTemplateKHR,       cmdPushDescriptorSetWithTemplateKHR),
        VK_NULL_FUNC_ENTRY(vkGetSwapchainStatusKHR,                                     getSwapchainStatusKHR),
+       VK_NULL_FUNC_ENTRY(vkCmdDrawIndirectCountKHR,                           cmdDrawIndirectCountKHR),
+       VK_NULL_FUNC_ENTRY(vkCmdDrawIndexedIndirectCountKHR,            cmdDrawIndexedIndirectCountKHR),
        VK_NULL_FUNC_ENTRY(vkImportFenceWin32HandleKHR,                         importFenceWin32HandleKHR),
        VK_NULL_FUNC_ENTRY(vkGetFenceWin32HandleKHR,                            getFenceWin32HandleKHR),
        VK_NULL_FUNC_ENTRY(vkImportFenceFdKHR,                                          importFenceFdKHR),
index 3f6246d..500f189 100644 (file)
@@ -134,6 +134,8 @@ virtual void                destroyDescriptorUpdateTemplateKHR              (VkDevice device, VkDescriptor
 virtual void           updateDescriptorSetWithTemplateKHR              (VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, const void* pData) const = 0;
 virtual void           cmdPushDescriptorSetWithTemplateKHR             (VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, VkPipelineLayout layout, deUint32 set, const void* pData) const = 0;
 virtual VkResult       getSwapchainStatusKHR                                   (VkDevice device, VkSwapchainKHR swapchain) const = 0;
+virtual void           cmdDrawIndirectCountKHR                                 (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, deUint32 maxDrawCount, deUint32 stride) const = 0;
+virtual void           cmdDrawIndexedIndirectCountKHR                  (VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, deUint32 maxDrawCount, deUint32 stride) const = 0;
 virtual VkResult       importFenceWin32HandleKHR                               (VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo) const = 0;
 virtual VkResult       getFenceWin32HandleKHR                                  (VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, pt::Win32Handle* pHandle) const = 0;
 virtual VkResult       importFenceFdKHR                                                (VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo) const = 0;
index f70b924..04e49bd 100644 (file)
@@ -711,6 +711,7 @@ void checkDeviceExtensions (tcu::ResultCollector& results, const vector<string>&
                "VK_KHR_maintenance2",
                "VK_KHR_image_format_list",
                "VK_KHR_sampler_ycbcr_conversion",
+               "VK_KHR_draw_indirect_count"
        };
 
        checkKhrExtensions(results, extensions, DE_LENGTH_OF_ARRAY(s_allowedDeviceKhrExtensions), s_allowedDeviceKhrExtensions);
index cb89897..0c72ccf 100644 (file)
@@ -34,6 +34,7 @@
 #include "tcuImageCompare.hpp"
 #include "tcuTextureUtil.hpp"
 #include "tcuRGBA.hpp"
+#include "vkQueryUtil.hpp"
 
 #include "vkDefs.hpp"
 
@@ -70,7 +71,14 @@ enum DrawType
 
 struct DrawTypedTestSpec : public TestSpecBase
 {
-       DrawType drawType;
+       DrawTypedTestSpec()
+               : testFirstInstanceNdx(false)
+               , testIndirectCountExt(false)
+       {};
+
+       DrawType        drawType;
+       bool            testFirstInstanceNdx;
+       bool            testIndirectCountExt;
 };
 
 class IndirectDraw : public DrawTestsBaseClass
@@ -84,28 +92,37 @@ public:
        template<typename T> void       addCommand              (const T&);
 
 protected:
-       std::vector<char>               m_indirectBufferContents;
+       void                                            setVertexBuffer                                         (void);
+       void                                            setFirstInstanceVertexBuffer            (void);
+
+       std::vector<char>                       m_indirectBufferContents;
        de::SharedPtr<Buffer>           m_indirectBuffer;
-       vk::VkDeviceSize                m_offsetInBuffer;
-       deUint32                        m_strideInBuffer;
+       vk::VkDeviceSize                        m_offsetInBuffer;
+       deUint32                                        m_strideInBuffer;
+
+       const bool                                      m_testIndirectCountExt;
+       de::SharedPtr<Buffer>           m_indirectCountBuffer;
+       vk::VkDeviceSize                        m_offsetInCountBuffer;
+       const deUint32                          m_indirectCountExtDrawPadding;
 
-       deUint32                        m_drawCount;
-       JunkData                        m_junkData;
+       deUint32                                        m_drawCount;
+       JunkData                                        m_junkData;
 
-       const DrawType                  m_drawType;
-       deBool                          m_isMultiDrawEnabled;
-       deUint32                        m_drawIndirectMaxCount;
+       const DrawType                          m_drawType;
+       const bool                                      m_testFirstInstanceNdx;
+       deBool                                          m_isMultiDrawEnabled;
+       deUint32                                        m_drawIndirectMaxCount;
 
        de::SharedPtr<Buffer>           m_indexBuffer;
 };
 
-struct FirtsInstanceSupported
+struct FirstInstanceSupported
 {
        static deUint32 getFirstInstance        (void)                                                                                  { return 2; }
        static bool             isTestSupported         (const vk::VkPhysicalDeviceFeatures& features)  { return features.drawIndirectFirstInstance == VK_TRUE; }
 };
 
-struct FirtsInstanceNotSupported
+struct FirstInstanceNotSupported
 {
        static deUint32 getFirstInstance        (void)                                                                                  { return 0; }
        static bool             isTestSupported         (const vk::VkPhysicalDeviceFeatures&)                   { return true; }
@@ -119,14 +136,11 @@ public:
        virtual tcu::TestStatus         iterate                                 (void);
 };
 
-IndirectDraw::IndirectDraw (Context &context, TestSpec testSpec)
-       : DrawTestsBaseClass    (context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], testSpec.topology)
-       , m_drawType                    (testSpec.drawType)
+void IndirectDraw::setVertexBuffer (void)
 {
-
        int refVertexIndex = 2;
 
-       if (testSpec.drawType == DRAW_TYPE_INDEXED)
+       if (m_drawType == DRAW_TYPE_INDEXED)
        {
                for (int unusedIdx = 0; unusedIdx < VERTEX_OFFSET; unusedIdx++)
                {
@@ -136,7 +150,7 @@ IndirectDraw::IndirectDraw (Context &context, TestSpec testSpec)
        }
 
        m_data.push_back(VertexElementData(tcu::Vec4( 1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
-       m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
+       m_data.push_back(VertexElementData(tcu::Vec4(-1.0f,  1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
 
        switch (m_topology)
        {
@@ -164,6 +178,78 @@ IndirectDraw::IndirectDraw (Context &context, TestSpec testSpec)
        }
 
        m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
+}
+
+void IndirectDraw::setFirstInstanceVertexBuffer (void)
+{
+       if (m_context.getDeviceFeatures().drawIndirectFirstInstance != VK_TRUE)
+       {
+               TCU_THROW(NotSupportedError, "Required 'drawIndirectFirstInstance' feature is not supported");
+       }
+
+       if (m_drawType == DRAW_TYPE_INDEXED)
+       {
+               for (int unusedIdx = 0; unusedIdx < VERTEX_OFFSET; unusedIdx++)
+               {
+                       m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
+               }
+       }
+
+       m_data.push_back(VertexElementData(tcu::Vec4( 1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
+       m_data.push_back(VertexElementData(tcu::Vec4(-1.0f,  1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
+
+       switch (m_topology)
+       {
+               case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
+               {
+                       int refInstanceIndex = 1;
+                       m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,     -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
+                       m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
+                       m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,     -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
+
+                       refInstanceIndex = 0;
+                       m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,     -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
+                       m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,      0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
+                       m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refInstanceIndex));
+                       break;
+               }
+               case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
+               {
+                       int refInstanceIndex = 1;
+                       m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.0f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
+                       m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,      0.0f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
+                       m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,     -0.3f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
+                       m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,     -0.3f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
+
+                       refInstanceIndex = 0;
+                       m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.3f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
+                       m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,      0.3f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
+                       m_data.push_back(VertexElementData(tcu::Vec4(-0.3f,      0.0f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
+                       m_data.push_back(VertexElementData(tcu::Vec4( 0.3f,      0.0f, 1.0f, 1.0f),      tcu::RGBA::blue().toVec(), refInstanceIndex));
+                       break;
+               }
+               default:
+                       DE_FATAL("Unknown topology");
+                       break;
+       }
+
+       m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
+}
+
+IndirectDraw::IndirectDraw (Context &context, TestSpec testSpec)
+       : DrawTestsBaseClass                            (context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], testSpec.topology)
+       , m_testIndirectCountExt                        (testSpec.testIndirectCountExt)
+       , m_indirectCountExtDrawPadding         (1u)
+       , m_drawType                                            (testSpec.drawType)
+       , m_testFirstInstanceNdx                        (testSpec.testFirstInstanceNdx)
+{
+       if (m_testIndirectCountExt && !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_draw_indirect_count"))
+               TCU_THROW(NotSupportedError, "Missing extension: VK_KHR_draw_indirect_count");
+
+       if (m_testFirstInstanceNdx)
+               setFirstInstanceVertexBuffer();
+       else
+               setVertexBuffer();
 
        initialize();
 
@@ -181,13 +267,12 @@ IndirectDraw::IndirectDraw (Context &context, TestSpec testSpec)
        }
 
        // Check device for multidraw support:
-       if (m_context.getDeviceFeatures().multiDrawIndirect)
-               m_isMultiDrawEnabled = true;
-       else
+       if (!m_context.getDeviceFeatures().multiDrawIndirect || m_testFirstInstanceNdx)
                m_isMultiDrawEnabled = false;
+       else
+               m_isMultiDrawEnabled = true;
 
        m_drawIndirectMaxCount = m_context.getDeviceProperties().limits.maxDrawIndirectCount;
-
 }
 
 template<>
@@ -203,7 +288,7 @@ void IndirectDraw::addCommand<vk::VkDrawIndirectCommand> (const vk::VkDrawIndire
 }
 
 template<>
-void IndirectDraw::addCommand<vk::VkDrawIndexedIndirectCommand>(const vk::VkDrawIndexedIndirectCommand& command)
+void IndirectDraw::addCommand<vk::VkDrawIndexedIndirectCommand> (const vk::VkDrawIndexedIndirectCommand& command)
 {
        DE_ASSERT(m_drawType == DRAW_TYPE_INDEXED);
 
@@ -228,22 +313,27 @@ tcu::TestStatus IndirectDraw::iterate (void)
                        vk::VkDrawIndirectCommand drawCommands[] =
                        {
                                {
-                                       3,              //vertexCount
-                                       1,              //instanceCount
-                                       2,              //firstVertex
-                                       0               //firstInstance
+                                       3u,                                                                     //vertexCount
+                                       1u,                                                                     //instanceCount
+                                       2u,                                                                     //firstVertex
+                                       (m_testFirstInstanceNdx ? 1u : 0u)      //firstInstance
                                },
                                { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
                                {
-                                       3,              //vertexCount
-                                       1,              //instanceCount
-                                       5,              //firstVertex
-                                       0               //firstInstance
+                                       3u,                                                                     //vertexCount
+                                       1u,                                                                     //instanceCount
+                                       5u,                                                                     //firstVertex
+                                       0u                                                                      //firstInstance
                                }
                        };
                        addCommand(drawCommands[0]);
                        addCommand(drawCommands[1]);
                        addCommand(drawCommands[2]);
+                       if (m_testIndirectCountExt)
+                       {
+                               addCommand(drawCommands[1]);
+                               addCommand(drawCommands[1]);
+                       }
                        break;
                }
                case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
@@ -251,22 +341,27 @@ tcu::TestStatus IndirectDraw::iterate (void)
                        vk::VkDrawIndirectCommand drawCommands[] =
                        {
                                {
-                                       4,              //vertexCount
-                                       1,              //instanceCount
-                                       2,              //firstVertex
-                                       0               //firstInstance
+                                       4u,                                                                     //vertexCount
+                                       1u,                                                                     //instanceCount
+                                       2u,                                                                     //firstVertex
+                                       (m_testFirstInstanceNdx ? 1u : 0u)      //firstInstance
                                },
                                { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deUint32)-9 }, // junk (stride)
                                {
-                                       4,              //vertexCount
-                                       1,              //instanceCount
-                                       6,              //firstVertex
-                                       0               //firstInstance
+                                       4u,                                                                     //vertexCount
+                                       1u,                                                                     //instanceCount
+                                       6u,                                                                     //firstVertex
+                                       0u                                                                      //firstInstance
                                }
                        };
                        addCommand(drawCommands[0]);
                        addCommand(drawCommands[1]);
                        addCommand(drawCommands[2]);
+                       if (m_testIndirectCountExt)
+                       {
+                               addCommand(drawCommands[1]);
+                               addCommand(drawCommands[1]);
+                       }
                        break;
                }
                default:
@@ -284,24 +379,29 @@ tcu::TestStatus IndirectDraw::iterate (void)
                        vk::VkDrawIndexedIndirectCommand drawCommands[] =
                        {
                                {
-                                       3,                                      // indexCount
-                                       1,                                      // instanceCount
-                                       2,                                      // firstIndex
-                                       VERTEX_OFFSET,          // vertexOffset
-                                       0,                                      // firstInstance
+                                       3u,                                                                     // indexCount
+                                       1u,                                                                     // instanceCount
+                                       2u,                                                                     // firstIndex
+                                       VERTEX_OFFSET,                                          // vertexOffset
+                                       (m_testFirstInstanceNdx ? 1u : 0u),     // firstInstance
                                },
                                { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
                                {
-                                       3,                                      // indexCount
-                                       1,                                      // instanceCount
-                                       5,                                      // firstIndex
-                                       VERTEX_OFFSET,          // vertexOffset
-                                       0,                                      // firstInstance
+                                       3u,                                                                     // indexCount
+                                       1u,                                                                     // instanceCount
+                                       5u,                                                                     // firstIndex
+                                       VERTEX_OFFSET,                                          // vertexOffset
+                                       0u                                                                      // firstInstance
                                }
                        };
                        addCommand(drawCommands[0]);
                        addCommand(drawCommands[1]);
                        addCommand(drawCommands[2]);
+                       if (m_testIndirectCountExt)
+                       {
+                               addCommand(drawCommands[1]);
+                               addCommand(drawCommands[1]);
+                       }
                        break;
                }
                case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
@@ -309,24 +409,29 @@ tcu::TestStatus IndirectDraw::iterate (void)
                        vk::VkDrawIndexedIndirectCommand drawCommands[] =
                        {
                                {
-                                       4,                              // indexCount
-                                       1,                              // instanceCount
-                                       2,                              // firstIndex
-                                       VERTEX_OFFSET,  // vertexOffset
-                                       0,                              // firstInstance
+                                       4u,                                                                     // indexCount
+                                       1u,                                                                     // instanceCount
+                                       2u,                                                                     // firstIndex
+                                       VERTEX_OFFSET,                                          // vertexOffset
+                                       (m_testFirstInstanceNdx ? 1u : 0u),     // firstInstance
                                },
                                { (deUint32)-4, (deUint32)-2, (deUint32)-11, (deInt32)9, (deUint32)-7 }, // junk (stride)
                                {
-                                       4,                              // indexCount
-                                       1,                              // instanceCount
-                                       6,                              // firstIndex
-                                       VERTEX_OFFSET,  // vertexOffset
-                                       0,                              // firstInstance
+                                       4u,                                                                     // indexCount
+                                       1u,                                                                     // instanceCount
+                                       6u,                                                                     // firstIndex
+                                       VERTEX_OFFSET,                                          // vertexOffset
+                                       0u                                                                      // firstInstance
                                }
                        };
                        addCommand(drawCommands[0]);
                        addCommand(drawCommands[1]);
                        addCommand(drawCommands[2]);
+                       if (m_testIndirectCountExt)
+                       {
+                               addCommand(drawCommands[1]);
+                               addCommand(drawCommands[1]);
+                       }
                        break;
                }
                default:
@@ -366,6 +471,30 @@ tcu::TestStatus IndirectDraw::iterate (void)
                                                           m_indirectBuffer->getBoundMemory().getOffset(),
                                                           dataSize + m_offsetInBuffer);
 
+       if (m_testIndirectCountExt)
+       {
+               m_offsetInCountBuffer = sizeof(tcu::Vec3);
+               m_indirectCountBuffer = Buffer::createAndAlloc(m_vk,
+                                                                                                          m_context.getDevice(),
+                                                                                                          BufferCreateInfo(m_offsetInCountBuffer + sizeof(m_drawCount),
+                                                                                                                                               vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
+                                                                                                          m_context.getDefaultAllocator(),
+                                                                                                          vk::MemoryRequirement::HostVisible);
+
+               deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
+
+               if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
+                       *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = m_drawCount;
+               else
+                       *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = 1u;
+
+               vk::flushMappedMemoryRange(m_vk,
+                                                                  m_context.getDevice(),
+                                                                  m_indirectCountBuffer->getBoundMemory().getMemory(),
+                                                                  m_indirectCountBuffer->getBoundMemory().getOffset(),
+                                                                  m_offsetInCountBuffer + sizeof(m_drawCount));
+       }
+
        m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
 
        if (m_drawType == DRAW_TYPE_INDEXED)
@@ -378,11 +507,25 @@ tcu::TestStatus IndirectDraw::iterate (void)
                switch (m_drawType)
                {
                        case DRAW_TYPE_SEQUENTIAL:
-                               m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
+                       {
+                               if (m_testIndirectCountExt)
+                                       m_vk.cmdDrawIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
+                                                                                                m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
+                                                                                                m_strideInBuffer);
+                               else
+                                       m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
                                break;
+                       }
                        case DRAW_TYPE_INDEXED:
-                               m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
+                       {
+                               if (m_testIndirectCountExt)
+                                       m_vk.cmdDrawIndexedIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
+                                                                                                               m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
+                                                                                                               m_strideInBuffer);
+                               else
+                                       m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
                                break;
+                       }
                        default:
                                TCU_FAIL("impossible");
                }
@@ -394,11 +537,25 @@ tcu::TestStatus IndirectDraw::iterate (void)
                        switch (m_drawType)
                        {
                                case DRAW_TYPE_SEQUENTIAL:
-                                       m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
+                               {
+                                       if (m_testIndirectCountExt)
+                                               m_vk.cmdDrawIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
+                                                                                                        m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
+                                                                                                        m_strideInBuffer);
+                                       else
+                                               m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
                                        break;
+                               }
                                case DRAW_TYPE_INDEXED:
-                                       m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
+                               {
+                                       if (m_testIndirectCountExt)
+                                               m_vk.cmdDrawIndexedIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
+                                                                                                                       m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
+                                                                                                                       m_strideInBuffer);
+                                       else
+                                               m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
                                        break;
+                               }
                                default:
                                        TCU_FAIL("impossible");
                        }
@@ -457,13 +614,12 @@ tcu::TestStatus IndirectDraw::iterate (void)
        qpTestResult res = QP_TEST_RESULT_PASS;
 
        if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
-               referenceFrame.getLevel(0), renderedFrame, 0.05f,
-               tcu::COMPARE_LOG_RESULT)) {
+               referenceFrame.getLevel(0), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
+       {
                res = QP_TEST_RESULT_FAIL;
        }
 
        return tcu::TestStatus(res, qpGetTestResultName(res));
-
 }
 
 template<class FirstInstanceSupport>
@@ -507,6 +663,11 @@ tcu::TestStatus IndirectDrawInstanced<FirstInstanceSupport>::iterate (void)
                                addCommand(drawCmd[0]);
                                addCommand(drawCmd[1]);
                                addCommand(drawCmd[2]);
+                               if (m_testIndirectCountExt)
+                               {
+                                       addCommand(drawCmd[1]);
+                                       addCommand(drawCmd[1]);
+                               }
                                break;
                        }
                        case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
@@ -530,6 +691,11 @@ tcu::TestStatus IndirectDrawInstanced<FirstInstanceSupport>::iterate (void)
                                addCommand(drawCmd[0]);
                                addCommand(drawCmd[1]);
                                addCommand(drawCmd[2]);
+                               if (m_testIndirectCountExt)
+                               {
+                                       addCommand(drawCmd[1]);
+                                       addCommand(drawCmd[1]);
+                               }
                                break;
                        }
                        default:
@@ -566,6 +732,11 @@ tcu::TestStatus IndirectDrawInstanced<FirstInstanceSupport>::iterate (void)
                                addCommand(drawCmd[0]);
                                addCommand(drawCmd[1]);
                                addCommand(drawCmd[2]);
+                               if (m_testIndirectCountExt)
+                               {
+                                       addCommand(drawCmd[1]);
+                                       addCommand(drawCmd[1]);
+                               }
                                break;
                        }
                        case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
@@ -591,6 +762,11 @@ tcu::TestStatus IndirectDrawInstanced<FirstInstanceSupport>::iterate (void)
                                addCommand(drawCmd[0]);
                                addCommand(drawCmd[1]);
                                addCommand(drawCmd[2]);
+                               if (m_testIndirectCountExt)
+                               {
+                                       addCommand(drawCmd[1]);
+                                       addCommand(drawCmd[1]);
+                               }
                                break;
                        }
                        default:
@@ -631,6 +807,30 @@ tcu::TestStatus IndirectDrawInstanced<FirstInstanceSupport>::iterate (void)
                                                           m_indirectBuffer->getBoundMemory().getOffset(),
                                                           dataSize + m_offsetInBuffer);
 
+       if (m_testIndirectCountExt)
+       {
+               m_offsetInCountBuffer = sizeof(tcu::Vec3);
+               m_indirectCountBuffer = Buffer::createAndAlloc(m_vk,
+                                                                                                          m_context.getDevice(),
+                                                                                                          BufferCreateInfo(m_offsetInCountBuffer + sizeof(m_drawCount),
+                                                                                                                                               vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
+                                                                                                          m_context.getDefaultAllocator(),
+                                                                                                          vk::MemoryRequirement::HostVisible);
+
+               deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
+
+               if (m_isMultiDrawEnabled && m_drawCount <= m_drawIndirectMaxCount)
+                       *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = m_drawCount;
+               else
+                       *(deUint32*)(countBufferPtr + m_offsetInCountBuffer) = 1u;
+
+               vk::flushMappedMemoryRange(m_vk,
+                                                                  m_context.getDevice(),
+                                                                  m_indirectCountBuffer->getBoundMemory().getMemory(),
+                                                                  m_indirectCountBuffer->getBoundMemory().getOffset(),
+                                                                  m_offsetInCountBuffer + sizeof(m_drawCount));
+       }
+
        m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
 
        if (m_drawType == DRAW_TYPE_INDEXED)
@@ -643,11 +843,25 @@ tcu::TestStatus IndirectDrawInstanced<FirstInstanceSupport>::iterate (void)
                switch (m_drawType)
                {
                        case DRAW_TYPE_SEQUENTIAL:
-                               m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
+                       {
+                               if (m_testIndirectCountExt)
+                                       m_vk.cmdDrawIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
+                                                                                                m_indirectCountBuffer->object(), m_offsetInCountBuffer,
+                                                                                                m_drawCount + m_indirectCountExtDrawPadding, m_strideInBuffer);
+                               else
+                                       m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
                                break;
+                       }
                        case DRAW_TYPE_INDEXED:
-                               m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
+                       {
+                               if (m_testIndirectCountExt)
+                                       m_vk.cmdDrawIndexedIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer,
+                                                                                                               m_indirectCountBuffer->object(), m_offsetInCountBuffer,
+                                                                                                               m_drawCount + m_indirectCountExtDrawPadding, m_strideInBuffer);
+                               else
+                                       m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer, m_drawCount, m_strideInBuffer);
                                break;
+                       }
                        default:
                                TCU_FAIL("impossible");
                }
@@ -659,11 +873,25 @@ tcu::TestStatus IndirectDrawInstanced<FirstInstanceSupport>::iterate (void)
                        switch (m_drawType)
                        {
                                case DRAW_TYPE_SEQUENTIAL:
-                                       m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
+                               {
+                                       if (m_testIndirectCountExt)
+                                               m_vk.cmdDrawIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
+                                                                                                        m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
+                                                                                                        m_strideInBuffer);
+                                       else
+                                               m_vk.cmdDrawIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
                                        break;
+                               }
                                case DRAW_TYPE_INDEXED:
-                                       m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
+                               {
+                                       if (m_testIndirectCountExt)
+                                               m_vk.cmdDrawIndexedIndirectCountKHR(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer,
+                                                                                                                       m_indirectCountBuffer->object(), m_offsetInCountBuffer, m_drawCount + m_indirectCountExtDrawPadding,
+                                                                                                                       m_strideInBuffer);
+                                       else
+                                               m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, m_indirectBuffer->object(), m_offsetInBuffer + drawNdx*m_strideInBuffer, 1u, 0u);
                                        break;
+                               }
                                default:
                                        TCU_FAIL("impossible");
                        }
@@ -725,14 +953,13 @@ tcu::TestStatus IndirectDrawInstanced<FirstInstanceSupport>::iterate (void)
        qpTestResult res = QP_TEST_RESULT_PASS;
 
        if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
-               referenceFrame.getLevel(0), renderedFrame, 0.05f,
-               tcu::COMPARE_LOG_RESULT)) {
+               referenceFrame.getLevel(0), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
+       {
                res = QP_TEST_RESULT_FAIL;
        }
 
        return tcu::TestStatus(res, qpGetTestResultName(res));
-
-       }
+}
 
 }      // anonymous
 
@@ -764,7 +991,8 @@ void IndirectDrawTests::init (void)
 
                tcu::TestCaseGroup* drawTypeGroup = new tcu::TestCaseGroup(m_testCtx, drawTypeStr.c_str(), ("Draws geometry using " + drawTypeStr + "draw call").c_str());
                {
-                       tcu::TestCaseGroup* indirectDrawGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw", "Draws geometry");
+                       tcu::TestCaseGroup* indirectDrawGroup           = new tcu::TestCaseGroup(m_testCtx, "indirect_draw", "Draws geometry");
+                       tcu::TestCaseGroup* indirectDrawCountGroup      = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_count", "Draws geometry with VK_KHR_draw_indirect_count extension");
                        {
                                IndirectDraw::TestSpec testSpec;
                                testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
@@ -774,43 +1002,91 @@ void IndirectDrawTests::init (void)
                                indirectDrawGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_list", "Draws triangle list", testSpec));
                                testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
                                indirectDrawGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec));
+
+                               testSpec.testIndirectCountExt = true;
+                               testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+                               indirectDrawCountGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_list", "Draws triangle list", testSpec));
+                               testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+                               indirectDrawCountGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec));
                        }
                        drawTypeGroup->addChild(indirectDrawGroup);
+                       drawTypeGroup->addChild(indirectDrawCountGroup);
+
+                       {
+                               tcu::TestCaseGroup* indirectDrawFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_first_instance", "Draws geometry with different first instance in one commandbuffer");
+                               tcu::TestCaseGroup* indirectDrawCountFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_count_first_instance", "Draws geometry with VK_KHR_draw_indirect_count extension with different first instance in one commandbuffer using ");
+                               {
+                                       IndirectDraw::TestSpec testSpec;
+                                       testSpec.testFirstInstanceNdx = true;
+                                       testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
+                                       testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstanceIndex.vert";
+                                       testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
+                                       testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+                                       indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_list", "Draws triangle list", testSpec));
+                                       testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+                                       indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec));
 
+                                       testSpec.testIndirectCountExt = true;
+                                       testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+                                       indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_list", "Draws triangle list", testSpec));
+                                       testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+                                       indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDraw>(m_testCtx, "triangle_strip", "Draws triangle strip", testSpec));
+                               }
+                               drawTypeGroup->addChild(indirectDrawFirstInstanceGroup);
+                               drawTypeGroup->addChild(indirectDrawCountFirstInstanceGroup);
+                       }
 
-                       tcu::TestCaseGroup* indirectDrawInstancedGroup = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_instanced", "Draws an instanced geometry");
+                       tcu::TestCaseGroup* indirectDrawInstancedGroup          = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_instanced", "Draws an instanced geometry");
+                       tcu::TestCaseGroup* indirectDrawCountInstancedGroup     = new tcu::TestCaseGroup(m_testCtx, "indirect_draw_count_instanced", "Draws an instanced geometry with VK_KHR_draw_indirect_count extension");
                        {
-                               tcu::TestCaseGroup*     noFirstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "no_first_instance", "Use 0 as firstInstance");
+                               tcu::TestCaseGroup*     indirectDrawNoFirstInstanceGroup                = new tcu::TestCaseGroup(m_testCtx, "no_first_instance", "Use 0 as firstInstance");
+                               tcu::TestCaseGroup*     indirectDrawCountNoFirstInstanceGroup   = new tcu::TestCaseGroup(m_testCtx, "no_first_instance", "Use 0 as firstInstance");
                                {
-                                       IndirectDrawInstanced<FirtsInstanceNotSupported>::TestSpec testSpec;
+                                       IndirectDrawInstanced<FirstInstanceNotSupported>::TestSpec testSpec;
                                        testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
 
                                        testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstanced.vert";
                                        testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
 
                                        testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
-                                       noFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirtsInstanceNotSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
+                                       indirectDrawNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
+                                       testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+                                       indirectDrawNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
+
+                                       testSpec.testIndirectCountExt = true;
+                                       testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+                                       indirectDrawCountNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
                                        testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
-                                       noFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirtsInstanceNotSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
+                                       indirectDrawCountNoFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceNotSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
                                }
-                               indirectDrawInstancedGroup->addChild(noFirstInstanceGroup);
+                               indirectDrawInstancedGroup->addChild(indirectDrawNoFirstInstanceGroup);
+                               indirectDrawCountInstancedGroup->addChild(indirectDrawCountNoFirstInstanceGroup);
 
-                               tcu::TestCaseGroup*     firstInstanceGroup = new tcu::TestCaseGroup(m_testCtx, "first_instance", "Use drawIndirectFirstInstance optional feature");
+                               tcu::TestCaseGroup*     indirectDrawFirstInstanceGroup          = new tcu::TestCaseGroup(m_testCtx, "first_instance", "Use drawIndirectFirstInstance optional feature");
+                               tcu::TestCaseGroup*     indirectDrawCountFirstInstanceGroup     = new tcu::TestCaseGroup(m_testCtx, "first_instance", "Use drawIndirectFirstInstance optional feature");
                                {
-                                       IndirectDrawInstanced<FirtsInstanceSupported>::TestSpec testSpec;
+                                       IndirectDrawInstanced<FirstInstanceSupported>::TestSpec testSpec;
                                        testSpec.drawType = static_cast<DrawType>(drawTypeIdx);
 
                                        testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/draw/VertexFetchInstancedFirstInstance.vert";
                                        testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/draw/VertexFetch.frag";
 
                                        testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
-                                       firstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirtsInstanceSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
+                                       indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
+                                       testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+                                       indirectDrawFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
+
+                                       testSpec.testIndirectCountExt = true;
+                                       testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+                                       indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported> >(m_testCtx, "triangle_list", "Draws an instanced triangle list", testSpec));
                                        testSpec.topology = vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
-                                       firstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirtsInstanceSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
+                                       indirectDrawCountFirstInstanceGroup->addChild(new InstanceFactory<IndirectDrawInstanced<FirstInstanceSupported> >(m_testCtx, "triangle_strip", "Draws an instanced triangle strip", testSpec));
                                }
-                               indirectDrawInstancedGroup->addChild(firstInstanceGroup);
+                               indirectDrawInstancedGroup->addChild(indirectDrawFirstInstanceGroup);
+                               indirectDrawCountInstancedGroup->addChild(indirectDrawCountFirstInstanceGroup);
                        }
                        drawTypeGroup->addChild(indirectDrawInstancedGroup);
+                       drawTypeGroup->addChild(indirectDrawCountInstancedGroup);
                }
 
                addChild(drawTypeGroup);
index a696771..c15eadf 100644 (file)
@@ -171604,16 +171604,36 @@ dEQP-VK.draw.indexed_draw.draw_instanced_indexed_triangle_list
 dEQP-VK.draw.indexed_draw.draw_instanced_indexed_triangle_strip
 dEQP-VK.draw.indirect_draw.sequential.indirect_draw.triangle_list
 dEQP-VK.draw.indirect_draw.sequential.indirect_draw.triangle_strip
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count.triangle_list
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count.triangle_strip
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_first_instance.triangle_strip
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count_first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count_first_instance.triangle_strip
 dEQP-VK.draw.indirect_draw.sequential.indirect_draw_instanced.no_first_instance.triangle_list
 dEQP-VK.draw.indirect_draw.sequential.indirect_draw_instanced.no_first_instance.triangle_strip
 dEQP-VK.draw.indirect_draw.sequential.indirect_draw_instanced.first_instance.triangle_list
 dEQP-VK.draw.indirect_draw.sequential.indirect_draw_instanced.first_instance.triangle_strip
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count_instanced.no_first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count_instanced.no_first_instance.triangle_strip
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count_instanced.first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.sequential.indirect_draw_count_instanced.first_instance.triangle_strip
 dEQP-VK.draw.indirect_draw.indexed.indirect_draw.triangle_list
 dEQP-VK.draw.indirect_draw.indexed.indirect_draw.triangle_strip
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count.triangle_list
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count.triangle_strip
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_first_instance.triangle_strip
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count_first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count_first_instance.triangle_strip
 dEQP-VK.draw.indirect_draw.indexed.indirect_draw_instanced.no_first_instance.triangle_list
 dEQP-VK.draw.indirect_draw.indexed.indirect_draw_instanced.no_first_instance.triangle_strip
 dEQP-VK.draw.indirect_draw.indexed.indirect_draw_instanced.first_instance.triangle_list
 dEQP-VK.draw.indirect_draw.indexed.indirect_draw_instanced.first_instance.triangle_strip
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count_instanced.no_first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count_instanced.no_first_instance.triangle_strip
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count_instanced.first_instance.triangle_list
+dEQP-VK.draw.indirect_draw.indexed.indirect_draw_count_instanced.first_instance.triangle_strip
 dEQP-VK.draw.basic_draw.draw.point_list.1
 dEQP-VK.draw.basic_draw.draw.point_list.3
 dEQP-VK.draw.basic_draw.draw.point_list.17
index 25c49d0..ab65ab3 100644 (file)
@@ -4200,11 +4200,38 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR(
     VkSwapchainKHR                              swapchain);
 #endif
 
+#define VK_KHR_draw_indirect_count 1
+#define VK_KHR_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
+#define VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_KHR_draw_indirect_count"
+
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountKHR)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountKHR(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset,
+    VkBuffer                                    countBuffer,
+    VkDeviceSize                                countBufferOffset,
+    uint32_t                                    maxDrawCount,
+    uint32_t                                    stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountKHR(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset,
+    VkBuffer                                    countBuffer,
+    VkDeviceSize                                countBufferOffset,
+    uint32_t                                    maxDrawCount,
+    uint32_t                                    stride);
+#endif
+
+
 #define VK_KHR_maintenance2 1
 #define VK_KHR_MAINTENANCE2_SPEC_VERSION  1
 #define VK_KHR_MAINTENANCE2_EXTENSION_NAME "VK_KHR_maintenance2"
 
-
 typedef enum VkPointClippingBehaviorKHR {
     VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR = 0,
     VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR = 1,