Move non-automated tests into new folder

This commit is contained in:
Brad Davis 2018-05-08 09:04:59 -07:00
parent 59b9e08f58
commit d5afb3a49b
73 changed files with 704 additions and 0 deletions

View file

@ -0,0 +1,16 @@
set(TARGET_NAME gpu-textures-tests)
AUTOSCRIBE_SHADER_LIB(gpu graphics render-utils)
# This is not a testcase -- just set it up as a regular hifi project
setup_hifi_project(Quick Gui Script)
setup_memory_debugger()
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
link_hifi_libraries(
shared task networking gl
ktx gpu octree
${PLATFORM_GL_BACKEND}
)
set(EXTRA_DEPLOY_OPTIONS "--qmldir \"${PROJECT_SOURCE_DIR}/qml\"")
package_libraries_for_deployment()
target_nsight()

View file

@ -0,0 +1,52 @@
import QtQuick 2.5
import QtQuick.Controls 2.3
Item {
width: 400
height: 600
Column {
spacing: 10
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: 10
Text { text: qsTr("Total") }
Text { text: Stats.total + " MB" }
Text { text: qsTr("Allocated") }
Text { text: Stats.allocated }
Text { text: qsTr("Populated") }
Text { text: Stats.populated }
Text { text: qsTr("Pending") }
Text { text: Stats.pending }
Text { text: qsTr("Current Index") }
Text { text: Stats.index }
Text { text: qsTr("Current Source") }
Text { text: Stats.source }
Text { text: qsTr("Current Rez") }
Text { text: Stats.rez.width + " x " + Stats.rez.height }
}
Row {
id: row1
spacing: 10
anchors.bottom: row2.top
anchors.left: parent.left
anchors.margins: 10
Button { text: "1024"; onClicked: Stats.maxTextureMemory(1024); }
Button { text: "256"; onClicked: Stats.maxTextureMemory(256); }
}
Row {
id: row2
spacing: 10
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.margins: 10
Button { text: "Change Textures"; onClicked: Stats.changeTextures(); }
Button { text: "Next"; onClicked: Stats.nextTexture(); }
Button { text: "Previous"; onClicked: Stats.prevTexture(); }
}
}

View file

@ -0,0 +1,26 @@
//
// Created by Bradley Austin Davis on 2016/05/16
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "TestHelpers.h"
#include <QtCore/QFileInfo>
gpu::ShaderPointer makeShader(const std::string & vertexShaderSrc, const std::string & fragmentShaderSrc, const gpu::Shader::BindingSet & bindings) {
auto vs = gpu::Shader::createVertex(vertexShaderSrc);
auto fs = gpu::Shader::createPixel(fragmentShaderSrc);
auto shader = gpu::Shader::createProgram(vs, fs);
if (!gpu::Shader::makeProgram(*shader, bindings)) {
printf("Could not compile shader\n");
exit(-1);
}
return shader;
}
QString projectRootDir() {
static QString projectRootPath = QFileInfo(QFileInfo(__FILE__).absolutePath() + "/..").absoluteFilePath();
return projectRootPath;
}

View file

@ -0,0 +1,40 @@
//
// Created by Bradley Austin Davis on 2016/05/16
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#include <vector>
#include <GLMHelpers.h>
#include <Transform.h>
#include <NumericalConstants.h>
#include <gpu/Resource.h>
#include <gpu/Forward.h>
#include <gpu/Shader.h>
#include <gpu/Stream.h>
struct RenderArgs {
gpu::ContextPointer _context;
ivec4 _viewport;
gpu::Batch* _batch;
};
class GpuTestBase : public QObject {
public:
virtual ~GpuTestBase() {}
virtual bool isReady() const { return true; }
virtual size_t getTestCount() const { return 1; }
virtual void renderTest(size_t test, const RenderArgs& args) = 0;
virtual QObject * statsObject() { return nullptr; }
virtual QUrl statUrl() { return QUrl(); }
};
uint32_t toCompactColor(const glm::vec4& color);
gpu::ShaderPointer makeShader(const std::string & vertexShaderSrc, const std::string & fragmentShaderSrc, const gpu::Shader::BindingSet & bindings);
QString projectRootDir();

View file

@ -0,0 +1,168 @@
//
// Created by Bradley Austin Davis on 2016/05/16
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "TestTextures.h"
#include <random>
#include <algorithm>
#include <QtCore/QDir>
#include <QtQuick/QQuickView>
#include <QtQml/QQmlContext>
#include <gpu/Batch.h>
#include <gpu/Context.h>
#include "TestHelpers.h"
#pragma optimize("", off)
std::string vertexShaderSource = R"SHADER(
#line 14
layout(location = 0) out vec2 outTexCoord0;
const vec4 VERTICES[] = vec4[](
vec4(-1.0, -1.0, 0.0, 1.0),
vec4( 1.0, -1.0, 0.0, 1.0),
vec4(-1.0, 1.0, 0.0, 1.0),
vec4( 1.0, 1.0, 0.0, 1.0)
);
void main() {
outTexCoord0 = VERTICES[gl_VertexID].xy;
outTexCoord0 += 1.0;
outTexCoord0 /= 2.0;
gl_Position = VERTICES[gl_VertexID];
}
)SHADER";
std::string fragmentShaderSource = R"SHADER(
#line 28
uniform sampler2D tex;
layout(location = 0) in vec2 inTexCoord0;
layout(location = 0) out vec4 outFragColor;
void main() {
outFragColor = texture(tex, inTexCoord0);
outFragColor.a = 1.0;
//outFragColor.rb = inTexCoord0;
}
)SHADER";
#define STAT_UPDATE(name, src) \
{ \
auto val = src; \
if (_##name != val) { \
_##name = val; \
emit name##Changed(); \
} \
}
void TextureTestStats::update(int curIndex, const gpu::TexturePointer& texture) {
STAT_UPDATE(total, (int)BYTES_TO_MB(gpu::Context::getTextureGPUMemSize()));
STAT_UPDATE(allocated, (int)gpu::Context::getTextureResourceGPUMemSize());
STAT_UPDATE(pending, (int)gpu::Context::getTexturePendingGPUTransferMemSize());
STAT_UPDATE(populated, (int)gpu::Context::getTextureResourcePopulatedGPUMemSize());
STAT_UPDATE(source, texture->source().c_str());
STAT_UPDATE(index, curIndex);
auto dims = texture->getDimensions();
STAT_UPDATE(rez, QSize(dims.x, dims.y));
}
TexturesTest::TexturesTest() {
connect(&stats, &TextureTestStats::changeTextures, this, &TexturesTest::onChangeTextures);
connect(&stats, &TextureTestStats::nextTexture, this, &TexturesTest::onNextTexture);
connect(&stats, &TextureTestStats::prevTexture, this, &TexturesTest::onPrevTexture);
connect(&stats, &TextureTestStats::maxTextureMemory, this, &TexturesTest::onMaxTextureMemory);
{
auto VS = gpu::Shader::createVertex(vertexShaderSource);
auto PS = gpu::Shader::createPixel(fragmentShaderSource);
auto program = gpu::Shader::createProgram(VS, PS);
gpu::Shader::BindingSet slotBindings;
gpu::Shader::makeProgram(*program, slotBindings);
// If the pipeline did not exist, make it
auto state = std::make_shared<gpu::State>();
state->setCullMode(gpu::State::CULL_NONE);
state->setDepthTest({});
state->setBlendFunction({ false });
pipeline = gpu::Pipeline::create(program, state);
}
onChangeTextures();
}
void TexturesTest::renderTest(size_t testId, const RenderArgs& args) {
stats.update((int)index, textures[index]);
gpu::Batch& batch = *(args._batch);
batch.setPipeline(pipeline);
batch.setInputFormat(vertexFormat);
for (const auto& texture : textures) {
batch.setResourceTexture(0, texture);
batch.draw(gpu::TRIANGLE_STRIP, 4, 0);
}
batch.setResourceTexture(0, textures[index]);
batch.draw(gpu::TRIANGLE_STRIP, 4, 0);
}
#define LOAD_TEXTURE_COUNT 64
void TexturesTest::onChangeTextures() {
static const QDir TEST_DIR("D:/ktx_texture_test");
static std::vector<std::string> ALL_TEXTURE_FILES;
if (ALL_TEXTURE_FILES.empty()) {
auto entryList = TEST_DIR.entryList({ "*.ktx" }, QDir::Filter::Files);
ALL_TEXTURE_FILES.reserve(entryList.size());
for (auto entry : entryList) {
auto textureFile = TEST_DIR.absoluteFilePath(entry).toStdString();
ALL_TEXTURE_FILES.push_back(textureFile);
}
}
oldTextures.clear();
oldTextures.swap(textures);
#if 0
static const std::string bad = "D:/ktx_texture_test/b4beed38675dbc7a827ecd576399c1f4.ktx";
auto texture = gpu::Texture::unserialize(bad);
auto texelFormat = texture->getTexelFormat();
qDebug() << texture->getTexelFormat().getSemantic();
qDebug() << texture->getTexelFormat().getScalarCount();
textures.push_back(texture);
#else
std::shuffle(ALL_TEXTURE_FILES.begin(), ALL_TEXTURE_FILES.end(), std::default_random_engine());
size_t newTextureCount = std::min<size_t>(ALL_TEXTURE_FILES.size(), LOAD_TEXTURE_COUNT);
for (size_t i = 0; i < newTextureCount; ++i) {
const auto& textureFile = ALL_TEXTURE_FILES[i];
auto texture = gpu::Texture::unserialize(textureFile);
qDebug() << textureFile.c_str();
qDebug() << texture->getTexelFormat().getSemantic();
qDebug() << texture->getTexelFormat().getScalarCount();
textures.push_back(texture);
}
#endif
index = 0;
qDebug() << "Done";
}
void TexturesTest::onNextTexture() {
index += textures.size() + 1;
index %= textures.size();
}
void TexturesTest::onPrevTexture() {
index += textures.size() - 1;
index %= textures.size();
}
void TexturesTest::onMaxTextureMemory(int maxTextureMemory) {
gpu::Texture::setAllowedGPUMemoryUsage(MB_TO_BYTES(maxTextureMemory));
}

View file

@ -0,0 +1,74 @@
//
// Created by Bradley Austin Davis on 2016/05/16
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#include "TestHelpers.h"
#define STATS_PROPERTY(type, name, initialValue) \
Q_PROPERTY(type name READ name NOTIFY name##Changed) \
public: \
type name() { return _##name; }; \
private: \
type _##name{ initialValue };
class TextureTestStats : public QObject {
Q_OBJECT;
STATS_PROPERTY(int, pending, 0)
STATS_PROPERTY(int, total, 0)
STATS_PROPERTY(int, populated, 0)
STATS_PROPERTY(int, allocated, 0)
STATS_PROPERTY(int, index, 0)
STATS_PROPERTY(QString, source, QString())
STATS_PROPERTY(QSize, rez, QSize(0, 0))
public:
void update(int index, const gpu::TexturePointer& texture);
signals:
void pendingChanged();
void totalChanged();
void populatedChanged();
void allocatedChanged();
void changeTextures();
void rezChanged();
void indexChanged();
void sourceChanged();
void maxTextureMemory(int);
void nextTexture();
void prevTexture();
};
class TexturesTest : public GpuTestBase {
Q_OBJECT
gpu::Stream::FormatPointer vertexFormat { std::make_shared<gpu::Stream::Format>() };
std::vector<gpu::TexturePointer> textures;
std::vector<gpu::TexturePointer> oldTextures;
gpu::PipelinePointer pipeline;
TextureTestStats stats;
size_t index{ 0 };
public:
TexturesTest();
QObject* statsObject() override { return &stats; }
QUrl statUrl() override { return QUrl::fromLocalFile(projectRootDir() + "/qml/textureStats.qml"); }
void renderTest(size_t testId, const RenderArgs& args) override;
protected slots:
void onChangeTextures();
void onMaxTextureMemory(int newValue);
void onNextTexture();
void onPrevTexture();
};

View file

@ -0,0 +1,117 @@
//
// Created by Bradley Austin Davis on 2016/05/16
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "TestWindow.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <QtCore/QTimer>
#include <QtGui/QResizeEvent>
#include <gl/GLHelpers.h>
#include <gpu/gl/GLBackend.h>
TestWindow::TestWindow() {
auto timer = new QTimer(this);
timer->setTimerType(Qt::PreciseTimer);
timer->setInterval(5);
connect(timer, &QTimer::timeout, [&] { draw(); });
timer->start();
connect(qApp, &QCoreApplication::aboutToQuit, [this, timer] {
timer->stop();
_aboutToQuit = true;
});
setSurfaceType(QSurface::OpenGLSurface);
QSurfaceFormat format = getDefaultOpenGLSurfaceFormat();
format.setOption(QSurfaceFormat::DebugContext);
setFormat(format);
_glContext.setFormat(format);
_glContext.create();
_glContext.makeCurrent(this);
show();
}
void TestWindow::initGl() {
_glContext.makeCurrent(this);
gl::initModuleGl();
gpu::Context::init<gpu::gl::GLBackend>();
_renderArgs->_context = std::make_shared<gpu::Context>();
_glContext.makeCurrent(this);
resize(QSize(800, 600));
}
void TestWindow::resizeWindow(const QSize& size) {
_size = size;
_renderArgs->_viewport = ivec4(0, 0, _size.width(), _size.height());
}
void TestWindow::beginFrame() {
_renderArgs->_context->recycle();
_renderArgs->_context->beginFrame();
gpu::doInBatch("TestWindow::beginFrame", _renderArgs->_context, [&](gpu::Batch& batch) {
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLORS, { 0.0f, 0.1f, 0.2f, 1.0f });
batch.clearDepthFramebuffer(1e4);
batch.setViewportTransform({ 0, 0, _size.width() * devicePixelRatio(), _size.height() * devicePixelRatio() });
});
gpu::doInBatch("TestWindow::beginFrame", _renderArgs->_context, [&](gpu::Batch& batch) {
batch.setViewportTransform(_renderArgs->_viewport);
batch.setStateScissorRect(_renderArgs->_viewport);
batch.setProjectionTransform(_projectionMatrix);
});
}
void TestWindow::endFrame() {
gpu::doInBatch("TestWindow::endFrame::finish", _renderArgs->_context, [&](gpu::Batch& batch) {
batch.resetStages();
});
auto framePointer = _renderArgs->_context->endFrame();
_renderArgs->_context->consumeFrameUpdates(framePointer);
_renderArgs->_context->executeFrame(framePointer);
_glContext.swapBuffers(this);
}
void TestWindow::draw() {
if (_aboutToQuit) {
return;
}
// Attempting to draw before we're visible and have a valid size will
// produce GL errors.
if (!isVisible() || _size.width() <= 0 || _size.height() <= 0) {
return;
}
if (!_glContext.makeCurrent(this)) {
return;
}
static std::once_flag once;
std::call_once(once, [&] { initGl(); });
beginFrame();
renderFrame();
endFrame();
}
void TestWindow::resizeEvent(QResizeEvent* ev) {
resizeWindow(ev->size());
float fov_degrees = 60.0f;
float aspect_ratio = (float)_size.width() / _size.height();
float near_clip = 0.1f;
float far_clip = 1000.0f;
_projectionMatrix = glm::perspective(glm::radians(fov_degrees), aspect_ratio, near_clip, far_clip);
}

View file

@ -0,0 +1,41 @@
//
// Created by Bradley Austin Davis on 2016/05/16
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#include <QtGui/QWindow>
#include <QtCore/QTime>
#include <GLMHelpers.h>
#include <gl/QOpenGLContextWrapper.h>
#include <gpu/Forward.h>
#include "TestHelpers.h"
#define DEFERRED_LIGHTING
class TestWindow : public QWindow {
protected:
QOpenGLContextWrapper _glContext;
QSize _size;
glm::mat4 _projectionMatrix;
bool _aboutToQuit { false };
std::shared_ptr<RenderArgs> _renderArgs{ std::make_shared<RenderArgs>() };
TestWindow();
virtual void initGl();
virtual void renderFrame() = 0;
private:
void resizeWindow(const QSize& size);
void beginFrame();
void endFrame();
void draw();
void resizeEvent(QResizeEvent* ev) override;
};

View file

@ -0,0 +1,170 @@
//
// main.cpp
// tests/gpu-test/src
//
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <unordered_map>
#include <memory>
#include <cstdio>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <QtCore/QTime>
#include <QtCore/QTimer>
#include <QtCore/QDir>
#include <QtCore/QElapsedTimer>
#include <QtCore/QFile>
#include <QtCore/QLoggingCategory>
#include <QtGui/QDesktopServices>
#include <QtGui/QResizeEvent>
#include <QtGui/QWindow>
#include <QtGui/QGuiApplication>
#include <QtGui/QImage>
#include <QtGui/QScreen>
#include <QtWidgets/QApplication>
#include <gl/Config.h>
#include <QtQuick/QQuickWindow>
#include <QtQuick/QQuickView>
#include <QtQml/QQmlContext>
#include <gpu/Context.h>
#include <gpu/Batch.h>
#include <gpu/Stream.h>
#include <gpu/gl/GLBackend.h>
#include <gl/QOpenGLContextWrapper.h>
#include <gl/GLHelpers.h>
#include <GLMHelpers.h>
#include <PathUtils.h>
#include <NumericalConstants.h>
#include <PerfStat.h>
#include <PathUtils.h>
#include <SharedUtil.h>
#include <ViewFrustum.h>
#include <gpu/Pipeline.h>
#include <gpu/Context.h>
#include "TestWindow.h"
#include "TestTextures.h"
using TestBuilder = std::function<GpuTestBase*()>;
using TestBuilders = std::list<TestBuilder>;
#define INTERACTIVE
class MyTestWindow : public TestWindow {
using Parent = TestWindow;
TestBuilders _testBuilders;
GpuTestBase* _currentTest{ nullptr };
size_t _currentTestId{ 0 };
size_t _currentMaxTests{ 0 };
glm::mat4 _camera;
QTime _time;
void initGl() override {
Parent::initGl();
_time.start();
updateCamera();
_testBuilders = TestBuilders({
[] { return new TexturesTest(); },
});
}
void updateCamera() {
float t = _time.elapsed() * 1e-3f;
glm::vec3 unitscale{ 1.0f };
glm::vec3 up{ 0.0f, 1.0f, 0.0f };
float distance = 3.0f;
glm::vec3 camera_position{ distance * sinf(t), 0.5f, distance * cosf(t) };
static const vec3 camera_focus(0);
static const vec3 camera_up(0, 1, 0);
_camera = glm::inverse(glm::lookAt(camera_position, camera_focus, up));
ViewFrustum frustum;
frustum.setPosition(camera_position);
frustum.setOrientation(glm::quat_cast(_camera));
frustum.setProjection(_projectionMatrix);
}
void renderFrame() override {
updateCamera();
while ((!_currentTest || (_currentTestId >= _currentMaxTests)) && !_testBuilders.empty()) {
if (_currentTest) {
delete _currentTest;
_currentTest = nullptr;
}
_currentTest = _testBuilders.front()();
_testBuilders.pop_front();
if (_currentTest) {
auto statsObject = _currentTest->statsObject();
QUrl url = _currentTest->statUrl();
if (statsObject) {
auto screens = qApp->screens();
auto primaryScreen = qApp->primaryScreen();
auto targetScreen = primaryScreen;
for (const auto& screen : screens) {
if (screen == primaryScreen) {
continue;
}
targetScreen = screen;
break;
}
auto destPoint = targetScreen->availableGeometry().topLeft();
QQuickView* view = new QQuickView();
view->rootContext()->setContextProperty("Stats", statsObject);
view->setSource(url);
view->show();
view->setPosition({ destPoint.x() + 100, destPoint.y() + 100 });
}
_currentMaxTests = _currentTest->getTestCount();
_currentTestId = 0;
}
}
if (!_currentTest && _testBuilders.empty()) {
qApp->quit();
return;
}
// Tests might need to wait for resources to download
if (!_currentTest->isReady()) {
return;
}
gpu::doInBatch("main::renderFrame", _renderArgs->_context, [&](gpu::Batch& batch) {
batch.setViewTransform(_camera);
_renderArgs->_batch = &batch;
_currentTest->renderTest(_currentTestId, *_renderArgs);
_renderArgs->_batch = nullptr;
});
}
};
int main(int argc, char** argv) {
setupHifiApplication("GPU Test");
qputenv("HIFI_DEBUG_OPENGL", QByteArray("1"));
QApplication app(argc, argv);
MyTestWindow window;
app.exec();
return 0;
}