mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
801 lines
34 KiB
801 lines
34 KiB
|
5 years ago
|
/*
|
||
|
|
This file is part of Magnum.
|
||
|
|
|
||
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
|
||
|
|
2020, 2021 Vladimír Vondruš <mosra@centrum.cz>
|
||
|
|
|
||
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
|
copy of this software and associated documentation files (the "Software"),
|
||
|
|
to deal in the Software without restriction, including without limitation
|
||
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
||
|
|
Software is furnished to do so, subject to the following conditions:
|
||
|
|
|
||
|
|
The above copyright notice and this permission notice shall be included
|
||
|
|
in all copies or substantial portions of the Software.
|
||
|
|
|
||
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
|
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||
|
|
DEALINGS IN THE SOFTWARE.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <Corrade/PluginManager/Manager.h>
|
||
|
|
#include <Corrade/Utility/Directory.h>
|
||
|
|
#include <Corrade/Utility/FormatStl.h>
|
||
|
|
|
||
|
|
#include "Magnum/Image.h"
|
||
|
|
#include "Magnum/ImageView.h"
|
||
|
|
#include "Magnum/PixelFormat.h"
|
||
|
|
#include "Magnum/DebugTools/CompareImage.h"
|
||
|
|
#include "Magnum/GL/Extensions.h"
|
||
|
|
#include "Magnum/GL/Framebuffer.h"
|
||
|
|
#include "Magnum/GL/Mesh.h"
|
||
|
|
#include "Magnum/GL/OpenGLTester.h"
|
||
|
|
#include "Magnum/GL/Renderbuffer.h"
|
||
|
|
#include "Magnum/GL/RenderbufferFormat.h"
|
||
|
|
#include "Magnum/GL/Texture.h"
|
||
|
|
#include "Magnum/GL/TextureFormat.h"
|
||
|
|
#include "Magnum/Math/Color.h"
|
||
|
|
#include "Magnum/Math/Matrix4.h"
|
||
|
|
#include "Magnum/MeshTools/Compile.h"
|
||
|
|
#include "Magnum/MeshTools/Duplicate.h"
|
||
|
|
#include "Magnum/MeshTools/Interleave.h"
|
||
|
|
#include "Magnum/Primitives/Grid.h"
|
||
|
|
#include "Magnum/Shaders/DistanceFieldVectorGL.h"
|
||
|
|
#include "Magnum/Shaders/FlatGL.h"
|
||
|
|
#include "Magnum/Shaders/MeshVisualizerGL.h"
|
||
|
|
#include "Magnum/Shaders/PhongGL.h"
|
||
|
|
#include "Magnum/Shaders/VertexColorGL.h"
|
||
|
|
#include "Magnum/Shaders/VectorGL.h"
|
||
|
|
#include "Magnum/Trade/AbstractImporter.h"
|
||
|
|
#include "Magnum/Trade/MeshData.h"
|
||
|
|
|
||
|
|
#include "configure.h"
|
||
|
|
|
||
|
|
namespace Magnum { namespace Shaders { namespace Test { namespace {
|
||
|
|
|
||
|
|
/*
|
||
|
|
The goal of this is to not duplicate all testing work here, but instead
|
||
|
|
have a set of simple-to-setup benchmarks with trivial output that allow for
|
||
|
|
measuring cost of particular shader features or seeing performance
|
||
|
|
differences between different implementations of the same (e.g., using the
|
||
|
|
VertexColor shader vs Flat with vertex colors enabled). Thus:
|
||
|
|
|
||
|
|
- all shaders render the same mesh, 2D shaders only ignore the Z
|
||
|
|
coordinate (so it should be possible to compare the perf between 2D and
|
||
|
|
3D)
|
||
|
|
- the mesh contains all attributes the shader might ever need including
|
||
|
|
instanced ones, to avoid differences caused by different memory access
|
||
|
|
patterns
|
||
|
|
- transformation and projection is identity
|
||
|
|
- textures are always single-pixel to measure the sampler overhead, not
|
||
|
|
memory access overhead
|
||
|
|
- if texture transformation is enabled, it's identity
|
||
|
|
- if instancing features are enabled, there's exactly one instance
|
||
|
|
- if alpha mask is enabled, it's 0.0
|
||
|
|
- uniforms / binding overhead is not included in the benchmark
|
||
|
|
*/
|
||
|
|
|
||
|
|
struct ShadersGLBenchmark: GL::OpenGLTester {
|
||
|
|
explicit ShadersGLBenchmark();
|
||
|
|
|
||
|
|
void renderSetup();
|
||
|
|
void renderTeardown();
|
||
|
|
|
||
|
|
template<UnsignedInt dimensions> void flat();
|
||
|
|
void phong();
|
||
|
|
template<UnsignedInt dimensions> void vertexColor();
|
||
|
|
template<UnsignedInt dimensions> void vector();
|
||
|
|
template<UnsignedInt dimensions> void distanceFieldVector();
|
||
|
|
void meshVisualizer2D();
|
||
|
|
void meshVisualizer3D();
|
||
|
|
/** @todo mesh visualizer TBN, how to verify output? */
|
||
|
|
|
||
|
|
private:
|
||
|
|
PluginManager::Manager<Trade::AbstractImporter> _manager{"nonexistent"};
|
||
|
|
|
||
|
|
GL::Renderbuffer _color;
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
GL::Renderbuffer _objectId{NoCreate};
|
||
|
|
#endif
|
||
|
|
GL::Framebuffer _framebuffer;
|
||
|
|
|
||
|
|
GL::Buffer _indices, _vertices;
|
||
|
|
GL::Mesh _mesh, _meshInstanced, _meshDuplicated;
|
||
|
|
|
||
|
|
GL::Texture2D _textureWhite, _textureBlue;
|
||
|
|
};
|
||
|
|
|
||
|
|
using namespace Math::Literals;
|
||
|
|
|
||
|
|
constexpr Vector2i GridSubdivisions{64, 64};
|
||
|
|
constexpr Vector2i RenderSize{512, 512};
|
||
|
|
constexpr std::size_t WarmupIterations{100};
|
||
|
|
constexpr std::size_t BenchmarkIterations{1000};
|
||
|
|
constexpr std::size_t BenchmarkRepeats{4};
|
||
|
|
|
||
|
|
const struct {
|
||
|
|
const char* name;
|
||
|
|
FlatGL2D::Flags flags;
|
||
|
|
} FlatData[] {
|
||
|
|
{"", {}},
|
||
|
|
{"vertex color", FlatGL2D::Flag::VertexColor},
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
{"object ID", FlatGL2D::Flag::ObjectId},
|
||
|
|
#endif
|
||
|
|
{"textured", FlatGL2D::Flag::Textured},
|
||
|
|
{"textured + alpha mask", FlatGL2D::Flag::Textured|FlatGL2D::Flag::AlphaMask},
|
||
|
|
{"texture transformation", FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation},
|
||
|
|
{"instanced transformation", FlatGL2D::Flag::InstancedTransformation},
|
||
|
|
{"instanced transformation + color", FlatGL2D::Flag::InstancedTransformation|FlatGL2D::Flag::VertexColor},
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
{"instanced transformation + object ID", FlatGL2D::Flag::InstancedTransformation|FlatGL2D::Flag::InstancedObjectId},
|
||
|
|
#endif
|
||
|
|
{"instanced transformation + texture offset", FlatGL2D::Flag::Textured|FlatGL2D::Flag::InstancedTransformation|FlatGL2D::Flag::InstancedTextureOffset},
|
||
|
|
};
|
||
|
|
|
||
|
|
const struct {
|
||
|
|
const char* name;
|
||
|
|
PhongGL::Flags flags;
|
||
|
|
UnsignedInt lights;
|
||
|
|
} PhongData[] {
|
||
|
|
{"", {}, 1},
|
||
|
|
{"zero lights", {}, 0},
|
||
|
|
{"five lights", {}, 5},
|
||
|
|
{"vertex color", PhongGL::Flag::VertexColor, 1},
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
{"object ID", PhongGL::Flag::ObjectId, 1},
|
||
|
|
#endif
|
||
|
|
{"diffuse texture", PhongGL::Flag::DiffuseTexture, 1},
|
||
|
|
{"ADS textures", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture, 1},
|
||
|
|
{"ADS textures + alpha mask", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::AlphaMask, 1},
|
||
|
|
{"ADS textures + transformation", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::TextureTransformation, 1},
|
||
|
|
{"normal texture", PhongGL::Flag::NormalTexture, 1},
|
||
|
|
{"normal texture with separate bitangent", PhongGL::Flag::NormalTexture|PhongGL::Flag::Bitangent, 1},
|
||
|
|
{"instanced transformation", PhongGL::Flag::InstancedTransformation, 1},
|
||
|
|
{"instanced transformation + color", PhongGL::Flag::InstancedTransformation|PhongGL::Flag::VertexColor, 1},
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
{"instanced transformation + object ID", PhongGL::Flag::InstancedTransformation|PhongGL::Flag::InstancedObjectId, 1},
|
||
|
|
#endif
|
||
|
|
{"instanced transformation + ADS texture offset", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTransformation|PhongGL::Flag::InstancedTextureOffset, 1},
|
||
|
|
};
|
||
|
|
|
||
|
|
const struct {
|
||
|
|
const char* name;
|
||
|
|
VectorGL2D::Flags flags;
|
||
|
|
} VectorData[] {
|
||
|
|
{"", {}},
|
||
|
|
{"texture transformation", VectorGL2D::Flag::TextureTransformation}
|
||
|
|
};
|
||
|
|
|
||
|
|
const struct {
|
||
|
|
const char* name;
|
||
|
|
DistanceFieldVectorGL2D::Flags flags;
|
||
|
|
} DistanceFieldVectorData[] {
|
||
|
|
{"", {}},
|
||
|
|
{"texture transformation", DistanceFieldVectorGL2D::Flag::TextureTransformation}
|
||
|
|
};
|
||
|
|
|
||
|
|
const struct {
|
||
|
|
const char* name;
|
||
|
|
MeshVisualizerGL2D::Flags flags;
|
||
|
|
} MeshVisualizer2DData[] {
|
||
|
|
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
|
||
|
|
{"wireframe", MeshVisualizerGL2D::Flag::Wireframe},
|
||
|
|
#endif
|
||
|
|
{"wireframe w/o a GS", MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader},
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
{"instanced object ID", MeshVisualizerGL2D::Flag::InstancedObjectId},
|
||
|
|
{"vertex ID", MeshVisualizerGL2D::Flag::VertexId},
|
||
|
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
|
{"primitive ID", MeshVisualizerGL2D::Flag::PrimitiveId},
|
||
|
|
{"primitive ID from vertex ID", MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId},
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
};
|
||
|
|
|
||
|
|
const struct {
|
||
|
|
const char* name;
|
||
|
|
MeshVisualizerGL3D::Flags flags;
|
||
|
|
} MeshVisualizer3DData[] {
|
||
|
|
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
|
||
|
|
{"wireframe", MeshVisualizerGL3D::Flag::Wireframe},
|
||
|
|
#endif
|
||
|
|
{"wireframe w/o a GS", MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader},
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
{"instanced object ID", MeshVisualizerGL3D::Flag::InstancedObjectId},
|
||
|
|
{"vertex ID", MeshVisualizerGL3D::Flag::VertexId},
|
||
|
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
|
{"primitive ID", MeshVisualizerGL3D::Flag::PrimitiveId},
|
||
|
|
{"primitive ID from vertex ID", MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId},
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
};
|
||
|
|
|
||
|
|
ShadersGLBenchmark::ShadersGLBenchmark(): _framebuffer{{{}, RenderSize}} {
|
||
|
|
addInstancedBenchmarks({&ShadersGLBenchmark::flat<2>,
|
||
|
|
&ShadersGLBenchmark::flat<3>},
|
||
|
|
BenchmarkRepeats, Containers::arraySize(FlatData),
|
||
|
|
&ShadersGLBenchmark::renderSetup,
|
||
|
|
&ShadersGLBenchmark::renderTeardown,
|
||
|
|
BenchmarkType::GpuTime);
|
||
|
|
|
||
|
|
addInstancedBenchmarks({&ShadersGLBenchmark::phong},
|
||
|
|
BenchmarkRepeats, Containers::arraySize(PhongData),
|
||
|
|
&ShadersGLBenchmark::renderSetup,
|
||
|
|
&ShadersGLBenchmark::renderTeardown,
|
||
|
|
BenchmarkType::GpuTime);
|
||
|
|
|
||
|
|
addBenchmarks({&ShadersGLBenchmark::vertexColor<2>,
|
||
|
|
&ShadersGLBenchmark::vertexColor<3>},
|
||
|
|
BenchmarkRepeats,
|
||
|
|
&ShadersGLBenchmark::renderSetup,
|
||
|
|
&ShadersGLBenchmark::renderTeardown,
|
||
|
|
BenchmarkType::GpuTime);
|
||
|
|
|
||
|
|
addInstancedBenchmarks({&ShadersGLBenchmark::vector<2>,
|
||
|
|
&ShadersGLBenchmark::vector<3>},
|
||
|
|
BenchmarkRepeats, Containers::arraySize(VectorData),
|
||
|
|
&ShadersGLBenchmark::renderSetup,
|
||
|
|
&ShadersGLBenchmark::renderTeardown,
|
||
|
|
BenchmarkType::GpuTime);
|
||
|
|
|
||
|
|
addInstancedBenchmarks({&ShadersGLBenchmark::distanceFieldVector<2>,
|
||
|
|
&ShadersGLBenchmark::distanceFieldVector<3>},
|
||
|
|
BenchmarkRepeats, Containers::arraySize(DistanceFieldVectorData),
|
||
|
|
&ShadersGLBenchmark::renderSetup,
|
||
|
|
&ShadersGLBenchmark::renderTeardown,
|
||
|
|
BenchmarkType::GpuTime);
|
||
|
|
|
||
|
|
addInstancedBenchmarks({&ShadersGLBenchmark::meshVisualizer2D},
|
||
|
|
BenchmarkRepeats, Containers::arraySize(MeshVisualizer2DData),
|
||
|
|
&ShadersGLBenchmark::renderSetup,
|
||
|
|
&ShadersGLBenchmark::renderTeardown,
|
||
|
|
BenchmarkType::GpuTime);
|
||
|
|
|
||
|
|
addInstancedBenchmarks({&ShadersGLBenchmark::meshVisualizer3D},
|
||
|
|
BenchmarkRepeats, Containers::arraySize(MeshVisualizer3DData),
|
||
|
|
&ShadersGLBenchmark::renderSetup,
|
||
|
|
&ShadersGLBenchmark::renderTeardown,
|
||
|
|
BenchmarkType::GpuTime);
|
||
|
|
|
||
|
|
/* Set up the framebuffer */
|
||
|
|
_color.setStorage(
|
||
|
|
#if !defined(MAGNUM_TARGET_GLES2) || !defined(MAGNUM_TARGET_WEBGL)
|
||
|
|
GL::RenderbufferFormat::RGBA8,
|
||
|
|
#else
|
||
|
|
GL::RenderbufferFormat::RGBA4,
|
||
|
|
#endif
|
||
|
|
RenderSize);
|
||
|
|
_framebuffer.attachRenderbuffer(GL::Framebuffer::ColorAttachment{0}, _color)
|
||
|
|
.bind();
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
/* If we don't have EXT_gpu_shader4, we likely don't have integer
|
||
|
|
framebuffers either (Mesa's Zink), so skip setting up integer
|
||
|
|
attachments to avoid GL errors */
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
if(GL::Context::current().isExtensionSupported<GL::Extensions::EXT::gpu_shader4>())
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
_objectId = GL::Renderbuffer{};
|
||
|
|
_objectId.setStorage(GL::RenderbufferFormat::R32UI, RenderSize);
|
||
|
|
_framebuffer.attachRenderbuffer(GL::Framebuffer::ColorAttachment{1}, _objectId)
|
||
|
|
.mapForDraw({
|
||
|
|
{FlatGL2D::ColorOutput, GL::Framebuffer::ColorAttachment{0}},
|
||
|
|
{FlatGL2D::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/* Set up the mesh */
|
||
|
|
{
|
||
|
|
Trade::MeshData data = Primitives::grid3DSolid(GridSubdivisions,
|
||
|
|
Primitives::GridFlag::TextureCoordinates|
|
||
|
|
Primitives::GridFlag::Normals|
|
||
|
|
Primitives::GridFlag::Tangents);
|
||
|
|
Containers::Array<Color4> vertexColors{DirectInit, data.vertexCount(), 0xffffffff_rgbaf};
|
||
|
|
Containers::Array<Vector3> bitangents{DirectInit, data.vertexCount(), Vector3{0.0f, 1.0f, 0.0f}};
|
||
|
|
Trade::MeshData dataWithVertexColors = MeshTools::interleave(std::move(data), {
|
||
|
|
Trade::MeshAttributeData{Trade::MeshAttribute::Color, arrayView(vertexColors)},
|
||
|
|
Trade::MeshAttributeData{Trade::MeshAttribute::Bitangent, arrayView(bitangents)}
|
||
|
|
});
|
||
|
|
_indices.setData(dataWithVertexColors.indexData());
|
||
|
|
_vertices.setData(dataWithVertexColors.vertexData());
|
||
|
|
_mesh = MeshTools::compile(dataWithVertexColors, _indices, _vertices);
|
||
|
|
|
||
|
|
/* Instanced variant, if the divisor-related extension is supported */
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
if(GL::Context::current().isExtensionSupported<GL::Extensions::ARB::instanced_arrays>())
|
||
|
|
#elif defined(MAGNUM_TARGET_GLES2)
|
||
|
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
|
if(GL::Context::current().isExtensionSupported<GL::Extensions::ANGLE::instanced_arrays>() ||
|
||
|
|
GL::Context::current().isExtensionSupported<GL::Extensions::EXT::instanced_arrays>() ||
|
||
|
|
GL::Context::current().isExtensionSupported<GL::Extensions::NV::instanced_arrays>())
|
||
|
|
#else
|
||
|
|
if(GL::Context::current().isExtensionSupported<GL::Extensions::ANGLE::instanced_arrays>())
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
_meshInstanced = MeshTools::compile(dataWithVertexColors, _indices, _vertices);
|
||
|
|
struct {
|
||
|
|
/* Given the way the matrix attribute is specified (column by
|
||
|
|
column), it should work for 2D as well */
|
||
|
|
Matrix4 transformation{Math::IdentityInit};
|
||
|
|
Matrix3x3 normalMatrix{Math::IdentityInit};
|
||
|
|
Vector2 textureOffset{0.0f, 0.0f};
|
||
|
|
Color4 color{0xffffffff_rgbaf};
|
||
|
|
UnsignedInt objectId{0};
|
||
|
|
} instanceData[1];
|
||
|
|
_meshInstanced.addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0,
|
||
|
|
GenericGL3D::TransformationMatrix{},
|
||
|
|
GenericGL3D::NormalMatrix{},
|
||
|
|
GenericGL3D::TextureOffset{},
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
GenericGL3D::ObjectId{}
|
||
|
|
#else
|
||
|
|
sizeof(UnsignedInt)
|
||
|
|
#endif
|
||
|
|
);
|
||
|
|
/** @todo hmm, this doesn't really issue an instanced draw call, does
|
||
|
|
that matter? */
|
||
|
|
_meshInstanced.setInstanceCount(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Non-indexed variant for GS-less wireframe drawing */
|
||
|
|
_meshDuplicated = MeshTools::compile(MeshTools::duplicate(dataWithVertexColors));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Set up the textures */
|
||
|
|
{
|
||
|
|
const Color4ub white[1] { 0xffffffff_rgba };
|
||
|
|
_textureWhite.setMinificationFilter(GL::SamplerFilter::Linear)
|
||
|
|
.setMagnificationFilter(GL::SamplerFilter::Linear)
|
||
|
|
.setWrapping(GL::SamplerWrapping::ClampToEdge)
|
||
|
|
.setStorage(1,
|
||
|
|
#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL))
|
||
|
|
GL::TextureFormat::RGBA8
|
||
|
|
#else
|
||
|
|
GL::TextureFormat::RGBA
|
||
|
|
#endif
|
||
|
|
, {1, 1})
|
||
|
|
.setSubImage(0, {}, ImageView2D{PixelFormat::RGBA8Unorm, {1, 1}, white});
|
||
|
|
} {
|
||
|
|
const Color4ub blue[1] { 0x0000ffff_rgba };
|
||
|
|
_textureBlue.setMinificationFilter(GL::SamplerFilter::Linear)
|
||
|
|
.setMagnificationFilter(GL::SamplerFilter::Linear)
|
||
|
|
.setWrapping(GL::SamplerWrapping::ClampToEdge)
|
||
|
|
.setStorage(1,
|
||
|
|
#if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL))
|
||
|
|
GL::TextureFormat::RGBA8
|
||
|
|
#else
|
||
|
|
GL::TextureFormat::RGBA
|
||
|
|
#endif
|
||
|
|
, {1, 1})
|
||
|
|
.setSubImage(0, {}, ImageView2D{PixelFormat::RGBA8Unorm, {1, 1}, blue});
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Load the plugins directly from the build tree. Otherwise they're either
|
||
|
|
static and already loaded or not present in the build tree */
|
||
|
|
#ifdef ANYIMAGEIMPORTER_PLUGIN_FILENAME
|
||
|
|
CORRADE_INTERNAL_ASSERT_OUTPUT(_manager.load(ANYIMAGEIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
|
||
|
|
#endif
|
||
|
|
#ifdef TGAIMPORTER_PLUGIN_FILENAME
|
||
|
|
CORRADE_INTERNAL_ASSERT_OUTPUT(_manager.load(TGAIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void ShadersGLBenchmark::renderSetup() {
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
if(GL::Context::current().isExtensionSupported<GL::Extensions::EXT::gpu_shader4>())
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
_framebuffer
|
||
|
|
.clearColor(0, Color4{})
|
||
|
|
.clearColor(1, Vector4ui{});
|
||
|
|
}
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
else
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
_framebuffer.clear(GL::FramebufferClear::Color);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void ShadersGLBenchmark::renderTeardown() {
|
||
|
|
/* Nothing to do here */
|
||
|
|
}
|
||
|
|
|
||
|
|
template<UnsignedInt dimensions> void ShadersGLBenchmark::flat() {
|
||
|
|
auto&& data = FlatData[testCaseInstanceId()];
|
||
|
|
setTestCaseTemplateName(Utility::formatString("{}", dimensions));
|
||
|
|
setTestCaseDescription(data.name);
|
||
|
|
|
||
|
|
if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
|
||
|
|
!(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
|
||
|
|
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found.");
|
||
|
|
|
||
|
|
FlatGL<dimensions> shader{data.flags};
|
||
|
|
if(data.flags >= FlatGL2D::Flag::AlphaMask)
|
||
|
|
shader.setAlphaMask(0.0f);
|
||
|
|
if(data.flags >= FlatGL2D::Flag::Textured)
|
||
|
|
shader.bindTexture(_textureWhite);
|
||
|
|
|
||
|
|
GL::Mesh* mesh;
|
||
|
|
/* InstancedTextureOffset is a superset of TextureTransformation, so
|
||
|
|
remove those bits first when deciding if instanced */
|
||
|
|
if((data.flags & ~FlatGL2D::Flag::TextureTransformation) & (FlatGL2D::Flag::InstancedTransformation|FlatGL2D::Flag::InstancedTextureOffset
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
|FlatGL2D::Flag::InstancedObjectId
|
||
|
|
#endif
|
||
|
|
)) {
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::instanced_arrays>())
|
||
|
|
CORRADE_SKIP(GL::Extensions::ARB::instanced_arrays::string() << "is not supported.");
|
||
|
|
#elif defined(MAGNUM_TARGET_GLES2)
|
||
|
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
|
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ANGLE::instanced_arrays>() &&
|
||
|
|
!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::instanced_arrays>() &&
|
||
|
|
!GL::Context::current().isExtensionSupported<GL::Extensions::NV::instanced_arrays>())
|
||
|
|
CORRADE_SKIP("Required extension is not available.");
|
||
|
|
#else
|
||
|
|
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ANGLE::instanced_arrays>())
|
||
|
|
CORRADE_SKIP(GL::Extensions::ANGLE::instanced_arrays::string() << "is not supported.");
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
mesh = &_meshInstanced;
|
||
|
|
} else {
|
||
|
|
mesh = &_mesh;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Warmup run */
|
||
|
|
/** @todo make this possible to do inside CORRADE_BENCHMARK() */
|
||
|
|
for(std::size_t i = 0; i != 100; ++i)
|
||
|
|
shader.draw(*mesh);
|
||
|
|
|
||
|
|
CORRADE_BENCHMARK(BenchmarkIterations)
|
||
|
|
shader.draw(*mesh);
|
||
|
|
|
||
|
|
MAGNUM_VERIFY_NO_GL_ERROR();
|
||
|
|
|
||
|
|
CORRADE_COMPARE_WITH(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}),
|
||
|
|
Utility::Directory::join(SHADERS_TEST_DIR, "BenchmarkFiles/trivial.tga"),
|
||
|
|
DebugTools::CompareImageToFile{_manager});
|
||
|
|
}
|
||
|
|
|
||
|
|
void ShadersGLBenchmark::phong() {
|
||
|
|
auto&& data = PhongData[testCaseInstanceId()];
|
||
|
|
setTestCaseDescription(data.name);
|
||
|
|
|
||
|
|
if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
|
||
|
|
!(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
|
||
|
|
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found.");
|
||
|
|
|
||
|
|
PhongGL shader{data.flags, data.lights};
|
||
|
|
/* White ambient so we always have a white output */
|
||
|
|
shader.setAmbientColor(0xffffffff_rgbaf);
|
||
|
|
if(data.flags >= PhongGL::Flag::AlphaMask)
|
||
|
|
shader.setAlphaMask(0.0f);
|
||
|
|
if(data.flags >= PhongGL::Flag::AmbientTexture)
|
||
|
|
shader.bindAmbientTexture(_textureWhite);
|
||
|
|
if(data.flags >= PhongGL::Flag::DiffuseTexture)
|
||
|
|
shader.bindDiffuseTexture(_textureWhite);
|
||
|
|
if(data.flags >= PhongGL::Flag::SpecularTexture)
|
||
|
|
shader.bindSpecularTexture(_textureWhite);
|
||
|
|
if(data.flags >= PhongGL::Flag::NormalTexture)
|
||
|
|
shader.bindNormalTexture(_textureBlue);
|
||
|
|
|
||
|
|
GL::Mesh* mesh;
|
||
|
|
/* InstancedTextureOffset is a superset of TextureTransformation, so
|
||
|
|
remove those bits first when deciding if instanced */
|
||
|
|
if((data.flags & ~PhongGL::Flag::TextureTransformation) & (PhongGL::Flag::InstancedTransformation|PhongGL::Flag::InstancedTextureOffset
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
|PhongGL::Flag::InstancedObjectId
|
||
|
|
#endif
|
||
|
|
)) {
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::draw_instanced>())
|
||
|
|
CORRADE_SKIP(GL::Extensions::ARB::draw_instanced::string() << "is not supported.");
|
||
|
|
#elif defined(MAGNUM_TARGET_GLES2)
|
||
|
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
|
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ANGLE::instanced_arrays>() &&
|
||
|
|
!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::instanced_arrays>() &&
|
||
|
|
!GL::Context::current().isExtensionSupported<GL::Extensions::NV::instanced_arrays>())
|
||
|
|
CORRADE_SKIP("Required extension is not available.");
|
||
|
|
#else
|
||
|
|
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ANGLE::instanced_arrays>())
|
||
|
|
CORRADE_SKIP(GL::Extensions::ANGLE::instanced_arrays::string() << "is not supported.");
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
mesh = &_meshInstanced;
|
||
|
|
} else {
|
||
|
|
mesh = &_mesh;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Warmup run */
|
||
|
|
/** @todo make this possible to do inside CORRADE_BENCHMARK() */
|
||
|
|
for(std::size_t i = 0; i != WarmupIterations; ++i)
|
||
|
|
shader.draw(*mesh);
|
||
|
|
|
||
|
|
CORRADE_BENCHMARK(BenchmarkIterations)
|
||
|
|
shader.draw(*mesh);
|
||
|
|
|
||
|
|
MAGNUM_VERIFY_NO_GL_ERROR();
|
||
|
|
|
||
|
|
CORRADE_COMPARE_WITH(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}),
|
||
|
|
Utility::Directory::join(SHADERS_TEST_DIR, "BenchmarkFiles/trivial.tga"),
|
||
|
|
DebugTools::CompareImageToFile{_manager});
|
||
|
|
}
|
||
|
|
|
||
|
|
template<UnsignedInt dimensions> void ShadersGLBenchmark::vertexColor() {
|
||
|
|
setTestCaseTemplateName(Utility::formatString("{}", dimensions));
|
||
|
|
|
||
|
|
if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
|
||
|
|
!(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
|
||
|
|
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found.");
|
||
|
|
|
||
|
|
VertexColorGL<dimensions> shader;
|
||
|
|
|
||
|
|
/* Warmup run */
|
||
|
|
/** @todo make this possible to do inside CORRADE_BENCHMARK() */
|
||
|
|
for(std::size_t i = 0; i != WarmupIterations; ++i)
|
||
|
|
shader.draw(_mesh);
|
||
|
|
|
||
|
|
CORRADE_BENCHMARK(BenchmarkIterations)
|
||
|
|
shader.draw(_mesh);
|
||
|
|
|
||
|
|
MAGNUM_VERIFY_NO_GL_ERROR();
|
||
|
|
|
||
|
|
CORRADE_COMPARE_WITH(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}),
|
||
|
|
Utility::Directory::join(SHADERS_TEST_DIR, "BenchmarkFiles/trivial.tga"),
|
||
|
|
DebugTools::CompareImageToFile{_manager});
|
||
|
|
}
|
||
|
|
|
||
|
|
template<UnsignedInt dimensions> void ShadersGLBenchmark::vector() {
|
||
|
|
auto&& data = VectorData[testCaseInstanceId()];
|
||
|
|
setTestCaseTemplateName(Utility::formatString("{}", dimensions));
|
||
|
|
setTestCaseDescription(data.name);
|
||
|
|
|
||
|
|
if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
|
||
|
|
!(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
|
||
|
|
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found.");
|
||
|
|
|
||
|
|
VectorGL<dimensions> shader{data.flags};
|
||
|
|
shader.bindVectorTexture(_textureWhite);
|
||
|
|
|
||
|
|
/* Warmup run */
|
||
|
|
/** @todo make this possible to do inside CORRADE_BENCHMARK() */
|
||
|
|
for(std::size_t i = 0; i != WarmupIterations; ++i)
|
||
|
|
shader.draw(_mesh);
|
||
|
|
|
||
|
|
CORRADE_BENCHMARK(BenchmarkIterations)
|
||
|
|
shader.draw(_mesh);
|
||
|
|
|
||
|
|
MAGNUM_VERIFY_NO_GL_ERROR();
|
||
|
|
|
||
|
|
CORRADE_COMPARE_WITH(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}),
|
||
|
|
Utility::Directory::join(SHADERS_TEST_DIR, "BenchmarkFiles/trivial.tga"),
|
||
|
|
DebugTools::CompareImageToFile{_manager});
|
||
|
|
}
|
||
|
|
|
||
|
|
template<UnsignedInt dimensions> void ShadersGLBenchmark::distanceFieldVector() {
|
||
|
|
auto&& data = DistanceFieldVectorData[testCaseInstanceId()];
|
||
|
|
setTestCaseTemplateName(Utility::formatString("{}", dimensions));
|
||
|
|
setTestCaseDescription(data.name);
|
||
|
|
|
||
|
|
if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
|
||
|
|
!(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
|
||
|
|
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found.");
|
||
|
|
|
||
|
|
DistanceFieldVectorGL<dimensions> shader{data.flags};
|
||
|
|
shader.bindVectorTexture(_textureWhite);
|
||
|
|
|
||
|
|
/* Warmup run */
|
||
|
|
/** @todo make this possible to do inside CORRADE_BENCHMARK() */
|
||
|
|
for(std::size_t i = 0; i != WarmupIterations; ++i)
|
||
|
|
shader.draw(_mesh);
|
||
|
|
|
||
|
|
CORRADE_BENCHMARK(BenchmarkIterations)
|
||
|
|
shader.draw(_mesh);
|
||
|
|
|
||
|
|
MAGNUM_VERIFY_NO_GL_ERROR();
|
||
|
|
|
||
|
|
CORRADE_COMPARE_WITH(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}),
|
||
|
|
Utility::Directory::join(SHADERS_TEST_DIR, "BenchmarkFiles/trivial.tga"),
|
||
|
|
DebugTools::CompareImageToFile{_manager});
|
||
|
|
}
|
||
|
|
|
||
|
|
void ShadersGLBenchmark::meshVisualizer2D() {
|
||
|
|
auto&& data = MeshVisualizer2DData[testCaseInstanceId()];
|
||
|
|
setTestCaseDescription(data.name);
|
||
|
|
|
||
|
|
if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
|
||
|
|
!(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
|
||
|
|
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found.");
|
||
|
|
|
||
|
|
/* Checks verbatim copied from MeshVisualizerGLTest::construct2D() */
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
if((data.flags & MeshVisualizerGL2D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported<GL::Extensions::EXT::gpu_shader4>())
|
||
|
|
CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported.");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
|
||
|
|
if(data.flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId &&
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
!GL::Context::current().isVersionSupported(GL::Version::GL300)
|
||
|
|
#else
|
||
|
|
!GL::Context::current().isVersionSupported(GL::Version::GLES300)
|
||
|
|
#endif
|
||
|
|
) CORRADE_SKIP("gl_VertexID not supported.");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
|
||
|
|
if(data.flags & MeshVisualizerGL2D::Flag::PrimitiveId && !(data.flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId) &&
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
!GL::Context::current().isVersionSupported(GL::Version::GL320)
|
||
|
|
#else
|
||
|
|
!GL::Context::current().isVersionSupported(GL::Version::GLES320)
|
||
|
|
#endif
|
||
|
|
) CORRADE_SKIP("gl_PrimitiveID not supported.");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
|
||
|
|
if((data.flags & MeshVisualizerGL2D::Flag::Wireframe) && !(data.flags & MeshVisualizerGL2D::Flag::NoGeometryShader)) {
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::geometry_shader4>())
|
||
|
|
CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported.");
|
||
|
|
#else
|
||
|
|
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::geometry_shader>())
|
||
|
|
CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported.");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef MAGNUM_TARGET_GLES
|
||
|
|
if(GL::Context::current().isExtensionSupported<GL::Extensions::NV::shader_noperspective_interpolation>())
|
||
|
|
CORRADE_INFO("Using" << GL::Extensions::NV::shader_noperspective_interpolation::string());
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
MeshVisualizerGL2D shader{data.flags};
|
||
|
|
shader.setViewportSize(Vector2{RenderSize});
|
||
|
|
if(data.flags >= MeshVisualizerGL2D::Flag::Wireframe)
|
||
|
|
shader.setWireframeColor(0xffffffff_rgbaf);
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
if(data.flags & (MeshVisualizerGL2D::Flag::InstancedObjectId|MeshVisualizerGL2D::Flag::VertexId|MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId
|
||
|
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
|
|MeshVisualizerGL2D::Flag::PrimitiveId
|
||
|
|
#endif
|
||
|
|
))
|
||
|
|
shader.bindColorMapTexture(_textureWhite);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
GL::Mesh* mesh;
|
||
|
|
if(data.flags >= MeshVisualizerGL2D::Flag::NoGeometryShader) {
|
||
|
|
mesh = &_meshDuplicated;
|
||
|
|
}
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
else if(data.flags & MeshVisualizerGL2D::Flag::InstancedObjectId) {
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::draw_instanced>())
|
||
|
|
CORRADE_SKIP(GL::Extensions::ARB::draw_instanced::string() << "is not supported.");
|
||
|
|
#endif
|
||
|
|
mesh = &_meshInstanced;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
else {
|
||
|
|
mesh = &_mesh;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Warmup run */
|
||
|
|
/** @todo make this possible to do inside CORRADE_BENCHMARK() */
|
||
|
|
for(std::size_t i = 0; i != WarmupIterations; ++i)
|
||
|
|
shader.draw(*mesh);
|
||
|
|
|
||
|
|
CORRADE_BENCHMARK(BenchmarkIterations)
|
||
|
|
shader.draw(*mesh);
|
||
|
|
|
||
|
|
MAGNUM_VERIFY_NO_GL_ERROR();
|
||
|
|
|
||
|
|
CORRADE_COMPARE_WITH(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}),
|
||
|
|
Utility::Directory::join(SHADERS_TEST_DIR, "BenchmarkFiles/trivial.tga"),
|
||
|
|
DebugTools::CompareImageToFile{_manager});
|
||
|
|
}
|
||
|
|
|
||
|
|
void ShadersGLBenchmark::meshVisualizer3D() {
|
||
|
|
auto&& data = MeshVisualizer3DData[testCaseInstanceId()];
|
||
|
|
setTestCaseDescription(data.name);
|
||
|
|
|
||
|
|
if(!(_manager.loadState("AnyImageImporter") & PluginManager::LoadState::Loaded) ||
|
||
|
|
!(_manager.loadState("TgaImporter") & PluginManager::LoadState::Loaded))
|
||
|
|
CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found.");
|
||
|
|
|
||
|
|
/* Checks verbatim copied from MeshVisualizerGLTest:.construct3D() */
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
if((data.flags & MeshVisualizerGL3D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported<GL::Extensions::EXT::gpu_shader4>())
|
||
|
|
CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported.");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
|
||
|
|
if(data.flags >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId &&
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
!GL::Context::current().isVersionSupported(GL::Version::GL300)
|
||
|
|
#else
|
||
|
|
!GL::Context::current().isVersionSupported(GL::Version::GLES300)
|
||
|
|
#endif
|
||
|
|
) CORRADE_SKIP("gl_VertexID not supported.");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
|
||
|
|
if(data.flags & MeshVisualizerGL3D::Flag::PrimitiveId && !(data.flags >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId) &&
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
!GL::Context::current().isVersionSupported(GL::Version::GL320)
|
||
|
|
#else
|
||
|
|
!GL::Context::current().isVersionSupported(GL::Version::GLES320)
|
||
|
|
#endif
|
||
|
|
) CORRADE_SKIP("gl_PrimitiveID not supported.");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
|
||
|
|
if(((data.flags & MeshVisualizerGL3D::Flag::Wireframe) && !(data.flags & MeshVisualizerGL3D::Flag::NoGeometryShader)) || (data.flags & (MeshVisualizerGL3D::Flag::TangentDirection|MeshVisualizerGL3D::Flag::BitangentDirection|MeshVisualizerGL3D::Flag::BitangentFromTangentDirection|MeshVisualizerGL3D::Flag::NormalDirection))) {
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::geometry_shader4>())
|
||
|
|
CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported.");
|
||
|
|
#else
|
||
|
|
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::geometry_shader>())
|
||
|
|
CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported.");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef MAGNUM_TARGET_GLES
|
||
|
|
if(GL::Context::current().isExtensionSupported<GL::Extensions::NV::shader_noperspective_interpolation>())
|
||
|
|
CORRADE_INFO("Using" << GL::Extensions::NV::shader_noperspective_interpolation::string());
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
MeshVisualizerGL3D shader{data.flags};
|
||
|
|
shader.setViewportSize(Vector2{RenderSize});
|
||
|
|
if(data.flags >= MeshVisualizerGL3D::Flag::Wireframe)
|
||
|
|
shader.setWireframeColor(0xffffffff_rgbaf);
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
if(data.flags & (MeshVisualizerGL3D::Flag::InstancedObjectId|MeshVisualizerGL3D::Flag::VertexId|MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId
|
||
|
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
|
|MeshVisualizerGL3D::Flag::PrimitiveId
|
||
|
|
#endif
|
||
|
|
))
|
||
|
|
shader.bindColorMapTexture(_textureWhite);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
GL::Mesh* mesh;
|
||
|
|
if(data.flags >= MeshVisualizerGL3D::Flag::NoGeometryShader)
|
||
|
|
mesh = &_meshDuplicated;
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
else if(data.flags & MeshVisualizerGL3D::Flag::InstancedObjectId)
|
||
|
|
mesh = &_meshInstanced;
|
||
|
|
#endif
|
||
|
|
else
|
||
|
|
mesh = &_mesh;
|
||
|
|
|
||
|
|
/* Warmup run */
|
||
|
|
/** @todo make this possible to do inside CORRADE_BENCHMARK() */
|
||
|
|
for(std::size_t i = 0; i != WarmupIterations; ++i)
|
||
|
|
shader.draw(*mesh);
|
||
|
|
|
||
|
|
CORRADE_BENCHMARK(BenchmarkIterations)
|
||
|
|
shader.draw(*mesh);
|
||
|
|
|
||
|
|
MAGNUM_VERIFY_NO_GL_ERROR();
|
||
|
|
|
||
|
|
CORRADE_COMPARE_WITH(_framebuffer.read(_framebuffer.viewport(), {PixelFormat::RGBA8Unorm}),
|
||
|
|
Utility::Directory::join(SHADERS_TEST_DIR, "BenchmarkFiles/trivial.tga"),
|
||
|
|
DebugTools::CompareImageToFile{_manager});
|
||
|
|
}
|
||
|
|
|
||
|
|
}}}}
|
||
|
|
|
||
|
|
CORRADE_TEST_MAIN(Magnum::Shaders::Test::ShadersGLBenchmark)
|