560 lines
26 KiB
C++
560 lines
26 KiB
C++
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
|
|
|
#pragma once
|
|
|
|
#if GRAPHICS_API_OPENGL
|
|
|
|
#include "Engine/Graphics/Config.h"
|
|
#include "Engine/Graphics/GPULimits.h"
|
|
#include "Engine/Graphics/RenderTools.h"
|
|
#include "GPUDeviceOGL.h"
|
|
#if BUILD_DEBUG
|
|
#include "Engine/Core/Types/StringBuilder.h"
|
|
#endif
|
|
|
|
struct TextureFormatOGL
|
|
{
|
|
public:
|
|
|
|
GLenum InternalFormat;
|
|
GLenum Format;
|
|
GLenum Type;
|
|
bool IsCompressed;
|
|
|
|
public:
|
|
|
|
TextureFormatOGL()
|
|
{
|
|
InternalFormat = GL_NONE;
|
|
Format = GL_NONE;
|
|
Type = GL_NONE;
|
|
IsCompressed = false;
|
|
}
|
|
|
|
TextureFormatOGL(GLenum internalFormat, GLenum format, GLenum type, bool isCompressed = false, bool isBGRA = false)
|
|
{
|
|
InternalFormat = internalFormat;
|
|
Format = format;
|
|
Type = type;
|
|
IsCompressed = isCompressed;
|
|
}
|
|
};
|
|
|
|
/// <summary>
|
|
/// Implementation of GPU Limits for OpenGL
|
|
/// </summary>
|
|
/// <seealso cref="GPULimits" />
|
|
class GPULimitsOGL : public GPULimits
|
|
{
|
|
protected:
|
|
|
|
GPUDeviceOGL * _device;
|
|
|
|
public:
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="GPULimitsOGL"/> class.
|
|
/// </summary>
|
|
/// <param name="device">The device.</param>
|
|
GPULimitsOGL(GPUDeviceOGL* device)
|
|
: _device(device)
|
|
{
|
|
}
|
|
|
|
public:
|
|
|
|
bool SupportsTessellation;
|
|
bool SupportsGPUMemoryInfo;
|
|
bool SupportsComputeShaders;
|
|
bool SupportsVertexAttribBinding;
|
|
bool SupportsTextureView;
|
|
bool SupportsVolumeTextureRendering;
|
|
bool SupportsASTC;
|
|
bool SupportsCopyImage;
|
|
bool SupportsSeamlessCubemap;
|
|
bool SupportsTextureFilterAnisotropic;
|
|
bool SupportsDrawBuffersBlend;
|
|
bool SupportsSeparateShaderObjects;
|
|
bool SupportsClipControl;
|
|
|
|
uint64 VideoMemorySize;
|
|
int32 MaxTextureMipCount;
|
|
int32 MaxTextureSize;
|
|
int32 MaxCubeTextureSize;
|
|
int32 MaxVolumeTextureSize;
|
|
int32 MaxTextureArraySize;
|
|
int32 MaxOpenGLDrawBuffers;
|
|
int32 MaxTextureImageUnits;
|
|
int32 MaxCombinedTextureImageUnits;
|
|
int32 MaxVertexTextureImageUnits;
|
|
int32 MaxGeometryTextureImageUnits;
|
|
int32 MaxHullTextureImageUnits;
|
|
int32 MaxDomainTextureImageUnits;
|
|
int32 MaxVaryingVectors;
|
|
int32 MaxVertexUniformComponents;
|
|
int32 MaxPixelUniformComponents;
|
|
int32 MaxGeometryUniformComponents;
|
|
int32 MaxHullUniformComponents;
|
|
int32 MaxDomainUniformComponents;
|
|
int32 MaxComputeTextureImageUnits;
|
|
int32 MaxComputeUniformComponents;
|
|
|
|
TextureFormatOGL TextureFormats[static_cast<int32>(PixelFormat::Maximum)];
|
|
|
|
public:
|
|
|
|
GLenum GetInternalTextureFormat(PixelFormat format)
|
|
{
|
|
return TextureFormats[(int32)format].InternalFormat;
|
|
}
|
|
|
|
GLenum GetInternalTextureFormat(PixelFormat format, GPUTextureFlags flags)
|
|
{
|
|
GLenum f = TextureFormats[(int32)format].InternalFormat;
|
|
|
|
// Correct GL texure format
|
|
if (flags & GPUTextureFlags::DepthStencil)
|
|
{
|
|
if (f == GL_R32F)
|
|
f = GL_DEPTH_COMPONENT32F;
|
|
else if (f == GL_R16)
|
|
f = GL_DEPTH_COMPONENT16;
|
|
}
|
|
|
|
return f;
|
|
}
|
|
|
|
private:
|
|
|
|
void InitFormats()
|
|
{
|
|
// References:
|
|
// http://www.opengl.org/wiki/Image_Format
|
|
// http://www.g-truc.net/post-0335.html
|
|
// http://renderingpipeline.com/2012/07/texture-compression/
|
|
|
|
TextureFormats[(int32)PixelFormat::Unknown] = TextureFormatOGL();
|
|
|
|
TextureFormats[(int32)PixelFormat::R32G32B32A32_Typeless] = TextureFormatOGL(GL_RGBA32F, GL_RGBA, GL_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::R32G32B32A32_Float] = TextureFormatOGL(GL_RGBA32F, GL_RGBA, GL_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::R32G32B32A32_UInt] = TextureFormatOGL(GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT);
|
|
TextureFormats[(int32)PixelFormat::R32G32B32A32_SInt] = TextureFormatOGL(GL_RGBA32I, GL_RGBA_INTEGER, GL_INT);
|
|
|
|
TextureFormats[(int32)PixelFormat::R32G32B32_Typeless] = TextureFormatOGL(GL_RGB32F, GL_RGB, GL_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::R32G32B32_Float] = TextureFormatOGL(GL_RGB32F, GL_RGB, GL_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::R32G32B32_UInt] = TextureFormatOGL(GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT);
|
|
TextureFormats[(int32)PixelFormat::R32G32B32_SInt] = TextureFormatOGL(GL_RGB32I, GL_RGB_INTEGER, GL_INT);
|
|
|
|
TextureFormats[(int32)PixelFormat::R16G16B16A16_Typeless] = TextureFormatOGL(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::R16G16B16A16_Float] = TextureFormatOGL(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::R16G16B16A16_UNorm] = TextureFormatOGL(GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT);
|
|
TextureFormats[(int32)PixelFormat::R16G16B16A16_UInt] = TextureFormatOGL(GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT);
|
|
TextureFormats[(int32)PixelFormat::R16G16B16A16_SNorm] = TextureFormatOGL(GL_RGBA16_SNORM, GL_RGBA, GL_SHORT);
|
|
TextureFormats[(int32)PixelFormat::R16G16B16A16_SInt] = TextureFormatOGL(GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT);
|
|
|
|
TextureFormats[(int32)PixelFormat::R32G32_Typeless] = TextureFormatOGL(GL_RG32F, GL_RG, GL_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::R32G32_Float] = TextureFormatOGL(GL_RG32F, GL_RG, GL_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::R32G32_UInt] = TextureFormatOGL(GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT);
|
|
TextureFormats[(int32)PixelFormat::R32G32_SInt] = TextureFormatOGL(GL_RG32I, GL_RG_INTEGER, GL_INT);
|
|
|
|
TextureFormats[(int32)PixelFormat::R32G8X24_Typeless] = TextureFormatOGL(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
|
|
TextureFormats[(int32)PixelFormat::D32_Float_S8X24_UInt] = TextureFormatOGL(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
|
|
TextureFormats[(int32)PixelFormat::R32_Float_X8X24_Typeless] = TextureFormatOGL(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
|
|
TextureFormats[(int32)PixelFormat::X32_Typeless_G8X24_UInt] = TextureFormatOGL(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
|
|
|
|
TextureFormats[(int32)PixelFormat::R10G10B10A2_Typeless] = TextureFormatOGL(GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV);
|
|
TextureFormats[(int32)PixelFormat::R10G10B10A2_UNorm] = TextureFormatOGL(GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV);
|
|
TextureFormats[(int32)PixelFormat::R10G10B10A2_UInt] = TextureFormatOGL(GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV);
|
|
TextureFormats[(int32)PixelFormat::R11G11B10_Float] = TextureFormatOGL(GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV);
|
|
|
|
TextureFormats[(int32)PixelFormat::R8G8B8A8_Typeless] = TextureFormatOGL(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
|
|
TextureFormats[(int32)PixelFormat::R8G8B8A8_UNorm] = TextureFormatOGL(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
|
|
TextureFormats[(int32)PixelFormat::R8G8B8A8_UNorm_sRGB] = TextureFormatOGL(GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE);
|
|
TextureFormats[(int32)PixelFormat::R8G8B8A8_UInt] = TextureFormatOGL(GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE);
|
|
TextureFormats[(int32)PixelFormat::R8G8B8A8_SNorm] = TextureFormatOGL(GL_RGBA8_SNORM, GL_RGBA, GL_BYTE);
|
|
TextureFormats[(int32)PixelFormat::R8G8B8A8_SInt] = TextureFormatOGL(GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE);
|
|
|
|
TextureFormats[(int32)PixelFormat::R16G16_Typeless] = TextureFormatOGL(GL_RG16F, GL_RG, GL_HALF_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::R16G16_Float] = TextureFormatOGL(GL_RG16F, GL_RG, GL_HALF_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::R16G16_UNorm] = TextureFormatOGL(GL_RG16, GL_RG, GL_UNSIGNED_SHORT);
|
|
TextureFormats[(int32)PixelFormat::R16G16_UInt] = TextureFormatOGL(GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT);
|
|
TextureFormats[(int32)PixelFormat::R16G16_SNorm] = TextureFormatOGL(GL_RG16_SNORM, GL_RG, GL_SHORT);
|
|
TextureFormats[(int32)PixelFormat::R16G16_SInt] = TextureFormatOGL(GL_RG16I, GL_RG_INTEGER, GL_SHORT);
|
|
|
|
TextureFormats[(int32)PixelFormat::R32_Typeless] = TextureFormatOGL(GL_R32F, GL_RED, GL_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::D32_Float] = TextureFormatOGL(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::R32_Float] = TextureFormatOGL(GL_R32F, GL_RED, GL_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::R32_UInt] = TextureFormatOGL(GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT);
|
|
TextureFormats[(int32)PixelFormat::R32_SInt] = TextureFormatOGL(GL_R32I, GL_RED_INTEGER, GL_INT);
|
|
|
|
TextureFormats[(int32)PixelFormat::R24G8_Typeless] = TextureFormatOGL(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
|
|
TextureFormats[(int32)PixelFormat::D24_UNorm_S8_UInt] = TextureFormatOGL(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
|
|
TextureFormats[(int32)PixelFormat::R24_UNorm_X8_Typeless] = TextureFormatOGL(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
|
|
TextureFormats[(int32)PixelFormat::X24_Typeless_G8_UInt] = TextureFormatOGL(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
|
|
|
|
TextureFormats[(int32)PixelFormat::R8G8_Typeless] = TextureFormatOGL(GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
|
|
TextureFormats[(int32)PixelFormat::R8G8_UNorm] = TextureFormatOGL(GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
|
|
TextureFormats[(int32)PixelFormat::R8G8_UInt] = TextureFormatOGL(GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE);
|
|
TextureFormats[(int32)PixelFormat::R8G8_SNorm] = TextureFormatOGL(GL_RG8_SNORM, GL_RG, GL_BYTE);
|
|
TextureFormats[(int32)PixelFormat::R8G8_SInt] = TextureFormatOGL(GL_RG8I, GL_RG_INTEGER, GL_BYTE);
|
|
|
|
TextureFormats[(int32)PixelFormat::R16_Typeless] = TextureFormatOGL(GL_R16F, GL_RED, GL_HALF_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::R16_Float] = TextureFormatOGL(GL_R16F, GL_RED, GL_HALF_FLOAT);
|
|
TextureFormats[(int32)PixelFormat::D16_UNorm] = TextureFormatOGL(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
|
|
TextureFormats[(int32)PixelFormat::R16_UNorm] = TextureFormatOGL(GL_R16, GL_RED, GL_UNSIGNED_SHORT);
|
|
TextureFormats[(int32)PixelFormat::R16_UInt] = TextureFormatOGL(GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT);
|
|
TextureFormats[(int32)PixelFormat::R16_SNorm] = TextureFormatOGL(GL_R16_SNORM, GL_RED, GL_SHORT);
|
|
TextureFormats[(int32)PixelFormat::R16_SInt] = TextureFormatOGL(GL_R16I, GL_RED_INTEGER, GL_SHORT);
|
|
|
|
TextureFormats[(int32)PixelFormat::R8_Typeless] = TextureFormatOGL(GL_R8, GL_RED, GL_UNSIGNED_BYTE);
|
|
TextureFormats[(int32)PixelFormat::R8_UNorm] = TextureFormatOGL(GL_R8, GL_RED, GL_UNSIGNED_BYTE);
|
|
TextureFormats[(int32)PixelFormat::R8_UInt] = TextureFormatOGL(GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE);
|
|
TextureFormats[(int32)PixelFormat::R8_SNorm] = TextureFormatOGL(GL_R8_SNORM, GL_RED, GL_BYTE);
|
|
TextureFormats[(int32)PixelFormat::R8_SInt] = TextureFormatOGL(GL_R8I, GL_RED_INTEGER, GL_BYTE);
|
|
TextureFormats[(int32)PixelFormat::A8_UNorm] = TextureFormatOGL();
|
|
|
|
TextureFormats[(int32)PixelFormat::R1_UNorm] = TextureFormatOGL();
|
|
|
|
TextureFormats[(int32)PixelFormat::R9G9B9E5_SharedExp] = TextureFormatOGL(GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV);
|
|
TextureFormats[(int32)PixelFormat::R8G8_B8G8_UNorm] = TextureFormatOGL();
|
|
TextureFormats[(int32)PixelFormat::G8R8_G8B8_UNorm] = TextureFormatOGL();
|
|
|
|
TextureFormats[(int32)PixelFormat::BC1_Typeless] = TextureFormatOGL(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC1_UNorm] = TextureFormatOGL(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC1_UNorm_sRGB] = TextureFormatOGL(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC2_Typeless] = TextureFormatOGL(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC2_UNorm] = TextureFormatOGL(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC2_UNorm_sRGB] = TextureFormatOGL(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC3_Typeless] = TextureFormatOGL(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC3_UNorm] = TextureFormatOGL(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC3_UNorm_sRGB] = TextureFormatOGL(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC4_Typeless] = TextureFormatOGL(GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC4_UNorm] = TextureFormatOGL(GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC4_SNorm] = TextureFormatOGL(GL_COMPRESSED_SIGNED_RED_RGTC1, GL_RED, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC5_Typeless] = TextureFormatOGL(GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC5_UNorm] = TextureFormatOGL(GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC5_SNorm] = TextureFormatOGL(GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::B5G6R5_UNorm] = TextureFormatOGL(GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV);
|
|
TextureFormats[(int32)PixelFormat::B5G5R5A1_UNorm] = TextureFormatOGL(GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV);
|
|
TextureFormats[(int32)PixelFormat::B8G8R8A8_UNorm] = TextureFormatOGL();
|
|
TextureFormats[(int32)PixelFormat::B8G8R8X8_UNorm] = TextureFormatOGL();
|
|
TextureFormats[(int32)PixelFormat::R10G10B10_Xr_Bias_A2_UNorm] = TextureFormatOGL();
|
|
TextureFormats[(int32)PixelFormat::B8G8R8A8_Typeless] = TextureFormatOGL(GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV);
|
|
TextureFormats[(int32)PixelFormat::B8G8R8A8_UNorm_sRGB] = TextureFormatOGL(GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV);
|
|
TextureFormats[(int32)PixelFormat::B8G8R8X8_Typeless] = TextureFormatOGL(GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV);
|
|
TextureFormats[(int32)PixelFormat::B8G8R8X8_UNorm_sRGB] = TextureFormatOGL(GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV);
|
|
TextureFormats[(int32)PixelFormat::BC6H_Typeless] = TextureFormatOGL(GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, GL_RGB, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC6H_Uf16] = TextureFormatOGL(GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, GL_RGB, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC6H_Sf16] = TextureFormatOGL(GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, GL_RGB, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC7_Typeless] = TextureFormatOGL(GL_COMPRESSED_RGBA_BPTC_UNORM, GL_RGB, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC7_UNorm] = TextureFormatOGL(GL_COMPRESSED_RGBA_BPTC_UNORM, GL_RGB, GL_UNSIGNED_BYTE, true);
|
|
TextureFormats[(int32)PixelFormat::BC7_UNorm_sRGB] = TextureFormatOGL(GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, GL_RGB, GL_UNSIGNED_BYTE, true);
|
|
|
|
// Check features for each PixelFormat
|
|
for (int32 i = 0; i < static_cast<int32>(PixelFormat::Maximum); i++)
|
|
{
|
|
// TODO: try to detect MSAA or some feature levels like on D3D11
|
|
auto format = static_cast<PixelFormat>(i);
|
|
auto& info = TextureFormats[i];
|
|
FormatSupport support = FormatSupport::None;
|
|
if (info.Format != 0)
|
|
{
|
|
support = FormatSupport::Texture1D | FormatSupport::Texture2D | FormatSupport::Texture3D | FormatSupport::DepthStencil | FormatSupport::Buffer;
|
|
}
|
|
_featuresPerFormat[i] = FeaturesPerFormat(format, MSAALevel::None, support);
|
|
}
|
|
}
|
|
|
|
#if BUILD_DEBUG
|
|
|
|
void PrintStats()
|
|
{
|
|
#define PRINT_STAT(name) sb.AppendFormat(TEXT("{0} = {1}\n"), TEXT(#name), name)
|
|
|
|
StringBuilder sb;
|
|
sb.AppendLine();
|
|
sb.AppendLine();
|
|
|
|
auto adapter = (AdapterOGL*)_device->GetAdapter();
|
|
sb.AppendFormat(TEXT("OpenGL {0}.{1}\n"), adapter->VersionMajor, adapter->VersionMinor);
|
|
|
|
sb.AppendLine();
|
|
PRINT_STAT(SupportsTessellation);
|
|
PRINT_STAT(SupportsGPUMemoryInfo);
|
|
PRINT_STAT(SupportsComputeShaders);
|
|
PRINT_STAT(SupportsVertexAttribBinding);
|
|
PRINT_STAT(SupportsTextureView);
|
|
PRINT_STAT(SupportsVolumeTextureRendering);
|
|
PRINT_STAT(SupportsASTC);
|
|
PRINT_STAT(SupportsCopyImage);
|
|
PRINT_STAT(SupportsSeamlessCubemap);
|
|
PRINT_STAT(SupportsTextureFilterAnisotropic);
|
|
PRINT_STAT(SupportsDrawBuffersBlend);
|
|
PRINT_STAT(SupportsSeparateShaderObjects);
|
|
PRINT_STAT(SupportsClipControl);
|
|
|
|
sb.AppendLine();
|
|
PRINT_STAT(VideoMemorySize);
|
|
PRINT_STAT(MaxTextureMipCount);
|
|
PRINT_STAT(MaxTextureSize);
|
|
PRINT_STAT(MaxCubeTextureSize);
|
|
PRINT_STAT(MaxVolumeTextureSize);
|
|
PRINT_STAT(MaxTextureArraySize);
|
|
PRINT_STAT(MaxOpenGLDrawBuffers);
|
|
PRINT_STAT(MaxTextureImageUnits);
|
|
PRINT_STAT(MaxCombinedTextureImageUnits);
|
|
PRINT_STAT(MaxVertexTextureImageUnits);
|
|
PRINT_STAT(MaxGeometryTextureImageUnits);
|
|
PRINT_STAT(MaxHullTextureImageUnits);
|
|
PRINT_STAT(MaxDomainTextureImageUnits);
|
|
PRINT_STAT(MaxVaryingVectors);
|
|
PRINT_STAT(MaxVertexUniformComponents);
|
|
PRINT_STAT(MaxPixelUniformComponents);
|
|
PRINT_STAT(MaxGeometryUniformComponents);
|
|
PRINT_STAT(MaxHullUniformComponents);
|
|
PRINT_STAT(MaxDomainUniformComponents);
|
|
PRINT_STAT(MaxComputeTextureImageUnits);
|
|
PRINT_STAT(MaxComputeUniformComponents);
|
|
|
|
sb.AppendLine();
|
|
|
|
LOG_STR(Info, sb.ToString());
|
|
|
|
#undef PRINT_STAT
|
|
}
|
|
|
|
#endif
|
|
|
|
public:
|
|
|
|
// [GPULimits]
|
|
bool Init() override
|
|
{
|
|
auto adapter = (AdapterOGL*)_device->GetAdapter();
|
|
auto VersionMajor = adapter->VersionMajor;
|
|
auto VersionMinor = adapter->VersionMinor;
|
|
|
|
// Test graphics pipeline features support
|
|
SupportsTessellation = (VersionMajor >= 4) || adapter->HasExtension("GL_ARB_tessellation_shader");
|
|
SupportsGPUMemoryInfo = adapter->HasExtension("GL_NVX_gpu_memory_info");
|
|
SupportsComputeShaders = (VersionMajor == 4 && VersionMinor >= 3) || (VersionMajor > 4) || adapter->HasExtension("GL_ARB_compute_shader");
|
|
SupportsVertexAttribBinding = (VersionMajor == 4 && VersionMinor >= 3) || (VersionMajor > 4) || adapter->HasExtension("GL_ARB_vertex_attrib_binding");
|
|
SupportsTextureView = (VersionMajor == 4 && VersionMinor >= 3) || (VersionMajor > 4) || adapter->HasExtension("GL_ARB_texture_view");
|
|
SupportsASTC = adapter->HasExtension("GL_KHR_texture_compression_astc_ldr");
|
|
SupportsCopyImage = adapter->HasExtension("GL_ARB_copy_image");
|
|
SupportsSeamlessCubemap = adapter->HasExtension("GL_ARB_seamless_cube_map");
|
|
SupportsTextureFilterAnisotropic = adapter->HasExtension("GL_EXT_texture_filter_anisotropic");
|
|
SupportsDrawBuffersBlend = adapter->HasExtension("GL_ARB_draw_buffers_blend");
|
|
SupportsClipControl = adapter->HasExtension("GL_ARB_clip_control");
|
|
#if GRAPHICS_API_OPENGL_ES
|
|
SupportsSeparateShaderObjects = false;
|
|
#else
|
|
SupportsSeparateShaderObjects = (VersionMajor == 4 && VersionMinor >= 4) || adapter->HasExtension("GL_ARB_separate_shader_objects");
|
|
#endif
|
|
|
|
// Get video memory size (in bytes)
|
|
VideoMemorySize = 0;
|
|
if (SupportsGPUMemoryInfo)
|
|
{
|
|
GLint VMSizeKB = 0;
|
|
glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &VMSizeKB);
|
|
VideoMemorySize = VMSizeKB * 1024ll;
|
|
}
|
|
|
|
// Test whether the GPU can support volume-texture rendering.
|
|
// There is no API to query this - you just have to test whether a 3D texture is framebuffer-complete.
|
|
{
|
|
GLuint frameBuffer;
|
|
glGenFramebuffers(1, &frameBuffer);
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer);
|
|
GLuint volumeTexture;
|
|
glGenTextures(1, &volumeTexture);
|
|
glBindTexture(GL_TEXTURE_3D, volumeTexture);
|
|
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 256, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, volumeTexture, 0);
|
|
|
|
SupportsVolumeTextureRendering = (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
|
|
|
|
glDeleteTextures(1, &volumeTexture);
|
|
glDeleteFramebuffers(1, &frameBuffer);
|
|
}
|
|
|
|
// Get the device limits with OpenGL API
|
|
#define LOG_AND_GET_GL_INT_TEMP(IntEnum, Default) GLint Value_##IntEnum = Default; if (IntEnum) {glGetIntegerv(IntEnum, &Value_##IntEnum); glGetError();} else {Value_##IntEnum = Default;}
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_TEXTURE_SIZE, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_CUBE_MAP_TEXTURE_SIZE, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_ARRAY_TEXTURE_LAYERS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_3D_TEXTURE_SIZE, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_RENDERBUFFER_SIZE, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_TEXTURE_IMAGE_UNITS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_DRAW_BUFFERS, 1);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_COLOR_ATTACHMENTS, 1);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_SAMPLES, 1);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_COLOR_TEXTURE_SAMPLES, 1);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_DEPTH_TEXTURE_SAMPLES, 1);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_INTEGER_SAMPLES, 1);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_VERTEX_ATTRIBS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_VERTEX_UNIFORM_COMPONENTS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_VARYING_VECTORS, 0);
|
|
|
|
// Setup the actual limits
|
|
MaxTextureSize = Value_GL_MAX_TEXTURE_SIZE;
|
|
MaxTextureMipCount = Math::Min<int32>(GPU_MAX_TEXTURE_MIP_LEVELS, MipLevelsCount(MaxTextureSize));
|
|
MaxCubeTextureSize = Value_GL_MAX_CUBE_MAP_TEXTURE_SIZE;
|
|
MaxTextureArraySize = Value_GL_MAX_ARRAY_TEXTURE_LAYERS;
|
|
MaxVolumeTextureSize = MaxCubeTextureSize;
|
|
MaxOpenGLDrawBuffers = Value_GL_MAX_DRAW_BUFFERS;
|
|
MaxTextureImageUnits = Value_GL_MAX_TEXTURE_IMAGE_UNITS;
|
|
MaxCombinedTextureImageUnits = Value_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS;
|
|
MaxVertexTextureImageUnits = Value_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS;
|
|
MaxGeometryTextureImageUnits = Value_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS;
|
|
MaxHullTextureImageUnits = Value_GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS;
|
|
MaxDomainTextureImageUnits = Value_GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS;
|
|
MaxVaryingVectors = Value_GL_MAX_VARYING_VECTORS;
|
|
MaxVertexUniformComponents = Value_GL_MAX_VERTEX_UNIFORM_COMPONENTS;
|
|
MaxPixelUniformComponents = Value_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS;
|
|
MaxGeometryUniformComponents = Value_GL_MAX_GEOMETRY_UNIFORM_COMPONENTS;
|
|
if (SupportsTessellation)
|
|
{
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS, 0);
|
|
MaxHullUniformComponents = Value_GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS;
|
|
MaxDomainUniformComponents = Value_GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS;
|
|
}
|
|
else
|
|
{
|
|
MaxHullUniformComponents = 0;
|
|
MaxDomainUniformComponents = 0;
|
|
}
|
|
if (SupportsComputeShaders)
|
|
{
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, 0);
|
|
LOG_AND_GET_GL_INT_TEMP(GL_MAX_COMPUTE_UNIFORM_COMPONENTS, 0);
|
|
MaxComputeTextureImageUnits = Value_GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS;
|
|
MaxComputeUniformComponents = Value_GL_MAX_COMPUTE_UNIFORM_COMPONENTS;
|
|
}
|
|
else
|
|
{
|
|
MaxComputeTextureImageUnits = 0;
|
|
MaxComputeUniformComponents = 0;
|
|
}
|
|
|
|
// For now, just allocate additional units if available and advertise no tessellation units for HW that can't handle more
|
|
if (MaxCombinedTextureImageUnits < 48)
|
|
{
|
|
// To work around AMD driver limitation of 32 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
|
|
// Going to hard code this for now (16 units in PS, 8 units in VS, 8 units in GS).
|
|
// This is going to be a problem for tessellation.
|
|
MaxTextureImageUnits = MaxTextureImageUnits > 16 ? 16 : MaxTextureImageUnits;
|
|
MaxVertexTextureImageUnits = MaxVertexTextureImageUnits > 8 ? 8 : MaxVertexTextureImageUnits;
|
|
MaxGeometryTextureImageUnits = MaxGeometryTextureImageUnits > 8 ? 8 : MaxGeometryTextureImageUnits;
|
|
MaxHullTextureImageUnits = 0;
|
|
MaxDomainTextureImageUnits = 0;
|
|
MaxCombinedTextureImageUnits = MaxCombinedTextureImageUnits > 32 ? 32 : MaxCombinedTextureImageUnits;
|
|
}
|
|
else
|
|
{
|
|
// Clamp things to the levels that the other path is going, but allow additional units for tessellation
|
|
MaxTextureImageUnits = MaxTextureImageUnits > 16 ? 16 : MaxTextureImageUnits;
|
|
MaxVertexTextureImageUnits = MaxVertexTextureImageUnits > 8 ? 8 : MaxVertexTextureImageUnits;
|
|
MaxGeometryTextureImageUnits = MaxGeometryTextureImageUnits > 8 ? 8 : MaxGeometryTextureImageUnits;
|
|
MaxHullTextureImageUnits = MaxHullTextureImageUnits > 8 ? 8 : MaxHullTextureImageUnits;
|
|
MaxDomainTextureImageUnits = MaxDomainTextureImageUnits > 8 ? 8 : MaxDomainTextureImageUnits;
|
|
MaxCombinedTextureImageUnits = MaxCombinedTextureImageUnits > 48 ? 48 : MaxCombinedTextureImageUnits;
|
|
}
|
|
|
|
InitFormats();
|
|
|
|
#if BUILD_DEBUG
|
|
PrintStats();
|
|
#endif
|
|
|
|
// Validate minimum specs for the engine to start
|
|
if (!SupportsTextureView)
|
|
{
|
|
LOG(Error, "The GPU does not meet minimal requirements.");
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
bool HasCompute() const override
|
|
{
|
|
return SupportsComputeShaders;
|
|
}
|
|
bool HasTessellation() const override
|
|
{
|
|
return SupportsTessellation;
|
|
}
|
|
bool HasGeometryShaders() const override
|
|
{
|
|
#if GRAPHICS_API_OPENGLES
|
|
return false;
|
|
#else
|
|
return true;
|
|
#endif
|
|
}
|
|
bool HasVolumeTextureRendering() const override
|
|
{
|
|
return SupportsVolumeTextureRendering;
|
|
}
|
|
bool HasDrawIndirect() const override
|
|
{
|
|
return false;
|
|
}
|
|
bool HasAppendConsumeBuffers() const override
|
|
{
|
|
return false;
|
|
}
|
|
bool HasSeparateRenderTargetBlendState() const override
|
|
{
|
|
return false;
|
|
}
|
|
bool HasDepthAsSRV() const override
|
|
{
|
|
return true;
|
|
}
|
|
bool HasMultisampleDepthAsSRV() const override
|
|
{
|
|
return true;
|
|
}
|
|
int32 MaximumMipLevelsCount() const override
|
|
{
|
|
return MaxTextureMipCount;
|
|
}
|
|
int32 MaximumTexture1DSize() const override
|
|
{
|
|
return MaxTextureSize;
|
|
}
|
|
int32 MaximumTexture1DArraySize() const override
|
|
{
|
|
return MaxTextureArraySize;
|
|
}
|
|
int32 MaximumTexture2DSize() const override
|
|
{
|
|
return MaxTextureSize;
|
|
}
|
|
int32 MaximumTexture2DArraySize() const override
|
|
{
|
|
return MaxTextureArraySize;
|
|
}
|
|
int32 MaximumTexture3DSize() const override
|
|
{
|
|
return MaxVolumeTextureSize;
|
|
}
|
|
int32 MaximumTextureCubeSize() const override
|
|
{
|
|
return MaxCubeTextureSize;
|
|
}
|
|
};
|
|
|
|
#endif
|