Add vertex uniform buffers to pipeline barrier tests.
authorMika Isojärvi <misojarvi@google.com>
Thu, 30 Jun 2016 00:33:37 +0000 (17:33 -0700)
committerMika Isojärvi <misojarvi@google.com>
Wed, 3 Aug 2016 16:48:18 +0000 (09:48 -0700)
Change-Id: Iaf1b5b5d033c5076afffe84574bb462f58d92bc4

external/vulkancts/modules/vulkan/memory/vktMemoryPipelineBarrierTests.cpp

index c2e6d60..754f68c 100644 (file)
@@ -78,6 +78,18 @@ namespace memory
 {
 namespace
 {
+// \todo [mika] Add to utilities
+template<typename T>
+T divRoundUp (const T& a, const T& b)
+{
+       return (a / b) + (a % b == 0 ? 0 : 1);
+}
+
+enum
+{
+       MAX_UNIFORM_BUFFER_SIZE = 1024
+};
+
 enum
 {
        ALL_PIPELINE_STAGES = vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
@@ -4624,8 +4636,9 @@ void SubmitRenderPass::verify (VerifyContext& context, size_t commandIndex)
 
 struct PipelineResources
 {
-       vk::Move<vk::VkPipeline>                pipeline;
-       vk::Move<vk::VkPipelineLayout>  pipelineLayout;
+       vk::Move<vk::VkPipeline>                        pipeline;
+       vk::Move<vk::VkDescriptorSetLayout>     descriptorSetLayout;
+       vk::Move<vk::VkPipelineLayout>          pipelineLayout;
 };
 
 void createPipelineWithResources (const vk::DeviceInterface&                                                   vkd,
@@ -4638,16 +4651,35 @@ void createPipelineWithResources (const vk::DeviceInterface&                                                    vkd,
                                                                  const deUint32                                                                                viewPortHeight,
                                                                  const vector<vk::VkVertexInputBindingDescription>&    vertexBindingDescriptions,
                                                                  const vector<vk::VkVertexInputAttributeDescription>&  vertexAttributeDescriptions,
+                                                                 const vector<vk::VkDescriptorSetLayoutBinding>&               bindings,
                                                                  PipelineResources&                                                                    resources)
 {
+       if (!bindings.empty())
        {
-               const vk::VkPipelineLayoutCreateInfo    createInfo      =
+               const vk::VkDescriptorSetLayoutCreateInfo createInfo =
+               {
+                       vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+                       DE_NULL,
+
+                       0u,
+                       (deUint32)bindings.size(),
+                       bindings.empty() ? DE_NULL : &bindings[0]
+               };
+
+               resources.descriptorSetLayout = vk::createDescriptorSetLayout(vkd, device, &createInfo);
+       }
+
+       {
+               const vk::VkDescriptorSetLayout                 descriptorSetLayout_    = *resources.descriptorSetLayout;
+               const vk::VkPipelineLayoutCreateInfo    createInfo                              =
                {
                        vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
                        DE_NULL,
                        0,
-                       0,
-                       DE_NULL,
+
+                       resources.descriptorSetLayout ? 1u : 0u,
+                       resources.descriptorSetLayout ? &descriptorSetLayout_ : DE_NULL,
+
                        0,
                        DE_NULL
                };
@@ -4872,7 +4904,7 @@ void RenderIndexBuffer::prepare (PrepareRenderPassContext& context)
        const vk::Unique<vk::VkShaderModule>    fragmentShaderModule    (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-white.frag"), 0));
 
        createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
-                                                               vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), m_resources);
+                                                               vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), vector<vk::VkDescriptorSetLayoutBinding>(), m_resources);
        m_bufferSize = context.getBufferSize();
 }
 
@@ -4959,7 +4991,7 @@ void RenderVertexBuffer::prepare (PrepareRenderPassContext& context)
                vertexAttributeDescriptions.push_back(vertexAttributeDescription);
        }
        createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
-                                                               vertexBindingDescriptions, vertexAttributeDescriptions, m_resources);
+                                                               vertexBindingDescriptions, vertexAttributeDescriptions, vector<vk::VkDescriptorSetLayoutBinding>(), m_resources);
 
        m_bufferSize = context.getBufferSize();
 }
@@ -4987,6 +5019,173 @@ void RenderVertexBuffer::verify (VerifyRenderPassContext& context, size_t)
        }
 }
 
+class RenderVertexUniformBuffer : public RenderPassCommand
+{
+public:
+                                                                       RenderVertexUniformBuffer       (void) {}
+                                                                       ~RenderVertexUniformBuffer      (void);
+
+       const char*                                             getName                                         (void) const { return "RenderVertexUniformBuffer"; }
+       void                                                    logPrepare                                      (TestLog&, size_t) const;
+       void                                                    logSubmit                                       (TestLog&, size_t) const;
+       void                                                    prepare                                         (PrepareRenderPassContext&);
+       void                                                    submit                                          (SubmitContext& context);
+       void                                                    verify                                          (VerifyRenderPassContext&, size_t);
+
+private:
+       PipelineResources                               m_resources;
+       vk::Move<vk::VkDescriptorPool>  m_descriptorPool;
+       vector<vk::VkDescriptorSet>             m_descriptorSets;
+
+       vk::VkDeviceSize                                m_bufferSize;
+};
+
+RenderVertexUniformBuffer::~RenderVertexUniformBuffer (void)
+{
+}
+
+void RenderVertexUniformBuffer::logPrepare (TestLog& log, size_t commandIndex) const
+{
+       log << TestLog::Message << commandIndex << ":" << getName() << " Create pipeline for render buffer as uniform buffer." << TestLog::EndMessage;
+}
+
+void RenderVertexUniformBuffer::logSubmit (TestLog& log, size_t commandIndex) const
+{
+       log << TestLog::Message << commandIndex << ":" << getName() << " Render using buffer as uniform buffer." << TestLog::EndMessage;
+}
+
+void RenderVertexUniformBuffer::prepare (PrepareRenderPassContext& context)
+{
+       const vk::DeviceInterface&                                      vkd                                             = context.getContext().getDeviceInterface();
+       const vk::VkDevice                                                      device                                  = context.getContext().getDevice();
+       const vk::VkRenderPass                                          renderPass                              = context.getRenderPass();
+       const deUint32                                                          subpass                                 = 0;
+       const vk::Unique<vk::VkShaderModule>            vertexShaderModule              (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("uniform-buffer.vert"), 0));
+       const vk::Unique<vk::VkShaderModule>            fragmentShaderModule    (vk::createShaderModule(vkd, device, context.getBinaryCollection().get("render-white.frag"), 0));
+       vector<vk::VkDescriptorSetLayoutBinding>        bindings;
+
+       m_bufferSize = context.getBufferSize();
+
+       {
+               const vk::VkDescriptorSetLayoutBinding binding =
+               {
+                       0u,
+                       vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+                       1,
+                       vk::VK_SHADER_STAGE_VERTEX_BIT,
+                       DE_NULL
+               };
+
+               bindings.push_back(binding);
+       }
+
+       createPipelineWithResources(vkd, device, renderPass, subpass, *vertexShaderModule, *fragmentShaderModule, context.getTargetWidth(), context.getTargetHeight(),
+                                                               vector<vk::VkVertexInputBindingDescription>(), vector<vk::VkVertexInputAttributeDescription>(), bindings, m_resources);
+
+       {
+               const deUint32                                                  descriptorCount = (deUint32)(divRoundUp(m_bufferSize, (vk::VkDeviceSize)MAX_UNIFORM_BUFFER_SIZE));
+               const vk::VkDescriptorPoolSize                  poolSizes               =
+               {
+                       vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+                       descriptorCount
+               };
+               const vk::VkDescriptorPoolCreateInfo    createInfo              =
+               {
+                       vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+                       DE_NULL,
+                       vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
+
+                       descriptorCount,
+                       1u,
+                       &poolSizes,
+               };
+
+               m_descriptorPool = vk::createDescriptorPool(vkd, device, &createInfo);
+               m_descriptorSets.resize(descriptorCount);
+       }
+
+       for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
+       {
+               const vk::VkDescriptorSetLayout                 layout                  = *m_resources.descriptorSetLayout;
+               const vk::VkDescriptorSetAllocateInfo   allocateInfo    =
+               {
+                       vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+                       DE_NULL,
+
+                       *m_descriptorPool,
+                       1,
+                       &layout
+               };
+
+               m_descriptorSets[descriptorSetNdx] = vk::allocateDescriptorSet(vkd, device, &allocateInfo).disown();
+
+               {
+                       const vk::VkDescriptorBufferInfo                bufferInfo      =
+                       {
+                               context.getBuffer(),
+                               descriptorSetNdx * MAX_UNIFORM_BUFFER_SIZE,
+                               m_bufferSize < (descriptorSetNdx + 1) * (vk::VkDeviceSize)MAX_UNIFORM_BUFFER_SIZE
+                                       ? m_bufferSize - descriptorSetNdx * (vk::VkDeviceSize)MAX_UNIFORM_BUFFER_SIZE
+                                       : MAX_UNIFORM_BUFFER_SIZE
+                       };
+                       const vk::VkWriteDescriptorSet                  write           =
+                       {
+                               vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+                               DE_NULL,
+                               m_descriptorSets[descriptorSetNdx],
+                               0u,
+                               0u,
+                               1u,
+                               vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+                               DE_NULL,
+                               &bufferInfo,
+                               DE_NULL,
+                       };
+
+                       vkd.updateDescriptorSets(device, 1u, &write, 0u, DE_NULL);
+               }
+       }
+}
+
+void RenderVertexUniformBuffer::submit (SubmitContext& context)
+{
+       const vk::DeviceInterface&      vkd                             = context.getContext().getDeviceInterface();
+       const vk::VkCommandBuffer       commandBuffer   = context.getCommandBuffer();
+
+       vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipeline);
+
+       for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
+       {
+               const size_t    size    = (size_t)(m_bufferSize < (descriptorSetNdx + 1) * (vk::VkDeviceSize)MAX_UNIFORM_BUFFER_SIZE
+                                                               ? m_bufferSize - descriptorSetNdx * (vk::VkDeviceSize)MAX_UNIFORM_BUFFER_SIZE
+                                                               : MAX_UNIFORM_BUFFER_SIZE);
+               const deUint32  count   = (deUint32)(size / 2);
+
+               vkd.cmdBindDescriptorSets(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_resources.pipelineLayout, 0u, 1u, &m_descriptorSets[descriptorSetNdx], 0u, DE_NULL);
+               vkd.cmdDraw(commandBuffer, count, 1, 0, 0);
+       }
+}
+
+void RenderVertexUniformBuffer::verify (VerifyRenderPassContext& context, size_t)
+{
+       for (size_t descriptorSetNdx = 0; descriptorSetNdx < m_descriptorSets.size(); descriptorSetNdx++)
+       {
+               const size_t    offset  = descriptorSetNdx * MAX_UNIFORM_BUFFER_SIZE;
+               const size_t    size    = (size_t)(m_bufferSize < (descriptorSetNdx + 1) * (vk::VkDeviceSize)MAX_UNIFORM_BUFFER_SIZE
+                                                               ? m_bufferSize - descriptorSetNdx * (vk::VkDeviceSize)MAX_UNIFORM_BUFFER_SIZE
+                                                               : MAX_UNIFORM_BUFFER_SIZE);
+               const size_t    count   = size / 2;
+
+               for (size_t pos = 0; pos < count; pos++)
+               {
+                       const deUint8 x  = context.getReference().get(offset + pos * 2);
+                       const deUint8 y  = context.getReference().get(offset + (pos * 2) + 1);
+
+                       context.getReferenceTarget().getAccess().setPixel(Vec4(1.0f, 1.0f, 1.0f, 1.0f), x, y);
+               }
+       }
+}
+
 enum Op
 {
        OP_MAP,
@@ -5046,7 +5245,8 @@ enum Op
 
        // Commands inside render pass
        OP_RENDER_VERTEX_BUFFER,
-       OP_RENDER_INDEX_BUFFER
+       OP_RENDER_INDEX_BUFFER,
+       OP_RENDER_VERTEX_UNIFORM_BUFFER
 };
 
 enum Stage
@@ -5741,7 +5941,8 @@ void getAvailableOps (const State& state, bool supportsBuffers, bool supportsIma
 
                // \todo [2016-03-09 mika] Add other usages?
                if (((usage & USAGE_VERTEX_BUFFER) && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT))
-                       || ((usage & USAGE_INDEX_BUFFER) && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT)))
+                       || ((usage & USAGE_INDEX_BUFFER) && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT))
+                       || ((usage & USAGE_UNIFORM_BUFFER) && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT)))
                        ops.push_back(OP_RENDERPASS_BEGIN);
 
                // \note This depends on previous operations and has to be always the
@@ -5767,6 +5968,14 @@ void getAvailableOps (const State& state, bool supportsBuffers, bool supportsIma
                        ops.push_back(OP_RENDER_INDEX_BUFFER);
                }
 
+               if (usage & USAGE_UNIFORM_BUFFER
+                       && state.memoryDefined
+                       && state.hasBoundBufferMemory
+                       && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT))
+               {
+                       ops.push_back(OP_RENDER_VERTEX_UNIFORM_BUFFER);
+               }
+
                ops.push_back(OP_RENDERPASS_END);
        }
        else
@@ -6158,6 +6367,14 @@ void applyOp (State& state, const Memory& memory, Op op, Usage usage)
                        break;
                }
 
+               case OP_RENDER_VERTEX_UNIFORM_BUFFER:
+               {
+                       DE_ASSERT(state.stage == STAGE_RENDER_PASS);
+
+                       state.cache.perform(vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, vk::VK_ACCESS_UNIFORM_READ_BIT);
+                       break;
+               }
+
                default:
                        DE_FATAL("Unknown op");
        }
@@ -6327,8 +6544,9 @@ de::MovePtr<RenderPassCommand> createRenderPassCommand (de::Random&,
 {
        switch (op)
        {
-               case OP_RENDER_VERTEX_BUFFER:   return de::MovePtr<RenderPassCommand>(new RenderVertexBuffer());
-               case OP_RENDER_INDEX_BUFFER:    return de::MovePtr<RenderPassCommand>(new RenderIndexBuffer());
+               case OP_RENDER_VERTEX_BUFFER:                   return de::MovePtr<RenderPassCommand>(new RenderVertexBuffer());
+               case OP_RENDER_INDEX_BUFFER:                    return de::MovePtr<RenderPassCommand>(new RenderIndexBuffer());
+               case OP_RENDER_VERTEX_UNIFORM_BUFFER:   return de::MovePtr<RenderPassCommand>(new RenderVertexUniformBuffer());
 
                default:
                        DE_FATAL("Unknown op");
@@ -6803,6 +7021,42 @@ struct AddPrograms
                                << glu::VertexSource(vertexShader);
                }
 
+               // Vertex uniform buffer rendering
+               if (config.usage & USAGE_UNIFORM_BUFFER)
+               {
+                       std::ostringstream vertexShader;
+
+                       vertexShader <<
+                               "#version 310 es\n"
+                               "highp float;\n"
+                               "layout(set=0, binding=0) uniform Block\n"
+                               "{\n"
+                               "\thighp uvec4 values[" << de::toString<size_t>(MAX_UNIFORM_BUFFER_SIZE / (sizeof(deUint32) * 4)) << "];\n"
+                               "} block;\n"
+                               "void main (void) {\n"
+                               "\tgl_PointSize = 1.0;\n"
+                               "\thighp uvec4 vecVal = block.values[gl_VertexIndex / 8];\n"
+                               "\thighp uint val;\n"
+                               "\tif (((gl_VertexIndex / 2) % 4 == 0))\n"
+                               "\t\tval = vecVal.x;\n"
+                               "\telse if (((gl_VertexIndex / 2) % 4 == 1))\n"
+                               "\t\tval = vecVal.y;\n"
+                               "\telse if (((gl_VertexIndex / 2) % 4 == 2))\n"
+                               "\t\tval = vecVal.z;\n"
+                               "\telse if (((gl_VertexIndex / 2) % 4 == 3))\n"
+                               "\t\tval = vecVal.w;\n"
+                               "\tif ((gl_VertexIndex % 2) == 0)\n"
+                               "\t\tval = val & 0xFFFFu;\n"
+                               "\telse\n"
+                               "\t\tval = val >> 16u;\n"
+                               "\thighp vec2 pos = vec2(val & 0xFFu, val >> 8u) / vec2(255.0);\n"
+                               "\tgl_Position = vec4(1.998 * pos - vec2(0.999), 0.0, 1.0);\n"
+                               "}\n";
+
+                       sources.glslSources.add("uniform-buffer.vert")
+                               << glu::VertexSource(vertexShader.str());
+               }
+
                {
                        const char* const fragmentShader =
                                "#version 310 es\n"
@@ -6836,14 +7090,16 @@ tcu::TestCaseGroup* createPipelineBarrierTests (tcu::TestContext& testCtx)
                USAGE_TRANSFER_SRC,
                USAGE_TRANSFER_DST,
                USAGE_VERTEX_BUFFER,
-               USAGE_INDEX_BUFFER
+               USAGE_INDEX_BUFFER,
+               USAGE_UNIFORM_BUFFER
        };
        const Usage                                             readUsages[]            =
        {
                USAGE_HOST_READ,
                USAGE_TRANSFER_SRC,
                USAGE_VERTEX_BUFFER,
-               USAGE_INDEX_BUFFER
+               USAGE_INDEX_BUFFER,
+               USAGE_UNIFORM_BUFFER
        };
 
        const Usage                                             writeUsages[]   =