From 80e93a8e3852613c124493e89ed3a44f10871c75 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sat, 28 Jan 2017 17:56:17 -1000 Subject: [PATCH] Mipmapped array textures --- include/boo/graphicsdev/GL.hpp | 4 +- .../boo/graphicsdev/IGraphicsDataFactory.hpp | 11 ++-- include/boo/graphicsdev/Metal.hpp | 4 +- lib/graphicsdev/GL.cpp | 58 ++++++++++++++----- lib/graphicsdev/Metal.mm | 40 ++++++++----- 5 files changed, 81 insertions(+), 36 deletions(-) diff --git a/include/boo/graphicsdev/GL.hpp b/include/boo/graphicsdev/GL.hpp index 352ddb8..de9c733 100644 --- a/include/boo/graphicsdev/GL.hpp +++ b/include/boo/graphicsdev/GL.hpp @@ -49,8 +49,8 @@ public: ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz); - ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt, - const void* data, size_t sz); + ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, + TextureFormat fmt, const void* data, size_t sz); ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt); ITextureR* newRenderTexture(size_t width, size_t height, bool enableShaderColorBinding, bool enableShaderDepthBinding); diff --git a/include/boo/graphicsdev/IGraphicsDataFactory.hpp b/include/boo/graphicsdev/IGraphicsDataFactory.hpp index b62af19..3355beb 100644 --- a/include/boo/graphicsdev/IGraphicsDataFactory.hpp +++ b/include/boo/graphicsdev/IGraphicsDataFactory.hpp @@ -220,8 +220,8 @@ struct IGraphicsDataFactory newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz)=0; virtual ITextureSA* - newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt, - const void* data, size_t sz)=0; + newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, + TextureFormat fmt, const void* data, size_t sz)=0; virtual ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt)=0; virtual ITextureR* @@ -367,12 +367,15 @@ public: IGraphicsBufferD* newPoolBuffer(BufferUse use, size_t stride, size_t count) { - return m_factory->newPoolBuffer(m_pool, use, stride, count); + if (m_factory) + return m_factory->newPoolBuffer(m_pool, use, stride, count); + return nullptr; } void deletePoolBuffer(IGraphicsBufferD* buf) { - m_factory->deletePoolBuffer(m_pool, buf); + if (m_factory) + m_factory->deletePoolBuffer(m_pool, buf); } }; diff --git a/include/boo/graphicsdev/Metal.hpp b/include/boo/graphicsdev/Metal.hpp index 8af0d15..905bdec 100644 --- a/include/boo/graphicsdev/Metal.hpp +++ b/include/boo/graphicsdev/Metal.hpp @@ -53,8 +53,8 @@ public: ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz); - ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt, - const void* data, size_t sz); + ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, + TextureFormat fmt, const void* data, size_t sz); ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt); ITextureR* newRenderTexture(size_t width, size_t height, bool enableShaderColorBinding, bool enableShaderDepthBinding); diff --git a/lib/graphicsdev/GL.cpp b/lib/graphicsdev/GL.cpp index c323ea7..06dd010 100644 --- a/lib/graphicsdev/GL.cpp +++ b/lib/graphicsdev/GL.cpp @@ -138,7 +138,7 @@ class GLTextureS : public ITextureS switch (fmt) { case TextureFormat::RGBA8: - intFormat = GL_RGBA; + intFormat = GL_RGBA8; format = GL_RGBA; pxPitch = 4; break; @@ -162,8 +162,10 @@ class GLTextureS : public ITextureS size_t dataSz = width * height / 2; glCompressedTexImage2D(GL_TEXTURE_2D, i, intFormat, width, height, 0, dataSz, dataIt); dataIt += dataSz; - width /= 2; - height /= 2; + if (width > 1) + width /= 2; + if (height > 1) + height /= 2; } } else @@ -172,8 +174,10 @@ class GLTextureS : public ITextureS { glTexImage2D(GL_TEXTURE_2D, i, intFormat, width, height, 0, format, GL_UNSIGNED_BYTE, dataIt); dataIt += width * height * pxPitch; - width /= 2; - height /= 2; + if (width > 1) + width /= 2; + if (height > 1) + height /= 2; } } } @@ -191,17 +195,45 @@ class GLTextureSA : public ITextureSA { friend class GLDataFactory; GLuint m_tex; - GLTextureSA(size_t width, size_t height, size_t layers, + GLTextureSA(size_t width, size_t height, size_t layers, size_t mips, TextureFormat fmt, const void* data, size_t sz) { + const uint8_t* dataIt = static_cast(data); glGenTextures(1, &m_tex); glBindTexture(GL_TEXTURE_2D_ARRAY, m_tex); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + if (mips > 1) + { + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, mips-1); + } + else + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + GLenum intFormat, format; + int pxPitch; if (fmt == TextureFormat::RGBA8) - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, width, height, layers, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + { + intFormat = GL_RGBA8; + format = GL_RGBA; + pxPitch = 4; + } else if (fmt == TextureFormat::I8) - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R8, width, height, layers, 0, GL_RED, GL_UNSIGNED_BYTE, data); + { + intFormat = GL_R8; + format = GL_RED; + pxPitch = 1; + } + + for (size_t i=0 ; i 1) + width /= 2; + if (height > 1) + height /= 2; + } } public: ~GLTextureSA() {glDeleteTextures(1, &m_tex);} @@ -317,10 +349,10 @@ GLDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mip } ITextureSA* -GLDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt, - const void *data, size_t sz) +GLDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, + TextureFormat fmt, const void *data, size_t sz) { - GLTextureSA* retval = new GLTextureSA(width, height, layers, fmt, data, sz); + GLTextureSA* retval = new GLTextureSA(width, height, layers, mips, fmt, data, sz); m_deferredData->m_SATexs.emplace_back(retval); return retval; } @@ -1382,7 +1414,7 @@ GLTextureD::GLTextureD(size_t width, size_t height, TextureFormat fmt) switch (fmt) { case TextureFormat::RGBA8: - m_intFormat = GL_RGBA; + m_intFormat = GL_RGBA8; m_format = GL_RGBA; pxPitch = 4; break; diff --git a/lib/graphicsdev/Metal.mm b/lib/graphicsdev/Metal.mm index 2c20e63..2396007 100644 --- a/lib/graphicsdev/Metal.mm +++ b/lib/graphicsdev/Metal.mm @@ -123,8 +123,10 @@ class MetalTextureS : public ITextureS withBytes:dataIt bytesPerRow:width * ppitchNum / ppitchDenom]; dataIt += width * height * ppitchNum / ppitchDenom; - width /= 2; - height /= 2; + if (width > 1) + width /= 2; + if (height > 1) + height /= 2; } } } @@ -136,7 +138,7 @@ public: class MetalTextureSA : public ITextureSA { friend class MetalDataFactory; - MetalTextureSA(MetalContext* ctx, size_t width, size_t height, size_t layers, + MetalTextureSA(MetalContext* ctx, size_t width, size_t height, size_t layers, size_t mips, TextureFormat fmt, const void* data, size_t sz) { MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm; @@ -155,21 +157,29 @@ class MetalTextureSA : public ITextureSA MTLTextureDescriptor* desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pfmt width:width height:height - mipmapped:NO]; + mipmapped:(mips>1)?YES:NO]; desc.textureType = MTLTextureType2DArray; desc.arrayLength = layers; + desc.mipmapLevelCount = mips; desc.usage = MTLTextureUsageShaderRead; m_tex = [ctx->m_dev newTextureWithDescriptor:desc]; const uint8_t* dataIt = reinterpret_cast(data); - for (size_t i=0 ; i 1) + width /= 2; + if (height > 1) + height /= 2; } } } @@ -1056,10 +1066,10 @@ ITextureS* MetalDataFactory::Context::newStaticTexture(size_t width, size_t heig m_deferredData->m_STexs.emplace_back(retval); return retval; } -ITextureSA* MetalDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt, - const void* data, size_t sz) +ITextureSA* MetalDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, + TextureFormat fmt, const void* data, size_t sz) { - MetalTextureSA* retval = new MetalTextureSA(m_parent.m_ctx, width, height, layers, fmt, data, sz); + MetalTextureSA* retval = new MetalTextureSA(m_parent.m_ctx, width, height, layers, mips, fmt, data, sz); m_deferredData->m_SATexs.emplace_back(retval); return retval; }