Renderer: Improve texture view support (and support emulation for OGL)
This commit is contained in:
parent
08ea4c87a7
commit
56acbb2694
|
|
@ -27,6 +27,7 @@ namespace Nz::GL
|
|||
inline void DrawBuffers(GLsizei n, const GLenum* bufs);
|
||||
inline void Renderbuffer(GLenum attachment, GLenum renderbuffer);
|
||||
inline void Texture2D(GLenum attachment, GLenum textarget, GLuint texture, GLint level = 0);
|
||||
inline void TextureLayer(GLenum attachment, GLuint texture, GLint level = 0, GLint layer = 0);
|
||||
|
||||
Framebuffer& operator=(const Framebuffer&) = delete;
|
||||
Framebuffer& operator=(Framebuffer&&) noexcept = default;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,15 @@ namespace Nz::GL
|
|||
context.glFramebufferTexture2D(target, attachment, textarget, texture, level);
|
||||
}
|
||||
|
||||
inline void Framebuffer::TextureLayer(GLenum attachment, GLuint texture, GLint level, GLint layer)
|
||||
{
|
||||
assert(m_objectId);
|
||||
|
||||
const Context& context = EnsureContext();
|
||||
GLenum target = context.BindFramebuffer(m_objectId);
|
||||
context.glFramebufferTextureLayer(target, attachment, texture, level, layer);
|
||||
}
|
||||
|
||||
inline GLuint Framebuffer::CreateHelper(const Context& context)
|
||||
{
|
||||
GLuint fbo = 0;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace Nz::GL
|
|||
inline void TexStorage3D(TextureTarget target, GLint levels, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth);
|
||||
inline void TexSubImage2D(TextureTarget target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data);
|
||||
inline void TexSubImage3D(TextureTarget target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* data);
|
||||
inline void TextureView(GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
|
||||
inline void TextureView(TextureTarget target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
|
||||
|
||||
Texture& operator=(const Texture&) = delete;
|
||||
Texture& operator=(Texture&&) noexcept = default;
|
||||
|
|
|
|||
|
|
@ -111,10 +111,12 @@ namespace Nz::GL
|
|||
//< TODO: Handle errors
|
||||
}
|
||||
|
||||
inline void Texture::TextureView(GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers)
|
||||
inline void Texture::TextureView(TextureTarget target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers)
|
||||
{
|
||||
m_target = target;
|
||||
|
||||
const Context& context = EnsureDeviceContext();
|
||||
context.glTextureView(m_objectId, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers);
|
||||
context.glTextureView(m_objectId, ToOpenGL(target), origtexture, internalformat, minlevel, numlevels, minlayer, numlayers);
|
||||
}
|
||||
|
||||
inline GLuint Texture::CreateHelper(OpenGLDevice& /*device*/, const Context& context)
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ namespace Nz
|
|||
textureInfo.width = GetLevelSize(textureInfo.width, viewInfo.baseMipLevel);
|
||||
textureInfo.height = GetLevelSize(textureInfo.height, viewInfo.baseMipLevel);
|
||||
textureInfo.depth = GetLevelSize(textureInfo.depth, viewInfo.baseMipLevel);
|
||||
textureInfo.levelCount = (textureInfo.levelCount > viewInfo.baseMipLevel) ? (textureInfo.levelCount - viewInfo.baseMipLevel) : 1;
|
||||
textureInfo.layerCount = (textureInfo.layerCount > viewInfo.baseArrayLayer) ? (textureInfo.layerCount - viewInfo.baseArrayLayer) : 1;
|
||||
textureInfo.levelCount = viewInfo.levelCount;
|
||||
textureInfo.layerCount = viewInfo.layerCount;
|
||||
|
||||
return textureInfo;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,40 @@ namespace Nz
|
|||
throw std::runtime_error("unhandled pixel format " + PixelFormatInfo::GetName(textureFormat));
|
||||
}
|
||||
|
||||
m_framebuffer.Texture2D(attachment, ToOpenGL(OpenGLTexture::ToTextureTarget(glTexture.GetType())), glTexture.GetTexture().GetObjectId());
|
||||
if (glTexture.RequiresTextureViewEmulation())
|
||||
{
|
||||
const TextureViewInfo& texViewInfo = glTexture.GetTextureViewInfo();
|
||||
if (texViewInfo.viewType != ImageType::E2D)
|
||||
throw std::runtime_error("unrestricted texture views can only be used as 2D texture attachment");
|
||||
|
||||
const OpenGLTexture& parentTexture = *glTexture.GetParentTexture();
|
||||
|
||||
switch (parentTexture.GetType())
|
||||
{
|
||||
case ImageType::Cubemap:
|
||||
{
|
||||
constexpr std::array<GLenum, 6> faceTargets = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
|
||||
assert(texViewInfo.baseArrayLayer < faceTargets.size());
|
||||
|
||||
GLenum texTarget = faceTargets[texViewInfo.baseArrayLayer];
|
||||
m_framebuffer.Texture2D(GL_COLOR_ATTACHMENT0, texTarget, parentTexture.GetTexture().GetObjectId(), texViewInfo.baseMipLevel);
|
||||
break;
|
||||
}
|
||||
|
||||
case ImageType::E1D:
|
||||
case ImageType::E2D:
|
||||
m_framebuffer.Texture2D(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, parentTexture.GetTexture().GetObjectId(), texViewInfo.baseMipLevel);
|
||||
break;
|
||||
|
||||
case ImageType::E1D_Array:
|
||||
case ImageType::E2D_Array:
|
||||
case ImageType::E3D:
|
||||
m_framebuffer.TextureLayer(GL_COLOR_ATTACHMENT0, parentTexture.GetTexture().GetObjectId(), texViewInfo.baseArrayLayer, texViewInfo.baseMipLevel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_framebuffer.Texture2D(attachment, ToOpenGL(OpenGLTexture::ToTextureTarget(glTexture.GetType())), glTexture.GetTexture().GetObjectId());
|
||||
}
|
||||
|
||||
GLenum status = m_framebuffer.Check();
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ namespace Nz
|
|||
NazaraAssert(viewInfo.layerCount <= m_parentTexture->m_textureInfo.layerCount - viewInfo.baseArrayLayer, "layer count exceeds number of layers");
|
||||
NazaraAssert(viewInfo.levelCount <= m_parentTexture->m_textureInfo.levelCount - viewInfo.baseMipLevel, "level count exceeds number of levels");
|
||||
|
||||
m_textureInfo = ApplyView(m_parentTexture->m_textureInfo, viewInfo);
|
||||
m_viewInfo = viewInfo;
|
||||
|
||||
// Try to use texture views if supported (core in GL 4.3 or extension)
|
||||
|
|
@ -77,11 +78,10 @@ namespace Nz
|
|||
if (m_texture.Create(*m_parentTexture->m_texture.GetDevice()))
|
||||
{
|
||||
auto format = DescribeTextureFormat(viewInfo.reinterpretFormat);
|
||||
GLenum target = ToOpenGL(ToTextureTarget(viewInfo.viewType));
|
||||
|
||||
context.ClearErrorStack();
|
||||
|
||||
m_texture.TextureView(target, m_parentTexture->m_texture.GetObjectId(), format->internalFormat, viewInfo.baseMipLevel, viewInfo.levelCount, viewInfo.baseArrayLayer, viewInfo.layerCount);
|
||||
m_texture.TextureView(ToTextureTarget(viewInfo.viewType), m_parentTexture->m_texture.GetObjectId(), format->internalFormat, viewInfo.baseMipLevel, viewInfo.levelCount, viewInfo.baseArrayLayer, viewInfo.layerCount);
|
||||
|
||||
if (!context.DidLastCallSucceed())
|
||||
m_texture.Destroy();
|
||||
|
|
|
|||
|
|
@ -294,28 +294,39 @@ namespace Nz::GL
|
|||
if (texture.RequiresTextureViewEmulation())
|
||||
{
|
||||
const TextureViewInfo& texViewInfo = texture.GetTextureViewInfo();
|
||||
if (texViewInfo.viewType != ImageType::E2D)
|
||||
throw std::runtime_error("unrestricted texture views can only be used as 2D texture attachment");
|
||||
|
||||
GLenum texTarget;
|
||||
if (texture.GetType() == ImageType::Cubemap)
|
||||
const OpenGLTexture& parentTexture = *texture.GetParentTexture();
|
||||
|
||||
switch (parentTexture.GetType())
|
||||
{
|
||||
constexpr std::array<GLenum, 6> faceTargets = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
|
||||
assert(texViewInfo.baseArrayLayer < faceTargets.size());
|
||||
texTarget = faceTargets[texViewInfo.baseArrayLayer];
|
||||
case ImageType::Cubemap:
|
||||
{
|
||||
constexpr std::array<GLenum, 6> faceTargets = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
|
||||
assert(texViewInfo.baseArrayLayer < faceTargets.size());
|
||||
|
||||
GLenum texTarget = faceTargets[texViewInfo.baseArrayLayer];
|
||||
framebuffer.Texture2D(GL_COLOR_ATTACHMENT0, texTarget, parentTexture.GetTexture().GetObjectId(), texViewInfo.baseMipLevel);
|
||||
break;
|
||||
}
|
||||
|
||||
case ImageType::E1D:
|
||||
case ImageType::E2D:
|
||||
framebuffer.Texture2D(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, parentTexture.GetTexture().GetObjectId(), texViewInfo.baseMipLevel);
|
||||
break;
|
||||
|
||||
case ImageType::E1D_Array:
|
||||
case ImageType::E2D_Array:
|
||||
case ImageType::E3D:
|
||||
framebuffer.TextureLayer(GL_COLOR_ATTACHMENT0, parentTexture.GetTexture().GetObjectId(), texViewInfo.baseArrayLayer, texViewInfo.baseMipLevel);
|
||||
break;
|
||||
}
|
||||
else if (texture.GetType() == ImageType::E2D)
|
||||
texTarget = GL_TEXTURE_2D;
|
||||
else
|
||||
throw std::runtime_error("unrestricted texture views are not supported on this device, blit is only permitted from/to a cubemap face or a 2D texture");
|
||||
|
||||
//TODO: Support texture arrays (one slice at a time)
|
||||
|
||||
framebuffer.Texture2D(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.GetParentTexture()->GetTexture().GetObjectId(), texture.GetTextureViewInfo().baseMipLevel);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (texture.GetTexture().GetTarget() != TextureTarget::Target2D)
|
||||
throw std::runtime_error("blit is not yet supported from other texture type than 2D textures");
|
||||
throw std::runtime_error("blit is not yet supported from/to other texture type than 2D textures");
|
||||
|
||||
framebuffer.Texture2D(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.GetTexture().GetObjectId(), 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,13 +37,32 @@ namespace Nz
|
|||
NazaraAssert(params.IsValid(), "Invalid TextureParams");
|
||||
|
||||
Nz::TextureInfo texParams;
|
||||
texParams.depth = image.GetDepth();
|
||||
texParams.height = image.GetHeight();
|
||||
texParams.pixelFormat = image.GetFormat();
|
||||
texParams.type = image.GetType();
|
||||
texParams.width = image.GetWidth();
|
||||
texParams.usageFlags = params.usageFlags;
|
||||
|
||||
switch (image.GetType())
|
||||
{
|
||||
case ImageType::E1D:
|
||||
case ImageType::E2D:
|
||||
case ImageType::E3D:
|
||||
break;
|
||||
|
||||
case ImageType::E1D_Array:
|
||||
texParams.layerCount = image.GetHeight();
|
||||
break;
|
||||
|
||||
case ImageType::E2D_Array:
|
||||
texParams.layerCount = image.GetDepth();
|
||||
break;
|
||||
|
||||
case ImageType::Cubemap:
|
||||
texParams.layerCount = 6;
|
||||
break;
|
||||
}
|
||||
|
||||
std::shared_ptr<Texture> texture = params.renderDevice->InstantiateTexture(texParams);
|
||||
if (!texture->Update(image.GetConstPixels()))
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue