mirror of https://github.com/mosra/magnum.git
Browse Source
Took me a while (several years?) to figure out a way to benchmark this without basically duplicating the testing effort and without new variants being too hard to add.pull/518/head
10 changed files with 827 additions and 7 deletions
Binary file not shown.
@ -0,0 +1,800 @@ |
|||||||
|
/*
|
||||||
|
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) |
||||||
Loading…
Reference in new issue