Skip to content

Commit

Permalink
implement createTextureViewSwizzled() in the GL backend
Browse files Browse the repository at this point in the history
  • Loading branch information
pixelflinger committed Aug 28, 2024
1 parent d161ef2 commit 6de6a21
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 86 deletions.
14 changes: 0 additions & 14 deletions filament/backend/include/private/backend/DriverAPI.inc
Original file line number Diff line number Diff line change
Expand Up @@ -212,20 +212,6 @@ DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureViewSwizzle,
backend::TextureSwizzle, b,
backend::TextureSwizzle, a)

DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureSwizzled,
backend::SamplerType, target,
uint8_t, levels,
backend::TextureFormat, format,
uint8_t, samples,
uint32_t, width,
uint32_t, height,
uint32_t, depth,
backend::TextureUsage, usage,
backend::TextureSwizzle, r,
backend::TextureSwizzle, g,
backend::TextureSwizzle, b,
backend::TextureSwizzle, a)

DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImage,
backend::TextureFormat, format,
uint32_t, width,
Expand Down
14 changes: 0 additions & 14 deletions filament/backend/src/metal/MetalDriver.mm
Original file line number Diff line number Diff line change
Expand Up @@ -457,16 +457,6 @@
th.getId(), stringify(target), levels, samples, width, height, depth, stringify(usage));
}

void MetalDriver::createTextureSwizzledR(Handle<HwTexture> th, SamplerType target, uint8_t levels,
TextureFormat format, uint8_t samples, uint32_t width, uint32_t height,
uint32_t depth, TextureUsage usage,
TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a) {
auto texture = alloc_handle<MetalTexture>();
createTextureR(texture, target, levels, format, samples, width, height, depth, usage);
createTextureViewSwizzleR(th, texture, r, g, b, a);
destroyTexture(texture);
}

void MetalDriver::createTextureViewR(
Handle<HwTexture> th, Handle<HwTexture> srch, uint8_t baseLevel, uint8_t levelCount) {
MetalTexture const* src = handle_cast<MetalTexture>(srch);
Expand Down Expand Up @@ -701,10 +691,6 @@
return alloc_handle<MetalTexture>();
}

Handle<HwTexture> MetalDriver::createTextureSwizzledS() noexcept {
return alloc_handle<MetalTexture>();
}

Handle<HwTexture> MetalDriver::createTextureViewS() noexcept {
return alloc_handle<MetalTexture>();
}
Expand Down
31 changes: 21 additions & 10 deletions filament/backend/src/opengl/GLDescriptorSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@
#include <utils/bitset.h>
#include <utils/compiler.h>
#include <utils/debug.h>

#include <algorithm>

#include <type_traits>
#include <utility>
#include <variant>

#include <stddef.h>
Expand All @@ -50,7 +51,7 @@ namespace filament::backend {
GLDescriptorSet::GLDescriptorSet(OpenGLContext& gl, DescriptorSetLayoutHandle dslh,
GLDescriptorSetLayout const* layout) noexcept
: descriptors(layout->maxDescriptorBinding + 1),
dslh(dslh) {
dslh(std::move(dslh)) {

// We have allocated enough storage for all descriptors. Now allocate the empty descriptor
// themselves.
Expand Down Expand Up @@ -178,6 +179,7 @@ void GLDescriptorSet::update(OpenGLContext& gl,
arg.ref = t->ref;
arg.baseLevel = t->gl.baseLevel;
arg.maxLevel = t->gl.maxLevel;
arg.swizzle = t->gl.swizzle;
}
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
arg.sampler = gl.getSampler(params);
Expand All @@ -195,17 +197,17 @@ void GLDescriptorSet::update(OpenGLContext& gl,
}

template<typename T>
void GLDescriptorSet::updateTextureLod(OpenGLContext& gl,
void GLDescriptorSet::updateTextureView(OpenGLContext& gl,
HandleAllocatorGL& handleAllocator, GLuint unit, T const& desc) noexcept {
// The common case is that we don't have a ref handle (we only have one if
// the texture ever had a View on it.
// the texture ever had a View on it).
assert_invariant(desc.ref);
GLTextureRef* const ref = handleAllocator.handle_cast<GLTextureRef*>(desc.ref);
if (UTILS_UNLIKELY((desc.baseLevel != ref->baseLevel
|| desc.maxLevel != ref->maxLevel))) {
if (UTILS_UNLIKELY((desc.baseLevel != ref->baseLevel || desc.maxLevel != ref->maxLevel))) {
// If we have views, then it's still uncommon that we'll switch often
// handle the case where we reset to the original texture
GLint baseLevel = desc.baseLevel;
GLint maxLevel = desc.maxLevel;
GLint baseLevel = GLint(desc.baseLevel); // NOLINT(*-signed-char-misuse)
GLint maxLevel = GLint(desc.maxLevel); // NOLINT(*-signed-char-misuse)
if (baseLevel > maxLevel) {
baseLevel = 0;
maxLevel = 1000; // per OpenGL spec
Expand All @@ -217,6 +219,15 @@ void GLDescriptorSet::updateTextureLod(OpenGLContext& gl,
ref->baseLevel = desc.baseLevel;
ref->maxLevel = desc.maxLevel;
}
if (UTILS_UNLIKELY(desc.swizzle != ref->swizzle)) {
using namespace GLUtils;
gl.activeTexture(unit);
glTexParameteri(desc.target, GL_TEXTURE_SWIZZLE_R, (GLint)getSwizzleChannel(desc.swizzle[0]));
glTexParameteri(desc.target, GL_TEXTURE_SWIZZLE_G, (GLint)getSwizzleChannel(desc.swizzle[1]));
glTexParameteri(desc.target, GL_TEXTURE_SWIZZLE_B, (GLint)getSwizzleChannel(desc.swizzle[2]));
glTexParameteri(desc.target, GL_TEXTURE_SWIZZLE_A, (GLint)getSwizzleChannel(desc.swizzle[3]));
ref->swizzle = desc.swizzle;
}
}

void GLDescriptorSet::bind(
Expand Down Expand Up @@ -272,7 +283,7 @@ void GLDescriptorSet::bind(
gl.bindTexture(unit, arg.target, arg.id);
gl.bindSampler(unit, arg.sampler);
if (UTILS_UNLIKELY(arg.ref)) {
updateTextureLod(gl, handleAllocator, unit, arg);
updateTextureView(gl, handleAllocator, unit, arg);
}
} else {
gl.unbindTextureUnit(unit);
Expand All @@ -283,7 +294,7 @@ void GLDescriptorSet::bind(
gl.bindTexture(unit, arg.target, arg.id);
gl.bindSampler(unit, arg.sampler);
if (UTILS_UNLIKELY(arg.ref)) {
updateTextureLod(gl, handleAllocator, unit, arg);
updateTextureView(gl, handleAllocator, unit, arg);
}
#if defined(GL_EXT_texture_filter_anisotropic)
// Driver claims to support anisotropic filtering, but it fails when set on
Expand Down
15 changes: 14 additions & 1 deletion filament/backend/src/opengl/GLDescriptorSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include <math/half.h>

#include <array>
#include <variant>

#include <stddef.h>
Expand Down Expand Up @@ -112,6 +113,12 @@ struct GLDescriptorSet : public HwDescriptorSet {
Handle<GLTextureRef> ref; // 4
int8_t baseLevel = 0x7f; // 1
int8_t maxLevel = -1; // 1
std::array<TextureSwizzle, 4> swizzle{ // 4
TextureSwizzle::CHANNEL_0,
TextureSwizzle::CHANNEL_1,
TextureSwizzle::CHANNEL_2,
TextureSwizzle::CHANNEL_3
};
};

struct SamplerWithAnisotropyWorkaround {
Expand All @@ -122,6 +129,12 @@ struct GLDescriptorSet : public HwDescriptorSet {
math::half anisotropy = 1.0f; // 2
int8_t baseLevel = 0x7f; // 1
int8_t maxLevel = -1; // 1
std::array<TextureSwizzle, 4> swizzle{ // 4
TextureSwizzle::CHANNEL_0,
TextureSwizzle::CHANNEL_1,
TextureSwizzle::CHANNEL_2,
TextureSwizzle::CHANNEL_3
};
};

// A sampler descriptor for ES2
Expand All @@ -143,7 +156,7 @@ struct GLDescriptorSet : public HwDescriptorSet {
static_assert(sizeof(Descriptor) <= 32);

template<typename T>
static void updateTextureLod(OpenGLContext& gl,
static void updateTextureView(OpenGLContext& gl,
HandleAllocatorGL& handleAllocator, GLuint unit, T const& desc) noexcept;

utils::FixedCapacityVector<Descriptor> descriptors; // 16
Expand Down
18 changes: 18 additions & 0 deletions filament/backend/src/opengl/GLTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,29 @@
#include "gl_headers.h"

#include <backend/Handle.h>
#include <backend/DriverEnums.h>
#include <backend/platforms/OpenGLPlatform.h>

#include <array>

#include <stdint.h>

namespace filament::backend {

struct GLTextureRef {
GLTextureRef() = default;
// view reference counter
uint16_t count = 1;
// current per-view values of the texture (in GL we can only have a single View active at
// a time, and this tracks that state). It's used to avoid unnecessarily change state.
int8_t baseLevel = 127;
int8_t maxLevel = -1;
std::array<TextureSwizzle, 4> swizzle{
TextureSwizzle::CHANNEL_0,
TextureSwizzle::CHANNEL_1,
TextureSwizzle::CHANNEL_2,
TextureSwizzle::CHANNEL_3
};
};

struct GLTexture : public HwTexture {
Expand All @@ -52,6 +64,12 @@ struct GLTexture : public HwTexture {
bool imported : 1;
uint8_t sidecarSamples : 4;
uint8_t reserved1 : 3;
std::array<TextureSwizzle, 4> swizzle{
TextureSwizzle::CHANNEL_0,
TextureSwizzle::CHANNEL_1,
TextureSwizzle::CHANNEL_2,
TextureSwizzle::CHANNEL_3
};
} gl;
mutable Handle<GLTextureRef> ref;
OpenGLPlatform::ExternalTexture* externalTexture = nullptr;
Expand Down
90 changes: 59 additions & 31 deletions filament/backend/src/opengl/OpenGLDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,10 +544,6 @@ Handle<HwTexture> OpenGLDriver::createTextureS() noexcept {
return initHandle<GLTexture>();
}

Handle<HwTexture> OpenGLDriver::createTextureSwizzledS() noexcept {
return initHandle<GLTexture>();
}

Handle<HwTexture> OpenGLDriver::createTextureViewS() noexcept {
return initHandle<GLTexture>();
}
Expand Down Expand Up @@ -927,32 +923,6 @@ void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
CHECK_GL_ERROR(utils::slog.e)
}

void OpenGLDriver::createTextureSwizzledR(Handle<HwTexture> th,
SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples,
uint32_t w, uint32_t h, uint32_t depth, TextureUsage usage,
TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a) {
DEBUG_MARKER()

assert_invariant(uint8_t(usage) & uint8_t(TextureUsage::SAMPLEABLE));

createTextureR(th, target, levels, format, samples, w, h, depth, usage);

// WebGL does not support swizzling. We assert for this in the Texture builder,
// so it is probably fine to silently ignore the swizzle state here.
#if !defined(__EMSCRIPTEN__) && !defined(FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2)
if (!mContext.isES2()) {
// the texture is still bound and active from createTextureR
GLTexture* t = handle_cast<GLTexture*>(th);
glTexParameteri(t->gl.target, GL_TEXTURE_SWIZZLE_R, (GLint)getSwizzleChannel(r));
glTexParameteri(t->gl.target, GL_TEXTURE_SWIZZLE_G, (GLint)getSwizzleChannel(g));
glTexParameteri(t->gl.target, GL_TEXTURE_SWIZZLE_B, (GLint)getSwizzleChannel(b));
glTexParameteri(t->gl.target, GL_TEXTURE_SWIZZLE_A, (GLint)getSwizzleChannel(a));
}
#endif

CHECK_GL_ERROR(utils::slog.e)
}

void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
Handle<HwTexture> srch, uint8_t baseLevel, uint8_t levelCount) {
DEBUG_MARKER()
Expand Down Expand Up @@ -1002,7 +972,65 @@ void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
backend::TextureSwizzle a) {
// TODO: implement swizzle

DEBUG_MARKER()
GLTexture const* const src = handle_cast<GLTexture const*>(srch);

FILAMENT_CHECK_PRECONDITION(any(src->usage & TextureUsage::SAMPLEABLE))
<< "TextureView can only be created on a SAMPLEABLE texture";

FILAMENT_CHECK_PRECONDITION(!src->gl.imported)
<< "TextureView can't be created on imported textures";

if (!src->ref) {
// lazily create the ref handle, because most textures will never get a texture view
src->ref = initHandle<GLTextureRef>();
}

GLTexture* t = construct<GLTexture>(th,
src->target,
src->levels,
src->samples,
src->width, src->height, src->depth,
src->format,
src->usage);

t->gl = src->gl;
t->gl.baseLevel = src->gl.baseLevel;
t->gl.maxLevel = src->gl.maxLevel;
t->gl.sidecarRenderBufferMS = 0;
t->gl.sidecarSamples = 1;

auto getChannel = [&swizzle = src->gl.swizzle](TextureSwizzle ch) {
switch (ch) {
case TextureSwizzle::SUBSTITUTE_ZERO:
case TextureSwizzle::SUBSTITUTE_ONE:
return ch;
case TextureSwizzle::CHANNEL_0:
return swizzle[0];
case TextureSwizzle::CHANNEL_1:
return swizzle[1];
case TextureSwizzle::CHANNEL_2:
return swizzle[2];
case TextureSwizzle::CHANNEL_3:
return swizzle[3];
}
};

t->gl.swizzle = {
getChannel(r),
getChannel(g),
getChannel(b),
getChannel(a),
};

// increase reference count to this texture handle
t->ref = src->ref;
GLTextureRef* ref = handle_cast<GLTextureRef*>(t->ref);
assert_invariant(ref);
ref->count++;

CHECK_GL_ERROR(utils::slog.e)
}

void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::TextureFormat format,
Expand Down
28 changes: 12 additions & 16 deletions filament/backend/src/vulkan/VulkanDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,18 +559,18 @@ void VulkanDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
mResourceManager.acquire(vktexture);
}

void VulkanDriver::createTextureSwizzledR(Handle<HwTexture> th, SamplerType target, uint8_t levels,
TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
TextureUsage usage,
TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a) {
TextureSwizzle swizzleArray[] = {r, g, b, a};
const VkComponentMapping swizzleMap = getSwizzleMap(swizzleArray);
auto vktexture = mResourceAllocator.construct<VulkanTexture>(th, mPlatform->getDevice(),
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, &mResourceAllocator,
target, levels, format, samples, w, h, depth, usage, mStagePool,
false /*heap allocated */, swizzleMap);
mResourceManager.acquire(vktexture);
}
//void VulkanDriver::createTextureSwizzledR(Handle<HwTexture> th, SamplerType target, uint8_t levels,
// TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
// TextureUsage usage,
// TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a) {
// TextureSwizzle swizzleArray[] = {r, g, b, a};
// const VkComponentMapping swizzleMap = getSwizzleMap(swizzleArray);
// auto vktexture = mResourceAllocator.construct<VulkanTexture>(th, mPlatform->getDevice(),
// mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, &mResourceAllocator,
// target, levels, format, samples, w, h, depth, usage, mStagePool,
// false /*heap allocated */, swizzleMap);
// mResourceManager.acquire(vktexture);
//}

void VulkanDriver::createTextureViewR(Handle<HwTexture> th,
Handle<HwTexture> srch, uint8_t baseLevel, uint8_t levelCount) {
Expand Down Expand Up @@ -780,10 +780,6 @@ Handle<HwTexture> VulkanDriver::createTextureS() noexcept {
return mResourceAllocator.allocHandle<VulkanTexture>();
}

Handle<HwTexture> VulkanDriver::createTextureSwizzledS() noexcept {
return mResourceAllocator.allocHandle<VulkanTexture>();
}

Handle<HwTexture> VulkanDriver::createTextureViewS() noexcept {
return mResourceAllocator.allocHandle<VulkanTexture>();
}
Expand Down

0 comments on commit 6de6a21

Please sign in to comment.