Add ability to generate images with the reference renderer
authorDavid Sodman <dsodman@google.com>
Fri, 9 Sep 2016 02:58:35 +0000 (19:58 -0700)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Thu, 31 Aug 2017 18:19:15 +0000 (14:19 -0400)
*Separate DrawContext into a DrawContext and DrawContextState to reflect
  graphics API's are split between state and action parts
* Add abstract DrawContext class

Test: Test clipping and synchronization primitives

Change-Id: I9f3945c6c3de169325fadea7bf70a9d5d7bfd932
(cherry picked from commit 11da53fb71eced942e89bac59407a5681dba3bb1)

external/vulkancts/modules/vulkan/clipping/vktClippingTests.cpp
external/vulkancts/modules/vulkan/vktDrawUtil.cpp
external/vulkancts/modules/vulkan/vktDrawUtil.hpp
framework/referencerenderer/rrRasterizer.cpp
framework/referencerenderer/rrRasterizer.hpp
framework/referencerenderer/rrRenderState.hpp
framework/referencerenderer/rrRenderer.cpp
framework/referencerenderer/rrShadingContext.cpp
framework/referencerenderer/rrShadingContext.hpp

index 627e06d..bc8e443 100644 (file)
@@ -47,6 +47,17 @@ using tcu::Vec4;
 using tcu::IVec2;
 using namespace drawutil;
 
+enum TestConstants
+{
+       RENDER_SIZE                                                             = 16,
+       RENDER_SIZE_LARGE                                               = 128,
+       NUM_RENDER_PIXELS                                               = RENDER_SIZE * RENDER_SIZE,
+       NUM_PATCH_CONTROL_POINTS                                = 3,
+       MAX_CLIP_DISTANCES                                              = 8,
+       MAX_CULL_DISTANCES                                              = 8,
+       MAX_COMBINED_CLIP_AND_CULL_DISTANCES    = 8,
+};
+
 enum FeatureFlagBits
 {
        FEATURE_TESSELLATION_SHADER                                                     = 1u << 0,
@@ -407,7 +418,11 @@ tcu::TestStatus testPrimitivesInside (Context& context, const VkPrimitiveTopolog
                log << tcu::TestLog::Message << cases[caseNdx].desc << tcu::TestLog::EndMessage;
 
                const std::vector<Vec4> vertices = genVertices(topology, Vec4(0.0f, 0.0f, cases[caseNdx].zPos, 0.0f), 0.0f);
-               DrawContext drawContext(context, shaders, vertices, topology);
+               DrawState                       drawState               (topology, RENDER_SIZE, RENDER_SIZE);
+               DrawCallData            drawCallData    (vertices);
+               VulkanProgram           vulkanProgram   (shaders);
+
+               VulkanDrawContext       drawContext(context, drawState, drawCallData, vulkanProgram);
                drawContext.draw();
 
                const int numBlackPixels = countPixels(drawContext.getColorPixels(), Vec4(0.0f, 0.0f, 0.0f, 1.0f), Vec4());
@@ -445,7 +460,11 @@ tcu::TestStatus testPrimitivesOutside (Context& context, const VkPrimitiveTopolo
                log << tcu::TestLog::Message << cases[caseNdx].desc << tcu::TestLog::EndMessage;
 
                const std::vector<Vec4> vertices = genVertices(topology, Vec4(0.0f, 0.0f, cases[caseNdx].zPos, 0.0f), 0.0f);
-               DrawContext drawContext(context, shaders, vertices, topology);
+               DrawState                               drawState               (topology, RENDER_SIZE, RENDER_SIZE);
+               DrawCallData                    drawCallData    (vertices);
+               VulkanProgram                   vulkanProgram   (shaders);
+
+               VulkanDrawContext               drawContext(context, drawState, drawCallData, vulkanProgram);
                drawContext.draw();
 
                // All pixels must be black -- nothing is drawn.
@@ -525,7 +544,13 @@ tcu::TestStatus testPrimitivesDepthClamp (Context& context, const VkPrimitiveTop
                log << tcu::TestLog::Message << cases[caseNdx].desc << tcu::TestLog::EndMessage;
 
                const std::vector<Vec4> vertices = genVertices(topology, Vec4(0.0f, 0.0f, cases[caseNdx].zPos, 0.0f), 1.0f);
-               DrawContext drawContext(context, shaders, vertices, topology, static_cast<deUint32>(RENDER_SIZE), cases[caseNdx].depthClampEnable);
+
+               DrawState                                       drawState               (topology, RENDER_SIZE, RENDER_SIZE);
+               DrawCallData                            drawCallData    (vertices);
+               VulkanProgram                           vulkanProgram   (shaders);
+               drawState.depthClampEnable = cases[caseNdx].depthClampEnable;
+
+               VulkanDrawContext                       drawContext(context, drawState, drawCallData, vulkanProgram);
                drawContext.draw();
 
                const int numPixels = countPixels(drawContext.getColorPixels(), cases[caseNdx].regionOffset, regionSize, cases[caseNdx].color, Vec4());
@@ -590,7 +615,11 @@ tcu::TestStatus testLargePoints (Context& context)
 
        log << tcu::TestLog::Message << "Drawing several large points just outside the clip volume. Expecting an empty image." << tcu::TestLog::EndMessage;
 
-       DrawContext drawContext(context, shaders, vertices, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
+       DrawState                       drawState               (VK_PRIMITIVE_TOPOLOGY_POINT_LIST, RENDER_SIZE, RENDER_SIZE);
+       DrawCallData            drawCallData    (vertices);
+       VulkanProgram           vulkanProgram   (shaders);
+
+       VulkanDrawContext       drawContext(context, drawState, drawCallData, vulkanProgram);
        drawContext.draw();
 
        const int       numBlackPixels  = countPixels(drawContext.getColorPixels(), Vec4(0.0f, 0.0f, 0.0f, 1.0f), Vec4());
@@ -664,7 +693,12 @@ tcu::TestStatus testWideLines (Context& context, const LineOrientation lineOrien
        log << tcu::TestLog::Message << "Drawing several wide lines just outside the clip volume. Expecting an empty image." << tcu::TestLog::EndMessage
                << tcu::TestLog::Message << "Line width is " << lineWidth << "." << tcu::TestLog::EndMessage;
 
-       DrawContext drawContext(context, shaders, vertices, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, static_cast<deUint32>(RENDER_SIZE), false, false, lineWidth);
+       DrawState                                       drawState               (VK_PRIMITIVE_TOPOLOGY_LINE_LIST, RENDER_SIZE, RENDER_SIZE);
+       DrawCallData                            drawCallData    (vertices);
+       VulkanProgram                           vulkanProgram   (shaders);
+       drawState.lineWidth                     = lineWidth;
+
+       VulkanDrawContext                       drawContext(context, drawState, drawCallData, vulkanProgram);
        drawContext.draw();
 
        // All pixels must be black -- nothing is drawn.
@@ -988,7 +1022,14 @@ tcu::TestStatus testClipDistance (Context& context, const CaseDefinition caseDef
                << tcu::TestLog::Message << "Using " << caseDef.numClipDistances << " ClipDistance(s) and " << caseDef.numCullDistances << " CullDistance(s)" << tcu::TestLog::EndMessage
                << tcu::TestLog::Message << "Expecting upper half of the clipped bars to be black." << tcu::TestLog::EndMessage;
 
-       DrawContext drawContext(context, shaders, vertices, caseDef.topology);
+       DrawState                       drawState               (caseDef.topology, RENDER_SIZE, RENDER_SIZE);
+       DrawCallData            drawCallData    (vertices);
+       VulkanProgram           vulkanProgram   (shaders);
+
+       if (caseDef.enableTessellation)
+               drawState.numPatchControlPoints = NUM_PATCH_CONTROL_POINTS;
+
+       VulkanDrawContext       drawContext(context, drawState, drawCallData, vulkanProgram);
        drawContext.draw();
 
        // Count black pixels in the whole image.
@@ -1109,7 +1150,12 @@ tcu::TestStatus testComplementarity (Context& context, const int numClipDistance
                << tcu::TestLog::Message << "Using " << numClipDistances << " clipping plane(s), one of them possibly having negative values." << tcu::TestLog::EndMessage
                << tcu::TestLog::Message << "Expecting a uniform gray area, no missing (black) nor overlapped (white) pixels." << tcu::TestLog::EndMessage;
 
-       DrawContext drawContext(context, shaders, vertices, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, static_cast<deUint32>(RENDER_SIZE_LARGE), false, true);
+       DrawState                                       drawState               (VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, RENDER_SIZE_LARGE, RENDER_SIZE_LARGE);
+       DrawCallData                            drawCallData    (vertices);
+       VulkanProgram                           vulkanProgram   (shaders);
+       drawState.blendEnable           = true;
+
+       VulkanDrawContext                       drawContext(context, drawState, drawCallData, vulkanProgram);
        drawContext.draw();
 
        const int numGrayPixels         = countPixels(drawContext.getColorPixels(), Vec4(0.5f, 0.5f, 0.5f, 1.0f), Vec4(0.02f, 0.02f, 0.02f, 0.0f));
index ae59db4..d2e2489 100644 (file)
  *//*--------------------------------------------------------------------*/
 
 #include "vktDrawUtil.hpp"
+#include "rrMultisamplePixelBufferAccess.hpp"
 #include "vkBufferWithMemory.hpp"
 #include "vkImageWithMemory.hpp"
 #include "vkTypeUtil.hpp"
+#include "rrRenderer.hpp"
+#include "rrPrimitiveTypes.hpp"
+#include "tcuTextureUtil.hpp"
+#include "deArrayUtil.hpp"
 #include "tcuTestLog.hpp"
 
 namespace vkt
@@ -37,6 +42,25 @@ using namespace de;
 using namespace tcu;
 using namespace vk;
 
+rr::PrimitiveType mapVkPrimitiveToRRPrimitive(const vk::VkPrimitiveTopology& primitiveTopology)
+{
+       static const rr::PrimitiveType primitiveTypeTable[] =
+       {
+               rr::PRIMITIVETYPE_POINTS,
+               rr::PRIMITIVETYPE_LINES,
+               rr::PRIMITIVETYPE_LINE_STRIP,
+               rr::PRIMITIVETYPE_TRIANGLES,
+               rr::PRIMITIVETYPE_TRIANGLE_STRIP,
+               rr::PRIMITIVETYPE_TRIANGLE_FAN,
+               rr::PRIMITIVETYPE_LINES_ADJACENCY,
+               rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY,
+               rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY,
+               rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY
+       };
+
+       return de::getSizedArrayElement<vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST>(primitiveTypeTable, primitiveTopology);
+}
+
 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize                    bufferSize,
                                                                                 const VkBufferUsageFlags       usage)
 {
@@ -212,10 +236,10 @@ void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer comman
 {
        const VkCommandBufferBeginInfo info =
        {
-               VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                          sType;
-               DE_NULL,                                                                                // const void*                              pNext;
-               VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,    // VkCommandBufferUsageFlags                flags;
-               DE_NULL,                                                                                // const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                                                      sType;
+               DE_NULL,                                                                                // const void*                                                          pNext;
+               VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,    // VkCommandBufferUsageFlags                            flags;
+               DE_NULL,                                                                                // const VkCommandBufferInheritanceInfo*        pInheritanceInfo;
        };
        VK_CHECK(vk.beginCommandBuffer(commandBuffer, &info));
 }
@@ -240,15 +264,15 @@ void submitCommandsAndWait (const DeviceInterface&        vk,
 
        const VkSubmitInfo submitInfo =
        {
-               VK_STRUCTURE_TYPE_SUBMIT_INFO,          // VkStructureType                sType;
-               DE_NULL,                                                        // const void*                    pNext;
-               0u,                                                                     // uint32_t                       waitSemaphoreCount;
-               DE_NULL,                                                        // const VkSemaphore*             pWaitSemaphores;
-               DE_NULL,                                                        // const VkPipelineStageFlags*    pWaitDstStageMask;
-               1u,                                                                     // uint32_t                       commandBufferCount;
-               &commandBuffer,                                         // const VkCommandBuffer*         pCommandBuffers;
-               0u,                                                                     // uint32_t                       signalSemaphoreCount;
-               DE_NULL,                                                        // const VkSemaphore*             pSignalSemaphores;
+               VK_STRUCTURE_TYPE_SUBMIT_INFO,          // VkStructureType                                      sType;
+               DE_NULL,                                                        // const void*                                          pNext;
+               0u,                                                                     // uint32_t                                                     waitSemaphoreCount;
+               DE_NULL,                                                        // const VkSemaphore*                           pWaitSemaphores;
+               DE_NULL,                                                        // const VkPipelineStageFlags*          pWaitDstStageMask;
+               1u,                                                                     // uint32_t                                                     commandBufferCount;
+               &commandBuffer,                                         // const VkCommandBuffer*                       pCommandBuffers;
+               0u,                                                                     // uint32_t                                                     signalSemaphoreCount;
+               DE_NULL,                                                        // const VkSemaphore*                           pSignalSemaphores;
        };
        VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
        VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
@@ -259,66 +283,109 @@ std::string getPrimitiveTopologyShortName (const VkPrimitiveTopology topology)
        std::string name(getPrimitiveTopologyName(topology));
        return de::toLower(name.substr(22));
 }
-DrawContext::DrawContext (Context&                                             context,
-                                                 const std::vector<Shader>&    shaders,
-                                                 const std::vector<Vec4>&              vertices,
-                                                 const VkPrimitiveTopology             primitiveTopology,
-                                                 const deUint32                                renderSize,
-                                                 const bool                                    depthClampEnable,
-                                                 const bool                                    blendEnable,
-                                                 const float                                   lineWidth)
-       : m_context                                     (context)
-       , m_colorFormat                         (VK_FORMAT_R8G8B8A8_UNORM)
-       , m_depthFormat                         (VK_FORMAT_D32_SFLOAT)
-       , m_colorSubresourceRange       (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))
-       , m_depthSubresourceRange       (makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u))
-       , m_renderSize                          (renderSize, renderSize)
-       , m_imageExtent                         (makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u))
-       , m_primitiveTopology           (primitiveTopology)
-       , m_depthClampEnable            (depthClampEnable)
-       , m_blendEnable                         (blendEnable)
-       , m_numVertices                         (static_cast<deUint32>(vertices.size()))
-       , m_lineWidth                           (lineWidth)
-       , m_numPatchControlPoints       (NUM_PATCH_CONTROL_POINTS)              // we're treating patches as triangles
+
+DrawState::DrawState(const vk::VkPrimitiveTopology topology_, deUint32 renderWidth_, deUint32 renderHeight_)
+       : topology                              (topology_)
+       , colorFormat                   (VK_FORMAT_R8G8B8A8_UNORM)
+       , depthFormat                   (VK_FORMAT_D32_SFLOAT)
+       , renderSize                    (tcu::UVec2(renderWidth_, renderHeight_))
+       , depthClampEnable              (false)
+       , blendEnable                   (false)
+       , lineWidth                             (1.0)
+       , numPatchControlPoints (0)
 {
-       const DeviceInterface&  vk                      = m_context.getDeviceInterface();
-       const VkDevice                  device          = m_context.getDevice();
-       Allocator&                              allocator       = m_context.getDefaultAllocator();
+       DE_ASSERT(renderSize.x() != 0 && renderSize.y() != 0);
+}
+
+ReferenceDrawContext::~ReferenceDrawContext (void)
+{
+}
+
+void ReferenceDrawContext::draw (void)
+{
+       m_refImage.setStorage(vk::mapVkFormat(m_drawState.colorFormat), m_drawState.renderSize.x(), m_drawState.renderSize.y());
+       tcu::clear(m_refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
+
+       {
+               const rr::Program                                               program(&m_vertexShader, &m_fragmentShader);
+               const rr::MultisamplePixelBufferAccess  referenceColorBuffer = rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(m_refImage.getAccess());
+               const rr::RenderTarget                                  renderTarget(referenceColorBuffer);
+               const rr::RenderState                                   renderState((rr::ViewportState(referenceColorBuffer)), rr::VIEWPORTORIENTATION_UPPER_LEFT);
+               const rr::Renderer                                              renderer;
+               const rr::VertexAttrib                                  vertexAttrib[] =
+               {
+                       rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &m_drawCallData.vertices[0])
+               };
+
+               renderer.draw(rr::DrawCommand(  renderState,
+                                                                               renderTarget,
+                                                                               program,
+                                                                               DE_LENGTH_OF_ARRAY(vertexAttrib),
+                                                                               &vertexAttrib[0],
+                                                                               rr::PrimitiveList(mapVkPrimitiveToRRPrimitive(m_drawState.topology), (int)m_drawCallData.vertices.size(), 0)));
+
+       }
+
+}
+
+tcu::ConstPixelBufferAccess ReferenceDrawContext::getColorPixels (void) const
+{
+       return tcu::ConstPixelBufferAccess( m_refImage.getAccess().getFormat(),
+                                                                               m_refImage.getAccess().getWidth(),
+                                                                               m_refImage.getAccess().getHeight(),
+                                                                               m_refImage.getAccess().getDepth(),
+                                                                               m_refImage.getAccess().getDataPtr());
+}
+
+VulkanDrawContext::VulkanDrawContext (  Context&                               context,
+                                                                               const DrawState&                drawState,
+                                                                               const DrawCallData&             drawCallData,
+                                                                               const VulkanProgram&    vulkanProgram)
+       : DrawContext                                           (drawState, drawCallData)
+       , m_context                                                     (context)
+       , m_program                                                     (vulkanProgram)
+{
+       const DeviceInterface&  vk                                              = m_context.getDeviceInterface();
+       const VkDevice                  device                                  = m_context.getDevice();
+       Allocator&                              allocator                               = m_context.getDefaultAllocator();
+       VkImageSubresourceRange colorSubresourceRange;
+       VkImageSubresourceRange depthSubresourceRange;
 
        // Command buffer
        {
-               m_cmdPool       = makeCommandPool(vk, device, m_context.getUniversalQueueFamilyIndex());
-               m_cmdBuffer     = makeCommandBuffer(vk, device, *m_cmdPool);
+               m_cmdPool                       = makeCommandPool(vk, device, m_context.getUniversalQueueFamilyIndex());
+               m_cmdBuffer                     = makeCommandBuffer(vk, device, *m_cmdPool);
        }
 
        // Color attachment image
        {
                const VkImageUsageFlags usage                   = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+               colorSubresourceRange                                   = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
                const VkImageCreateInfo imageCreateInfo =
                {
-                       VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType          sType;
-                       DE_NULL,                                                                        // const void*              pNext;
-                       (VkImageCreateFlags)0,                                          // VkImageCreateFlags       flags;
-                       VK_IMAGE_TYPE_2D,                                                       // VkImageType              imageType;
-                       m_colorFormat,                                                          // VkFormat                 format;
-                       m_imageExtent,                                                          // VkExtent3D               extent;
-                       1u,                                                                                     // uint32_t                 mipLevels;
-                       1u,                                                                                     // uint32_t                 arrayLayers;
-                       VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits    samples;
-                       VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling            tiling;
-                       usage,                                                                          // VkImageUsageFlags        usage;
-                       VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode            sharingMode;
-                       VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t                 queueFamilyIndexCount;
-                       DE_NULL,                                                                        // const uint32_t*          pQueueFamilyIndices;
-                       VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout            initialLayout;
+                       VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                            // VkStructureType                      sType;
+                       DE_NULL,                                                                                                                                        // const void*                          pNext;
+                       (VkImageCreateFlags)0,                                                                                                          // VkImageCreateFlags           flags;
+                       VK_IMAGE_TYPE_2D,                                                                                                                       // VkImageType                          imageType;
+                       m_drawState.colorFormat,                                                                                                        // VkFormat                                     format;
+                       makeExtent3D(m_drawState.renderSize.x(), m_drawState.renderSize.y(), 1u),       // VkExtent3D                           extent;
+                       1u,                                                                                                                                                     // uint32_t                                     mipLevels;
+                       1u,                                                                                                                                                     // uint32_t                                     arrayLayers;
+                       VK_SAMPLE_COUNT_1_BIT,                                                                                                          // VkSampleCountFlagBits        samples;
+                       VK_IMAGE_TILING_OPTIMAL,                                                                                                        // VkImageTiling                        tiling;
+                       usage,                                                                                                                                          // VkImageUsageFlags            usage;
+                       VK_SHARING_MODE_EXCLUSIVE,                                                                                                      // VkSharingMode                        sharingMode;
+                       VK_QUEUE_FAMILY_IGNORED,                                                                                                        // uint32_t                                     queueFamilyIndexCount;
+                       DE_NULL,                                                                                                                                        // const uint32_t*                      pQueueFamilyIndices;
+                       VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                      // VkImageLayout                        initialLayout;
                };
 
                m_colorImage = MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
-               m_colorImageView = makeImageView(vk, device, **m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange);
+               m_colorImageView = makeImageView(vk, device, **m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_drawState.colorFormat, colorSubresourceRange);
 
                // Buffer to copy attachment data after rendering
 
-               const VkDeviceSize bitmapSize = tcu::getPixelSize(mapVkFormat(m_colorFormat)) * m_renderSize.x() * m_renderSize.y();
+               const VkDeviceSize bitmapSize = tcu::getPixelSize(mapVkFormat(m_drawState.colorFormat)) * m_drawState.renderSize.x() * m_drawState.renderSize.y();
                m_colorAttachmentBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(
                        vk, device, allocator, makeBufferCreateInfo(bitmapSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible));
 
@@ -331,37 +398,38 @@ DrawContext::DrawContext (Context&                                                context,
 
        // Depth attachment image
        {
+               depthSubresourceRange                                   = makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
                const VkImageCreateInfo imageCreateInfo =
                {
-                       VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                    // VkStructureType                      sType
-                       DE_NULL,                                                                                // const void*                          pNext
-                       0u,                                                                                             // VkImageCreateFlags           flags
-                       VK_IMAGE_TYPE_2D,                                                               // VkImageType                          imageType
-                       m_depthFormat,                                                                  // VkFormat                                     depthFormat
-                       { m_renderSize.x(), m_renderSize.y(), 1u },             // VkExtent3D                           externt
-                       1u,                                                                                             // deUint32                                     mipLevels
-                       1u,                                                                                             // deUint32                                     arrayLayers
-                       VK_SAMPLE_COUNT_1_BIT,                                                  // VkSampleCountFlagBits        samples
-                       VK_IMAGE_TILING_OPTIMAL,                                                // VkImageTiling                        tiling
-                       VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,    // VkImageUsageFlags            usage
-                       VK_SHARING_MODE_EXCLUSIVE,                                              // VkSharingMode                        sharingMode
-                       0u,                                                                                             // deUint32                                     queueFamilyIndexCount
-                       DE_NULL,                                                                                // const deUint32*                      pQueueFamilyIndices
-                       VK_IMAGE_LAYOUT_UNDEFINED                                               // VkImageLayout                        initialLayout
+                       VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                            // VkStructureType                      sType
+                       DE_NULL,                                                                                                        // const void*                          pNext
+                       0u,                                                                                                                     // VkImageCreateFlags           flags
+                       VK_IMAGE_TYPE_2D,                                                                                       // VkImageType                          imageType
+                       m_drawState.depthFormat,                                                                        // VkFormat                                     depthFormat
+                       { m_drawState.renderSize.x(), m_drawState.renderSize.y(), 1u },         // VkExtent3D                           externt
+                       1u,                                                                                                                     // deUint32                                     mipLevels
+                       1u,                                                                                                                     // deUint32                                     arrayLayers
+                       VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits        samples
+                       VK_IMAGE_TILING_OPTIMAL,                                                                        // VkImageTiling                        tiling
+                       VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,                            // VkImageUsageFlags            usage
+                       VK_SHARING_MODE_EXCLUSIVE,                                                                      // VkSharingMode                        sharingMode
+                       0u,                                                                                                                     // deUint32                                     queueFamilyIndexCount
+                       DE_NULL,                                                                                                        // const deUint32*                      pQueueFamilyIndices
+                       VK_IMAGE_LAYOUT_UNDEFINED                                                                       // VkImageLayout                        initialLayout
                };
 
-               m_depthImage = MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::HostVisible));
-               m_depthImageView = makeImageView(vk, device, **m_depthImage, VK_IMAGE_VIEW_TYPE_2D, m_depthFormat, m_depthSubresourceRange);
+               m_depthImage = MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
+               m_depthImageView = makeImageView(vk, device, **m_depthImage, VK_IMAGE_VIEW_TYPE_2D, m_drawState.depthFormat, depthSubresourceRange);
        }
 
        // Vertex buffer
        {
-               const VkDeviceSize bufferSize = vertices.size() * sizeof(vertices[0]);
+               const VkDeviceSize bufferSize = m_drawCallData.vertices.size() * sizeof(m_drawCallData.vertices[0]);
                m_vertexBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(
                        vk, device, allocator, makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
 
                const Allocation& alloc = m_vertexBuffer->getAllocation();
-               deMemcpy(alloc.getHostPtr(), &vertices[0], (size_t)bufferSize);
+               deMemcpy(alloc.getHostPtr(), &m_drawCallData.vertices[0], (size_t)bufferSize);
                flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bufferSize);
        }
 
@@ -375,7 +443,7 @@ DrawContext::DrawContext (Context&                                          context,
                const VkAttachmentDescription colorAttachmentDescription =
                {
                        (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
-                       m_colorFormat,                                                                          // VkFormat                                                     format;
+                       m_drawState.colorFormat,                                                        // VkFormat                                                     format;
                        VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
                        VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
                        VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
@@ -436,15 +504,15 @@ DrawContext::DrawContext (Context&                                                context,
                };
 
                const VkFramebufferCreateInfo framebufferInfo = {
-                       VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,              // VkStructureType                             sType;
-                       DE_NULL,                                                                                // const void*                                 pNext;
-                       (VkFramebufferCreateFlags)0,                                    // VkFramebufferCreateFlags                    flags;
-                       *m_renderPass,                                                                  // VkRenderPass                                renderPass;
-                       DE_LENGTH_OF_ARRAY(attachmentBindInfos),                // uint32_t                                    attachmentCount;
-                       attachmentBindInfos,                                                    // const VkImageView*                          pAttachments;
-                       m_renderSize.x(),                                                               // uint32_t                                    width;
-                       m_renderSize.y(),                                                               // uint32_t                                    height;
-                       1u,                                                                                             // uint32_t                                    layers;
+                       VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,              // VkStructureType                                              sType;
+                       DE_NULL,                                                                                // const void*                                                  pNext;
+                       (VkFramebufferCreateFlags)0,                                    // VkFramebufferCreateFlags                             flags;
+                       *m_renderPass,                                                                  // VkRenderPass                                                 renderPass;
+                       DE_LENGTH_OF_ARRAY(attachmentBindInfos),                // uint32_t                                                             attachmentCount;
+                       attachmentBindInfos,                                                    // const VkImageView*                                   pAttachments;
+                       m_drawState.renderSize.x(),                                             // uint32_t                                                             width;
+                       m_drawState.renderSize.y(),                                             // uint32_t                                                             height;
+                       1u,                                                                                             // uint32_t                                                             layers;
                };
 
                m_framebuffer = createFramebuffer(vk, device, &framebufferInfo);
@@ -455,6 +523,8 @@ DrawContext::DrawContext (Context&                                          context,
                const deUint32  vertexStride    = sizeof(Vec4);
                const VkFormat  vertexFormat    = VK_FORMAT_R32G32B32A32_SFLOAT;
 
+               DE_ASSERT(m_drawState.topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST || m_drawState.numPatchControlPoints > 0);
+
                const VkVertexInputBindingDescription bindingDesc =
                {
                        0u,                                                                     // uint32_t                             binding;
@@ -471,60 +541,60 @@ DrawContext::DrawContext (Context&                                                context,
 
                const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
                {
-                       VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                             sType;
-                       DE_NULL,                                                                                                                // const void*                                 pNext;
-                       (VkPipelineVertexInputStateCreateFlags)0,                                               // VkPipelineVertexInputStateCreateFlags       flags;
-                       1u,                                                                                                                             // uint32_t                                    vertexBindingDescriptionCount;
-                       &bindingDesc,                                                                                                   // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
-                       1u,                                                                                                                             // uint32_t                                    vertexAttributeDescriptionCount;
-                       &attributeDesc,                                                                                                 // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
+                       VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                              sType;
+                       DE_NULL,                                                                                                                // const void*                                                                  pNext;
+                       (VkPipelineVertexInputStateCreateFlags)0,                                               // VkPipelineVertexInputStateCreateFlags                flags;
+                       1u,                                                                                                                             // uint32_t                                                                             vertexBindingDescriptionCount;
+                       &bindingDesc,                                                                                                   // const VkVertexInputBindingDescription*               pVertexBindingDescriptions;
+                       1u,                                                                                                                             // uint32_t                                                                             vertexAttributeDescriptionCount;
+                       &attributeDesc,                                                                                                 // const VkVertexInputAttributeDescription*             pVertexAttributeDescriptions;
                };
 
                const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
                {
-                       VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                             sType;
-                       DE_NULL,                                                                                                                // const void*                                 pNext;
-                       (VkPipelineInputAssemblyStateCreateFlags)0,                                             // VkPipelineInputAssemblyStateCreateFlags     flags;
-                       m_primitiveTopology,                                                                                    // VkPrimitiveTopology                         topology;
-                       VK_FALSE,                                                                                                               // VkBool32                                    primitiveRestartEnable;
+                       VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                                                              sType;
+                       DE_NULL,                                                                                                                // const void*                                                                  pNext;
+                       (VkPipelineInputAssemblyStateCreateFlags)0,                                             // VkPipelineInputAssemblyStateCreateFlags              flags;
+                       m_drawState.topology,                                                                                   // VkPrimitiveTopology                                                  topology;
+                       VK_FALSE,                                                                                                               // VkBool32                                                                             primitiveRestartEnable;
                };
 
                const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
                {
-                       VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,              // VkStructureType                             sType;
-                       DE_NULL,                                                                                                                // const void*                                 pNext;
-                       (VkPipelineTessellationStateCreateFlags)0,                                              // VkPipelineTessellationStateCreateFlags      flags;
-                       m_numPatchControlPoints,                                                                                // uint32_t                                    patchControlPoints;
+                       VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,              // VkStructureType                                                              sType;
+                       DE_NULL,                                                                                                                // const void*                                                                  pNext;
+                       (VkPipelineTessellationStateCreateFlags)0,                                              // VkPipelineTessellationStateCreateFlags               flags;
+                       m_drawState.numPatchControlPoints,                                                              // uint32_t                                                                             patchControlPoints;
                };
 
                const VkViewport viewport = makeViewport(
                        0.0f, 0.0f,
-                       static_cast<float>(m_renderSize.x()), static_cast<float>(m_renderSize.y()),
+                       static_cast<float>(m_drawState.renderSize.x()), static_cast<float>(m_drawState.renderSize.y()),
                        0.0f, 1.0f);
 
                const VkRect2D scissor = {
                        makeOffset2D(0, 0),
-                       makeExtent2D(m_renderSize.x(), m_renderSize.y()),
+                       makeExtent2D(m_drawState.renderSize.x(), m_drawState.renderSize.y()),
                };
 
                const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
                {
-                       VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,  // VkStructureType                             sType;
-                       DE_NULL,                                                                                                // const void*                                 pNext;
-                       (VkPipelineViewportStateCreateFlags)0,                                  // VkPipelineViewportStateCreateFlags          flags;
-                       1u,                                                                                                             // uint32_t                                    viewportCount;
-                       &viewport,                                                                                              // const VkViewport*                           pViewports;
-                       1u,                                                                                                             // uint32_t                                    scissorCount;
-                       &scissor,                                                                                               // const VkRect2D*                             pScissors;
+                       VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,  // VkStructureType                                                                      sType;
+                       DE_NULL,                                                                                                // const void*                                                                          pNext;
+                       (VkPipelineViewportStateCreateFlags)0,                                  // VkPipelineViewportStateCreateFlags                           flags;
+                       1u,                                                                                                             // uint32_t                                                                                     viewportCount;
+                       &viewport,                                                                                              // const VkViewport*                                                            pViewports;
+                       1u,                                                                                                             // uint32_t                                                                                     scissorCount;
+                       &scissor,                                                                                               // const VkRect2D*                                                                      pScissors;
                };
 
                const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
                {
-                       VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                          sType;
-                       DE_NULL,                                                                                                                // const void*                              pNext;
-                       (VkPipelineRasterizationStateCreateFlags)0,                                             // VkPipelineRasterizationStateCreateFlags  flags;
-                       m_depthClampEnable,                                                                                             // VkBool32                                 depthClampEnable;
-                       VK_FALSE,                                                                                                               // VkBool32                                 rasterizerDiscardEnable;
+                       VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                                // const void*                                                          pNext;
+                       (VkPipelineRasterizationStateCreateFlags)0,                                             // VkPipelineRasterizationStateCreateFlags      flags;
+                       m_drawState.depthClampEnable,                                                                   // VkBool32                                                                     depthClampEnable;
+                       VK_FALSE,                                                                                                               // VkBool32                                                                     rasterizerDiscardEnable;
                        VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                        polygonMode;
                        VK_CULL_MODE_NONE,                                                                                              // VkCullModeFlags                                                      cullMode;
                        VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
@@ -532,7 +602,7 @@ DrawContext::DrawContext (Context&                                          context,
                        0.0f,                                                                                                                   // float                                                                        depthBiasConstantFactor;
                        0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
                        0.0f,                                                                                                                   // float                                                                        depthBiasSlopeFactor;
-                       m_lineWidth,                                                                                                    // float                                                                        lineWidth;
+                       m_drawState.lineWidth,                                                                                  // float                                                                        lineWidth;
                };
 
                const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
@@ -576,7 +646,7 @@ DrawContext::DrawContext (Context&                                          context,
                const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
                const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
                {
-                       m_blendEnable,                                          // VkBool32                                     blendEnable;
+                       m_drawState.blendEnable,                        // VkBool32                                     blendEnable;
                        VK_BLEND_FACTOR_SRC_ALPHA,                      // VkBlendFactor                        srcColorBlendFactor;
                        VK_BLEND_FACTOR_ONE,                            // VkBlendFactor                        dstColorBlendFactor;
                        VK_BLEND_OP_ADD,                                        // VkBlendOp                            colorBlendOp;
@@ -603,31 +673,31 @@ DrawContext::DrawContext (Context&                                                context,
                std::vector<VkPipelineShaderStageCreateInfo>    shaderStages;
                VkShaderStageFlags                                                              stageFlags = (VkShaderStageFlags)0;
 
-               DE_ASSERT(shaders.size() <= MAX_NUM_SHADER_MODULES);
-               for (deUint32 shaderNdx = 0; shaderNdx < shaders.size(); ++shaderNdx)
+               DE_ASSERT(m_program.shaders.size() <= MAX_NUM_SHADER_MODULES);
+               for (deUint32 shaderNdx = 0; shaderNdx < m_program.shaders.size(); ++shaderNdx)
                {
-                       m_shaderModules[shaderNdx] = createShaderModule(vk, device, *shaders[shaderNdx].binary, (VkShaderModuleCreateFlags)0);
+                       m_shaderModules[shaderNdx] = createShaderModule(vk, device, *m_program.shaders[shaderNdx].binary, (VkShaderModuleCreateFlags)0);
 
                        const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
                        {
                                VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
                                DE_NULL,                                                                                                // const void*                                                  pNext;
                                (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
-                               shaders[shaderNdx].stage,                                                               // VkShaderStageFlagBits                                stage;
+                               m_program.shaders[shaderNdx].stage,                                             // VkShaderStageFlagBits                                stage;
                                *m_shaderModules[shaderNdx],                                                    // VkShaderModule                                               module;
                                "main",                                                                                                 // const char*                                                  pName;
                                DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
                        };
 
                        shaderStages.push_back(pipelineShaderStageInfo);
-                       stageFlags |= shaders[shaderNdx].stage;
+                       stageFlags |= m_program.shaders[shaderNdx].stage;
                }
 
                DE_ASSERT(
-                       (m_primitiveTopology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) ||
+                       (m_drawState.topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) ||
                        (stageFlags & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)));
 
-               const bool tessellationEnabled = (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
+               const bool tessellationEnabled = (m_drawState.topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
                const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
                {
                        VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                                                // VkStructureType                                                                      sType;
@@ -666,17 +736,17 @@ DrawContext::DrawContext (Context&                                                context,
                        const VkRect2D          renderArea =
                        {
                                makeOffset2D(0, 0),
-                               makeExtent2D(m_renderSize.x(), m_renderSize.y())
+                               makeExtent2D(m_drawState.renderSize.x(), m_drawState.renderSize.y())
                        };
 
                        const VkRenderPassBeginInfo renderPassBeginInfo = {
-                               VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType         sType;
-                               DE_NULL,                                                                                // const void*             pNext;
-                               *m_renderPass,                                                                  // VkRenderPass            renderPass;
-                               *m_framebuffer,                                                                 // VkFramebuffer           framebuffer;
-                               renderArea,                                                                             // VkRect2D                renderArea;
-                               1u,                                                                                             // uint32_t                clearValueCount;
-                               &clearValue,                                                                    // const VkClearValue*     pClearValues;
+                               VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                                                       // VkStructureType                                                              sType;
+                               DE_NULL,                                                                                                                        // const void*                                                                  pNext;
+                               *m_renderPass,                                                                                                          // VkRenderPass                                                                 renderPass;
+                               *m_framebuffer,                                                                                                         // VkFramebuffer                                                                framebuffer;
+                               renderArea,                                                                                                                     // VkRect2D                                                                             renderArea;
+                               1u,                                                                                                                                     // uint32_t                                                                             clearValueCount;
+                               &clearValue,                                                                                                            // const VkClearValue*                                                  pClearValues;
                        };
 
                        vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
@@ -685,7 +755,7 @@ DrawContext::DrawContext (Context&                                          context,
                vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
                vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &(**m_vertexBuffer), &zeroOffset);
 
-               vk.cmdDraw(*m_cmdBuffer, m_numVertices, 1u, 0u, 1u);
+               vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_drawCallData.vertices.size()), 1u, 0u, 1u);
                vk.cmdEndRenderPass(*m_cmdBuffer);
 
                // Barrier: draw -> copy from image
@@ -693,14 +763,15 @@ DrawContext::DrawContext (Context&                                                context,
                        const VkImageMemoryBarrier barrier = makeImageMemoryBarrier(
                                VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
-                               **m_colorImage, m_colorSubresourceRange);
+                               **m_colorImage, colorSubresourceRange);
 
                        vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
                                0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
                }
 
                {
-                       const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), m_imageExtent);
+                       const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),
+                                       makeExtent3D(m_drawState.renderSize.x(), m_drawState.renderSize.y(), 1u));
                        vk.cmdCopyImageToBuffer(*m_cmdBuffer, **m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_colorAttachmentBuffer, 1u, &copyRegion);
                }
 
@@ -718,7 +789,11 @@ DrawContext::DrawContext (Context&                                         context,
        }
 }
 
-void DrawContext::draw (void)
+VulkanDrawContext::~VulkanDrawContext (void)
+{
+}
+
+void VulkanDrawContext::draw (void)
 {
        const DeviceInterface&  vk                      = m_context.getDeviceInterface();
        const VkDevice                  device          = m_context.getDevice();
@@ -730,7 +805,7 @@ void DrawContext::draw (void)
        log << tcu::LogImageSet("attachments", "") << tcu::LogImage("color0", "", getColorPixels()) << tcu::TestLog::EndImageSet;
 }
 
-tcu::ConstPixelBufferAccess DrawContext::getColorPixels (void) const
+tcu::ConstPixelBufferAccess VulkanDrawContext::getColorPixels (void) const
 {
        const DeviceInterface&  vk                      = m_context.getDeviceInterface();
        const VkDevice                  device          = m_context.getDevice();
@@ -738,7 +813,7 @@ tcu::ConstPixelBufferAccess DrawContext::getColorPixels (void) const
        const Allocation& alloc = m_colorAttachmentBuffer->getAllocation();
        invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), VK_WHOLE_SIZE);
 
-       return tcu::ConstPixelBufferAccess(mapVkFormat(m_colorFormat), m_imageExtent.width, m_imageExtent.height, m_imageExtent.depth, alloc.getHostPtr());
+       return tcu::ConstPixelBufferAccess(mapVkFormat(m_drawState.colorFormat), m_drawState.renderSize.x(), m_drawState.renderSize.y(), 1u, alloc.getHostPtr());
 }
 } // drawutil
 } // vkt
index 9a74092..4cb00c2 100644 (file)
 #include "vkImageUtil.hpp"
 #include "vkPrograms.hpp"
 #include "vktTestCase.hpp"
+#include "vkTypeUtil.hpp"
+#include "rrRenderer.hpp"
 
 namespace vkt
 {
 namespace drawutil
 {
 
-enum Constants
-{
-       RENDER_SIZE                                                             = 16,
-       RENDER_SIZE_LARGE                                               = 128,
-       NUM_RENDER_PIXELS                                               = RENDER_SIZE * RENDER_SIZE,
-       NUM_PATCH_CONTROL_POINTS                                = 3,
-       MAX_NUM_SHADER_MODULES                                  = 5,
-       MAX_CLIP_DISTANCES                                              = 8,
-       MAX_CULL_DISTANCES                                              = 8,
-       MAX_COMBINED_CLIP_AND_CULL_DISTANCES    = 8,
-};
-
 struct Shader
 {
        vk::VkShaderStageFlagBits       stage;
@@ -61,39 +51,102 @@ struct Shader
        {
        }
 };
+
+struct DrawState
+{
+       const vk::VkPrimitiveTopology   topology;
+       const vk::VkFormat                              colorFormat;
+       const vk::VkFormat                              depthFormat;
+       tcu::UVec2                                              renderSize;
+       bool                                                    depthClampEnable;
+       bool                                                    blendEnable;
+       float                                                   lineWidth;
+       deUint32                                                numPatchControlPoints;
+
+       DrawState (const vk::VkPrimitiveTopology topology_, deUint32 renderWidth_, deUint32 renderHeight_);
+};
+
+struct DrawCallData
+{
+       const std::vector<tcu::Vec4>&   vertices;
+
+       DrawCallData            (const std::vector<tcu::Vec4>&  vertices_)
+               : vertices              (vertices_)
+       {
+       }
+};
+
 //! Sets up a graphics pipeline and enables simple draw calls to predefined attachments.
 //! Clip volume uses wc = 1.0, which gives clip coord ranges: x = [-1, 1], y = [-1, 1], z = [0, 1]
 //! Clip coords (-1,-1) map to viewport coords (0, 0).
 class DrawContext
 {
 public:
-                                                                       DrawContext             (Context&                                               context,
-                                                                                                        const std::vector<Shader>&             shaders,
-                                                                                                        const std::vector<tcu::Vec4>&  vertices,
-                                                                                                        const vk::VkPrimitiveTopology  primitiveTopology,
-                                                                                                        const deUint32                                 renderSize                      = static_cast<deUint32>(RENDER_SIZE),
-                                                                                                        const bool                                             depthClampEnable        = false,
-                                                                                                        const bool                                             blendEnable                     = false,
-                                                                                                        const float                                    lineWidth                       = 1.0f);
-
-       void                                                    draw                    (void);
-       tcu::ConstPixelBufferAccess             getColorPixels  (void) const;
+                                                                                       DrawContext                             (const DrawState&               drawState,
+                                                                                                                                        const DrawCallData&    drawCallData)
+               : m_drawState                                           (drawState)
+               , m_drawCallData                                        (drawCallData)
+       {
+       }
+       virtual                                                                 ~DrawContext                    (void)
+       {
+       }
+
+       virtual void                                                    draw                                    (void) = 0;
+       virtual tcu::ConstPixelBufferAccess             getColorPixels                  (void) const = 0;
+protected:
+               const DrawState                                         m_drawState;
+               const DrawCallData                                      m_drawCallData;
+};
+
+class ReferenceDrawContext : public DrawContext
+{
+public:
+                                                                                       ReferenceDrawContext    (const DrawState&                       drawState,
+                                                                                                                                        const DrawCallData&            drawCallData,
+                                                                                                                                        const rr::VertexShader&        vertexShader,
+                                                                                                                                        const rr::FragmentShader&      fragmentShader)
+               : DrawContext                                           (drawState, drawCallData)
+               , m_vertexShader                                        (vertexShader)
+               , m_fragmentShader                                      (fragmentShader)
+       {
+       }
+       virtual                                                                 ~ReferenceDrawContext   (void);
+       virtual void                                                    draw                                    (void);
+       virtual tcu::ConstPixelBufferAccess             getColorPixels                  (void) const;
+private:
+       const rr::VertexShader&                                 m_vertexShader;
+       const rr::FragmentShader&                               m_fragmentShader;
+       tcu::TextureLevel                                               m_refImage;
+};
+
+struct VulkanProgram
+{
+       const std::vector<Shader>&                              shaders;
+
+       VulkanProgram           (const std::vector<Shader>&                     shaders_)
+               : shaders               (shaders_)
+       {
+       }
+};
 
+class VulkanDrawContext : public DrawContext
+{
+public:
+                                                                                       VulkanDrawContext       (Context&                               context,
+                                                                                                                                const DrawState&               drawState,
+                                                                                                                                const DrawCallData&    drawCallData,
+                                                                                                                                const VulkanProgram&   vulkanProgram);
+       virtual                                                                 ~VulkanDrawContext      (void);
+       virtual void                                                    draw                            (void);
+       virtual tcu::ConstPixelBufferAccess             getColorPixels          (void) const;
 private:
+       enum Contants
+       {
+               MAX_NUM_SHADER_MODULES                                  = 5,
+       };
        Context&                                                                        m_context;
-       const vk::VkFormat                                                      m_colorFormat;
-       const vk::VkFormat                                                      m_depthFormat;
-       const vk::VkImageSubresourceRange                       m_colorSubresourceRange;
-       const vk::VkImageSubresourceRange                       m_depthSubresourceRange;
-       const tcu::UVec2                                                        m_renderSize;
-       const vk::VkExtent3D                                            m_imageExtent;
-       const vk::VkPrimitiveTopology                           m_primitiveTopology;
-       const bool                                                                      m_depthClampEnable;
-       const bool                                                                      m_blendEnable;
-       const deUint32                                                          m_numVertices;
-       const float                                                                     m_lineWidth;
-       const deUint32                                                          m_numPatchControlPoints;
-       de::MovePtr<vk::BufferWithMemory>                       m_vertexBuffer;
+       VulkanProgram                                                           m_program;
        de::MovePtr<vk::ImageWithMemory>                        m_colorImage;
        de::MovePtr<vk::ImageWithMemory>                        m_depthImage;
        de::MovePtr<vk::BufferWithMemory>                       m_colorAttachmentBuffer;
@@ -106,10 +159,9 @@ private:
        vk::refdetails::Move<vk::VkCommandPool>         m_cmdPool;
        vk::refdetails::Move<vk::VkCommandBuffer>       m_cmdBuffer;
        vk::refdetails::Move<vk::VkShaderModule>        m_shaderModules[MAX_NUM_SHADER_MODULES];
-
-                                                                       DrawContext             (const DrawContext&);   // "deleted"
-       DrawContext&                                    operator=               (const DrawContext&);   // "deleted"
+       de::MovePtr<vk::BufferWithMemory>                       m_vertexBuffer;
 };
+
 std::string getPrimitiveTopologyShortName (const vk::VkPrimitiveTopology topology);
 
 } // drwwutil
index df5b412..247a195 100644 (file)
@@ -446,12 +446,13 @@ bool doesLineSegmentExitDiamond (const SubpixelLineSegment& line, const tcu::Vec
 } // LineRasterUtil
 
 TriangleRasterizer::TriangleRasterizer (const tcu::IVec4& viewport, const int numSamples, const RasterizationState& state)
-       : m_viewport            (viewport)
-       , m_numSamples          (numSamples)
-       , m_winding                     (state.winding)
-       , m_horizontalFill      (state.horizontalFill)
-       , m_verticalFill        (state.verticalFill)
-       , m_face                        (FACETYPE_LAST)
+       : m_viewport                            (viewport)
+       , m_numSamples                          (numSamples)
+       , m_winding                                     (state.winding)
+       , m_horizontalFill                      (state.horizontalFill)
+       , m_verticalFill                        (state.verticalFill)
+       , m_face                                        (FACETYPE_LAST)
+       , m_viewportOrientation         (state.viewportOrientation)
 {
 }
 
@@ -493,7 +494,11 @@ void TriangleRasterizer::init (const tcu::Vec4& v0, const tcu::Vec4& v1, const t
        // Determine face.
        const deInt64   s                               = evaluateEdge(m_edge01, x2, y2);
        const bool              positiveArea    = (m_winding == WINDING_CCW) ? (s > 0) : (s < 0);
-       m_face = positiveArea ? FACETYPE_FRONT : FACETYPE_BACK;
+
+       if (m_viewportOrientation == VIEWPORTORIENTATION_UPPER_LEFT)
+               m_face = positiveArea ? FACETYPE_BACK : FACETYPE_FRONT;
+       else
+               m_face = positiveArea ? FACETYPE_FRONT : FACETYPE_BACK;
 
        if (!positiveArea)
        {
index dee7c15..bfb2624 100644 (file)
@@ -155,10 +155,11 @@ private:
        EdgeFunction                    m_edge01;
        EdgeFunction                    m_edge12;
        EdgeFunction                    m_edge20;
-       FaceType                                m_face;                 //!< Triangle orientation, eg. visible face.
-       tcu::IVec2                              m_bboxMin;              //!< Bounding box min (inclusive).
-       tcu::IVec2                              m_bboxMax;              //!< Bounding box max (inclusive).
-       tcu::IVec2                              m_curPos;               //!< Current rasterization position.
+       FaceType                                m_face;                                 //!< Triangle orientation, eg. visible face.
+       tcu::IVec2                              m_bboxMin;                              //!< Bounding box min (inclusive).
+       tcu::IVec2                              m_bboxMax;                              //!< Bounding box max (inclusive).
+       tcu::IVec2                              m_curPos;                               //!< Current rasterization position.
+       ViewportOrientation             m_viewportOrientation;  //!< Direction of +x+y axis
 } DE_WARN_UNUSED_TYPE;
 
 
index 671d4da..315225e 100644 (file)
@@ -63,18 +63,29 @@ enum CullMode
        CULLMODE_LAST
 };
 
+//! Viewport Orientation of renderer this will be compared against
+enum ViewportOrientation
+{
+       VIEWPORTORIENTATION_LOWER_LEFT = 0,     //<! Corresponds to GL
+       VIEWPORTORIENTATION_UPPER_LEFT,         //<! Corresponds to Vulkan
+
+       VIEWPORTORIENTATION_LAST
+};
+
 struct RasterizationState
 {
        RasterizationState (void)
-               : winding                       (WINDING_CCW)
-               , horizontalFill        (FILL_LEFT)
-               , verticalFill          (FILL_BOTTOM)
+               : winding                               (WINDING_CCW)
+               , horizontalFill                (FILL_LEFT)
+               , verticalFill                  (FILL_BOTTOM)
+               , viewportOrientation   (VIEWPORTORIENTATION_LAST)
        {
        }
 
-       Winding                 winding;
-       HorizontalFill  horizontalFill;
-       VerticalFill    verticalFill;
+       Winding                                 winding;
+       HorizontalFill                  horizontalFill;
+       VerticalFill                    verticalFill;
+       ViewportOrientation             viewportOrientation;
 };
 
 enum TestFunc
@@ -348,11 +359,13 @@ struct RestartState
 
 struct RenderState
 {
-       explicit RenderState (const ViewportState& viewport_)
+       explicit RenderState (const ViewportState& viewport_, ViewportOrientation viewportOrientation_ = VIEWPORTORIENTATION_LOWER_LEFT)
                : cullMode                                      (CULLMODE_NONE)
                , provokingVertexConvention     (PROVOKINGVERTEX_LAST)
                , viewport                                      (viewport_)
+               , viewportOrientation           (viewportOrientation_)
        {
+               rasterization.viewportOrientation = viewportOrientation;
        }
 
        CullMode                                        cullMode;
@@ -363,6 +376,7 @@ struct RenderState
        ViewportState                           viewport;
        LineState                                       line;
        RestartState                            restart;
+       ViewportOrientation                     viewportOrientation;
 };
 
 } // rr
index fc5e075..5dd13be 100644 (file)
@@ -1117,7 +1117,7 @@ void rasterizePrimitive (const RenderState&                                       state,
                return;
 
        // Shading context
-       FragmentShadingContext shadingContext(triangle.v0->outputs, triangle.v1->outputs, triangle.v2->outputs, &buffers.shaderOutputs[0], buffers.fragmentDepthBuffer, triangle.v2->primitiveID, (int)program.fragmentShader->getOutputs().size(), numSamples);
+       FragmentShadingContext shadingContext(triangle.v0->outputs, triangle.v1->outputs, triangle.v2->outputs, &buffers.shaderOutputs[0], buffers.fragmentDepthBuffer, triangle.v2->primitiveID, (int)program.fragmentShader->getOutputs().size(), numSamples, rasterizer.getVisibleFace());
 
        // Polygon offset
        if (buffers.fragmentDepthBuffer && state.fragOps.polygonOffsetEnabled)
@@ -1174,7 +1174,7 @@ void rasterizePrimitive (const RenderState&                                       state,
        const float                                     depthClampMin           = de::min(state.viewport.zn, state.viewport.zf);
        const float                                     depthClampMax           = de::max(state.viewport.zn, state.viewport.zf);
        const bool                                      msaa                            = numSamples > 1;
-       FragmentShadingContext          shadingContext          (line.v0->outputs, line.v1->outputs, DE_NULL, &buffers.shaderOutputs[0], buffers.fragmentDepthBuffer, line.v1->primitiveID, (int)program.fragmentShader->getOutputs().size(), numSamples);
+       FragmentShadingContext          shadingContext          (line.v0->outputs, line.v1->outputs, DE_NULL, &buffers.shaderOutputs[0], buffers.fragmentDepthBuffer, line.v1->primitiveID, (int)program.fragmentShader->getOutputs().size(), numSamples, FACETYPE_FRONT);
        SingleSampleLineRasterizer      aliasedRasterizer       (renderTargetRect);
        MultiSampleLineRasterizer       msaaRasterizer          (numSamples, renderTargetRect);
 
@@ -1240,7 +1240,7 @@ void rasterizePrimitive (const RenderState&                                       state,
        rasterizer2.init(w0, w2, w3);
 
        // Shading context
-       FragmentShadingContext shadingContext(point.v0->outputs, DE_NULL, DE_NULL, &buffers.shaderOutputs[0], buffers.fragmentDepthBuffer, point.v0->primitiveID, (int)program.fragmentShader->getOutputs().size(), numSamples);
+       FragmentShadingContext shadingContext(point.v0->outputs, DE_NULL, DE_NULL, &buffers.shaderOutputs[0], buffers.fragmentDepthBuffer, point.v0->primitiveID, (int)program.fragmentShader->getOutputs().size(), numSamples, FACETYPE_FRONT);
 
        // Execute rasterize - shade - write loop
        for (;;)
index 3262739..261970a 100644 (file)
 namespace rr
 {
 
-FragmentShadingContext::FragmentShadingContext (const GenericVec4* varying0, const GenericVec4* varying1, const GenericVec4* varying2, GenericVec4* outputArray_, float* fragmentDepths_, int primitiveID_, int numFragmentOutputs_, int numSamples_)
+FragmentShadingContext::FragmentShadingContext (const GenericVec4* varying0, const GenericVec4* varying1, const GenericVec4* varying2, GenericVec4* outputArray_, float* fragmentDepths_, int primitiveID_, int numFragmentOutputs_, int numSamples_, FaceType visibleFace_)
        : outputArray                   (outputArray_)
        , primitiveID                   (primitiveID_)
        , numFragmentOutputs    (numFragmentOutputs_)
        , numSamples                    (numSamples_)
        , fragmentDepths                (fragmentDepths_)
+       , visibleFace                   (visibleFace_)
 {
        varyings[0] = varying0;
        varyings[1] = varying1;
index 635d396..b506dd1 100644 (file)
@@ -37,7 +37,7 @@ namespace rr
  *//*--------------------------------------------------------------------*/
 struct FragmentShadingContext
 {
-                                                               FragmentShadingContext (const GenericVec4* varying0, const GenericVec4* varying1, const GenericVec4* varying2, GenericVec4* outputArray, float* fragmentDepths, int primitiveID, int numFragmentOutputs, int numSamples);
+                                                               FragmentShadingContext (const GenericVec4* varying0, const GenericVec4* varying1, const GenericVec4* varying2, GenericVec4* outputArray, float* fragmentDepths, int primitiveID, int numFragmentOutputs, int numSamples, FaceType visibleFace_);
 
        const GenericVec4*                      varyings[3];            //!< Vertex shader outputs. Pointer will be NULL if there is no such vertex.
        GenericVec4* const                      outputArray;            //!< Fragment output array
@@ -45,6 +45,7 @@ struct FragmentShadingContext
        const int                                       numFragmentOutputs;     //!< Fragment output count
        const int                                       numSamples;                     //!< Number of samples
        float*                                          fragmentDepths;         //!< Fragment packet depths. Pointer will be NULL if there is no depth buffer. Each sample has per-sample depth values
+       FaceType                                        visibleFace;            //!< Which face (front or back) is visible
 };
 
 // Write output