From 70913fdda5c73adcd76ba3547a1fb5907aebde91 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 21 Feb 2020 17:27:48 +0000 Subject: [PATCH] Add test that GL multi-draw mesh output works with builtins --- util/test/demos/gl/gl_mesh_zoo.cpp | 79 +++++++++++++++++++++++++++++- util/test/tests/GL/GL_Mesh_Zoo.py | 54 +++++++++++++++++++- 2 files changed, 131 insertions(+), 2 deletions(-) diff --git a/util/test/demos/gl/gl_mesh_zoo.cpp b/util/test/demos/gl/gl_mesh_zoo.cpp index ab053b889..1d53826ae 100644 --- a/util/test/demos/gl/gl_mesh_zoo.cpp +++ b/util/test/demos/gl/gl_mesh_zoo.cpp @@ -30,7 +30,7 @@ RD_TEST(GL_Mesh_Zoo, OpenGLGraphicsTest) std::string common = R"EOSHADER( -#version 420 core +#version 450 core )EOSHADER"; @@ -62,6 +62,33 @@ void main() gl_Position = pos; } +)EOSHADER"; + + std::string multivertex = R"EOSHADER( +#version 460 core + +out vec4 col; +flat out uint basevtx; +flat out uint baseinst; +flat out uint draw; +flat out uint inst; +flat out uint vert; + +void main() +{ + const vec4 verts[3] = vec4[3](vec4(-0.5, 0.5, 0.0, 1.0), vec4(0.0, -0.5, 0.0, 1.0), + vec4(0.5, 0.5, 0.0, 1.0)); + + gl_Position = verts[gl_VertexID%3]; + col = vec4(1, 1, 0, 1); + + basevtx = gl_BaseVertex; + baseinst = gl_BaseInstance; + draw = gl_DrawID; + inst = gl_InstanceID; + vert = gl_VertexID; +} + )EOSHADER"; std::string pixel = R"EOSHADER( @@ -113,6 +140,8 @@ void main() int main() { + glMinor = 6; + // initialise, create window, create context, etc if(!Init()) return 3; @@ -188,6 +217,8 @@ void main() GLuint geomprogram = MakeProgram(nopvertex, common + pixel, geometry); + GLuint multiprogram = MakeProgram(multivertex, common + pixel); + GLuint fbo = MakeFBO(); glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -208,6 +239,29 @@ void main() glDisable(GL_DEPTH_CLAMP); glDisable(GL_STENCIL_TEST); + struct DrawElementsIndirectCommand + { + uint32_t count; + uint32_t instanceCount; + uint32_t firstIndex; + int32_t baseVertex; + uint32_t baseInstance; + }; + + GLuint cmdBuf = MakeBuffer(); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, cmdBuf); + glBufferStorage(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawElementsIndirectCommand) * 4, NULL, + GL_DYNAMIC_STORAGE_BIT); + + GLuint countBuf = MakeBuffer(); + glBindBuffer(GL_PARAMETER_BUFFER, countBuf); + glBufferStorage(GL_PARAMETER_BUFFER, sizeof(uint32_t), NULL, GL_DYNAMIC_STORAGE_BIT); + + uint32_t indices[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + GLuint idxBuf = MakeBuffer(); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, idxBuf); + glBufferStorage(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, 0); + while(Running()) { glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -243,6 +297,29 @@ void main() glDrawArrays(GL_POINTS, 0, 1); + setMarker("Multi Draw"); + + glUseProgram(multiprogram); + + DrawElementsIndirectCommand cmd = {}; + cmd.count = 3; + cmd.instanceCount = 2; + cmd.baseVertex = 10; + cmd.baseInstance = 20; + + uint32_t count = 2; + glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(cmd), &cmd); + + cmd.instanceCount = 4; + cmd.baseVertex = 11; + cmd.baseInstance = 22; + + glBufferSubData(GL_DRAW_INDIRECT_BUFFER, sizeof(cmd), sizeof(cmd), &cmd); + glBufferSubData(GL_PARAMETER_BUFFER, 0, sizeof(count), &count); + + glMultiDrawElementsIndirectCount(GL_TRIANGLES, GL_UNSIGNED_INT, NULL, NULL, 4, + sizeof(DrawElementsIndirectCommand)); + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, diff --git a/util/test/tests/GL/GL_Mesh_Zoo.py b/util/test/tests/GL/GL_Mesh_Zoo.py index e718ec500..f391ae1b5 100644 --- a/util/test/tests/GL/GL_Mesh_Zoo.py +++ b/util/test/tests/GL/GL_Mesh_Zoo.py @@ -39,4 +39,56 @@ class GL_Mesh_Zoo(rdtest.TestCase): self.check_mesh_data(gsout_ref, self.get_postvs(rd.MeshDataStage.GSOut)) - rdtest.log.success("Geometry-only pass is as expected") + # Test GL-only thing with geometry shader only and completely no-op vertex shader + multibase = self.zoo_helper.find_draw("Multi Draw").next.parent + self.controller.SetFrameEvent(multibase.children[-1].eventId, False) + + baseVertex = [10, 11] + baseInstance = [20, 22] + + for d, draw in enumerate(multibase.children): + draw: rd.DrawcallDescription + + self.controller.SetFrameEvent(draw.eventId, False) + + pipe: rd.PipeState = self.controller.GetPipelineState() + + shad: rd.ShaderReflection = pipe.GetShaderReflection(rd.ShaderStage.Vertex) + + builtins = [sig.systemValue for sig in shad.inputSignature if sig.systemValue != rd.ShaderBuiltin.Undefined] + + self.check(rd.ShaderBuiltin.BaseInstance in builtins) + self.check(rd.ShaderBuiltin.BaseVertex in builtins) + self.check(rd.ShaderBuiltin.DrawIndex in builtins) + + bv = baseVertex[d] + bi = baseInstance[d] + + for inst in range(draw.numInstances): + multi_ref = { + 0: { + 'basevtx': bv, + 'baseinst': bi, + 'inst': inst, + 'draw': d, + 'vert': bv + 0, + }, + 1: { + 'basevtx': bv, + 'baseinst': bi, + 'inst': inst, + 'draw': d, + 'vert': bv + 1, + }, + 2: { + 'basevtx': bv, + 'baseinst': bi, + 'inst': inst, + 'draw': d, + 'vert': bv + 2, + }, + } + + self.check_mesh_data(multi_ref, self.get_postvs(rd.MeshDataStage.VSOut, instance=inst)) + + rdtest.log.success("Multi-draw pass is as expected")