Initial support for integer format textures.

They can't be rendered to and ImageData can't use the formats, for now.
This commit is contained in:
Alex Szpakowski
2021-08-12 16:38:54 -03:00
parent 4caeb27047
commit 48b3a4e860
11 changed files with 502 additions and 252 deletions
+177 -40
View File
@@ -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;