rhi: Add a many cubes manual test
Draw 25000 cubes while doing a uniform buffer update for each. Change-Id: I2216641c8bf7c6ea147fe3edd679317b472e1f04 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
parent
9d804a54ae
commit
f26e329c47
@ -20,6 +20,7 @@ add_subdirectory(shadowmap)
|
||||
add_subdirectory(computebuffer)
|
||||
add_subdirectory(computeimage)
|
||||
add_subdirectory(instancing)
|
||||
add_subdirectory(noninstanced)
|
||||
if(QT_FEATURE_widgets)
|
||||
add_subdirectory(qrhiprof)
|
||||
endif()
|
||||
|
31
tests/manual/rhi/noninstanced/CMakeLists.txt
Normal file
31
tests/manual/rhi/noninstanced/CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
||||
# Generated from noninstanced.pro.
|
||||
|
||||
#####################################################################
|
||||
## noninstanced Binary:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_manual_test(noninstanced
|
||||
GUI
|
||||
SOURCES
|
||||
noninstanced.cpp
|
||||
PUBLIC_LIBRARIES
|
||||
Qt::Gui
|
||||
Qt::GuiPrivate
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(noninstanced_resource_files
|
||||
"material.frag.qsb"
|
||||
"material.vert.qsb"
|
||||
)
|
||||
|
||||
qt_internal_add_resource(noninstanced "noninstanced"
|
||||
PREFIX
|
||||
"/"
|
||||
FILES
|
||||
${noninstanced_resource_files}
|
||||
)
|
||||
|
||||
|
||||
#### Keys ignored in scope 1:.:.:noninstanced.pro:<TRUE>:
|
||||
# TEMPLATE = "app"
|
2
tests/manual/rhi/noninstanced/buildshaders.bat
Normal file
2
tests/manual/rhi/noninstanced/buildshaders.bat
Normal file
@ -0,0 +1,2 @@
|
||||
qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 material.vert -o material.vert.qsb
|
||||
qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 material.frag -o material.frag.qsb
|
9
tests/manual/rhi/noninstanced/material.frag
Normal file
9
tests/manual/rhi/noninstanced/material.frag
Normal file
@ -0,0 +1,9 @@
|
||||
#version 440
|
||||
|
||||
layout(location = 0) in vec3 vColor;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = vec4(vColor, 1.0);
|
||||
}
|
BIN
tests/manual/rhi/noninstanced/material.frag.qsb
Normal file
BIN
tests/manual/rhi/noninstanced/material.frag.qsb
Normal file
Binary file not shown.
23
tests/manual/rhi/noninstanced/material.vert
Normal file
23
tests/manual/rhi/noninstanced/material.vert
Normal file
@ -0,0 +1,23 @@
|
||||
#version 440
|
||||
|
||||
layout(location = 0) in vec4 position;
|
||||
|
||||
layout(location = 0) out vec3 vColor;
|
||||
|
||||
out gl_PerVertex { vec4 gl_Position; };
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 mvp;
|
||||
vec3 translation;
|
||||
vec3 color;
|
||||
} ubuf;
|
||||
|
||||
void main()
|
||||
{
|
||||
vColor = ubuf.color;
|
||||
mat4 t = mat4(1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
ubuf.translation.x, ubuf.translation.y, ubuf.translation.z, 1);
|
||||
gl_Position = ubuf.mvp * t * position;
|
||||
}
|
BIN
tests/manual/rhi/noninstanced/material.vert.qsb
Normal file
BIN
tests/manual/rhi/noninstanced/material.vert.qsb
Normal file
Binary file not shown.
192
tests/manual/rhi/noninstanced/noninstanced.cpp
Normal file
192
tests/manual/rhi/noninstanced/noninstanced.cpp
Normal file
@ -0,0 +1,192 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** BSD License Usage
|
||||
** Alternatively, you may use this file under the terms of the BSD license
|
||||
** as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||
** contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#define EXAMPLEFW_PREINIT
|
||||
#include "../shared/examplefw.h"
|
||||
#include "../shared/cube.h"
|
||||
#include <QRandomGenerator>
|
||||
|
||||
// A variation on the instancing test. No instancing here, just
|
||||
// individual uniform buffer updates and draw calls.
|
||||
|
||||
const int INSTANCE_COUNT = 25000;
|
||||
|
||||
struct {
|
||||
QList<QRhiResource *> releasePool;
|
||||
|
||||
QRhiBuffer *vbuf;
|
||||
QRhiBuffer *ubuf[INSTANCE_COUNT];
|
||||
QRhiShaderResourceBindings *srb[INSTANCE_COUNT];
|
||||
QRhiGraphicsPipeline *ps;
|
||||
|
||||
QRhiResourceUpdateBatch *initialUpdates = nullptr;
|
||||
|
||||
struct {
|
||||
float x, y, z;
|
||||
float r, g, b;
|
||||
} instData[INSTANCE_COUNT];
|
||||
float rot = 0.0f;
|
||||
} d;
|
||||
|
||||
void preInit()
|
||||
{
|
||||
debugLayer = false;
|
||||
}
|
||||
|
||||
void Window::customInit()
|
||||
{
|
||||
d.initialUpdates = m_r->nextResourceUpdateBatch();
|
||||
|
||||
d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(cube));
|
||||
d.vbuf->create();
|
||||
d.releasePool << d.vbuf;
|
||||
|
||||
d.initialUpdates->uploadStaticBuffer(d.vbuf, cube);
|
||||
|
||||
for (int i = 0; i < INSTANCE_COUNT; ++i) {
|
||||
d.ubuf[i] = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 92);
|
||||
d.ubuf[i]->create();
|
||||
d.releasePool << d.ubuf[i];
|
||||
|
||||
d.srb[i] = m_r->newShaderResourceBindings();
|
||||
d.releasePool << d.srb[i];
|
||||
d.srb[i]->setBindings({
|
||||
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, d.ubuf[i])
|
||||
});
|
||||
d.srb[i]->create();
|
||||
}
|
||||
|
||||
d.ps = m_r->newGraphicsPipeline();
|
||||
d.releasePool << d.ps;
|
||||
d.ps->setShaderStages({
|
||||
{ QRhiShaderStage::Vertex, getShader(QLatin1String(":/material.vert.qsb")) },
|
||||
{ QRhiShaderStage::Fragment, getShader(QLatin1String(":/material.frag.qsb")) }
|
||||
});
|
||||
QRhiVertexInputLayout inputLayout;
|
||||
inputLayout.setBindings({
|
||||
{ 3 * sizeof(float) },
|
||||
});
|
||||
inputLayout.setAttributes({
|
||||
{ 0, 0, QRhiVertexInputAttribute::Float3, 0 },
|
||||
});
|
||||
d.ps->setVertexInputLayout(inputLayout);
|
||||
d.ps->setShaderResourceBindings(d.srb[0]);
|
||||
d.ps->setRenderPassDescriptor(m_rp);
|
||||
d.ps->create();
|
||||
|
||||
QRandomGenerator *rgen = QRandomGenerator::global();
|
||||
for (int i = 0; i < INSTANCE_COUNT; ++i) {
|
||||
d.instData[i].x = rgen->bounded(8000) / 100.0f - 40.0f;
|
||||
d.instData[i].y = rgen->bounded(8000) / 100.0f - 40.0f;
|
||||
d.instData[i].z = rgen->bounded(100) / -4.0f;
|
||||
d.instData[i].r = i / float(INSTANCE_COUNT);
|
||||
d.instData[i].g = 0.0f;
|
||||
d.instData[i].b = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
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 = nullptr;
|
||||
if (d.initialUpdates) {
|
||||
u = d.initialUpdates;
|
||||
d.initialUpdates = nullptr;
|
||||
}
|
||||
|
||||
for (int i = 0; i < INSTANCE_COUNT; ++i) {
|
||||
char *p = d.ubuf[i]->beginFullDynamicUniformBufferUpdateForCurrentFrame();
|
||||
QMatrix4x4 mvp = m_proj;
|
||||
mvp.rotate(d.rot, 0, 1, 0);
|
||||
mvp.scale(0.05f);
|
||||
memcpy(p, mvp.constData(), 64);
|
||||
|
||||
// float *v = reinterpret_cast<float *>(p + 64);
|
||||
// v[0] = d.instData[i].x;
|
||||
// v[1] = d.instData[i].y;
|
||||
// v[2] = d.instData[i].z;
|
||||
memcpy(p + 64, &d.instData[i].x, 4);
|
||||
memcpy(p + 68, &d.instData[i].y, 4);
|
||||
memcpy(p + 72, &d.instData[i].z, 4);
|
||||
|
||||
// v = reinterpret_cast<float *>(p + 80);
|
||||
// v[0] = d.instData[i].r;
|
||||
// v[1] = d.instData[i].g;
|
||||
// v[2] = d.instData[i].b;
|
||||
memcpy(p + 80, &d.instData[i].r, 4);
|
||||
memcpy(p + 84, &d.instData[i].g, 4);
|
||||
memcpy(p + 88, &d.instData[i].b, 4);
|
||||
|
||||
d.ubuf[i]->endFullDynamicUniformBufferUpdateForCurrentFrame();
|
||||
}
|
||||
|
||||
cb->beginPass(m_sc->currentFrameRenderTarget(), m_clearColor, { 1.0f, 0 }, u, QRhiCommandBuffer::DoNotTrackResourcesForCompute);
|
||||
for (int i = 0; i < INSTANCE_COUNT; ++i) {
|
||||
cb->setGraphicsPipeline(d.ps);
|
||||
if (i == 0)
|
||||
cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
|
||||
cb->setShaderResources(d.srb[i]);
|
||||
const QRhiCommandBuffer::VertexInput vbufBinding[] = {
|
||||
{ d.vbuf, 0 },
|
||||
};
|
||||
cb->setVertexInput(0, 1, vbufBinding);
|
||||
cb->draw(36);
|
||||
}
|
||||
cb->endPass();
|
||||
|
||||
d.rot += 0.1f;
|
||||
}
|
8
tests/manual/rhi/noninstanced/noninstanced.pro
Normal file
8
tests/manual/rhi/noninstanced/noninstanced.pro
Normal file
@ -0,0 +1,8 @@
|
||||
TEMPLATE = app
|
||||
|
||||
QT += gui-private
|
||||
|
||||
SOURCES = \
|
||||
noninstanced.cpp
|
||||
|
||||
RESOURCES = noninstanced.qrc
|
6
tests/manual/rhi/noninstanced/noninstanced.qrc
Normal file
6
tests/manual/rhi/noninstanced/noninstanced.qrc
Normal file
@ -0,0 +1,6 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>material.vert.qsb</file>
|
||||
<file>material.frag.qsb</file>
|
||||
</qresource>
|
||||
</RCC>
|
@ -20,7 +20,8 @@ SUBDIRS += \
|
||||
shadowmap \
|
||||
computebuffer \
|
||||
computeimage \
|
||||
instancing
|
||||
instancing \
|
||||
noninstanced
|
||||
|
||||
qtConfig(widgets) {
|
||||
SUBDIRS += \
|
||||
|
@ -129,6 +129,7 @@ QRhi::BeginFrameFlags beginFrameFlags;
|
||||
QRhi::EndFrameFlags endFrameFlags;
|
||||
int framesUntilTdr = -1;
|
||||
bool transparentBackground = false;
|
||||
bool debugLayer = true;
|
||||
|
||||
class Window : public QWindow
|
||||
{
|
||||
@ -287,7 +288,9 @@ void Window::init()
|
||||
#ifdef Q_OS_WIN
|
||||
if (graphicsApi == D3D11) {
|
||||
QRhiD3D11InitParams params;
|
||||
params.enableDebugLayer = true;
|
||||
if (debugLayer)
|
||||
qDebug("Enabling D3D11 debug layer");
|
||||
params.enableDebugLayer = debugLayer;
|
||||
if (framesUntilTdr > 0) {
|
||||
params.framesUntilKillingDeviceViaTdr = framesUntilTdr;
|
||||
params.repeatDeviceKill = true;
|
||||
@ -531,18 +534,21 @@ int main(int argc, char **argv)
|
||||
#if QT_CONFIG(vulkan)
|
||||
QVulkanInstance inst;
|
||||
if (graphicsApi == Vulkan) {
|
||||
if (debugLayer) {
|
||||
qDebug("Enabling Vulkan validation layer (if available)");
|
||||
#ifndef Q_OS_ANDROID
|
||||
inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
|
||||
inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
|
||||
#else
|
||||
inst.setLayers(QByteArrayList()
|
||||
<< "VK_LAYER_GOOGLE_threading"
|
||||
<< "VK_LAYER_LUNARG_parameter_validation"
|
||||
<< "VK_LAYER_LUNARG_object_tracker"
|
||||
<< "VK_LAYER_LUNARG_core_validation"
|
||||
<< "VK_LAYER_LUNARG_image"
|
||||
<< "VK_LAYER_LUNARG_swapchain"
|
||||
<< "VK_LAYER_GOOGLE_unique_objects");
|
||||
inst.setLayers(QByteArrayList()
|
||||
<< "VK_LAYER_GOOGLE_threading"
|
||||
<< "VK_LAYER_LUNARG_parameter_validation"
|
||||
<< "VK_LAYER_LUNARG_object_tracker"
|
||||
<< "VK_LAYER_LUNARG_core_validation"
|
||||
<< "VK_LAYER_LUNARG_image"
|
||||
<< "VK_LAYER_LUNARG_swapchain"
|
||||
<< "VK_LAYER_GOOGLE_unique_objects");
|
||||
#endif
|
||||
}
|
||||
inst.setExtensions(QByteArrayList()
|
||||
<< "VK_KHR_get_physical_device_properties2");
|
||||
if (!inst.create()) {
|
||||
|
Loading…
Reference in New Issue
Block a user