From 48b3a4e8604cdce854a89c510a7ba64d348ab5a8 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 12 Aug 2021 16:38:54 -0300 Subject: [PATCH] Initial support for integer format textures. They can't be rendered to and ImageData can't use the formats, for now. --- src/common/pixelformat.cpp | 201 ++++++++++------- src/common/pixelformat.h | 34 +++ src/modules/graphics/Graphics.cpp | 6 + src/modules/graphics/Shader.cpp | 5 +- src/modules/graphics/Shader.h | 6 +- src/modules/graphics/Texture.cpp | 3 + src/modules/graphics/opengl/Graphics.cpp | 3 +- src/modules/graphics/opengl/OpenGL.cpp | 217 ++++++++++++++---- src/modules/graphics/opengl/OpenGL.h | 4 +- src/modules/graphics/opengl/Shader.cpp | 270 +++++++++++++---------- src/modules/graphics/opengl/Shader.h | 5 +- 11 files changed, 502 insertions(+), 252 deletions(-) diff --git a/src/common/pixelformat.cpp b/src/common/pixelformat.cpp index e0c80f838..8224c00c4 100644 --- a/src/common/pixelformat.cpp +++ b/src/common/pixelformat.cpp @@ -26,81 +26,99 @@ namespace love static PixelFormatInfo formatInfo[] = { - // components, blockW, blockH, blockSize, color, depth, stencil, compressed - { 0, 1, 1, 0, false, false, false, false }, // PIXELFORMAT_UNKNOWN + // components, blockW, blockH, blockSize, color, depth, stencil, compressed, dataType + { 0, 1, 1, 0, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_UNKNOWN - { 0, 1, 1, 0, true, false, false, false }, // PIXELFORMAT_NORMAL - { 0, 1, 1, 0, true, false, false, false }, // PIXELFORMAT_HDR + { 0, 1, 1, 0, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_NORMAL + { 0, 1, 1, 0, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_HDR - { 1, 1, 1, 1, true, false, false, false }, // PIXELFORMAT_R8_UNORM - { 1, 1, 1, 2, true, false, false, false }, // PIXELFORMAT_R16_UNORM - { 1, 1, 1, 2, true, false, false, false }, // PIXELFORMAT_R16_FLOAT - { 1, 1, 1, 4, true, false, false, false }, // PIXELFORMAT_R32_FLOAT + { 1, 1, 1, 1, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R8_UNORM + { 1, 1, 1, 1, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R8_INT + { 1, 1, 1, 1, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R8_UINT + { 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R16_UNORM + { 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R16_FLOAT + { 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R16_INT + { 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R16_UINT + { 1, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R32_FLOAT + { 1, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R32_INT + { 1, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R32_UINT - { 2, 1, 1, 2, true, false, false, false }, // PIXELFORMAT_RG8_UNORM - { 2, 1, 1, 2, true, false, false, false }, // PIXELFORMAT_LA8_UNORM - { 2, 1, 1, 4, true, false, false, false }, // PIXELFORMAT_RG16_UNORM - { 2, 1, 1, 4, true, false, false, false }, // PIXELFORMAT_RG16_FLOAT - { 2, 1, 1, 8, true, false, false, false }, // PIXELFORMAT_RG32_FLOAT + { 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG8_UNORM + { 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG8_INT + { 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG8_UINT + { 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_LA8_UNORM + { 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG16_UNORM + { 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG16_FLOAT + { 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG16_INT + { 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG16_UINT + { 2, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG32_FLOAT + { 2, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG32_INT + { 2, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG32_UINT - { 4, 1, 1, 4, true, false, false, false }, // PIXELFORMAT_RGBA8_UNORM - { 4, 1, 1, 4, true, false, false, false }, // PIXELFORMAT_sRGBA8_UNORM - { 4, 1, 1, 8, true, false, false, false }, // PIXELFORMAT_RGBA16_UNORM - { 4, 1, 1, 8, true, false, false, false }, // PIXELFORMAT_RGBA16_FLOAT - { 4, 1, 1, 16, true, false, false, false }, // PIXELFORMAT_RGBA32_FLOAT + { 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA8_UNORM + { 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_sRGBA8_UNORM + { 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA8_INT + { 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA8_UINT + { 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA16_UNORM + { 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA16_FLOAT + { 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA16_INT + { 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA16_UINT + { 4, 1, 1, 16, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA32_FLOAT + { 4, 1, 1, 16, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA32_INT + { 4, 1, 1, 16, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA32_UINT - { 4, 1, 1, 2, true, false, false, false }, // PIXELFORMAT_RGBA4_UNORM - { 4, 1, 1, 2, true, false, false, false }, // PIXELFORMAT_RGB5A1_UNORM - { 3, 1, 1, 2, true, false, false, false }, // PIXELFORMAT_RGB565_UNORM - { 4, 1, 1, 4, true, false, false, false }, // PIXELFORMAT_RGB10A2_UNORM - { 3, 1, 1, 4, true, false, false, false }, // PIXELFORMAT_RG11B10_FLOAT + { 4, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA4_UNORM + { 4, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB5A1_UNORM + { 3, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB565_UNORM + { 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB10A2_UNORM + { 3, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_RG11B10_FLOAT - { 1, 1, 1, 1, false, false, true , false }, // PIXELFORMAT_STENCIL8 - { 1, 1, 1, 2, false, true, false, false }, // PIXELFORMAT_DEPTH16_UNORM - { 1, 1, 1, 3, false, true, false, false }, // PIXELFORMAT_DEPTH24_UNORM - { 1, 1, 1, 4, false, true, false, false }, // PIXELFORMAT_DEPTH32_FLOAT - { 2, 1, 1, 4, false, true, true , false }, // PIXELFORMAT_DEPTH24_UNORM_STENCIL8 - { 2, 1, 1, 5, false, true, true , false }, // PIXELFORMAT_DEPTH32_FLOAT_STENCIL8 + { 1, 1, 1, 1, false, false, true , false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_STENCIL8 + { 1, 1, 1, 2, false, true, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH16_UNORM + { 1, 1, 1, 3, false, true, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM + { 1, 1, 1, 4, false, true, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT + { 2, 1, 1, 4, false, true, true , false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM_STENCIL8 + { 2, 1, 1, 5, false, true, true , false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT_STENCIL8 - { 3, 4, 4, 8, true, false, false, true }, // PIXELFORMAT_DXT1_UNORM - { 4, 4, 4, 16, true, false, false, true }, // PIXELFORMAT_DXT3_UNORM - { 4, 4, 4, 16, true, false, false, true }, // PIXELFORMAT_DXT5_UNORM - { 1, 4, 4, 8, true, false, false, true }, // PIXELFORMAT_BC4_UNORM - { 1, 4, 4, 8, true, false, false, true }, // PIXELFORMAT_BC4_SNORM - { 2, 4, 4, 16, true, false, false, true }, // PIXELFORMAT_BC5_UNORM - { 2, 4, 4, 16, true, false, false, true }, // PIXELFORMAT_BC5_SNORM - { 3, 4, 4, 16, true, false, false, true }, // PIXELFORMAT_BC6H_UFLOAT - { 3, 4, 4, 16, true, false, false, true }, // PIXELFORMAT_BC6H_FLOAT - { 4, 4, 4, 16, true, false, false, true }, // PIXELFORMAT_BC7_UNORM + { 3, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT1_UNORM + { 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT3_UNORM + { 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT5_UNORM + { 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC4_UNORM + { 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC4_SNORM + { 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC5_UNORM + { 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC5_SNORM + { 3, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_BC6H_UFLOAT + { 3, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_BC6H_FLOAT + { 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC7_UNORM - { 3, 16, 8, 32, true, false, false, true }, // PIXELFORMAT_PVR1_RGB2_UNORM - { 3, 8, 8, 32, true, false, false, true }, // PIXELFORMAT_PVR1_RGB4_UNORM - { 4, 16, 8, 32, true, false, false, true }, // PIXELFORMAT_PVR1_RGBA2_UNORM - { 4, 8, 8, 32, true, false, false, true }, // PIXELFORMAT_PVR1_RGBA4_UNORM + { 3, 16, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB2_UNORM + { 3, 8, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB4_UNORM + { 4, 16, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA2_UNORM + { 4, 8, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA4_UNORM - { 3, 4, 4, 8, true, false, false, true }, // PIXELFORMAT_ETC1_UNORM - { 3, 4, 4, 8, true, false, false, true }, // PIXELFORMAT_ETC2_RGB_UNORM - { 4, 4, 4, 16, true, false, false, true }, // PIXELFORMAT_ETC2_RGBA_UNORM - { 4, 4, 4, 8, true, false, false, true }, // PIXELFORMAT_ETC2_RGBA1_UNORM - { 1, 4, 4, 8, true, false, false, true }, // PIXELFORMAT_EAC_R_UNORM - { 1, 4, 4, 8, true, false, false, true }, // PIXELFORMAT_EAC_R_SNORM - { 2, 4, 4, 16, true, false, false, true }, // PIXELFORMAT_EAC_RG_UNORM - { 2, 4, 4, 16, true, false, false, true }, // PIXELFORMAT_EAC_RG_SNORM + { 3, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC1_UNORM + { 3, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGB_UNORM + { 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA_UNORM + { 4, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA1_UNORM + { 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_R_UNORM + { 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_R_SNORM + { 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_RG_UNORM + { 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_RG_SNORM - { 4, 4, 4, 1, true, false, false, true }, // PIXELFORMAT_ASTC_4x4 - { 4, 5, 4, 1, true, false, false, true }, // PIXELFORMAT_ASTC_5x4 - { 4, 5, 5, 1, true, false, false, true }, // PIXELFORMAT_ASTC_5x5 - { 4, 6, 5, 1, true, false, false, true }, // PIXELFORMAT_ASTC_6x5 - { 4, 6, 6, 1, true, false, false, true }, // PIXELFORMAT_ASTC_6x6 - { 4, 8, 5, 1, true, false, false, true }, // PIXELFORMAT_ASTC_8x5 - { 4, 8, 6, 1, true, false, false, true }, // PIXELFORMAT_ASTC_8x6 - { 4, 8, 8, 1, true, false, false, true }, // PIXELFORMAT_ASTC_8x8 - { 4, 8, 5, 1, true, false, false, true }, // PIXELFORMAT_ASTC_10x5 - { 4, 10, 6, 1, true, false, false, true }, // PIXELFORMAT_ASTC_10x6 - { 4, 10, 8, 1, true, false, false, true }, // PIXELFORMAT_ASTC_10x8 - { 4, 10, 10, 1, true, false, false, true }, // PIXELFORMAT_ASTC_10x10 - { 4, 12, 10, 1, true, false, false, true }, // PIXELFORMAT_ASTC_12x10 - { 4, 12, 12, 1, true, false, false, true }, // PIXELFORMAT_ASTC_12x12 + { 4, 4, 4, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_4x4 + { 4, 5, 4, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x4 + { 4, 5, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x5 + { 4, 6, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x5 + { 4, 6, 6, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x6 + { 4, 8, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x5 + { 4, 8, 6, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x6 + { 4, 8, 8, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x8 + { 4, 8, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x5 + { 4, 10, 6, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x6 + { 4, 10, 8, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x8 + { 4, 10, 10, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x10 + { 4, 12, 10, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x10 + { 4, 12, 12, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x12 }; static_assert(sizeof(formatInfo) / sizeof(PixelFormatInfo) == PIXELFORMAT_MAX_ENUM, "Update the formatInfo array when adding or removing a PixelFormat"); @@ -112,22 +130,40 @@ static StringMap::Entry formatEntries[] = { "normal", PIXELFORMAT_NORMAL }, { "hdr", PIXELFORMAT_HDR }, - { "r8", PIXELFORMAT_R8_UNORM }, - { "r16", PIXELFORMAT_R16_UNORM }, - { "r16f", PIXELFORMAT_R16_FLOAT }, - { "r32f", PIXELFORMAT_R32_FLOAT }, + { "r8", PIXELFORMAT_R8_UNORM }, + { "r8i", PIXELFORMAT_R8_INT }, + { "r8ui", PIXELFORMAT_R8_UINT }, + { "r16", PIXELFORMAT_R16_UNORM }, + { "r16f", PIXELFORMAT_R16_FLOAT }, + { "r16i", PIXELFORMAT_R16_INT }, + { "r16ui", PIXELFORMAT_R16_UINT }, + { "r32f", PIXELFORMAT_R32_FLOAT }, + { "r32i", PIXELFORMAT_R32_INT }, + { "r32ui", PIXELFORMAT_R32_UINT }, - { "rg8", PIXELFORMAT_RG8_UNORM }, - { "la8", PIXELFORMAT_LA8_UNORM }, - { "rg16", PIXELFORMAT_RG16_UNORM }, - { "rg16f", PIXELFORMAT_RG16_FLOAT }, - { "rg32f", PIXELFORMAT_RG32_FLOAT }, + { "rg8", PIXELFORMAT_RG8_UNORM }, + { "rg8i", PIXELFORMAT_RG8_INT }, + { "rg8ui", PIXELFORMAT_RG8_UINT }, + { "la8", PIXELFORMAT_LA8_UNORM }, + { "rg16", PIXELFORMAT_RG16_UNORM }, + { "rg16f", PIXELFORMAT_RG16_FLOAT }, + { "rg16i", PIXELFORMAT_RG16_INT }, + { "rg16ui", PIXELFORMAT_RG16_UINT }, + { "rg32f", PIXELFORMAT_RG32_FLOAT }, + { "rg32i", PIXELFORMAT_RG32_INT }, + { "rg32ui", PIXELFORMAT_RG32_UINT }, - { "rgba8", PIXELFORMAT_RGBA8_UNORM }, - { "srgba8", PIXELFORMAT_sRGBA8_UNORM }, - { "rgba16", PIXELFORMAT_RGBA16_UNORM }, - { "rgba16f", PIXELFORMAT_RGBA16_FLOAT }, - { "rgba32f", PIXELFORMAT_RGBA32_FLOAT }, + { "rgba8", PIXELFORMAT_RGBA8_UNORM }, + { "srgba8", PIXELFORMAT_sRGBA8_UNORM }, + { "rgba8i", PIXELFORMAT_RGBA8_INT }, + { "rgba8ui", PIXELFORMAT_RGBA8_UINT }, + { "rgba16", PIXELFORMAT_RGBA16_UNORM }, + { "rgba16f", PIXELFORMAT_RGBA16_FLOAT }, + { "rgba16i", PIXELFORMAT_RGBA16_INT }, + { "rgba16ui", PIXELFORMAT_RGBA16_UINT }, + { "rgba32f", PIXELFORMAT_RGBA32_FLOAT }, + { "rgba32i", PIXELFORMAT_RGBA32_INT }, + { "rgba32ui", PIXELFORMAT_RGBA32_UINT }, { "rgba4", PIXELFORMAT_RGBA4_UNORM }, { "rgb5a1", PIXELFORMAT_RGB5A1_UNORM }, @@ -164,6 +200,7 @@ static StringMap::Entry formatEntries[] = { "EACrs", PIXELFORMAT_EAC_R_SNORM }, { "EACrg", PIXELFORMAT_EAC_RG_UNORM }, { "EACrgs", PIXELFORMAT_EAC_RG_SNORM }, + { "ASTC4x4", PIXELFORMAT_ASTC_4x4 }, { "ASTC5x4", PIXELFORMAT_ASTC_5x4 }, { "ASTC5x5", PIXELFORMAT_ASTC_5x5 }, @@ -220,6 +257,12 @@ bool isPixelFormatStencil(PixelFormat format) return formatInfo[format].stencil; } +bool isPixelFormatInteger(PixelFormat format) +{ + auto type = formatInfo[format].dataType; + return type == PIXELFORMATTYPE_SINT || type == PIXELFORMATTYPE_UINT; +} + PixelFormat getSRGBPixelFormat(PixelFormat format) { if (format == PIXELFORMAT_RGBA8_UNORM) diff --git a/src/common/pixelformat.h b/src/common/pixelformat.h index f44937f99..03df14d44 100644 --- a/src/common/pixelformat.h +++ b/src/common/pixelformat.h @@ -35,23 +35,41 @@ enum PixelFormat // 1-channel normal formats PIXELFORMAT_R8_UNORM, + PIXELFORMAT_R8_INT, + PIXELFORMAT_R8_UINT, PIXELFORMAT_R16_UNORM, PIXELFORMAT_R16_FLOAT, + PIXELFORMAT_R16_INT, + PIXELFORMAT_R16_UINT, PIXELFORMAT_R32_FLOAT, + PIXELFORMAT_R32_INT, + PIXELFORMAT_R32_UINT, // 2-channel normal formats PIXELFORMAT_RG8_UNORM, + PIXELFORMAT_RG8_INT, + PIXELFORMAT_RG8_UINT, PIXELFORMAT_LA8_UNORM, // Same as RG8, but accessed as (L, L, L, A) PIXELFORMAT_RG16_UNORM, PIXELFORMAT_RG16_FLOAT, + PIXELFORMAT_RG16_INT, + PIXELFORMAT_RG16_UINT, PIXELFORMAT_RG32_FLOAT, + PIXELFORMAT_RG32_INT, + PIXELFORMAT_RG32_UINT, // 4-channel normal formats PIXELFORMAT_RGBA8_UNORM, PIXELFORMAT_sRGBA8_UNORM, + PIXELFORMAT_RGBA8_INT, + PIXELFORMAT_RGBA8_UINT, PIXELFORMAT_RGBA16_UNORM, PIXELFORMAT_RGBA16_FLOAT, + PIXELFORMAT_RGBA16_INT, + PIXELFORMAT_RGBA16_UINT, PIXELFORMAT_RGBA32_FLOAT, + PIXELFORMAT_RGBA32_INT, + PIXELFORMAT_RGBA32_UINT, // packed formats PIXELFORMAT_RGBA4_UNORM, // LSB->MSB: [a, b, g, r] @@ -109,6 +127,16 @@ enum PixelFormat PIXELFORMAT_MAX_ENUM }; +enum PixelFormatType +{ + PIXELFORMATTYPE_UNORM, + PIXELFORMATTYPE_SNORM, + PIXELFORMATTYPE_UFLOAT, + PIXELFORMATTYPE_SFLOAT, + PIXELFORMATTYPE_UINT, + PIXELFORMATTYPE_SINT, +}; + struct PixelFormatInfo { int components; @@ -119,6 +147,7 @@ struct PixelFormatInfo bool depth; bool stencil; bool compressed; + PixelFormatType dataType; }; bool getConstant(PixelFormat in, const char *&out); @@ -146,6 +175,11 @@ bool isPixelFormatDepth(PixelFormat format); **/ bool isPixelFormatStencil(PixelFormat format); +/** + * Gets whether the specified pixel format is a signed or unsigned integer type. + **/ +bool isPixelFormatInteger(PixelFormat format); + /** * Gets the sRGB version of a linear pixel format, if applicable. **/ diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 719acaa51..74f939932 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -693,6 +693,9 @@ void Graphics::setRenderTargets(const RenderTargets &rts) if (!firsttex->isValidSlice(firsttarget.slice)) throw love::Exception("Invalid slice index: %d.", firsttarget.slice + 1); + if (isPixelFormatInteger(firstcolorformat)) + throw love::Exception("Textures with integer pixel formats cannot be rendered to, currently."); + bool hasSRGBtexture = firstcolorformat == PIXELFORMAT_sRGBA8_UNORM; int pixelw = firsttex->getPixelWidth(firsttarget.mipmap); int pixelh = firsttex->getPixelHeight(firsttarget.mipmap); @@ -726,6 +729,9 @@ void Graphics::setRenderTargets(const RenderTargets &rts) if (isPixelFormatDepthStencil(format)) throw love::Exception("Depth/stencil format textures must be used with the 'depthstencil' field of the table passed into setRenderTargets."); + if (isPixelFormatInteger(format)) + throw love::Exception("Textures with integer pixel formats cannot be rendered to, currently."); + if (format == PIXELFORMAT_sRGBA8_UNORM) hasSRGBtexture = true; } diff --git a/src/modules/graphics/Shader.cpp b/src/modules/graphics/Shader.cpp index bc6ea626f..82b62d161 100644 --- a/src/modules/graphics/Shader.cpp +++ b/src/modules/graphics/Shader.cpp @@ -635,10 +635,9 @@ bool Shader::isDefaultActive() return false; } -TextureType Shader::getMainTextureType() const +const Shader::UniformInfo *Shader::getMainTextureInfo() const { - const UniformInfo *info = getUniformInfo(BUILTIN_TEXTURE_MAIN); - return info != nullptr ? info->textureType : TEXTURE_MAX_ENUM; + return getUniformInfo(BUILTIN_TEXTURE_MAIN); } void Shader::validateDrawState(PrimitiveType primtype, Texture *maintex) const diff --git a/src/modules/graphics/Shader.h b/src/modules/graphics/Shader.h index ae4836e3e..543478f01 100644 --- a/src/modules/graphics/Shader.h +++ b/src/modules/graphics/Shader.h @@ -131,9 +131,9 @@ public: }; UniformType baseType; - Access access; + DataBaseType dataBaseType; TextureType textureType; - DataBaseType texelBufferType; + Access access; bool isDepthSampler; size_t bufferStride; size_t bufferMemberCount; @@ -221,7 +221,7 @@ public: **/ virtual void setVideoTextures(Texture *ytexture, Texture *cbtexture, Texture *crtexture) = 0; - TextureType getMainTextureType() const; + const UniformInfo *getMainTextureInfo() const; void validateDrawState(PrimitiveType primtype, Texture *maintexture) const; void getLocalThreadgroupSize(int *x, int *y, int *z); diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index 9f45db575..cae50dd65 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -504,6 +504,9 @@ void Texture::generateMipmaps() if (isPixelFormatDepthStencil(format)) throw love::Exception("generateMipmaps cannot be called on a depth/stencil Texture."); + if (isPixelFormatInteger(format)) + throw love::Exception("generateMipmaps cannot be called on an integer Texture."); + generateMipmapsInternal(); } diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index e78fb9545..2c87282ff 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -341,6 +341,7 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b batchedDrawState.indexBuffer = CreateStreamBuffer(BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX); } + // TODO: one buffer each for float, int, uint if (capabilities.features[FEATURE_TEXEL_BUFFER] && defaultBuffers[BUFFERUSAGE_TEXEL].get() == nullptr) { Buffer::Settings settings(BUFFERUSAGEFLAG_TEXEL, BUFFERDATAUSAGE_STATIC); @@ -1723,7 +1724,7 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, bool rendertarget, boo // Make sure at least something is bound to a color attachment. I believe // this is required on ES2 but I'm not positive. if (isPixelFormatDepthStencil(format)) - gl.framebufferTexture(GL_COLOR_ATTACHMENT0, TEXTURE_2D, gl.getDefaultTexture(TEXTURE_2D), 0, 0, 0); + gl.framebufferTexture(GL_COLOR_ATTACHMENT0, TEXTURE_2D, gl.getDefaultTexture(TEXTURE_2D, DATA_BASETYPE_FLOAT), 0, 0, 0); if (readable) { diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 7ebc85fb2..5bd065c0a 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -304,10 +304,13 @@ void OpenGL::deInitContext() for (int i = 0; i < TEXTURE_MAX_ENUM; i++) { - if (state.defaultTexture[i] != 0) + for (int datatype = DATA_BASETYPE_FLOAT; datatype <= DATA_BASETYPE_UINT; datatype++) { - gl.deleteTexture(state.defaultTexture[i]); - state.defaultTexture[i] = 0; + if (state.defaultTexture[i][datatype] != 0) + { + gl.deleteTexture(state.defaultTexture[i][datatype]); + state.defaultTexture[i][datatype] = 0; + } } } @@ -569,6 +572,7 @@ void OpenGL::createDefaultTexture() // which would create the need to use different "passthrough" shaders for // untextured primitives vs images. const GLubyte pix[] = {255, 255, 255, 255}; + const GLubyte intpix[] = {1, 1, 1, 1}; SamplerState s; s.minFilter = s.magFilter = SamplerState::FILTER_NEAREST; @@ -576,41 +580,55 @@ void OpenGL::createDefaultTexture() for (int i = 0; i < TEXTURE_MAX_ENUM; i++) { - state.defaultTexture[i] = 0; - - TextureType type = (TextureType) i; - - if (!isTextureTypeSupported(type)) - continue; - - GLuint curtexture = state.boundTextures[type][0]; - - glGenTextures(1, &state.defaultTexture[type]); - bindTextureToUnit(type, state.defaultTexture[type], 0, false); - - setSamplerState(type, s); - - bool isSRGB = false; - rawTexStorage(type, 1, PIXELFORMAT_RGBA8_UNORM, isSRGB, 1, 1); - - TextureFormat fmt = convertPixelFormat(PIXELFORMAT_RGBA8_UNORM, false, isSRGB); - - int slices = type == TEXTURE_CUBE ? 6 : 1; - - for (int slice = 0; slice < slices; slice++) + for (int datatype = (int)DATA_BASETYPE_FLOAT; datatype <= (int)DATA_BASETYPE_UINT; datatype++) { - GLenum gltarget = getGLTextureType(type); + state.defaultTexture[i][datatype] = 0; - if (type == TEXTURE_CUBE) - gltarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice; + TextureType type = (TextureType) i; - if (type == TEXTURE_2D || type == TEXTURE_CUBE) - glTexSubImage2D(gltarget, 0, 0, 0, 1, 1, fmt.externalformat, fmt.type, pix); - else if (type == TEXTURE_2D_ARRAY || type == TEXTURE_VOLUME) - glTexSubImage3D(gltarget, 0, 0, 0, slice, 1, 1, 1, fmt.externalformat, fmt.type, pix); + if (!isTextureTypeSupported(type)) + continue; + + if (datatype != DATA_BASETYPE_FLOAT && !(GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0)) + continue; + + GLuint curtexture = state.boundTextures[type][0]; + + glGenTextures(1, &state.defaultTexture[type][datatype]); + bindTextureToUnit(type, state.defaultTexture[type][datatype], 0, false); + + setSamplerState(type, s); + + PixelFormat format = PIXELFORMAT_RGBA8_UNORM; + if (datatype == DATA_BASETYPE_INT) + format = PIXELFORMAT_RGBA8_INT; + else if (datatype == DATA_BASETYPE_UINT) + format = PIXELFORMAT_RGBA8_UINT; + + const GLubyte *p = datatype == DATA_BASETYPE_FLOAT ? pix : intpix; + + bool isSRGB = false; + rawTexStorage(type, 1, format, isSRGB, 1, 1); + + TextureFormat fmt = convertPixelFormat(format, false, isSRGB); + + int slices = type == TEXTURE_CUBE ? 6 : 1; + + for (int slice = 0; slice < slices; slice++) + { + GLenum gltarget = getGLTextureType(type); + + if (type == TEXTURE_CUBE) + gltarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice; + + if (type == TEXTURE_2D || type == TEXTURE_CUBE) + glTexSubImage2D(gltarget, 0, 0, 0, 1, 1, fmt.externalformat, fmt.type, p); + else if (type == TEXTURE_2D_ARRAY || type == TEXTURE_VOLUME) + glTexSubImage3D(gltarget, 0, 0, 0, slice, 1, 1, 1, fmt.externalformat, fmt.type, p); + } + + bindTextureToUnit(type, curtexture, 0, false); } - - bindTextureToUnit(type, curtexture, 0, false); } } @@ -1113,9 +1131,9 @@ GLuint OpenGL::getDefaultFBO() const #endif } -GLuint OpenGL::getDefaultTexture(TextureType type) const +GLuint OpenGL::getDefaultTexture(TextureType type, DataBaseType datatype) const { - return state.defaultTexture[type]; + return state.defaultTexture[type][datatype]; } void OpenGL::setTextureUnit(int textureunit) @@ -1166,14 +1184,19 @@ void OpenGL::bindTextureToUnit(Texture *texture, int textureunit, bool restorepr } else { + DataBaseType datatype = DATA_BASETYPE_FLOAT; + if (textureunit == 0 && Shader::current != nullptr) { - TextureType shadertex = Shader::current->getMainTextureType(); - if (shadertex != TEXTURE_MAX_ENUM) - textype = shadertex; + const Shader::UniformInfo *info = Shader::current->getMainTextureInfo(); + if (info != nullptr) + { + textype = info->textureType; + datatype = info->dataBaseType; + } } - handle = getDefaultTexture(textype); + handle = getDefaultTexture(textype, datatype); } bindTextureToUnit(textype, handle, textureunit, restoreprev, bindforedit); @@ -1662,6 +1685,7 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r f.externalformat = GL_RGBA; f.type = GL_UNSIGNED_SHORT; break; + case PIXELFORMAT_R16_FLOAT: f.internalformat = GL_R16F; f.externalformat = GL_RED; @@ -1702,6 +1726,97 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r f.type = GL_FLOAT; break; + case PIXELFORMAT_R8_INT: + f.internalformat = GL_R8I; + f.externalformat = GL_RED_INTEGER; + f.type = GL_BYTE; + break; + case PIXELFORMAT_R8_UINT: + f.internalformat = GL_R8UI; + f.externalformat = GL_RED_INTEGER; + f.type = GL_UNSIGNED_BYTE; + break; + case PIXELFORMAT_RG8_INT: + f.internalformat = GL_RG8I; + f.externalformat = GL_RG_INTEGER; + f.type = GL_BYTE; + break; + case PIXELFORMAT_RG8_UINT: + f.internalformat = GL_RG8UI; + f.externalformat = GL_RG_INTEGER; + f.type = GL_UNSIGNED_BYTE; + break; + case PIXELFORMAT_RGBA8_INT: + f.internalformat = GL_RGBA8I; + f.externalformat = GL_RGBA_INTEGER; + f.type = GL_BYTE; + break; + case PIXELFORMAT_RGBA8_UINT: + f.internalformat = GL_RGBA8UI; + f.externalformat = GL_RGBA_INTEGER; + f.type = GL_UNSIGNED_BYTE; + break; + case PIXELFORMAT_R16_INT: + f.internalformat = GL_R16I; + f.externalformat = GL_RED_INTEGER; + f.type = GL_SHORT; + break; + case PIXELFORMAT_R16_UINT: + f.internalformat = GL_R16UI; + f.externalformat = GL_RED_INTEGER; + f.type = GL_UNSIGNED_SHORT; + break; + case PIXELFORMAT_RG16_INT: + f.internalformat = GL_RG16I; + f.externalformat = GL_RG_INTEGER; + f.type = GL_SHORT; + break; + case PIXELFORMAT_RG16_UINT: + f.internalformat = GL_RG16UI; + f.externalformat = GL_RG_INTEGER; + f.type = GL_UNSIGNED_SHORT; + break; + case PIXELFORMAT_RGBA16_INT: + f.internalformat = GL_RGBA16I; + f.externalformat = GL_RGBA_INTEGER; + f.type = GL_SHORT; + break; + case PIXELFORMAT_RGBA16_UINT: + f.internalformat = GL_RGBA16UI; + f.externalformat = GL_RGBA_INTEGER; + f.type = GL_UNSIGNED_SHORT; + break; + case PIXELFORMAT_R32_INT: + f.internalformat = GL_R32I; + f.externalformat = GL_RED_INTEGER; + f.type = GL_INT; + break; + case PIXELFORMAT_R32_UINT: + f.internalformat = GL_R32UI; + f.externalformat = GL_RED_INTEGER; + f.type = GL_UNSIGNED_INT; + break; + case PIXELFORMAT_RG32_INT: + f.internalformat = GL_RG32I; + f.externalformat = GL_RG_INTEGER; + f.type = GL_INT; + break; + case PIXELFORMAT_RG32_UINT: + f.internalformat = GL_RG32UI; + f.externalformat = GL_RG_INTEGER; + f.type = GL_UNSIGNED_INT; + break; + case PIXELFORMAT_RGBA32_INT: + f.internalformat = GL_RGBA32I; + f.externalformat = GL_RGBA_INTEGER; + f.type = GL_INT; + break; + case PIXELFORMAT_RGBA32_UINT: + f.internalformat = GL_RGBA32UI; + f.externalformat = GL_RGBA_INTEGER; + f.type = GL_UNSIGNED_INT; + break; + case PIXELFORMAT_LA8_UNORM: if (gl.isCoreProfile() || GLAD_ES_VERSION_3_0) { @@ -2046,6 +2161,28 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) flags &= ~PIXELFORMATUSAGEFLAGS_LINEAR; break; + case PIXELFORMAT_R8_INT: + case PIXELFORMAT_R8_UINT: + case PIXELFORMAT_RG8_INT: + case PIXELFORMAT_RG8_UINT: + case PIXELFORMAT_RGBA8_INT: + case PIXELFORMAT_RGBA8_UINT: + case PIXELFORMAT_R16_INT: + case PIXELFORMAT_R16_UINT: + case PIXELFORMAT_RG16_INT: + case PIXELFORMAT_RG16_UINT: + case PIXELFORMAT_RGBA16_INT: + case PIXELFORMAT_RGBA16_UINT: + case PIXELFORMAT_R32_INT: + case PIXELFORMAT_R32_UINT: + case PIXELFORMAT_RG32_INT: + case PIXELFORMAT_RG32_UINT: + case PIXELFORMAT_RGBA32_INT: + case PIXELFORMAT_RGBA32_UINT: + if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0) + flags |= PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_RENDERTARGET; + break; + case PIXELFORMAT_LA8_UNORM: flags |= commonsample; break; diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index ed66f28d0..4c073d1ae 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -312,7 +312,7 @@ public: /** * Gets the ID for love's default texture (used for "untextured" primitives.) **/ - GLuint getDefaultTexture(TextureType type) const; + GLuint getDefaultTexture(TextureType type, DataBaseType datatype) const; /** * Gets the texture ID for love's default texel buffer. @@ -523,7 +523,7 @@ private: GLuint boundFramebuffers[2]; - GLuint defaultTexture[TEXTURE_MAX_ENUM]; + GLuint defaultTexture[TEXTURE_MAX_ENUM][DATA_BASETYPE_MAX_ENUM]; GLuint defaultTexelBuffer; GLuint defaultStorageBuffer; diff --git a/src/modules/graphics/opengl/Shader.cpp b/src/modules/graphics/opengl/Shader.cpp index 10250ab47..c22b932d7 100644 --- a/src/modules/graphics/opengl/Shader.cpp +++ b/src/modules/graphics/opengl/Shader.cpp @@ -119,16 +119,8 @@ void Shader::mapActiveUniforms() u.name = std::string(cname, (size_t) namelen); u.location = glGetUniformLocation(program, u.name.c_str()); - u.baseType = getUniformBaseType(gltype); u.access = ACCESS_READ; - u.textureType = getUniformTextureType(gltype); - u.texelBufferType = getUniformTexelBufferType(gltype); - u.isDepthSampler = isDepthTextureType(gltype); - - if (u.baseType == UNIFORM_MATRIX) - u.matrix = getMatrixSize(gltype); - else - u.components = getUniformTypeComponents(gltype); + computeUniformTypeInfo(gltype, u); // glGetActiveUniform appends "[0]" to the end of array uniform names... if (u.name.length() > 3) @@ -160,7 +152,7 @@ void Shader::mapActiveUniforms() else { unit.isTexelBuffer = false; - unit.texture = gl.getDefaultTexture(u.textureType); + unit.texture = gl.getDefaultTexture(u.textureType, u.dataBaseType); } for (int i = 0; i < u.count; i++) @@ -718,6 +710,40 @@ void Shader::updateUniform(const UniformInfo *info, int count, bool internalupda } } +static bool isResourceBaseTypeCompatible(DataBaseType a, DataBaseType b) +{ + if (a == DATA_BASETYPE_FLOAT || a == DATA_BASETYPE_UNORM || a == DATA_BASETYPE_SNORM) + return b == DATA_BASETYPE_FLOAT || b == DATA_BASETYPE_UNORM || b == DATA_BASETYPE_SNORM; + + if (a == DATA_BASETYPE_INT && b == DATA_BASETYPE_INT) + return true; + + if (a == DATA_BASETYPE_UINT && b == DATA_BASETYPE_UINT) + return true; + + return false; +} + +static DataBaseType getDataBaseType(PixelFormat format) +{ + switch (getPixelFormatInfo(format).dataType) + { + case PIXELFORMATTYPE_UNORM: + return DATA_BASETYPE_UNORM; + case PIXELFORMATTYPE_SNORM: + return DATA_BASETYPE_SNORM; + case PIXELFORMATTYPE_UFLOAT: + case PIXELFORMATTYPE_SFLOAT: + return DATA_BASETYPE_FLOAT; + case PIXELFORMATTYPE_SINT: + return DATA_BASETYPE_INT; + case PIXELFORMATTYPE_UINT: + return DATA_BASETYPE_UINT; + default: + return DATA_BASETYPE_FLOAT; + } +} + void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **textures, int count) { Shader::sendTextures(info, textures, count, false); @@ -742,7 +768,6 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex if (tex != nullptr) { - const SamplerState &sampler = tex->getSamplerState(); if (!tex->isReadable()) { if (internalUpdate) @@ -750,7 +775,7 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex else throw love::Exception("Textures with non-readable formats cannot be sampled from in a shader."); } - else if (info->isDepthSampler != sampler.depthSampleMode.hasValue) + else if (info->isDepthSampler != tex->getSamplerState().depthSampleMode.hasValue) { if (internalUpdate) continue; @@ -772,6 +797,13 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex throw love::Exception("Texture's type (%s) must match the type of %s (%s).", textypestr, info->name.c_str(), shadertextypestr); } } + else if (!isResourceBaseTypeCompatible(info->dataBaseType, getDataBaseType(tex->getPixelFormat()))) + { + if (internalUpdate) + continue; + else + throw love::Exception("Texture's data format base type must match the uniform variable declared in the shader (float, int, or uint)."); + } tex->retain(); } @@ -785,7 +817,7 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex if (textures[i] != nullptr) gltex = (GLuint) tex->getHandle(); else - gltex = gl.getDefaultTexture(info->textureType); + gltex = gl.getDefaultTexture(info->textureType, info->dataBaseType); int texunit = info->ints[i]; @@ -802,20 +834,6 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe Shader::sendBuffers(info, buffers, count, false); } -static bool isTexelBufferTypeCompatible(DataBaseType a, DataBaseType b) -{ - if (a == DATA_BASETYPE_FLOAT || a == DATA_BASETYPE_UNORM || a == DATA_BASETYPE_SNORM) - return b == DATA_BASETYPE_FLOAT || b == DATA_BASETYPE_UNORM || b == DATA_BASETYPE_SNORM; - - if (a == DATA_BASETYPE_INT && b == DATA_BASETYPE_INT) - return true; - - if (a == DATA_BASETYPE_UINT && b == DATA_BASETYPE_UINT) - return true; - - return false; -} - void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffers, int count, bool internalUpdate) { uint32 requiredtypeflags = 0; @@ -860,7 +878,7 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe if (texelbinding) { DataBaseType basetype = buffer->getDataMember(0).info.baseType; - if (!isTexelBufferTypeCompatible(basetype, info->texelBufferType)) + if (!isResourceBaseTypeCompatible(basetype, info->dataBaseType)) { if (internalUpdate) continue; @@ -1043,11 +1061,6 @@ void Shader::updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW, int Shader::getUniformTypeComponents(GLenum type) const { - UniformType basetype = getUniformBaseType(type); - - if (basetype == UNIFORM_SAMPLER || basetype == UNIFORM_TEXELBUFFER) - return 1; - switch (type) { case GL_INT: @@ -1122,25 +1135,35 @@ Shader::MatrixSize Shader::getMatrixSize(GLenum type) const return m; } -Shader::UniformType Shader::getUniformBaseType(GLenum type) const +void Shader::computeUniformTypeInfo(GLenum type, UniformInfo &u) { + u.isDepthSampler = false; + u.components = getUniformTypeComponents(type); + u.baseType = UNIFORM_UNKNOWN; + switch (type) { case GL_INT: case GL_INT_VEC2: case GL_INT_VEC3: case GL_INT_VEC4: - return UNIFORM_INT; + u.baseType = UNIFORM_INT; + u.dataBaseType = DATA_BASETYPE_INT; + break; case GL_UNSIGNED_INT: case GL_UNSIGNED_INT_VEC2: case GL_UNSIGNED_INT_VEC3: case GL_UNSIGNED_INT_VEC4: - return UNIFORM_UINT; + u.baseType = UNIFORM_UINT; + u.dataBaseType = DATA_BASETYPE_UINT; + break; case GL_FLOAT: case GL_FLOAT_VEC2: case GL_FLOAT_VEC3: case GL_FLOAT_VEC4: - return UNIFORM_FLOAT; + u.baseType = UNIFORM_FLOAT; + u.dataBaseType = DATA_BASETYPE_FLOAT; + break; case GL_FLOAT_MAT2: case GL_FLOAT_MAT3: case GL_FLOAT_MAT4: @@ -1150,105 +1173,112 @@ Shader::UniformType Shader::getUniformBaseType(GLenum type) const case GL_FLOAT_MAT3x4: case GL_FLOAT_MAT4x2: case GL_FLOAT_MAT4x3: - return UNIFORM_MATRIX; + u.baseType = UNIFORM_MATRIX; + u.dataBaseType = DATA_BASETYPE_FLOAT; + u.matrix = getMatrixSize(type); + break; case GL_BOOL: case GL_BOOL_VEC2: case GL_BOOL_VEC3: case GL_BOOL_VEC4: - return UNIFORM_BOOL; - case GL_SAMPLER_1D: - case GL_SAMPLER_1D_SHADOW: - case GL_SAMPLER_1D_ARRAY: - case GL_SAMPLER_1D_ARRAY_SHADOW: + u.baseType = UNIFORM_BOOL; + u.dataBaseType = DATA_BASETYPE_BOOL; + break; + case GL_SAMPLER_2D: - case GL_SAMPLER_2D_MULTISAMPLE: - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: - case GL_SAMPLER_2D_RECT: - case GL_SAMPLER_2D_RECT_SHADOW: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_FLOAT; + u.textureType = TEXTURE_2D; + break; case GL_SAMPLER_2D_SHADOW: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_FLOAT; + u.textureType = TEXTURE_2D; + u.isDepthSampler = true; + break; + case GL_INT_SAMPLER_2D: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_INT; + u.textureType = TEXTURE_2D; + break; + case GL_UNSIGNED_INT_SAMPLER_2D: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_UINT; + u.textureType = TEXTURE_2D; + break; case GL_SAMPLER_2D_ARRAY: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_FLOAT; + u.textureType = TEXTURE_2D_ARRAY; + break; case GL_SAMPLER_2D_ARRAY_SHADOW: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_FLOAT; + u.textureType = TEXTURE_2D_ARRAY; + u.isDepthSampler = true; + break; + case GL_INT_SAMPLER_2D_ARRAY: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_INT; + u.textureType = TEXTURE_2D_ARRAY; + break; + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_UINT; + u.textureType = TEXTURE_2D_ARRAY; + break; case GL_SAMPLER_3D: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_FLOAT; + u.textureType = TEXTURE_VOLUME; + break; + case GL_INT_SAMPLER_3D: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_INT; + u.textureType = TEXTURE_VOLUME; + break; + case GL_UNSIGNED_INT_SAMPLER_3D: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_UINT; + u.textureType = TEXTURE_VOLUME; + break; case GL_SAMPLER_CUBE: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_FLOAT; + u.textureType = TEXTURE_CUBE; + break; case GL_SAMPLER_CUBE_SHADOW: - case GL_SAMPLER_CUBE_MAP_ARRAY: - case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: - return UNIFORM_SAMPLER; + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_FLOAT; + u.textureType = TEXTURE_CUBE; + u.isDepthSampler = true; + break; + case GL_INT_SAMPLER_CUBE: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_INT; + u.textureType = TEXTURE_CUBE; + break; + case GL_UNSIGNED_INT_SAMPLER_CUBE: + u.baseType = UNIFORM_SAMPLER; + u.dataBaseType = DATA_BASETYPE_UINT; + u.textureType = TEXTURE_CUBE; + break; + case GL_SAMPLER_BUFFER: + u.baseType = UNIFORM_TEXELBUFFER; + u.dataBaseType = DATA_BASETYPE_FLOAT; + break; case GL_INT_SAMPLER_BUFFER: + u.baseType = UNIFORM_TEXELBUFFER; + u.dataBaseType = DATA_BASETYPE_INT; + break; case GL_UNSIGNED_INT_SAMPLER_BUFFER: - return UNIFORM_TEXELBUFFER; - default: - return UNIFORM_UNKNOWN; - } -} + u.baseType = UNIFORM_TEXELBUFFER; + u.dataBaseType = DATA_BASETYPE_UINT; + break; -TextureType Shader::getUniformTextureType(GLenum type) const -{ - switch (type) - { - case GL_SAMPLER_1D: - case GL_SAMPLER_1D_SHADOW: - case GL_SAMPLER_1D_ARRAY: - case GL_SAMPLER_1D_ARRAY_SHADOW: - // 1D-typed textures are not supported. - return TEXTURE_MAX_ENUM; - case GL_SAMPLER_2D: - case GL_SAMPLER_2D_SHADOW: - return TEXTURE_2D; - case GL_SAMPLER_2D_MULTISAMPLE: - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: - // Multisample textures are not supported. - return TEXTURE_MAX_ENUM; - case GL_SAMPLER_2D_RECT: - case GL_SAMPLER_2D_RECT_SHADOW: - // Rectangle textures are not supported. - return TEXTURE_MAX_ENUM; - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_2D_ARRAY_SHADOW: - return TEXTURE_2D_ARRAY; - case GL_SAMPLER_3D: - return TEXTURE_VOLUME; - case GL_SAMPLER_CUBE: - case GL_SAMPLER_CUBE_SHADOW: - return TEXTURE_CUBE; - case GL_SAMPLER_CUBE_MAP_ARRAY: - case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: - // Cubemap array textures are not supported. - return TEXTURE_MAX_ENUM; default: - return TEXTURE_MAX_ENUM; - } -} - -DataBaseType Shader::getUniformTexelBufferType(GLenum type) const -{ - switch (type) - { - case GL_SAMPLER_BUFFER: - return DATA_BASETYPE_FLOAT; - case GL_INT_SAMPLER_BUFFER: - return DATA_BASETYPE_INT; - case GL_UNSIGNED_INT_SAMPLER_BUFFER: - return DATA_BASETYPE_UINT; - default: - return DATA_BASETYPE_MAX_ENUM; - } -} - -bool Shader::isDepthTextureType(GLenum type) const -{ - switch (type) - { - case GL_SAMPLER_1D_SHADOW: - case GL_SAMPLER_1D_ARRAY_SHADOW: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_SAMPLER_CUBE_SHADOW: - case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: - return true; - default: - return false; + break; } } diff --git a/src/modules/graphics/opengl/Shader.h b/src/modules/graphics/opengl/Shader.h index e2ee3a78d..987acec2a 100644 --- a/src/modules/graphics/opengl/Shader.h +++ b/src/modules/graphics/opengl/Shader.h @@ -92,11 +92,8 @@ private: void sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffers, int count, bool internalupdate); int getUniformTypeComponents(GLenum type) const; + void computeUniformTypeInfo(GLenum type, UniformInfo &u); MatrixSize getMatrixSize(GLenum type) const; - UniformType getUniformBaseType(GLenum type) const; - TextureType getUniformTextureType(GLenum type) const; - DataBaseType getUniformTexelBufferType(GLenum type) const; - bool isDepthTextureType(GLenum type) const; void flushBatchedDraws() const;