summaryrefslogtreecommitdiffstats
path: root/tests/manual/rhi/tessellation
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manual/rhi/tessellation')
-rw-r--r--tests/manual/rhi/tessellation/CMakeLists.txt25
-rw-r--r--tests/manual/rhi/tessellation/buildshaders.bat8
-rw-r--r--tests/manual/rhi/tessellation/tessellation.cpp129
-rw-r--r--tests/manual/rhi/tessellation/test.frag10
-rw-r--r--tests/manual/rhi/tessellation/test.frag.qsbbin0 -> 729 bytes
-rw-r--r--tests/manual/rhi/tessellation/test.tesc27
-rw-r--r--tests/manual/rhi/tessellation/test.tesc.qsbbin0 -> 1765 bytes
-rw-r--r--tests/manual/rhi/tessellation/test.tese27
-rw-r--r--tests/manual/rhi/tessellation/test.tese.qsbbin0 -> 2436 bytes
-rw-r--r--tests/manual/rhi/tessellation/test.vert12
-rw-r--r--tests/manual/rhi/tessellation/test.vert.qsbbin0 -> 1106 bytes
-rw-r--r--tests/manual/rhi/tessellation/test_domain.hlsl38
-rw-r--r--tests/manual/rhi/tessellation/test_hull.hlsl40
13 files changed, 316 insertions, 0 deletions
diff --git a/tests/manual/rhi/tessellation/CMakeLists.txt b/tests/manual/rhi/tessellation/CMakeLists.txt
new file mode 100644
index 0000000000..bdb3d8d2f7
--- /dev/null
+++ b/tests/manual/rhi/tessellation/CMakeLists.txt
@@ -0,0 +1,25 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_internal_add_manual_test(tessellation
+ GUI
+ SOURCES
+ tessellation.cpp
+ LIBRARIES
+ Qt::Gui
+ Qt::GuiPrivate
+)
+
+set(tessellation_resource_files
+ "test.vert.qsb"
+ "test.tesc.qsb"
+ "test.tese.qsb"
+ "test.frag.qsb"
+)
+
+qt_internal_add_resource(tessellation "tessellation"
+ PREFIX
+ "/"
+ FILES
+ ${tessellation_resource_files}
+)
diff --git a/tests/manual/rhi/tessellation/buildshaders.bat b/tests/manual/rhi/tessellation/buildshaders.bat
new file mode 100644
index 0000000000..61345d1906
--- /dev/null
+++ b/tests/manual/rhi/tessellation/buildshaders.bat
@@ -0,0 +1,8 @@
+:: Copyright (C) 2024 The Qt Company Ltd.
+:: SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+qsb --glsl 320es,410 --hlsl 50 --msl 12 --msltess test.vert -o test.vert.qsb
+qsb --glsl 320es,410 --msl 12 --tess-mode triangles test.tesc -o test.tesc.qsb
+qsb -r hlsl,50,test_hull.hlsl test.tesc.qsb
+qsb --glsl 320es,410 --msl 12 --tess-vertex-count 3 test.tese -o test.tese.qsb
+qsb -r hlsl,50,test_domain.hlsl test.tese.qsb
+qsb --glsl 320es,410 --hlsl 50 --msl 12 test.frag -o test.frag.qsb
diff --git a/tests/manual/rhi/tessellation/tessellation.cpp b/tests/manual/rhi/tessellation/tessellation.cpp
new file mode 100644
index 0000000000..a50ddeeeb2
--- /dev/null
+++ b/tests/manual/rhi/tessellation/tessellation.cpp
@@ -0,0 +1,129 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "../shared/examplefw.h"
+
+static const float tri[] = {
+ 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
+};
+
+static const bool INDEXED = false;
+static const quint32 indices[] = { 0, 1, 2 };
+
+struct {
+ QVector<QRhiResource *> releasePool;
+ QRhiBuffer *vbuf = nullptr;
+ QRhiBuffer *ibuf = nullptr;
+ QRhiBuffer *ubuf = nullptr;
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiGraphicsPipeline *ps = nullptr;
+ QRhiResourceUpdateBatch *initialUpdates = nullptr;
+ QMatrix4x4 winProj;
+ float time = 0.0f;
+} d;
+
+void Window::customInit()
+{
+ if (!m_r->isFeatureSupported(QRhi::Tessellation))
+ qFatal("Tessellation is not supported");
+
+ d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(tri));
+ d.vbuf->create();
+ d.releasePool << d.vbuf;
+
+ if (INDEXED) {
+ d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indices));
+ d.ibuf->create();
+ d.releasePool << d.ibuf;
+ }
+
+ d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64 + 4 + 4);
+ d.ubuf->create();
+ d.releasePool << d.ubuf;
+
+ d.srb = m_r->newShaderResourceBindings();
+ d.releasePool << d.srb;
+ const QRhiShaderResourceBinding::StageFlags tese = QRhiShaderResourceBinding::TessellationEvaluationStage;
+ d.srb->setBindings({ QRhiShaderResourceBinding::uniformBuffer(0, tese, d.ubuf) });
+ d.srb->create();
+
+ d.ps = m_r->newGraphicsPipeline();
+ d.releasePool << d.ps;
+
+ d.ps->setTopology(QRhiGraphicsPipeline::Patches);
+ d.ps->setPatchControlPointCount(3);
+
+ d.ps->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String(":/test.vert.qsb")) },
+ { QRhiShaderStage::TessellationControl, getShader(QLatin1String(":/test.tesc.qsb")) },
+ { QRhiShaderStage::TessellationEvaluation, getShader(QLatin1String(":/test.tese.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String(":/test.frag.qsb")) }
+ });
+
+ d.ps->setCullMode(QRhiGraphicsPipeline::Back);
+ d.ps->setPolygonMode(QRhiGraphicsPipeline::Line);
+ d.ps->setDepthTest(true);
+ d.ps->setDepthWrite(true);
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 6 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 3 * sizeof(float) }
+ });
+ d.ps->setVertexInputLayout(inputLayout);
+ d.ps->setShaderResourceBindings(d.srb);
+ d.ps->setRenderPassDescriptor(m_rp);
+ d.ps->create();
+
+ d.initialUpdates = m_r->nextResourceUpdateBatch();
+ d.initialUpdates->uploadStaticBuffer(d.vbuf, tri);
+
+ const float amplitude = 0.5f;
+ d.initialUpdates->updateDynamicBuffer(d.ubuf, 68, 4, &amplitude);
+
+ if (INDEXED)
+ d.initialUpdates->uploadStaticBuffer(d.ibuf, indices);
+}
+
+void Window::customRelease()
+{
+ qDeleteAll(d.releasePool);
+ d.releasePool.clear();
+}
+
+void Window::customRender()
+{
+ const QSize outputSizeInPixels = m_sc->currentPixelSize();
+ QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch();
+ if (d.initialUpdates) {
+ u->merge(d.initialUpdates);
+ d.initialUpdates->release();
+ d.initialUpdates = nullptr;
+ }
+ if (d.winProj != m_proj) {
+ d.winProj = m_proj;
+ u->updateDynamicBuffer(d.ubuf, 0, 64, d.winProj.constData());
+ }
+ u->updateDynamicBuffer(d.ubuf, 64, 4, &d.time);
+ d.time += 0.01f;
+
+ cb->beginPass(m_sc->currentFrameRenderTarget(), m_clearColor, { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(d.ps);
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ cb->setShaderResources();
+ QRhiCommandBuffer::VertexInput vbufBinding(d.vbuf, 0);
+ if (INDEXED) {
+ cb->setVertexInput(0, 1, &vbufBinding, d.ibuf, 0, QRhiCommandBuffer::IndexUInt32);
+ cb->drawIndexed(3);
+ } else {
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+ }
+
+ cb->endPass();
+}
diff --git a/tests/manual/rhi/tessellation/test.frag b/tests/manual/rhi/tessellation/test.frag
new file mode 100644
index 0000000000..375587662f
--- /dev/null
+++ b/tests/manual/rhi/tessellation/test.frag
@@ -0,0 +1,10 @@
+#version 440
+
+layout(location = 0) in vec3 v_color;
+
+layout(location = 0) out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(v_color, 1.0);
+}
diff --git a/tests/manual/rhi/tessellation/test.frag.qsb b/tests/manual/rhi/tessellation/test.frag.qsb
new file mode 100644
index 0000000000..4d49ede3ff
--- /dev/null
+++ b/tests/manual/rhi/tessellation/test.frag.qsb
Binary files differ
diff --git a/tests/manual/rhi/tessellation/test.tesc b/tests/manual/rhi/tessellation/test.tesc
new file mode 100644
index 0000000000..54937967fa
--- /dev/null
+++ b/tests/manual/rhi/tessellation/test.tesc
@@ -0,0 +1,27 @@
+#version 440
+
+layout(vertices = 3) out;
+
+layout(location = 0) in vec3 inColor[];
+
+layout(location = 0) out vec3 outColor[];
+
+// these serve no purpose, just exist to test per-patch outputs
+layout(location = 1) patch out vec3 stuff;
+layout(location = 2) patch out float more_stuff;
+
+void main()
+{
+ if (gl_InvocationID == 0) {
+ gl_TessLevelOuter[0] = 4.0;
+ gl_TessLevelOuter[1] = 4.0;
+ gl_TessLevelOuter[2] = 4.0;
+
+ gl_TessLevelInner[0] = 4.0;
+ }
+
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+ outColor[gl_InvocationID] = inColor[gl_InvocationID];
+ stuff = vec3(1.0);
+ more_stuff = 1.0;
+}
diff --git a/tests/manual/rhi/tessellation/test.tesc.qsb b/tests/manual/rhi/tessellation/test.tesc.qsb
new file mode 100644
index 0000000000..064e26040a
--- /dev/null
+++ b/tests/manual/rhi/tessellation/test.tesc.qsb
Binary files differ
diff --git a/tests/manual/rhi/tessellation/test.tese b/tests/manual/rhi/tessellation/test.tese
new file mode 100644
index 0000000000..c50230f852
--- /dev/null
+++ b/tests/manual/rhi/tessellation/test.tese
@@ -0,0 +1,27 @@
+#version 440
+
+layout(triangles, fractional_odd_spacing, ccw) in;
+
+layout(location = 0) in vec3 inColor[];
+
+layout(location = 0) out vec3 outColor;
+
+// these serve no purpose, just exist to test per-patch outputs
+layout(location = 1) patch in vec3 stuff;
+layout(location = 2) patch in float more_stuff;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ float time;
+ float amplitude;
+};
+
+void main()
+{
+ vec4 pos = (gl_TessCoord.x * gl_in[0].gl_Position) + (gl_TessCoord.y * gl_in[1].gl_Position) + (gl_TessCoord.z * gl_in[2].gl_Position);
+ gl_Position = mvp * pos;
+ gl_Position.x += sin(time + pos.y) * amplitude;
+ outColor = gl_TessCoord.x * inColor[0] + gl_TessCoord.y * inColor[1] + gl_TessCoord.z * inColor[2]
+ // these are all 1.0, just here to exercise the shader generation and the runtime pipeline setup
+ * stuff.x * more_stuff * (gl_TessLevelOuter[0] / 4.0) * (gl_TessLevelInner[0] / 4.0);
+}
diff --git a/tests/manual/rhi/tessellation/test.tese.qsb b/tests/manual/rhi/tessellation/test.tese.qsb
new file mode 100644
index 0000000000..a6caab67c3
--- /dev/null
+++ b/tests/manual/rhi/tessellation/test.tese.qsb
Binary files differ
diff --git a/tests/manual/rhi/tessellation/test.vert b/tests/manual/rhi/tessellation/test.vert
new file mode 100644
index 0000000000..3838d2f3bb
--- /dev/null
+++ b/tests/manual/rhi/tessellation/test.vert
@@ -0,0 +1,12 @@
+#version 440
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec3 color;
+
+layout(location = 0) out vec3 v_color;
+
+void main()
+{
+ gl_Position = vec4(position, 1.0);
+ v_color = color;
+}
diff --git a/tests/manual/rhi/tessellation/test.vert.qsb b/tests/manual/rhi/tessellation/test.vert.qsb
new file mode 100644
index 0000000000..39734b6d5d
--- /dev/null
+++ b/tests/manual/rhi/tessellation/test.vert.qsb
Binary files differ
diff --git a/tests/manual/rhi/tessellation/test_domain.hlsl b/tests/manual/rhi/tessellation/test_domain.hlsl
new file mode 100644
index 0000000000..a9697d32cf
--- /dev/null
+++ b/tests/manual/rhi/tessellation/test_domain.hlsl
@@ -0,0 +1,38 @@
+struct Input
+{
+ float edges[3] : SV_TessFactor;
+ float inside : SV_InsideTessFactor;
+};
+
+struct PatchInput
+{
+ float3 position : POSITION;
+ float3 color : COLOR;
+};
+
+struct PixelInput
+{
+ float3 color : TEXCOORD0;
+ float4 position : SV_POSITION;
+};
+
+cbuffer buf : register(b0)
+{
+ row_major float4x4 mvp : packoffset(c0);
+ float time : packoffset(c4);
+ float amplitude : packoffset(c4.y);
+};
+
+[domain("tri")]
+PixelInput main(Input input, float3 uvwCoord : SV_DomainLocation, const OutputPatch<PatchInput, 3> patch)
+{
+ PixelInput output;
+
+ float3 vertexPosition = uvwCoord.x * patch[0].position + uvwCoord.y * patch[1].position + uvwCoord.z * patch[2].position;
+ output.position = mul(float4(vertexPosition, 1.0f), mvp);
+ output.position.x += sin(time + vertexPosition.y) * amplitude;
+
+ output.color = uvwCoord.x * patch[0].color + uvwCoord.y * patch[1].color + uvwCoord.z * patch[2].color;
+
+ return output;
+}
diff --git a/tests/manual/rhi/tessellation/test_hull.hlsl b/tests/manual/rhi/tessellation/test_hull.hlsl
new file mode 100644
index 0000000000..3d09307159
--- /dev/null
+++ b/tests/manual/rhi/tessellation/test_hull.hlsl
@@ -0,0 +1,40 @@
+struct Input
+{
+ float3 color : TEXCOORD0;
+ float4 position : SV_Position;
+};
+
+struct Output
+{
+ float3 position : POSITION;
+ float3 color : COLOR;
+};
+
+struct ConstantData
+{
+ float edges[3] : SV_TessFactor;
+ float inside : SV_InsideTessFactor;
+};
+
+ConstantData patchConstFunc(InputPatch<Input, 3> ip, uint PatchID : SV_PrimitiveID )
+{
+ ConstantData d;
+ d.edges[0] = 4.0;
+ d.edges[1] = 4.0;
+ d.edges[2] = 4.0;
+ d.inside = 4.0;
+ return d;
+}
+
+[domain("tri")]
+[partitioning("integer")]
+[outputtopology("triangle_cw")]
+[outputcontrolpoints(3)]
+[patchconstantfunc("patchConstFunc")]
+Output main(InputPatch<Input, 3> patch, uint pointId : SV_OutputControlPointID, uint patchId : SV_PrimitiveID)
+{
+ Output output;
+ output.position = patch[pointId].position;
+ output.color = patch[pointId].color;
+ return output;
+}