diff --git a/filament/backend/include/private/backend/Driver.h b/filament/backend/include/private/backend/Driver.h index 7e7f836be3..1fd585fe90 100644 --- a/filament/backend/include/private/backend/Driver.h +++ b/filament/backend/include/private/backend/Driver.h @@ -27,6 +27,7 @@ #include #include +#include #include #include diff --git a/filament/backend/include/private/backend/DriverAPI.inc b/filament/backend/include/private/backend/DriverAPI.inc index a4b2a83cab..5a024c2a6f 100644 --- a/filament/backend/include/private/backend/DriverAPI.inc +++ b/filament/backend/include/private/backend/DriverAPI.inc @@ -108,15 +108,15 @@ DECL_DRIVER_API_RETURN(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__), PAIR_ARGS_N(PARAM, ##__VA_ARGS__)) #define DECL_DRIVER_API_TAGGED_R_N(R, N, ...) \ - DECL_DRIVER_API_RETURN(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__, utils::CString&&, tag = {}), \ - PAIR_ARGS_N(PARAM, ##__VA_ARGS__, utils::CString&&, tag)) + DECL_DRIVER_API_RETURN(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__, utils::ImmutableCString&&, tag = {}), \ + PAIR_ARGS_N(PARAM, ##__VA_ARGS__, utils::ImmutableCString&&, tag)) #define DECL_DRIVER_API_SYNCHRONOUS_N(R, N, ...) \ DECL_DRIVER_API_SYNCHRONOUS(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__), PAIR_ARGS_N(PARAM, ##__VA_ARGS__)) #define DECL_DRIVER_API_SYNCHRONOUS_TAGGED_N(R, N, ...) \ - DECL_DRIVER_API_SYNCHRONOUS(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__, utils::CString, tag = {}), \ - PAIR_ARGS_N(PARAM, ##__VA_ARGS__, utils::CString, tag)) + DECL_DRIVER_API_SYNCHRONOUS(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__, utils::ImmutableCString, tag = {}), \ + PAIR_ARGS_N(PARAM, ##__VA_ARGS__, utils::ImmutableCString, tag)) // on some compilers the ##__VA_ARGS__ hack is not supported, so we can't handle 0-parameter APIs // with DECL_DRIVER_API_SYNCHRONOUS_N diff --git a/filament/backend/include/private/backend/HandleAllocator.h b/filament/backend/include/private/backend/HandleAllocator.h index f0fb62434e..3bc9633d3f 100644 --- a/filament/backend/include/private/backend/HandleAllocator.h +++ b/filament/backend/include/private/backend/HandleAllocator.h @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -52,16 +53,16 @@ namespace filament::backend { class DebugTag { public: DebugTag(); - void writePoolHandleTag(HandleBase::HandleId key, utils::CString&& tag) noexcept; - void writeHeapHandleTag(HandleBase::HandleId key, utils::CString&& tag) noexcept; - utils::CString findHandleTag(HandleBase::HandleId key) const noexcept; + void writePoolHandleTag(HandleBase::HandleId key, utils::ImmutableCString&& tag) noexcept; + void writeHeapHandleTag(HandleBase::HandleId key, utils::ImmutableCString&& tag) noexcept; + utils::ImmutableCString findHandleTag(HandleBase::HandleId key) const noexcept; private: // This is used to associate a tag to a handle. mDebugTags is only written the in the main // driver thread, but it can be accessed from any thread, because it's called from handle_cast<> // which is used by synchronous calls. mutable utils::Mutex mDebugTagLock; - tsl::robin_map mDebugTags; + tsl::robin_map mDebugTags; }; /* @@ -222,7 +223,7 @@ public: return static_cast(p); } - utils::CString getHandleTag(HandleBase::HandleId key) const noexcept; + utils::ImmutableCString getHandleTag(HandleBase::HandleId key) const noexcept; template bool is_valid(Handle& handle) { @@ -248,7 +249,7 @@ public: return handle_cast(const_cast&>(handle)); } - void associateTagToHandle(HandleBase::HandleId id, utils::CString&& tag) noexcept { + void associateTagToHandle(HandleBase::HandleId id, utils::ImmutableCString&& tag) noexcept { if (tag.empty()) { return; } diff --git a/filament/backend/src/HandleAllocator.cpp b/filament/backend/src/HandleAllocator.cpp index 794064581a..5eb386d23f 100644 --- a/filament/backend/src/HandleAllocator.cpp +++ b/filament/backend/src/HandleAllocator.cpp @@ -156,7 +156,7 @@ void HandleAllocator::deallocateHandleSlow(HandleBase::HandleId id, template UTILS_NOINLINE -CString HandleAllocator::getHandleTag(HandleBase::HandleId id) const noexcept { +ImmutableCString HandleAllocator::getHandleTag(HandleBase::HandleId id) const noexcept { uint32_t key = id; if (UTILS_LIKELY(isPoolHandle(id))) { // Truncate the age to get the debug tag @@ -172,7 +172,7 @@ DebugTag::DebugTag() { } UTILS_NOINLINE -CString DebugTag::findHandleTag(HandleBase::HandleId key) const noexcept { +ImmutableCString DebugTag::findHandleTag(HandleBase::HandleId key) const noexcept { std::unique_lock const lock(mDebugTagLock); if (auto pos = mDebugTags.find(key); pos != mDebugTags.end()) { return pos->second; @@ -181,7 +181,7 @@ CString DebugTag::findHandleTag(HandleBase::HandleId key) const noexcept { } UTILS_NOINLINE -void DebugTag::writePoolHandleTag(HandleBase::HandleId key, CString&& tag) noexcept { +void DebugTag::writePoolHandleTag(HandleBase::HandleId key, ImmutableCString&& tag) noexcept { // This line is the costly part. In the future, we could potentially use a custom // allocator. std::unique_lock const lock(mDebugTagLock); @@ -190,7 +190,7 @@ void DebugTag::writePoolHandleTag(HandleBase::HandleId key, CString&& tag) noexc } UTILS_NOINLINE -void DebugTag::writeHeapHandleTag(HandleBase::HandleId key, CString&& tag) noexcept { +void DebugTag::writeHeapHandleTag(HandleBase::HandleId key, ImmutableCString&& tag) noexcept { // This line is the costly part. In the future, we could potentially use a custom // allocator. std::unique_lock const lock(mDebugTagLock); diff --git a/filament/backend/src/metal/MetalBuffer.h b/filament/backend/src/metal/MetalBuffer.h index d3368181a7..464bafd623 100644 --- a/filament/backend/src/metal/MetalBuffer.h +++ b/filament/backend/src/metal/MetalBuffer.h @@ -192,7 +192,7 @@ public: void* getCpuBuffer() const noexcept { return mCpuBuffer; } - void setLabel(const utils::CString& label) { + void setLabel(const utils::ImmutableCString& label) { #if FILAMENT_METAL_DEBUG_LABELS if (label.empty()) { return; diff --git a/filament/backend/src/metal/MetalDriver.mm b/filament/backend/src/metal/MetalDriver.mm index d6473fad5e..fab963d7a7 100644 --- a/filament/backend/src/metal/MetalDriver.mm +++ b/filament/backend/src/metal/MetalDriver.mm @@ -42,6 +42,7 @@ #include #include #include +#include #include @@ -418,14 +419,14 @@ void MetalDriver::finish(int) { } void MetalDriver::createVertexBufferInfoR(Handle vbih, uint8_t bufferCount, - uint8_t attributeCount, AttributeArray attributes, utils::CString&& tag) { + uint8_t attributeCount, AttributeArray attributes, utils::ImmutableCString&& tag) { construct_handle(vbih, *mContext, bufferCount, attributeCount, attributes); mHandleAllocator.associateTagToHandle(vbih.getId(), std::move(tag)); } void MetalDriver::createVertexBufferR(Handle vbh, - uint32_t vertexCount, Handle vbih, utils::CString&& tag) { + uint32_t vertexCount, Handle vbih, utils::ImmutableCString&& tag) { MetalVertexBufferInfo const* const vbi = handle_cast(vbih); construct_handle(vbh, *mContext, vertexCount, vbi->bufferCount, vbih); mHandleAllocator.associateTagToHandle(vbh.getId(), std::move(tag)); @@ -433,7 +434,7 @@ void MetalDriver::createVertexBufferR(Handle vbh, } void MetalDriver::createIndexBufferR(Handle ibh, ElementType elementType, - uint32_t indexCount, BufferUsage usage, utils::CString&& tag) { + uint32_t indexCount, BufferUsage usage, utils::ImmutableCString&& tag) { auto elementSize = (uint8_t)getElementTypeSize(elementType); auto* indexBuffer = construct_handle(ibh, *mContext, usage, elementSize, indexCount); @@ -446,7 +447,7 @@ void MetalDriver::createIndexBufferR(Handle ibh, ElementType elem } void MetalDriver::createBufferObjectR(Handle boh, uint32_t byteCount, - BufferObjectBinding bindingType, BufferUsage usage, utils::CString&& tag) { + BufferObjectBinding bindingType, BufferUsage usage, utils::ImmutableCString&& tag) { auto* bufferObject = construct_handle(boh, *mContext, bindingType, usage, byteCount); FILAMENT_CHECK_POSTCONDITION(bufferObject->getBuffer()->wasAllocationSuccessful()) @@ -488,7 +489,7 @@ inline const char* stringify(SamplerType samplerType) { void MetalDriver::createTextureR(Handle th, SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples, uint32_t width, uint32_t height, - uint32_t depth, TextureUsage usage, utils::CString&& tag) { + uint32_t depth, TextureUsage usage, utils::ImmutableCString&& tag) { // Clamp sample count to what the device supports. auto& sc = mContext->sampleCountLookup; samples = sc[std::min(MAX_SAMPLE_COUNT, samples)]; @@ -508,7 +509,7 @@ void MetalDriver::createTextureR(Handle th, SamplerType target, uint8 } void MetalDriver::createTextureViewR(Handle th, Handle srch, - uint8_t baseLevel, uint8_t levelCount, utils::CString&& tag) { + uint8_t baseLevel, uint8_t levelCount, utils::ImmutableCString&& tag) { MetalTexture const* src = handle_cast(srch); MetalTexture* texture = construct_handle(th, *mContext, src, baseLevel, levelCount); @@ -519,7 +520,7 @@ void MetalDriver::createTextureViewR(Handle th, Handle src void MetalDriver::createTextureViewSwizzleR(Handle th, Handle srch, backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b, - backend::TextureSwizzle a, utils::CString&& tag) { + backend::TextureSwizzle a, utils::ImmutableCString&& tag) { MetalTexture const* src = handle_cast(srch); MetalTexture* texture = construct_handle(th, *mContext, src, r, g, b, a); mContext->textures.insert(texture); @@ -531,13 +532,13 @@ void MetalDriver::createTextureExternalImage2R(Handle th, backend::SamplerType target, backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage, - Platform::ExternalImageHandleRef image, utils::CString&& tag) { + Platform::ExternalImageHandleRef image, utils::ImmutableCString&& tag) { // FIXME: implement createTextureExternalImage2R } void MetalDriver::createTextureExternalImageR(Handle th, backend::SamplerType target, backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage, - void* image, utils::CString&& tag) { + void* image, utils::ImmutableCString&& tag) { MetalTexture* texture = construct_handle(th, *mContext, format, width, height, usage, (CVPixelBufferRef) image); mContext->textures.insert(texture); @@ -550,7 +551,7 @@ void MetalDriver::createTextureExternalImageR(Handle th, backend::Sam void MetalDriver::createTextureExternalImagePlaneR(Handle th, backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage, - void* image, uint32_t plane, utils::CString&& tag) { + void* image, uint32_t plane, utils::ImmutableCString&& tag) { MetalTexture* texture = construct_handle(th, *mContext, format, width, height, usage, (CVPixelBufferRef) image, plane); mContext->textures.insert(texture); @@ -564,7 +565,7 @@ void MetalDriver::createTextureExternalImagePlaneR(Handle th, void MetalDriver::importTextureR(Handle th, intptr_t i, SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples, uint32_t width, uint32_t height, - uint32_t depth, TextureUsage usage, utils::CString&& tag) { + uint32_t depth, TextureUsage usage, utils::ImmutableCString&& tag) { id metalTexture = (id) CFBridgingRelease((void*) i); FILAMENT_CHECK_PRECONDITION(metalTexture.width == width) << "Imported id width (" << metalTexture.width @@ -588,13 +589,13 @@ void MetalDriver::importTextureR(Handle th, intptr_t i, void MetalDriver::createRenderPrimitiveR(Handle rph, Handle vbh, Handle ibh, - PrimitiveType pt, utils::CString&& tag) { + PrimitiveType pt, utils::ImmutableCString&& tag) { construct_handle(rph); MetalDriver::setRenderPrimitiveBuffer(rph, pt, vbh, ibh); mHandleAllocator.associateTagToHandle(rph.getId(), std::move(tag)); } -void MetalDriver::createProgramR(Handle rph, Program&& program, utils::CString&& tag) { +void MetalDriver::createProgramR(Handle rph, Program&& program, utils::ImmutableCString&& tag) { #if FILAMENT_METAL_DEBUG_LOG auto handleId = rph.getId(); DEBUG_LOG("createProgramR(rph = %d, program = ", handleId); @@ -604,7 +605,7 @@ void MetalDriver::createProgramR(Handle rph, Program&& program, utils mHandleAllocator.associateTagToHandle(rph.getId(), std::move(tag)); } -void MetalDriver::createDefaultRenderTargetR(Handle rth, utils::CString&& tag) { +void MetalDriver::createDefaultRenderTargetR(Handle rth, utils::ImmutableCString&& tag) { construct_handle(rth, mContext); mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag)); } @@ -612,7 +613,7 @@ void MetalDriver::createDefaultRenderTargetR(Handle rth, utils:: void MetalDriver::createRenderTargetR(Handle rth, TargetBufferFlags targetBufferFlags, uint32_t width, uint32_t height, uint8_t samples, uint8_t layerCount, MRT color, - TargetBufferInfo depth, TargetBufferInfo stencil, utils::CString&& tag) { + TargetBufferInfo depth, TargetBufferInfo stencil, utils::ImmutableCString&& tag) { FILAMENT_CHECK_PRECONDITION(!isInRenderPass(mContext)) << "createRenderTarget must be called outside of a render pass."; // Clamp sample count to what the device supports. @@ -659,14 +660,14 @@ void MetalDriver::createRenderTargetR(Handle rth, mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag)); } -void MetalDriver::createFenceR(Handle fh, utils::CString&& tag) { +void MetalDriver::createFenceR(Handle fh, utils::ImmutableCString&& tag) { auto* fence = handle_cast(fh); fence->encode(); mHandleAllocator.associateTagToHandle(fh.getId(), std::move(tag)); } void MetalDriver::createSwapChainR(Handle sch, void* nativeWindow, uint64_t flags, - utils::CString&& tag) { + utils::ImmutableCString&& tag) { // TODO: support MSAA swapchain if (UTILS_UNLIKELY(flags & SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER)) { @@ -683,18 +684,18 @@ void MetalDriver::createSwapChainR(Handle sch, void* nativeWindow, } void MetalDriver::createSwapChainHeadlessR(Handle sch, - uint32_t width, uint32_t height, uint64_t flags, utils::CString&& tag) { + uint32_t width, uint32_t height, uint64_t flags, utils::ImmutableCString&& tag) { construct_handle(sch, *mContext, mPlatform, width, height, flags); mHandleAllocator.associateTagToHandle(sch.getId(), std::move(tag)); } -void MetalDriver::createSyncR(Handle sh, utils::CString&& tag) { +void MetalDriver::createSyncR(Handle sh, utils::ImmutableCString&& tag) { // TODO: Ensure sync is active, and then invoke and clear all pending // callbacks. mHandleAllocator.associateTagToHandle(sh.getId(), std::move(tag)); } -void MetalDriver::createTimerQueryR(Handle tqh, utils::CString&& tag) { +void MetalDriver::createTimerQueryR(Handle tqh, utils::ImmutableCString&& tag) { // nothing to do, timer query was constructed in createTimerQueryS mHandleAllocator.associateTagToHandle(tqh.getId(), std::move(tag)); } @@ -733,12 +734,12 @@ const char* toString(DescriptorFlags flags) { } void MetalDriver::createDescriptorSetLayoutR( - Handle dslh, DescriptorSetLayout&& info, utils::CString&& tag) { + Handle dslh, DescriptorSetLayout&& info, utils::ImmutableCString&& tag) { #if FILAMENT_METAL_DEBUG_LOG == 1 const char* labelStr = ""; std::visit([&labelStr](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { labelStr = arg.c_str(); } }, info.label); @@ -758,7 +759,7 @@ void MetalDriver::createDescriptorSetLayoutR( } void MetalDriver::createDescriptorSetR( - Handle dsh, Handle dslh, utils::CString&& tag) { + Handle dsh, Handle dslh, utils::ImmutableCString&& tag) { DEBUG_LOG("createDescriptorSetR(dsh = %d, dslh = %d)\n", dsh.getId(), dslh.getId()); MetalDescriptorSetLayout* layout = handle_cast(dslh); MetalDescriptorSet* ds = construct_handle(dsh, layout); @@ -1010,11 +1011,11 @@ utils::FixedCapacityVector MetalDriver::getShaderLanguages( return { backend::ShaderLanguage::METAL_LIBRARY, backend::ShaderLanguage::MSL }; } -Handle MetalDriver::createStreamNative(void* stream, utils::CString tag) { +Handle MetalDriver::createStreamNative(void* stream, utils::ImmutableCString tag) { return {}; } -Handle MetalDriver::createStreamAcquired(utils::CString tag) { +Handle MetalDriver::createStreamAcquired(utils::ImmutableCString tag) { return {}; } @@ -2231,7 +2232,7 @@ MemoryMappedBufferHandle MetalDriver::mapBufferS() noexcept { void MetalDriver::mapBufferR(MemoryMappedBufferHandle mmbh, BufferObjectHandle boh, size_t offset, - size_t size, MapBufferAccessFlags access, utils::CString&& tag) { + size_t size, MapBufferAccessFlags access, utils::ImmutableCString&& tag) { construct_handle(mmbh, boh, offset, size, access); mHandleAllocator.associateTagToHandle(mmbh.getId(), std::move(tag)); } diff --git a/filament/backend/src/metal/MetalHandles.h b/filament/backend/src/metal/MetalHandles.h index 2847c50104..1a0917df14 100644 --- a/filament/backend/src/metal/MetalHandles.h +++ b/filament/backend/src/metal/MetalHandles.h @@ -267,7 +267,7 @@ public: static MTLPixelFormat decidePixelFormat(MetalContext* context, TextureFormat format); - void setLabel(const utils::CString& label) { + void setLabel(const utils::ImmutableCString& label) { #if FILAMENT_METAL_DEBUG_LABELS if (label.empty()) { return; @@ -494,7 +494,7 @@ struct MetalDescriptorSet : public HwDescriptorSet { void finalize(MetalDriver* driver); - void setLabel(const utils::CString& l) { + void setLabel(const utils::ImmutableCString& l) { #if FILAMENT_METAL_DEBUG_LABELS if (l.empty()) { return; @@ -527,7 +527,7 @@ struct MetalDescriptorSet : public HwDescriptorSet { std::array cachedBuffer = { nil }; #if FILAMENT_METAL_DEBUG_LABELS - utils::CString label; + utils::ImmutableCString label; #endif }; diff --git a/filament/backend/src/noop/NoopDriver.cpp b/filament/backend/src/noop/NoopDriver.cpp index 3602a54df2..23b09ca349 100644 --- a/filament/backend/src/noop/NoopDriver.cpp +++ b/filament/backend/src/noop/NoopDriver.cpp @@ -21,6 +21,8 @@ #include "noop/NoopDriver.h" #include "CommandStreamDispatcher.h" +#include + #include namespace filament::backend { @@ -135,11 +137,11 @@ void NoopDriver::destroyDescriptorSetLayout(Handle tqh) { void NoopDriver::destroyDescriptorSet(Handle tqh) { } -Handle NoopDriver::createStreamNative(void* nativeStream, utils::CString tag) { +Handle NoopDriver::createStreamNative(void* nativeStream, utils::ImmutableCString tag) { return {}; } -Handle NoopDriver::createStreamAcquired(utils::CString tag) { +Handle NoopDriver::createStreamAcquired(utils::ImmutableCString tag) { return {}; } diff --git a/filament/backend/src/opengl/OpenGLDriver.cpp b/filament/backend/src/opengl/OpenGLDriver.cpp index b62b734285..a313240e47 100644 --- a/filament/backend/src/opengl/OpenGLDriver.cpp +++ b/filament/backend/src/opengl/OpenGLDriver.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -661,7 +662,7 @@ void OpenGLDriver::createVertexBufferInfoR( uint8_t bufferCount, uint8_t attributeCount, AttributeArray attributes, - CString&& tag) { + ImmutableCString&& tag) { DEBUG_MARKER() construct(vbih, bufferCount, attributeCount, attributes); mHandleAllocator.associateTagToHandle(vbih.getId(), std::move(tag)); @@ -671,7 +672,7 @@ void OpenGLDriver::createVertexBufferR( Handle vbh, uint32_t vertexCount, Handle vbih, - CString&& tag) { + ImmutableCString&& tag) { DEBUG_MARKER() construct(vbh, vertexCount, vbih); mHandleAllocator.associateTagToHandle(vbh.getId(), std::move(tag)); @@ -682,7 +683,7 @@ void OpenGLDriver::createIndexBufferR( ElementType const elementType, uint32_t indexCount, BufferUsage const usage, - CString&& tag) { + ImmutableCString&& tag) { DEBUG_MARKER() auto& gl = mContext; @@ -698,7 +699,7 @@ void OpenGLDriver::createIndexBufferR( } void OpenGLDriver::createBufferObjectR(Handle boh, uint32_t byteCount, - BufferObjectBinding bindingType, BufferUsage usage, CString&& tag) { + BufferObjectBinding bindingType, BufferUsage usage, ImmutableCString&& tag) { DEBUG_MARKER() assert_invariant(byteCount > 0); @@ -725,7 +726,7 @@ void OpenGLDriver::createBufferObjectR(Handle boh, uint32_t byte void OpenGLDriver::createRenderPrimitiveR(Handle rph, Handle vbh, Handle ibh, - PrimitiveType const pt, CString&& tag) { + PrimitiveType const pt, ImmutableCString&& tag) { DEBUG_MARKER() auto& gl = mContext; @@ -761,7 +762,7 @@ void OpenGLDriver::createRenderPrimitiveR(Handle rph, mHandleAllocator.associateTagToHandle(rph.getId(), std::move(tag)); } -void OpenGLDriver::createProgramR(Handle ph, Program&& program, CString&& tag) { +void OpenGLDriver::createProgramR(Handle ph, Program&& program, ImmutableCString&& tag) { DEBUG_MARKER() construct(ph, *this, std::move(program)); @@ -871,7 +872,7 @@ void OpenGLDriver::textureStorage(GLTexture* t, void OpenGLDriver::createTextureR(Handle th, SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples, uint32_t width, uint32_t height, uint32_t depth, - TextureUsage usage, CString&& tag) { + TextureUsage usage, ImmutableCString&& tag) { DEBUG_MARKER() GLenum internalFormat = getInternalFormat(format); @@ -964,7 +965,7 @@ void OpenGLDriver::createTextureR(Handle th, SamplerType target, uint } void OpenGLDriver::createTextureViewR(Handle th, - Handle srch, uint8_t const baseLevel, uint8_t const levelCount, CString&& tag) { + Handle srch, uint8_t const baseLevel, uint8_t const levelCount, ImmutableCString&& tag) { DEBUG_MARKER() GLTexture const* const src = handle_cast(srch); @@ -1012,7 +1013,7 @@ void OpenGLDriver::createTextureViewR(Handle th, void OpenGLDriver::createTextureViewSwizzleR(Handle th, Handle srch, TextureSwizzle const r, TextureSwizzle const g, TextureSwizzle const b, TextureSwizzle const a, - CString&& tag) { + ImmutableCString&& tag) { DEBUG_MARKER() GLTexture const* const src = handle_cast(srch); @@ -1078,7 +1079,7 @@ void OpenGLDriver::createTextureViewSwizzleR(Handle th, Handle th, SamplerType target, TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage, - Platform::ExternalImageHandleRef image, CString&& tag) { + Platform::ExternalImageHandleRef image, ImmutableCString&& tag) { DEBUG_MARKER() usage |= TextureUsage::SAMPLEABLE; @@ -1130,7 +1131,7 @@ void OpenGLDriver::createTextureExternalImage2R(Handle th, SamplerTyp void OpenGLDriver::createTextureExternalImageR(Handle th, SamplerType target, TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage, void* image, - CString&& tag) { + ImmutableCString&& tag) { DEBUG_MARKER() usage |= TextureUsage::SAMPLEABLE; @@ -1181,13 +1182,13 @@ void OpenGLDriver::createTextureExternalImageR(Handle th, SamplerType void OpenGLDriver::createTextureExternalImagePlaneR(Handle th, TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage, - void* image, uint32_t plane, CString&&) { + void* image, uint32_t plane, ImmutableCString&&) { // not relevant for the OpenGL backend } void OpenGLDriver::importTextureR(Handle th, intptr_t const id, SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples, - uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage, CString&& tag) { + uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage, ImmutableCString&& tag) { DEBUG_MARKER() auto const& gl = mContext; @@ -1642,7 +1643,7 @@ void OpenGLDriver::renderBufferStorage(GLuint const rbo, GLenum internalformat, } void OpenGLDriver::createDefaultRenderTargetR( - Handle rth, CString&& tag) { + Handle rth, ImmutableCString&& tag) { DEBUG_MARKER() construct(rth, 0, 0); // FIXME: we don't know the width/height @@ -1665,7 +1666,7 @@ void OpenGLDriver::createRenderTargetR(Handle rth, MRT color, TargetBufferInfo depth, TargetBufferInfo stencil, - CString&& tag) { + ImmutableCString&& tag) { DEBUG_MARKER() GLRenderTarget* rt = construct(rth, width, height); @@ -1781,7 +1782,7 @@ void OpenGLDriver::createRenderTargetR(Handle rth, mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag)); } -void OpenGLDriver::createFenceR(Handle fh, CString&& tag) { +void OpenGLDriver::createFenceR(Handle fh, ImmutableCString&& tag) { DEBUG_MARKER() mHandleAllocator.associateTagToHandle(fh.getId(), std::move(tag)); @@ -1815,7 +1816,7 @@ void OpenGLDriver::createFenceR(Handle fh, CString&& tag) { #endif } -void OpenGLDriver::createSyncR(Handle sh, CString&& tag) { +void OpenGLDriver::createSyncR(Handle sh, ImmutableCString&& tag) { DEBUG_MARKER() GLSyncFence* s = handle_cast(sh); @@ -1834,7 +1835,7 @@ void OpenGLDriver::createSyncR(Handle sh, CString&& tag) { } void OpenGLDriver::createSwapChainR(Handle sch, void* nativeWindow, uint64_t const flags, - CString&& tag) { + ImmutableCString&& tag) { DEBUG_MARKER() GLSwapChain* sc = handle_cast(sch); @@ -1856,7 +1857,7 @@ void OpenGLDriver::createSwapChainR(Handle sch, void* nativeWindow, } void OpenGLDriver::createSwapChainHeadlessR(Handle sch, - uint32_t const width, uint32_t const height, uint64_t const flags, CString&& tag) { + uint32_t const width, uint32_t const height, uint64_t const flags, ImmutableCString&& tag) { DEBUG_MARKER() GLSwapChain* sc = handle_cast(sch); @@ -1878,7 +1879,7 @@ void OpenGLDriver::createSwapChainHeadlessR(Handle sch, mHandleAllocator.associateTagToHandle(sch.getId(), std::move(tag)); } -void OpenGLDriver::createTimerQueryR(Handle tqh, CString&& tag) { +void OpenGLDriver::createTimerQueryR(Handle tqh, ImmutableCString&& tag) { DEBUG_MARKER() GLTimerQuery* tq = handle_cast(tqh); mContext.createTimerQuery(tq); @@ -1886,14 +1887,14 @@ void OpenGLDriver::createTimerQueryR(Handle tqh, CString&& tag) { } void OpenGLDriver::createDescriptorSetLayoutR(Handle dslh, - DescriptorSetLayout&& info, CString&& tag) { + DescriptorSetLayout&& info, ImmutableCString&& tag) { DEBUG_MARKER() construct(dslh, std::move(info)); mHandleAllocator.associateTagToHandle(dslh.getId(), std::move(tag)); } void OpenGLDriver::createDescriptorSetR(Handle dsh, - Handle dslh, CString&& tag) { + Handle dslh, ImmutableCString&& tag) { DEBUG_MARKER() GLDescriptorSetLayout const* dsl = handle_cast(dslh); construct(dsh, mContext, dslh, dsl); @@ -1902,7 +1903,7 @@ void OpenGLDriver::createDescriptorSetR(Handle dsh, void OpenGLDriver::mapBufferR(MemoryMappedBufferHandle mmbh, BufferObjectHandle boh, size_t offset, - size_t size, MapBufferAccessFlags access, CString&& tag) { + size_t size, MapBufferAccessFlags access, ImmutableCString&& tag) { DEBUG_MARKER() construct(mmbh, mContext, mHandleAllocator, boh, offset, size, access); mHandleAllocator.associateTagToHandle(mmbh.getId(), std::move(tag)); @@ -2172,14 +2173,14 @@ void OpenGLDriver::unmapBuffer(MemoryMappedBufferHandle mmbh) { // These are called on the application's thread // ------------------------------------------------------------------------------------------------ -Handle OpenGLDriver::createStreamNative(void* nativeStream, CString tag) { +Handle OpenGLDriver::createStreamNative(void* nativeStream, ImmutableCString tag) { Platform::Stream* stream = mPlatform.createStream(nativeStream); auto handle = initHandle(stream); mHandleAllocator.associateTagToHandle(handle.getId(), std::move(tag)); return handle; } -Handle OpenGLDriver::createStreamAcquired(CString tag) { +Handle OpenGLDriver::createStreamAcquired(ImmutableCString tag) { auto handle = initHandle(); mHandleAllocator.associateTagToHandle(handle.getId(), std::move(tag)); return handle; diff --git a/filament/backend/src/opengl/OpenGLDriver.h b/filament/backend/src/opengl/OpenGLDriver.h index f6899dd8e5..f5ddea1d5a 100644 --- a/filament/backend/src/opengl/OpenGLDriver.h +++ b/filament/backend/src/opengl/OpenGLDriver.h @@ -45,6 +45,7 @@ #include #include #include +#include #include #include diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index a516b031d5..a2b50b14ad 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #ifndef NDEBUG @@ -524,7 +525,7 @@ void VulkanDriver::finish(int dummy) { void VulkanDriver::createRenderPrimitiveR(Handle rph, Handle vbh, Handle ibh, - PrimitiveType pt, utils::CString&& tag) { + PrimitiveType pt, utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); auto vb = resource_ptr::cast(&mResourceManager, vbh); auto ib = resource_ptr::cast(&mResourceManager, ibh); @@ -543,7 +544,7 @@ void VulkanDriver::destroyRenderPrimitive(Handle rph) { } void VulkanDriver::createVertexBufferInfoR(Handle vbih, uint8_t bufferCount, - uint8_t attributeCount, AttributeArray attributes, utils::CString&& tag) { + uint8_t attributeCount, AttributeArray attributes, utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); auto vbi = resource_ptr::make(&mResourceManager, vbih, bufferCount, attributeCount, attributes); @@ -561,7 +562,7 @@ void VulkanDriver::destroyVertexBufferInfo(Handle vbih) { } void VulkanDriver::createVertexBufferR(Handle vbh, uint32_t vertexCount, - Handle vbih, utils::CString&& tag) { + Handle vbih, utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); auto vbi = resource_ptr::cast(&mResourceManager, vbih); auto vb = resource_ptr::make(&mResourceManager, vbh, mContext, mStagePool, @@ -580,7 +581,7 @@ void VulkanDriver::destroyVertexBuffer(Handle vbh) { } void VulkanDriver::createIndexBufferR(Handle ibh, ElementType elementType, - uint32_t indexCount, BufferUsage usage, utils::CString&& tag) { + uint32_t indexCount, BufferUsage usage, utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); auto elementSize = (uint8_t) getElementTypeSize(elementType); auto ib = resource_ptr::make(&mResourceManager, ibh, mContext, mAllocator, @@ -599,7 +600,7 @@ void VulkanDriver::destroyIndexBuffer(Handle ibh) { } void VulkanDriver::createBufferObjectR(Handle boh, uint32_t byteCount, - BufferObjectBinding bindingType, BufferUsage usage, utils::CString&& tag) { + BufferObjectBinding bindingType, BufferUsage usage, utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); auto bo = resource_ptr::make(&mResourceManager, boh, mContext, mAllocator, mStagePool, mBufferCache, byteCount, bindingType, usage); @@ -618,7 +619,7 @@ void VulkanDriver::destroyBufferObject(Handle boh) { void VulkanDriver::createTextureR(Handle th, SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth, - TextureUsage usage, utils::CString&& tag) { + TextureUsage usage, utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); auto texture = resource_ptr::make(&mResourceManager, th, mPlatform->getDevice(), mPlatform->getPhysicalDevice(), mContext, mAllocator, &mResourceManager, &mCommands, @@ -635,7 +636,7 @@ void VulkanDriver::createTextureR(Handle th, SamplerType target, uint } void VulkanDriver::createTextureViewR(Handle th, Handle srch, - uint8_t baseLevel, uint8_t levelCount, utils::CString&& tag) { + uint8_t baseLevel, uint8_t levelCount, utils::ImmutableCString&& tag) { auto src = resource_ptr::cast(&mResourceManager, srch); auto texture = resource_ptr::make(&mResourceManager, th, mPlatform->getDevice(), mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, src, baseLevel, @@ -646,7 +647,7 @@ void VulkanDriver::createTextureViewR(Handle th, Handle sr void VulkanDriver::createTextureViewSwizzleR(Handle th, Handle srch, backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b, - backend::TextureSwizzle a, utils::CString&& tag) { + backend::TextureSwizzle a, utils::ImmutableCString&& tag) { TextureSwizzle const swizzleArray[] = { r, g, b, a }; VkComponentMapping const swizzle = fvkutils::getSwizzleMap(swizzleArray); auto src = resource_ptr::cast(&mResourceManager, srch); @@ -658,7 +659,7 @@ void VulkanDriver::createTextureViewSwizzleR(Handle th, Handle th, backend::SamplerType target, backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage, - Platform::ExternalImageHandleRef externalImage, utils::CString&& tag) { + Platform::ExternalImageHandleRef externalImage, utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); auto metadata = mPlatform->extractExternalImageMetadata(externalImage); @@ -709,7 +710,7 @@ void VulkanDriver::createTextureExternalImage2R(Handle th, backend::S void VulkanDriver::createTextureExternalImageR(Handle th, backend::SamplerType target, backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage, - void* externalImage, utils::CString&& tag) { + void* externalImage, utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); assert_invariant(false && "Not supported in Vulkan backend"); // not supported in this backend @@ -717,14 +718,14 @@ void VulkanDriver::createTextureExternalImageR(Handle th, backend::Sa void VulkanDriver::createTextureExternalImagePlaneR(Handle th, backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage, - void* image, uint32_t plane, utils::CString&& tag) { + void* image, uint32_t plane, utils::ImmutableCString&& tag) { assert_invariant(false && "Not supported in Vulkan backend"); } void VulkanDriver::importTextureR(Handle th, intptr_t id, SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth, - TextureUsage usage, utils::CString&& tag) { + TextureUsage usage, utils::ImmutableCString&& tag) { // not supported in this backend assert_invariant(false && "Not supported in Vulkan backend"); mResourceManager.associateHandle(th.getId(), std::move(tag)); @@ -740,7 +741,7 @@ void VulkanDriver::destroyTexture(Handle th) { mExternalImageManager.removeExternallySampledTexture(texture); } -void VulkanDriver::createProgramR(Handle ph, Program&& program, utils::CString&& tag) { +void VulkanDriver::createProgramR(Handle ph, Program&& program, utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); auto vprogram = resource_ptr::make(&mResourceManager, ph, mPlatform->getDevice(), program); @@ -756,7 +757,7 @@ void VulkanDriver::destroyProgram(Handle ph) { vprogram.dec(); } -void VulkanDriver::createDefaultRenderTargetR(Handle rth, utils::CString&& tag) { +void VulkanDriver::createDefaultRenderTargetR(Handle rth, utils::ImmutableCString&& tag) { assert_invariant(mDefaultRenderTarget); // Default render target should already exist. auto renderTarget = resource_ptr::make(&mResourceManager, rth, @@ -769,7 +770,7 @@ void VulkanDriver::createDefaultRenderTargetR(Handle rth, utils: void VulkanDriver::createRenderTargetR(Handle rth, TargetBufferFlags targets, uint32_t width, uint32_t height, uint8_t samples, uint8_t layerCount, MRT color, TargetBufferInfo depth, TargetBufferInfo stencil, - utils::CString&& tag) { + utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); @@ -846,7 +847,7 @@ void VulkanDriver::destroyRenderTarget(Handle rth) { } } -void VulkanDriver::createFenceR(Handle fh, utils::CString&& tag) { +void VulkanDriver::createFenceR(Handle fh, utils::ImmutableCString&& tag) { VulkanCommandBuffer* cmdbuf; if (mCurrentRenderPass.commandBuffer) { cmdbuf = mCurrentRenderPass.commandBuffer; @@ -861,7 +862,7 @@ void VulkanDriver::createFenceR(Handle fh, utils::CString&& tag) { mResourceManager.associateHandle(fh.getId(), std::move(tag)); } -void VulkanDriver::createSyncR(Handle sh, utils::CString&& tag) { +void VulkanDriver::createSyncR(Handle sh, utils::ImmutableCString&& tag) { auto sync = resource_ptr::cast(&mResourceManager, sh); VkFence fence = VK_NULL_HANDLE; std::shared_ptr fenceStatus; @@ -892,7 +893,7 @@ void VulkanDriver::createSyncR(Handle sh, utils::CString&& tag) { } void VulkanDriver::createSwapChainR(Handle sch, void* nativeWindow, uint64_t flags, - utils::CString&& tag) { + utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); // Running gc() to guard against an edge case where the old swapchains need to have been // destroyed before the new swapchain can be created. Otherwise, we would fail @@ -921,7 +922,7 @@ void VulkanDriver::createSwapChainR(Handle sch, void* nativeWindow, } void VulkanDriver::createSwapChainHeadlessR(Handle sch, uint32_t width, - uint32_t height, uint64_t flags, utils::CString&& tag) { + uint32_t height, uint64_t flags, utils::ImmutableCString&& tag) { if ((flags & backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0 && !isSRGBSwapChainSupported()) { FVK_LOGW << "sRGB swapchain requested, but Platform does not support it"; flags = flags | ~(backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE); @@ -934,13 +935,13 @@ void VulkanDriver::createSwapChainHeadlessR(Handle sch, uint32_t wi mResourceManager.associateHandle(sch.getId(), std::move(tag)); } -void VulkanDriver::createTimerQueryR(Handle tqh, utils::CString&& tag) { +void VulkanDriver::createTimerQueryR(Handle tqh, utils::ImmutableCString&& tag) { // nothing to do, timer query was constructed in createTimerQueryS mResourceManager.associateHandle(tqh.getId(), std::move(tag)); } void VulkanDriver::createDescriptorSetLayoutR(Handle dslh, - backend::DescriptorSetLayout&& info, utils::CString&& tag) { + backend::DescriptorSetLayout&& info, utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); auto layout = mDescriptorSetLayoutCache.createLayout(dslh, std::move(info)); layout.inc(); @@ -948,7 +949,7 @@ void VulkanDriver::createDescriptorSetLayoutR(Handle dslh } void VulkanDriver::createDescriptorSetR(Handle dsh, - Handle dslh, utils::CString&& tag) { + Handle dslh, utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); fvkmemory::resource_ptr layout = fvkmemory::resource_ptr::cast(&mResourceManager, dslh); @@ -964,7 +965,7 @@ void VulkanDriver::createDescriptorSetR(Handle dsh, void VulkanDriver::mapBufferR(MemoryMappedBufferHandle mmbh, BufferObjectHandle boh, size_t offset, - size_t size, MapBufferAccessFlags access, utils::CString&& tag) { + size_t size, MapBufferAccessFlags access, utils::ImmutableCString&& tag) { FVK_SYSTRACE_SCOPE(); auto mmb = resource_ptr::make(&mResourceManager, mmbh, boh, offset, size, access); @@ -1131,11 +1132,11 @@ void VulkanDriver::destroyDescriptorSet(Handle dsh) { } } -Handle VulkanDriver::createStreamNative(void* nativeStream, utils::CString tag) { +Handle VulkanDriver::createStreamNative(void* nativeStream, utils::ImmutableCString tag) { return {}; } -Handle VulkanDriver::createStreamAcquired(utils::CString tag) { +Handle VulkanDriver::createStreamAcquired(utils::ImmutableCString tag) { return {}; } diff --git a/filament/backend/src/vulkan/memory/ResourceManager.h b/filament/backend/src/vulkan/memory/ResourceManager.h index 97dfb53358..12a6ade19d 100644 --- a/filament/backend/src/vulkan/memory/ResourceManager.h +++ b/filament/backend/src/vulkan/memory/ResourceManager.h @@ -24,6 +24,7 @@ #include #include +#include namespace filament::backend::fvkmemory { @@ -36,7 +37,7 @@ public: return mHandleAllocatorImpl.allocate(); } - inline void associateHandle(HandleBase::HandleId id, utils::CString&& tag) noexcept { + inline void associateHandle(HandleBase::HandleId id, utils::ImmutableCString&& tag) noexcept { mHandleAllocatorImpl.associateTagToHandle(id, std::move(tag)); } diff --git a/filament/backend/src/webgpu/WebGPUDriver.cpp b/filament/backend/src/webgpu/WebGPUDriver.cpp index 5f1bdab8e9..6efa6ee972 100644 --- a/filament/backend/src/webgpu/WebGPUDriver.cpp +++ b/filament/backend/src/webgpu/WebGPUDriver.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -451,7 +452,7 @@ Handle WebGPUDriver::createTextureExternalImagePlaneS() noexcept { // ------------------------------------------------------------------------------------------------ void WebGPUDriver::createSwapChainR(Handle sch, void* nativeWindow, - const uint64_t flags, utils::CString&& tag) { + const uint64_t flags, utils::ImmutableCString&& tag) { FWGPU_SYSTRACE_SCOPE(); // TODO: support MSAA swapchain @@ -481,7 +482,7 @@ void WebGPUDriver::createSwapChainR(Handle sch, void* nativeWindow, } void WebGPUDriver::createSwapChainHeadlessR(Handle sch, uint32_t width, - uint32_t height, uint64_t flags, utils::CString&& tag) { + uint32_t height, uint64_t flags, utils::ImmutableCString&& tag) { wgpu::Extent2D extent = { .width = width, .height = height }; mSwapChain = constructHandle(sch, extent, mAdapter, mDevice, flags); @@ -494,7 +495,7 @@ void WebGPUDriver::createSwapChainHeadlessR(Handle sch, uint32_t wi void WebGPUDriver::createVertexBufferInfoR(Handle vertexBufferInfoHandle, const uint8_t bufferCount, const uint8_t attributeCount, const AttributeArray attributes, - utils::CString&& tag) { + utils::ImmutableCString&& tag) { FWGPU_SYSTRACE_SCOPE(); constructHandle(vertexBufferInfoHandle, bufferCount, attributeCount, attributes, mDeviceLimits); @@ -503,7 +504,7 @@ void WebGPUDriver::createVertexBufferInfoR(Handle vertexBuff void WebGPUDriver::createVertexBufferR(Handle vertexBufferHandle, const uint32_t vertexCount, Handle vertexBufferInfoHandle, - utils::CString&& tag) { + utils::ImmutableCString&& tag) { FWGPU_SYSTRACE_SCOPE(); const auto vertexBufferInfo = handleCast(vertexBufferInfoHandle); constructHandle(vertexBufferHandle, vertexCount, @@ -513,7 +514,7 @@ void WebGPUDriver::createVertexBufferR(Handle vertexBufferHandle void WebGPUDriver::createIndexBufferR(Handle indexBufferHandle, const ElementType elementType, const uint32_t indexCount, const BufferUsage usage, - utils::CString&& tag) { + utils::ImmutableCString&& tag) { FWGPU_SYSTRACE_SCOPE(); const auto elementSize = static_cast(getElementTypeSize(elementType)); constructHandle(indexBufferHandle, mDevice, elementSize, indexCount); @@ -522,7 +523,7 @@ void WebGPUDriver::createIndexBufferR(Handle indexBufferHandle, void WebGPUDriver::createBufferObjectR(Handle bufferObjectHandle, const uint32_t byteCount, const BufferObjectBinding bindingType, const BufferUsage usage, - utils::CString&& tag) { + utils::ImmutableCString&& tag) { FWGPU_SYSTRACE_SCOPE(); constructHandle(bufferObjectHandle, mDevice, bindingType, byteCount); setDebugTag(bufferObjectHandle.getId(), std::move(tag)); @@ -531,7 +532,7 @@ void WebGPUDriver::createBufferObjectR(Handle bufferObjectHandle void WebGPUDriver::createTextureR(Handle textureHandle, const SamplerType target, const uint8_t levels, const TextureFormat format, const uint8_t samples, const uint32_t width, const uint32_t height, const uint32_t depth, - const TextureUsage usage, utils::CString&& tag) { + const TextureUsage usage, utils::ImmutableCString&& tag) { FWGPU_SYSTRACE_SCOPE(); constructHandle(textureHandle, target, levels, format, samples, width, height, depth, usage, mDevice); @@ -540,7 +541,7 @@ void WebGPUDriver::createTextureR(Handle textureHandle, const Sampler void WebGPUDriver::createTextureViewR(Handle textureHandle, Handle sourceTextureHandle, const uint8_t baseLevel, const uint8_t levelCount, - utils::CString&& tag) { + utils::ImmutableCString&& tag) { auto source = handleCast(sourceTextureHandle); constructHandle(textureHandle, source, baseLevel, levelCount); @@ -551,7 +552,7 @@ void WebGPUDriver::createTextureViewR(Handle textureHandle, void WebGPUDriver::createTextureViewSwizzleR(Handle textureHandle, Handle sourceTextureHandle, const backend::TextureSwizzle r, const backend::TextureSwizzle g, const backend::TextureSwizzle b, - const backend::TextureSwizzle a, utils::CString&& tag) { + const backend::TextureSwizzle a, utils::ImmutableCString&& tag) { if (!isTextureSwizzleSupported()) { FWGPU_LOGW << "WebGPUDriver::createTextureViewSwizzleR called while texture swizzling is " @@ -578,7 +579,7 @@ void WebGPUDriver::createTextureViewSwizzleR(Handle textureHandle, void WebGPUDriver::createTextureExternalImage2R(Handle textureHandle, const backend::SamplerType target, const backend::TextureFormat format, const uint32_t width, const uint32_t height, const backend::TextureUsage usage, - Platform::ExternalImageHandleRef externalImage, utils::CString&& tag) { + Platform::ExternalImageHandleRef externalImage, utils::ImmutableCString&& tag) { FWGPU_SYSTRACE_SCOPE(); PANIC_POSTCONDITION("External WebGPU Texture is not supported"); } @@ -586,27 +587,27 @@ void WebGPUDriver::createTextureExternalImage2R(Handle textureHandle, void WebGPUDriver::createTextureExternalImageR(Handle textureHandle, const backend::SamplerType target, const backend::TextureFormat format, const uint32_t width, const uint32_t height, const backend::TextureUsage usage, - void* externalImage, utils::CString&& tag) { + void* externalImage, utils::ImmutableCString&& tag) { FWGPU_SYSTRACE_SCOPE(); PANIC_POSTCONDITION("External WebGPU Texture is not supported"); } void WebGPUDriver::createTextureExternalImagePlaneR(Handle textureHandle, const backend::TextureFormat format, const uint32_t width, const uint32_t height, - const backend::TextureUsage usage, void* image, const uint32_t plane, utils::CString&& tag) { + const backend::TextureUsage usage, void* image, const uint32_t plane, utils::ImmutableCString&& tag) { PANIC_POSTCONDITION("External WebGPU Texture is not supported"); } void WebGPUDriver::importTextureR(Handle textureHandle, const intptr_t id, const SamplerType target, const uint8_t levels, const TextureFormat format, const uint8_t samples, const uint32_t width, const uint32_t height, const uint32_t depth, - const TextureUsage usage, utils::CString&& tag) { + const TextureUsage usage, utils::ImmutableCString&& tag) { PANIC_POSTCONDITION("Import WebGPU Texture is not supported"); } void WebGPUDriver::createRenderPrimitiveR(Handle renderPrimitiveHandle, Handle vertexBufferHandle, Handle indexBufferHandle, - const PrimitiveType primitiveType, utils::CString&& tag) { + const PrimitiveType primitiveType, utils::ImmutableCString&& tag) { FWGPU_SYSTRACE_SCOPE(); assert_invariant(mDevice); const auto renderPrimitive = constructHandle(renderPrimitiveHandle); @@ -619,14 +620,14 @@ void WebGPUDriver::createRenderPrimitiveR(Handle renderPrimit } void WebGPUDriver::createProgramR(Handle programHandle, Program&& program, - utils::CString&& tag) { + utils::ImmutableCString&& tag) { FWGPU_SYSTRACE_SCOPE(); constructHandle(programHandle, mDevice, program); setDebugTag(programHandle.getId(), std::move(tag)); } void WebGPUDriver::createDefaultRenderTargetR(Handle renderTargetHandle, - utils::CString&& tag) { + utils::ImmutableCString&& tag) { assert_invariant(!mDefaultRenderTarget); mDefaultRenderTarget = constructHandle(renderTargetHandle); assert_invariant(mDefaultRenderTarget); @@ -639,7 +640,7 @@ void WebGPUDriver::createDefaultRenderTargetR(Handle renderTarge void WebGPUDriver::createRenderTargetR(Handle renderTargetHandle, const TargetBufferFlags targetFlags, const uint32_t width, const uint32_t height, const uint8_t samples, const uint8_t layerCount, const MRT color, - const TargetBufferInfo depth, const TargetBufferInfo stencil, utils::CString&& tag) { + const TargetBufferInfo depth, const TargetBufferInfo stencil, utils::ImmutableCString&& tag) { FWGPU_SYSTRACE_SCOPE(); constructHandle( renderTargetHandle, width, height, samples, layerCount, color, depth, stencil, @@ -651,7 +652,7 @@ void WebGPUDriver::createRenderTargetR(Handle renderTargetHandle setDebugTag(renderTargetHandle.getId(), std::move(tag)); } -void WebGPUDriver::createFenceR(Handle fenceHandle, utils::CString&& tag) { +void WebGPUDriver::createFenceR(Handle fenceHandle, utils::ImmutableCString&& tag) { // The handle is constructed synchronously in createFenceS. const auto fence = handleCast(fenceHandle); assert_invariant(mQueue); @@ -659,24 +660,24 @@ void WebGPUDriver::createFenceR(Handle fenceHandle, utils::CString&& ta setDebugTag(fenceHandle.getId(), std::move(tag)); } -void WebGPUDriver::createSyncR(Handle syncHandle, utils::CString&& tag) { +void WebGPUDriver::createSyncR(Handle syncHandle, utils::ImmutableCString&& tag) { // TODO: Ensure sync is active, and then invoke and clear all pending // callbacks. setDebugTag(syncHandle.getId(), std::move(tag)); } -void WebGPUDriver::createTimerQueryR(Handle tqh, utils::CString&& tag) {} +void WebGPUDriver::createTimerQueryR(Handle tqh, utils::ImmutableCString&& tag) {} void WebGPUDriver::createDescriptorSetLayoutR( Handle descriptorSetLayoutHandle, - backend::DescriptorSetLayout&& info, utils::CString&& tag) { + backend::DescriptorSetLayout&& info, utils::ImmutableCString&& tag) { FWGPU_SYSTRACE_SCOPE(); constructHandle(descriptorSetLayoutHandle, std::move(info), mDevice); setDebugTag(descriptorSetLayoutHandle.getId(), std::move(tag)); } void WebGPUDriver::createDescriptorSetR(Handle descriptorSetHandle, - Handle descriptorSetLayoutHandle, utils::CString&& tag) { + Handle descriptorSetLayoutHandle, utils::ImmutableCString&& tag) { FWGPU_SYSTRACE_SCOPE(); auto layout = handleCast(descriptorSetLayoutHandle); constructHandle(descriptorSetHandle, layout->getLayout(), @@ -684,13 +685,13 @@ void WebGPUDriver::createDescriptorSetR(Handle descriptorSetHan setDebugTag(descriptorSetHandle.getId(), std::move(tag)); } -Handle WebGPUDriver::createStreamNative(void* nativeStream, utils::CString tag) { +Handle WebGPUDriver::createStreamNative(void* nativeStream, utils::ImmutableCString tag) { return { //todo }; } -Handle WebGPUDriver::createStreamAcquired(utils::CString tag) { +Handle WebGPUDriver::createStreamAcquired(utils::ImmutableCString tag) { return { //todo }; @@ -2100,7 +2101,7 @@ void WebGPUDriver::bindDescriptorSet(Handle descriptorSetHandle .offsets = std::move(offsets) }; } -void WebGPUDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString&& tag) { +void WebGPUDriver::setDebugTag(HandleBase::HandleId handleId, utils::ImmutableCString&& tag) { //todo } @@ -2223,7 +2224,7 @@ MemoryMappedBufferHandle WebGPUDriver::mapBufferS() noexcept { void WebGPUDriver::mapBufferR(MemoryMappedBufferHandle mmbh, BufferObjectHandle boh, size_t offset, - size_t size, MapBufferAccessFlags access, utils::CString&& tag) { + size_t size, MapBufferAccessFlags access, utils::ImmutableCString&& tag) { // TODO: MetalDriver::mapBufferR } diff --git a/filament/backend/src/webgpu/WebGPUDriver.h b/filament/backend/src/webgpu/WebGPUDriver.h index 69110ea20f..d5ade73fec 100644 --- a/filament/backend/src/webgpu/WebGPUDriver.h +++ b/filament/backend/src/webgpu/WebGPUDriver.h @@ -70,7 +70,7 @@ private: ShaderLanguage preferredLanguage) const noexcept final; [[nodiscard]] wgpu::Sampler makeSampler(SamplerParams const& params); [[nodiscard]] static wgpu::AddressMode fWrapModeToWAddressMode(const filament::backend::SamplerWrapMode& fUsage); - void setDebugTag(HandleBase::HandleId handleId, utils::CString&& tag); + void setDebugTag(HandleBase::HandleId handleId, utils::ImmutableCString&& tag); // The platform (e.g. OS) specific aspects of the WebGPU backend are strictly only // handled in the WebGPUPlatform. diff --git a/filament/backend/test/test_MemoryMappedBuffer.cpp b/filament/backend/test/test_MemoryMappedBuffer.cpp index a5983310d0..5227ea8354 100644 --- a/filament/backend/test/test_MemoryMappedBuffer.cpp +++ b/filament/backend/test/test_MemoryMappedBuffer.cpp @@ -176,7 +176,7 @@ protected: // Map the buffer with a specific offset. MemoryMappedBufferHandle const memoryMappedBuffer = api.mapBuffer(bufferObject, mapOffset, vertexDataSize + copyOffset, - MapBufferAccessFlags::WRITE_BIT, utils::CString{ screenshotName }); + MapBufferAccessFlags::WRITE_BIT, utils::ImmutableCString{ screenshotName }); copyData(vertices.data(), vertexDataSize, copyOffset, memoryMappedBuffer, callbackExecuted); diff --git a/filament/include/filament/FilamentAPI.h b/filament/include/filament/FilamentAPI.h index ddfce15745..d59e051d90 100644 --- a/filament/include/filament/FilamentAPI.h +++ b/filament/include/filament/FilamentAPI.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include @@ -57,7 +57,7 @@ template using BuilderBase = utils::PrivateImplementation; // This needs to be public because it is used in the following template. -UTILS_PUBLIC void builderMakeName(utils::CString& outName, const char* name, size_t len) noexcept; +UTILS_PUBLIC void builderMakeName(utils::ImmutableCString& outName, const char* name, size_t len) noexcept; template class UTILS_PUBLIC BuilderNameMixin { @@ -73,18 +73,18 @@ public: return static_cast(*this); } - utils::CString const& getName() const noexcept { return mName; } + utils::ImmutableCString const& getName() const noexcept { return mName; } - utils::CString const& getNameOrDefault() const noexcept { + utils::ImmutableCString const& getNameOrDefault() const noexcept { if (const auto& name = getName(); !name.empty()) { return name; } - static const utils::CString sDefaultName = "(none)"; + static const utils::ImmutableCString sDefaultName = "(none)"; return sDefaultName; } private: - utils::CString mName; + utils::ImmutableCString mName; }; } // namespace filament diff --git a/filament/src/FilamentBuilder.cpp b/filament/src/FilamentBuilder.cpp index 67631eb4c9..e1c17ce4da 100644 --- a/filament/src/FilamentBuilder.cpp +++ b/filament/src/FilamentBuilder.cpp @@ -16,16 +16,18 @@ #include +#include + #include namespace filament { -void builderMakeName(utils::CString& outName, const char* name, size_t const len) noexcept { +void builderMakeName(utils::ImmutableCString& outName, const char* name, size_t const len) noexcept { if (!name) { return; } size_t const length = std::min(len, size_t { 128u }); - outName = utils::CString(name, length); + outName = utils::ImmutableCString(name, length); } } // namespace filament diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index 1f214d556d..c110c3d692 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -3637,7 +3637,7 @@ FrameGraphId PostProcessManager::blitDepth(FrameGraph& fg, } FrameGraphId PostProcessManager::resolve(FrameGraph& fg, - const char* outputBufferName, FrameGraphId const input, + utils::StaticString outputBufferName, FrameGraphId const input, FrameGraphTexture::Descriptor outDesc) noexcept { // Don't do anything if we're not a MSAA buffer @@ -3691,7 +3691,7 @@ FrameGraphId PostProcessManager::resolve(FrameGraph& fg, } FrameGraphId PostProcessManager::resolveDepth(FrameGraph& fg, - const char* outputBufferName, FrameGraphId const input, + utils::StaticString outputBufferName, FrameGraphId const input, FrameGraphTexture::Descriptor outDesc) noexcept { // Don't do anything if we're not a MSAA buffer @@ -3752,7 +3752,7 @@ FrameGraphId PostProcessManager::vsmMipmapPass(FrameGraph& fg auto const& depthMipmapPass = fg.addPass("VSM Generate Mipmap Pass", [&](FrameGraph::Builder& builder, auto& data) { - const char* name = builder.getName(input); + utils::StaticString name = builder.getName(input); data.in = builder.sample(input); auto out = builder.createSubresource(data.in, "Mip level", { diff --git a/filament/src/PostProcessManager.h b/filament/src/PostProcessManager.h index 50f2b3e7b2..b731ebd6a3 100644 --- a/filament/src/PostProcessManager.h +++ b/filament/src/PostProcessManager.h @@ -286,13 +286,13 @@ public: // Resolves base level of input and outputs a texture from outDesc. // outDesc with, height, format and samples will be overridden. FrameGraphId resolve(FrameGraph& fg, - const char* outputBufferName, FrameGraphId input, + utils::StaticString outputBufferName, FrameGraphId input, FrameGraphTexture::Descriptor outDesc) noexcept; // Resolves base level of input and outputs a texture from outDesc. // outDesc with, height, format and samples will be overridden. FrameGraphId resolveDepth(FrameGraph& fg, - const char* outputBufferName, FrameGraphId input, + utils::StaticString outputBufferName, FrameGraphId input, FrameGraphTexture::Descriptor outDesc) noexcept; // VSM shadow mipmap pass diff --git a/filament/src/RendererUtils.cpp b/filament/src/RendererUtils.cpp index d5249088c3..e9e1e21f49 100644 --- a/filament/src/RendererUtils.cpp +++ b/filament/src/RendererUtils.cpp @@ -119,8 +119,9 @@ RendererUtils::ColorPassOutput RendererUtils::colorPass( clearDepthFlags = TargetBufferFlags::DEPTH; clearStencilFlags = config.enabledStencilBuffer ? TargetBufferFlags::STENCIL : TargetBufferFlags::NONE; - const char* const textureName = config.enabledStencilBuffer ? - "Depth/Stencil Buffer" : "Depth Buffer"; + utils::StaticString const textureName = config.enabledStencilBuffer ? + utils::StaticString{"Depth/Stencil Buffer"} : + utils::StaticString{"Depth Buffer"}; bool const isES2 = engine.getDriverApi().getFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0; diff --git a/filament/src/ResourceAllocator.cpp b/filament/src/ResourceAllocator.cpp index 70e123928b..8b588c9ee2 100644 --- a/filament/src/ResourceAllocator.cpp +++ b/filament/src/ResourceAllocator.cpp @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include @@ -143,12 +145,12 @@ void ResourceAllocator::terminate() noexcept { } } -RenderTargetHandle ResourceAllocator::createRenderTarget(const char* name, +RenderTargetHandle ResourceAllocator::createRenderTarget(StaticString name, TargetBufferFlags const targetBufferFlags, uint32_t const width, uint32_t const height, uint8_t const samples, uint8_t const layerCount, MRT const color, TargetBufferInfo const depth, TargetBufferInfo const stencil) noexcept { auto handle = mBackend.createRenderTarget(targetBufferFlags, - width, height, samples ? samples : 1u, layerCount, color, depth, stencil, CString(name)); + width, height, samples ? samples : 1u, layerCount, color, depth, stencil, name); return handle; } @@ -156,7 +158,7 @@ void ResourceAllocator::destroyRenderTarget(RenderTargetHandle const h) noexcept mBackend.destroyRenderTarget(h); } -TextureHandle ResourceAllocator::createTexture(const char* name, +TextureHandle ResourceAllocator::createTexture(StaticString name, SamplerType const target, uint8_t const levels, TextureFormat const format, uint8_t samples, uint32_t const width, uint32_t const height, uint32_t const depth, std::array const swizzle, @@ -166,7 +168,7 @@ TextureHandle ResourceAllocator::createTexture(const char* name, samples = samples ? samples : uint8_t(1); using TS = TextureSwizzle; - constexpr const auto defaultSwizzle = std::array{ + constexpr const auto defaultSwizzle = std::array{ TS::CHANNEL_0, TS::CHANNEL_1, TS::CHANNEL_2, TS::CHANNEL_3}; // do we have a suitable texture in the cache? @@ -183,20 +185,20 @@ TextureHandle ResourceAllocator::createTexture(const char* name, } else { // we don't, allocate a new texture and populate the in-use list handle = mBackend.createTexture( - target, levels, format, samples, width, height, depth, usage, CString(name)); + target, levels, format, samples, width, height, depth, usage, name); if (swizzle != defaultSwizzle) { TextureHandle swizzledHandle = mBackend.createTextureViewSwizzle( - handle, swizzle[0], swizzle[1], swizzle[2], swizzle[3], CString(name)); + handle, swizzle[0], swizzle[1], swizzle[2], swizzle[3], name); mBackend.destroyTexture(handle); handle = swizzledHandle; } } } else { handle = mBackend.createTexture( - target, levels, format, samples, width, height, depth, usage, CString(name)); + target, levels, format, samples, width, height, depth, usage, name); if (swizzle != defaultSwizzle) { TextureHandle swizzledHandle = mBackend.createTextureViewSwizzle( - handle, swizzle[0], swizzle[1], swizzle[2], swizzle[3], CString(name)); + handle, swizzle[0], swizzle[1], swizzle[2], swizzle[3], name); mBackend.destroyTexture(handle); handle = swizzledHandle; } diff --git a/filament/src/ResourceAllocator.h b/filament/src/ResourceAllocator.h index 69eca3aa71..9aae5d8375 100644 --- a/filament/src/ResourceAllocator.h +++ b/filament/src/ResourceAllocator.h @@ -25,6 +25,7 @@ #include "backend/DriverApiForward.h" +#include #include #include @@ -53,7 +54,7 @@ protected: class ResourceAllocatorInterface { public: - virtual backend::RenderTargetHandle createRenderTarget(const char* name, + virtual backend::RenderTargetHandle createRenderTarget(utils::StaticString name, backend::TargetBufferFlags targetBufferFlags, uint32_t width, uint32_t height, @@ -65,7 +66,7 @@ public: virtual void destroyRenderTarget(backend::RenderTargetHandle h) noexcept = 0; - virtual backend::TextureHandle createTexture(const char* name, backend::SamplerType target, + virtual backend::TextureHandle createTexture(utils::StaticString name, backend::SamplerType target, uint8_t levels,backend::TextureFormat format, uint8_t samples, uint32_t width, uint32_t height, uint32_t depth, std::array swizzle, @@ -91,7 +92,7 @@ public: void terminate() noexcept; - backend::RenderTargetHandle createRenderTarget(const char* name, + backend::RenderTargetHandle createRenderTarget(utils::StaticString name, backend::TargetBufferFlags targetBufferFlags, uint32_t width, uint32_t height, @@ -103,7 +104,7 @@ public: void destroyRenderTarget(backend::RenderTargetHandle h) noexcept override; - backend::TextureHandle createTexture(const char* name, backend::SamplerType target, + backend::TextureHandle createTexture(utils::StaticString name, backend::SamplerType target, uint8_t levels, backend::TextureFormat format, uint8_t samples, uint32_t width, uint32_t height, uint32_t depth, std::array swizzle, @@ -119,7 +120,7 @@ private: size_t const mCacheMaxAge; struct TextureKey { - const char* name; // doesn't participate in the hash + utils::StaticString name; // doesn't participate in the hash backend::SamplerType target; uint8_t levels; backend::TextureFormat format; diff --git a/filament/src/details/BufferObject.cpp b/filament/src/details/BufferObject.cpp index a3c35f1177..7557753df9 100644 --- a/filament/src/details/BufferObject.cpp +++ b/filament/src/details/BufferObject.cpp @@ -76,7 +76,7 @@ FBufferObject::FBufferObject(FEngine& engine, const Builder& builder) : mByteCount(builder->mByteCount), mBindingType(builder->mBindingType) { FEngine::DriverApi& driver = engine.getDriverApi(); mHandle = driver.createBufferObject(builder->mByteCount, builder->mBindingType, - backend::BufferUsage::STATIC, utils::CString{ builder.getName() }); + backend::BufferUsage::STATIC, utils::ImmutableCString{ builder.getName() }); } void FBufferObject::terminate(FEngine& engine) { diff --git a/filament/src/details/InstanceBuffer.h b/filament/src/details/InstanceBuffer.h index e2563b4196..b1a61358da 100644 --- a/filament/src/details/InstanceBuffer.h +++ b/filament/src/details/InstanceBuffer.h @@ -55,7 +55,7 @@ public: PerRenderableData* buffer, uint32_t index, uint32_t count, math::mat4f const& rootTransform, PerRenderableData const& ubo); - utils::CString const& getName() const noexcept { return mName; } + utils::ImmutableCString const& getName() const noexcept { return mName; } uint32_t getIndex() const noexcept { return mIndex; } @@ -63,7 +63,7 @@ private: friend class RenderableManager; utils::FixedCapacityVector mLocalTransforms; - utils::CString mName; + utils::ImmutableCString mName; uint32_t mInstanceCount; uint32_t mIndex = 0; }; diff --git a/filament/src/details/Material.cpp b/filament/src/details/Material.cpp index 94224a520a..0fa29b964d 100644 --- a/filament/src/details/Material.cpp +++ b/filament/src/details/Material.cpp @@ -479,7 +479,8 @@ void FMaterial::createAndCacheProgram(Program&& p, Variant const variant) const } } - auto const program = driverApi.createProgram(std::move(p), CString{ mDefinition.name }); + auto const program = driverApi.createProgram(std::move(p), + ImmutableCString{ mDefinition.name.c_str_safe() }); assert_invariant(program); mCachedPrograms[variant.key] = program; diff --git a/filament/src/details/MaterialInstance.cpp b/filament/src/details/MaterialInstance.cpp index 0265535cab..88428dee08 100644 --- a/filament/src/details/MaterialInstance.cpp +++ b/filament/src/details/MaterialInstance.cpp @@ -81,7 +81,7 @@ FMaterialInstance::FMaterialInstance(FEngine& engine, FMaterial const* material, size_t const uboSize = std::max(size_t(16), material->getUniformInterfaceBlock().getSize()); mUniforms = UniformBuffer(uboSize); mUbHandle = driver.createBufferObject(mUniforms.getSize(), BufferObjectBinding::UNIFORM, - BufferUsage::STATIC, utils::CString{ material->getName() }); + BufferUsage::STATIC, utils::ImmutableCString{ material->getName().c_str_safe() }); // set the UBO, always descriptor 0 mDescriptorSet.setBuffer(material->getDescriptorSetLayout(), @@ -148,7 +148,7 @@ FMaterialInstance::FMaterialInstance(FEngine& engine, mUniforms.setUniforms(other->getUniformBuffer()); mUbHandle = driver.createBufferObject(mUniforms.getSize(), BufferObjectBinding::UNIFORM, - BufferUsage::DYNAMIC, CString{ material->getName() }); + BufferUsage::DYNAMIC, ImmutableCString{ material->getName().c_str_safe() }); // set the UBO, always descriptor 0 mDescriptorSet.setBuffer(mMaterial->getDescriptorSetLayout(), diff --git a/filament/src/details/MorphTargetBuffer.cpp b/filament/src/details/MorphTargetBuffer.cpp index cda888c33f..1ec2b35042 100644 --- a/filament/src/details/MorphTargetBuffer.cpp +++ b/filament/src/details/MorphTargetBuffer.cpp @@ -128,7 +128,7 @@ FMorphTargetBuffer::FMorphTargetBuffer(FEngine& engine, const Builder& builder) getHeight(mVertexCount), mCount, TextureUsage::DEFAULT, - utils::CString{ builder.getName() }); + utils::ImmutableCString{ builder.getName() }); mTbHandle = driver.createTexture(SamplerType::SAMPLER_2D_ARRAY, 1, TextureFormat::RGBA16I, 1, @@ -136,7 +136,7 @@ FMorphTargetBuffer::FMorphTargetBuffer(FEngine& engine, const Builder& builder) getHeight(mVertexCount), mCount, TextureUsage::DEFAULT, - utils::CString{ builder.getName() }); + utils::ImmutableCString{ builder.getName() }); } void FMorphTargetBuffer::terminate(FEngine& engine) { diff --git a/filament/src/details/RenderTarget.cpp b/filament/src/details/RenderTarget.cpp index a424df1dc8..c327da18ca 100644 --- a/filament/src/details/RenderTarget.cpp +++ b/filament/src/details/RenderTarget.cpp @@ -221,7 +221,8 @@ FRenderTarget::FRenderTarget(FEngine& engine, const Builder& builder) FEngine::DriverApi& driver = engine.getDriverApi(); mHandle = driver.createRenderTarget(mAttachmentMask, builder.mImpl->mWidth, builder.mImpl->mHeight, builder.mImpl->mSamples, - builder.mImpl->mLayerCount, mrt, dinfo, {}, utils::CString{ builder.getName() }); + builder.mImpl->mLayerCount, mrt, dinfo, {}, + utils::ImmutableCString{ builder.getName() }); } void FRenderTarget::terminate(FEngine& engine) { diff --git a/filament/src/details/SkinningBuffer.cpp b/filament/src/details/SkinningBuffer.cpp index 746be19b33..1146e3d2ff 100644 --- a/filament/src/details/SkinningBuffer.cpp +++ b/filament/src/details/SkinningBuffer.cpp @@ -91,7 +91,7 @@ FSkinningBuffer::FSkinningBuffer(FEngine& engine, const Builder& builder) getPhysicalBoneCount(mBoneCount) * sizeof(PerRenderableBoneUib::BoneData), BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC, - utils::CString{ builder.getName() }); + utils::ImmutableCString{ builder.getName() }); if (builder->mInitialize) { // initialize the bones to identity (before rounding up) diff --git a/filament/src/details/Texture.cpp b/filament/src/details/Texture.cpp index e23e94076f..12587a51cc 100644 --- a/filament/src/details/Texture.cpp +++ b/filament/src/details/Texture.cpp @@ -313,10 +313,7 @@ FTexture::FTexture(FEngine& engine, const Builder& builder) return; } - CString tag{ builder.getName() }; - if (tag.empty()) { - tag = CString{"FTexture"}; - } + ImmutableCString tag{ !builder.getName().empty() ? builder.getName() : "FTexture" }; if (UTILS_LIKELY(!isImported)) { mHandle = driver.createTexture( diff --git a/filament/src/details/VertexBuffer.cpp b/filament/src/details/VertexBuffer.cpp index dcbcc144ba..3251132c35 100644 --- a/filament/src/details/VertexBuffer.cpp +++ b/filament/src/details/VertexBuffer.cpp @@ -281,7 +281,7 @@ FVertexBuffer::FVertexBuffer(FEngine& engine, const Builder& builder) mBufferCount, mDeclaredAttributes.count(), mAttributes); mHandle = driver.createVertexBuffer(mVertexCount, mVertexBufferInfoHandle, - utils::CString{ builder.getName() }); + utils::ImmutableCString{ builder.getName() }); // calculate buffer sizes size_t bufferSizes[MAX_VERTEX_BUFFER_COUNT] = {}; @@ -309,7 +309,7 @@ FVertexBuffer::FVertexBuffer(FEngine& engine, const Builder& builder) if (!mBufferObjects[i]) { BufferObjectHandle const bo = driver.createBufferObject(bufferSizes[i], BufferObjectBinding::VERTEX, BufferUsage::STATIC, - utils::CString{ builder.getName() }); + utils::ImmutableCString{ builder.getName() }); driver.setVertexBufferObject(mHandle, i, bo); mBufferObjects[i] = bo; } @@ -326,7 +326,7 @@ FVertexBuffer::FVertexBuffer(FEngine& engine, const Builder& builder) if (!mBufferObjects[i]) { BufferObjectHandle const bo = driver.createBufferObject(bufferSizes[i], BufferObjectBinding::VERTEX, BufferUsage::STATIC, - utils::CString{ builder.getName() }); + utils::ImmutableCString{ builder.getName() }); driver.setVertexBufferObject(mHandle, i, bo); mBufferObjects[i] = bo; } diff --git a/filament/src/fg/FrameGraph.cpp b/filament/src/fg/FrameGraph.cpp index 0c9df6e43e..bc9523fd86 100644 --- a/filament/src/fg/FrameGraph.cpp +++ b/filament/src/fg/FrameGraph.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -54,11 +55,11 @@ void FrameGraph::Builder::sideEffect() noexcept { mPassNode->makeTarget(); } -const char* FrameGraph::Builder::getName(FrameGraphHandle const handle) const noexcept { +utils::StaticString FrameGraph::Builder::getName(FrameGraphHandle const handle) const noexcept { return mFrameGraph.getResource(handle)->name; } -uint32_t FrameGraph::Builder::declareRenderPass(const char* name, +uint32_t FrameGraph::Builder::declareRenderPass(utils::StaticString name, FrameGraphRenderPass::Descriptor const& desc) { // it's safe here to cast to RenderPassNode because we can't be here for a PresentPassNode // also only RenderPassNodes have the concept of render targets. @@ -438,7 +439,7 @@ FrameGraphHandle FrameGraph::forwardResourceInternal(FrameGraphHandle const reso return resourceHandle; } -FrameGraphId FrameGraph::import(char const* name, +FrameGraphId FrameGraph::import(utils::StaticString name, FrameGraphRenderPass::ImportDescriptor const& desc, backend::Handle target) { // create a resource that represents the imported render target @@ -590,13 +591,13 @@ fgviewer::FrameGraphInfo FrameGraph::getFrameGraphInfo(const char *viewName) con template void FrameGraph::present(FrameGraphId input); -template FrameGraphId FrameGraph::create(char const* name, +template FrameGraphId FrameGraph::create(utils::StaticString name, FrameGraphTexture::Descriptor const& desc) noexcept; template FrameGraphId FrameGraph::createSubresource(FrameGraphId parent, - char const* name, FrameGraphTexture::SubResourceDescriptor const& desc) noexcept; + utils::StaticString name, FrameGraphTexture::SubResourceDescriptor const& desc) noexcept; -template FrameGraphId FrameGraph::import(char const* name, +template FrameGraphId FrameGraph::import(utils::StaticString name, FrameGraphTexture::Descriptor const& desc, FrameGraphTexture::Usage usage, FrameGraphTexture const& resource) noexcept; template FrameGraphId FrameGraph::read(PassNode* passNode, diff --git a/filament/src/fg/FrameGraph.h b/filament/src/fg/FrameGraph.h index ece245b13e..1c8e9f9829 100644 --- a/filament/src/fg/FrameGraph.h +++ b/filament/src/fg/FrameGraph.h @@ -73,7 +73,7 @@ public: * @param desc Descriptor for the FrameGraphRenderPass. * @return An index to retrieve the concrete FrameGraphRenderPass in the execute phase. */ - uint32_t declareRenderPass(const char* name, + uint32_t declareRenderPass(utils::StaticString name, FrameGraphRenderPass::Descriptor const& desc); /** @@ -104,7 +104,7 @@ public: * @return A typed resource handle */ template - FrameGraphId create(const char* name, + FrameGraphId create(utils::StaticString name, typename RESOURCE::Descriptor const& desc = {}) noexcept { return mFrameGraph.create(name, desc); } @@ -122,7 +122,7 @@ public: */ template inline FrameGraphId createSubresource(FrameGraphId parent, - const char* name, + utils::StaticString name, typename RESOURCE::SubResourceDescriptor const& desc = {}) noexcept { return mFrameGraph.createSubresource(parent, name, desc); } @@ -191,7 +191,7 @@ public: * @param handle Handle to a virtual resource * @return C string to the name of the resource */ - const char* getName(FrameGraphHandle handle) const noexcept; + utils::StaticString getName(FrameGraphHandle handle) const noexcept; /** @@ -201,7 +201,7 @@ public: * @param desc Descriptor for this resources * @return A typed resource handle */ - FrameGraphId createTexture(const char* name, + FrameGraphId createTexture(utils::StaticString name, FrameGraphTexture::Descriptor const& desc = {}) noexcept { return create(name, desc); } @@ -375,7 +375,7 @@ public: * @return A handle that can be used normally in the frame graph */ template - FrameGraphId import(const char* name, + FrameGraphId import(utils::StaticString name, typename RESOURCE::Descriptor const& desc, typename RESOURCE::Usage usage, const RESOURCE& resource) noexcept; @@ -391,7 +391,7 @@ public: * @param target handle to the concrete FrameGraphRenderPass to import * @return A handle to a FrameGraphTexture */ - FrameGraphId import(const char* name, + FrameGraphId import(utils::StaticString name, FrameGraphRenderPass::ImportDescriptor const& desc, backend::Handle target); @@ -483,12 +483,12 @@ private: void assertValid(FrameGraphHandle handle) const; template - FrameGraphId create(char const* name, + FrameGraphId create(utils::StaticString name, typename RESOURCE::Descriptor const& desc) noexcept; template FrameGraphId createSubresource(FrameGraphId parent, - char const* name, typename RESOURCE::SubResourceDescriptor const& desc) noexcept; + utils::StaticString name, typename RESOURCE::SubResourceDescriptor const& desc) noexcept; template FrameGraphId read(PassNode* passNode, @@ -587,7 +587,7 @@ void FrameGraph::present(FrameGraphId input) { } template -FrameGraphId FrameGraph::create(char const* name, +FrameGraphId FrameGraph::create(utils::StaticString name, typename RESOURCE::Descriptor const& desc) noexcept { VirtualResource* vresource(mArena.make>(name, desc)); return FrameGraphId(addResourceInternal(vresource)); @@ -595,14 +595,14 @@ FrameGraphId FrameGraph::create(char const* name, template FrameGraphId FrameGraph::createSubresource(FrameGraphId parent, - char const* name, typename RESOURCE::SubResourceDescriptor const& desc) noexcept { + utils::StaticString name, typename RESOURCE::SubResourceDescriptor const& desc) noexcept { auto* parentResource = static_cast*>(getResource(parent)); VirtualResource* vresource(mArena.make>(parentResource, name, desc)); return FrameGraphId(addSubResourceInternal(parent, vresource)); } template -FrameGraphId FrameGraph::import(char const* name, +FrameGraphId FrameGraph::import(utils::StaticString name, typename RESOURCE::Descriptor const& desc, typename RESOURCE::Usage usage, RESOURCE const& resource) noexcept { @@ -665,13 +665,13 @@ FrameGraphId FrameGraph::forwardResource(char const* name, extern template void FrameGraph::present(FrameGraphId input); -extern template FrameGraphId FrameGraph::create(char const* name, +extern template FrameGraphId FrameGraph::create(utils::StaticString name, FrameGraphTexture::Descriptor const& desc) noexcept; extern template FrameGraphId FrameGraph::createSubresource(FrameGraphId parent, - char const* name, FrameGraphTexture::SubResourceDescriptor const& desc) noexcept; + utils::StaticString name, FrameGraphTexture::SubResourceDescriptor const& desc) noexcept; -extern template FrameGraphId FrameGraph::import(char const* name, +extern template FrameGraphId FrameGraph::import(utils::StaticString name, FrameGraphTexture::Descriptor const& desc, FrameGraphTexture::Usage usage, FrameGraphTexture const& resource) noexcept; extern template FrameGraphId FrameGraph::read(PassNode* passNode, diff --git a/filament/src/fg/FrameGraphResources.cpp b/filament/src/fg/FrameGraphResources.cpp index 23444393f0..b60aa81299 100644 --- a/filament/src/fg/FrameGraphResources.cpp +++ b/filament/src/fg/FrameGraphResources.cpp @@ -43,7 +43,7 @@ VirtualResource& FrameGraphResources::getResource(FrameGraphHandle const handle) FILAMENT_CHECK_PRECONDITION(hasReadOrWrite) << "Pass \"" << mPassNode.getName() << "\" didn't declare any access to resource \"" - << resource->name << "\""; + << resource->name.c_str() << "\""; assert_invariant(resource->refcount); diff --git a/filament/src/fg/FrameGraphTexture.cpp b/filament/src/fg/FrameGraphTexture.cpp index 03f29ad1f2..d913543d16 100644 --- a/filament/src/fg/FrameGraphTexture.cpp +++ b/filament/src/fg/FrameGraphTexture.cpp @@ -18,11 +18,14 @@ #include "ResourceAllocator.h" +#include + #include namespace filament { -void FrameGraphTexture::create(ResourceAllocatorInterface& resourceAllocator, const char* name, +void FrameGraphTexture::create(ResourceAllocatorInterface& resourceAllocator, + utils::StaticString const name, Descriptor const& descriptor, Usage usage, bool const useProtectedMemory) noexcept { if (useProtectedMemory) { diff --git a/filament/src/fg/FrameGraphTexture.h b/filament/src/fg/FrameGraphTexture.h index cb785bb7b6..29d10b9150 100644 --- a/filament/src/fg/FrameGraphTexture.h +++ b/filament/src/fg/FrameGraphTexture.h @@ -19,6 +19,8 @@ #include "fg/FrameGraphId.h" +#include + #include #include @@ -78,7 +80,7 @@ struct FrameGraphTexture { * @param resourceAllocator resource allocator for textures and such * @param descriptor Descriptor to the resource */ - void create(ResourceAllocatorInterface& resourceAllocator, const char* name, + void create(ResourceAllocatorInterface& resourceAllocator, utils::StaticString name, Descriptor const& descriptor, Usage usage, bool useProtectedMemory) noexcept; /** diff --git a/filament/src/fg/PassNode.cpp b/filament/src/fg/PassNode.cpp index 4efa7cd61d..a25ff290a0 100644 --- a/filament/src/fg/PassNode.cpp +++ b/filament/src/fg/PassNode.cpp @@ -81,7 +81,7 @@ void RenderPassNode::execute(FrameGraphResources const& resources, DriverApi& dr } uint32_t RenderPassNode::declareRenderTarget(FrameGraph& fg, FrameGraph::Builder&, - const char* name, FrameGraphRenderPass::Descriptor const& descriptor) { + utils::StaticString name, FrameGraphRenderPass::Descriptor const& descriptor) { RenderPassData data; data.name = name; diff --git a/filament/src/fg/Resource.cpp b/filament/src/fg/Resource.cpp index be974a0def..6439b95349 100644 --- a/filament/src/fg/Resource.cpp +++ b/filament/src/fg/Resource.cpp @@ -85,7 +85,7 @@ void VirtualResource::neededByPass(PassNode* pNode) noexcept { ImportedRenderTarget::~ImportedRenderTarget() noexcept = default; -ImportedRenderTarget::ImportedRenderTarget(char const* resourceName, +ImportedRenderTarget::ImportedRenderTarget(utils::StaticString resourceName, FrameGraphTexture::Descriptor const& mainAttachmentDesc, FrameGraphRenderPass::ImportDescriptor const& importedDesc, Handle target) @@ -101,7 +101,7 @@ void ImportedRenderTarget::assertConnect(FrameGraphTexture::Usage const u) { FrameGraphTexture::Usage::STENCIL_ATTACHMENT; FILAMENT_CHECK_PRECONDITION(none(u & ~ANY_ATTACHMENT)) - << "Imported render target resource \"" << name + << "Imported render target resource \"" << name.c_str() << "\" can only be used as an attachment (usage=" << utils::to_string(u).c_str() << ')'; } diff --git a/filament/src/fg/ResourceNode.cpp b/filament/src/fg/ResourceNode.cpp index ca75e33d57..1c8da3384e 100644 --- a/filament/src/fg/ResourceNode.cpp +++ b/filament/src/fg/ResourceNode.cpp @@ -65,7 +65,7 @@ ResourceNode* ResourceNode::getAncestorNode(ResourceNode* node) noexcept { } char const* ResourceNode::getName() const noexcept { - return mFrameGraph.getResource(resourceHandle)->name; + return mFrameGraph.getResource(resourceHandle)->name.c_str(); } void ResourceNode::addOutgoingEdge(ResourceEdgeBase* edge) noexcept { diff --git a/filament/src/fg/details/PassNode.h b/filament/src/fg/details/PassNode.h index 9f483e7a6c..66e7c7c9dc 100644 --- a/filament/src/fg/details/PassNode.h +++ b/filament/src/fg/details/PassNode.h @@ -67,7 +67,7 @@ public: class RenderPassData { public: static constexpr size_t ATTACHMENT_COUNT = backend::MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT + 2; - const char* name = {}; + utils::StaticString name{}; FrameGraphRenderPass::Descriptor descriptor; bool imported = false; backend::TargetBufferFlags targetBufferFlags = {}; @@ -88,7 +88,7 @@ public: ~RenderPassNode() noexcept override; uint32_t declareRenderTarget(FrameGraph& fg, FrameGraph::Builder& builder, - const char* name, FrameGraphRenderPass::Descriptor const& descriptor); + utils::StaticString name, FrameGraphRenderPass::Descriptor const& descriptor); RenderPassData const* getRenderPassData(uint32_t id) const noexcept; diff --git a/filament/src/fg/details/Resource.h b/filament/src/fg/details/Resource.h index 7acd0e1595..98c55d9863 100644 --- a/filament/src/fg/details/Resource.h +++ b/filament/src/fg/details/Resource.h @@ -23,6 +23,7 @@ #include "fg/details/DependencyGraph.h" #include +#include namespace filament { class ResourceAllocatorInterface; @@ -49,15 +50,19 @@ class VirtualResource { public: // constants VirtualResource* parent; - const char* const name; + utils::StaticString name; // computed during compile() uint32_t refcount = 0; PassNode* first = nullptr; // pass that needs to instantiate the resource PassNode* last = nullptr; // pass that can destroy the resource - explicit VirtualResource(const char* name) noexcept : parent(this), name(name) { } - VirtualResource(VirtualResource* parent, const char* name) noexcept : parent(parent), name(name) { } + explicit VirtualResource(utils::StaticString const name) noexcept : parent(this), name(name) { + } + + VirtualResource(VirtualResource* parent, + utils::StaticString const name) noexcept : parent(parent), name(name) { + } VirtualResource(VirtualResource const& rhs) noexcept = delete; VirtualResource& operator=(VirtualResource const&) = delete; virtual ~VirtualResource() noexcept; @@ -147,12 +152,12 @@ public: }; UTILS_NOINLINE - Resource(const char* name, Descriptor const& desc) noexcept + Resource(utils::StaticString name, Descriptor const& desc) noexcept : VirtualResource(name), descriptor(desc) { } UTILS_NOINLINE - Resource(Resource* parent, const char* name, SubResourceDescriptor const& desc) noexcept + Resource(Resource* parent, utils::StaticString name, SubResourceDescriptor const& desc) noexcept : VirtualResource(parent, name), descriptor(RESOURCE::generateSubResourceDescriptor(parent->descriptor, desc)), subResourceDescriptor(desc) { @@ -263,7 +268,7 @@ public: using Usage = typename RESOURCE::Usage; UTILS_NOINLINE - ImportedResource(const char* name, Descriptor const& desc, Usage usage, RESOURCE const& rsrc) noexcept + ImportedResource(utils::StaticString name, Descriptor const& desc, Usage usage, RESOURCE const& rsrc) noexcept : Resource(name, desc) { this->resource = rsrc; this->usage = usage; @@ -298,7 +303,7 @@ private: void assertConnect(FrameGraphTexture::Usage u) { FILAMENT_CHECK_PRECONDITION((u & this->usage) == u) << "Requested usage " << utils::to_string(u).c_str() - << " not available on imported resource \"" << this->name << "\" with usage " + << " not available on imported resource \"" << this->name.c_str() << "\" with usage " << utils::to_string(this->usage).c_str(); } }; @@ -310,7 +315,7 @@ public: FrameGraphRenderPass::ImportDescriptor importedDesc; UTILS_NOINLINE - ImportedRenderTarget(const char* name, + ImportedRenderTarget(utils::StaticString name, FrameGraphTexture::Descriptor const& mainAttachmentDesc, FrameGraphRenderPass::ImportDescriptor const& importedDesc, backend::Handle target); diff --git a/filament/test/filament_framegraph_test.cpp b/filament/test/filament_framegraph_test.cpp index 5734c23079..0ae4a42966 100644 --- a/filament/test/filament_framegraph_test.cpp +++ b/filament/test/filament_framegraph_test.cpp @@ -41,7 +41,7 @@ class MockResourceAllocator : public ResourceAllocatorInterface { } disposer; public: - backend::RenderTargetHandle createRenderTarget(const char* name, + backend::RenderTargetHandle createRenderTarget(utils::StaticString name, backend::TargetBufferFlags targetBufferFlags, uint32_t width, uint32_t height, @@ -56,7 +56,7 @@ public: void destroyRenderTarget(backend::RenderTargetHandle h) noexcept override { } - backend::TextureHandle createTexture(const char* name, backend::SamplerType target, + backend::TextureHandle createTexture(utils::StaticString name, backend::SamplerType target, uint8_t levels, backend::TextureFormat format, uint8_t samples, uint32_t width, uint32_t height, uint32_t depth, std::array, diff --git a/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt index 9b013e2015..13f5f76954 100644 --- a/libs/utils/CMakeLists.txt +++ b/libs/utils/CMakeLists.txt @@ -21,6 +21,7 @@ set(DIST_HDRS ${PUBLIC_HDR_DIR}/${TARGET}/compiler.h ${PUBLIC_HDR_DIR}/${TARGET}/compressed_pair.h ${PUBLIC_HDR_DIR}/${TARGET}/CString.h + ${PUBLIC_HDR_DIR}/${TARGET}/ImmutableCString.h ${PUBLIC_HDR_DIR}/${TARGET}/Entity.h ${PUBLIC_HDR_DIR}/${TARGET}/EntityInstance.h ${PUBLIC_HDR_DIR}/${TARGET}/EntityManager.h @@ -72,6 +73,7 @@ set(SRCS src/EntityManager.cpp src/EntityManagerImpl.h src/FixedCapacityVectorBase.cpp + src/ImmutableCString.cpp src/Invocable.cpp src/JobSystem.cpp src/Log.cpp @@ -169,6 +171,7 @@ set(TEST_SRCS test/test_bitset.cpp test/test_CountDownLatch.cpp test/test_CString.cpp + test/test_ImmutableCString.cpp test/test_CyclicBarrier.cpp test/test_Entity.cpp test/test_FixedCapacityVector.cpp diff --git a/libs/utils/include/utils/CString.h b/libs/utils/include/utils/CString.h index f3eabbb265..f591384c75 100644 --- a/libs/utils/include/utils/CString.h +++ b/libs/utils/include/utils/CString.h @@ -53,14 +53,15 @@ struct hashCStrings { template using StringLiteral = const char[N]; -namespace details { - template - constexpr bool is_char_pointer_v = std::is_pointer_v && std::is_same_v>>; -} // namespace details - // ------------------------------------------------------------------------------------------------ class UTILS_PUBLIC CString { + static constexpr bool TRACK_AND_LOG_ALLOCATIONS = false; + + template + static constexpr bool is_char_pointer_v = + std::is_pointer_v && std::is_same_v>>; + public: using value_type = char; using size_type = uint32_t; @@ -72,7 +73,9 @@ public: using iterator = value_type*; using const_iterator = const value_type*; - CString() noexcept {} // NOLINT(modernize-use-equals-default), Ubuntu compiler bug + CString() noexcept { + track(true); + } // Allocates memory and appends a null. This constructor can be used to hold arbitrary data // inside the string (i.e. it can contain nulls or non-ASCII encodings). @@ -86,25 +89,37 @@ public: // Allocates memory and copies traditional C string content. Unlike the above constructor, this // does not allow embedded nulls. This is explicit because this operation is costly. // This is a template to ensure it's not preferred over the string literal constructor below. - template>> + template>> explicit CString(T cstr) : CString(cstr, cstr ? strlen(cstr) : 0) { + track(true); } + // The string can't have NULs in it. template CString(StringLiteral const& other) noexcept // NOLINT(google-explicit-constructor) : CString(other, N - 1) { + track(true); } - CString(StaticString const& other) noexcept - : CString(other.c_str(), other.length()) {} + // This constructor can be used if the string has NULs in it. + template + CString(StringLiteral const& other, size_t const length) noexcept + : CString(other, length) { + track(true); + } + + CString(StaticString const& other) noexcept // NOLINT(*-explicit-constructor) + : CString(other.c_str(), other.length()) { + track(true); + } CString(const CString& rhs); CString(CString&& rhs) noexcept { + track(true); this->swap(rhs); } - CString& operator=(const CString& rhs); CString& operator=(CString&& rhs) noexcept { @@ -147,7 +162,7 @@ public: return replace(pos, len, str.c_str_safe(), str.size()); } - template >> + template >> CString& replace(size_type pos, size_type len, T str) & noexcept { if (str) { return replace(pos, len, str, strlen(str)); @@ -166,7 +181,7 @@ public: return std::move(*this); } - template >> + template >> CString&& replace(size_type pos, size_type len, T str) && noexcept { this->replace(pos, len, str); return std::move(*this); @@ -188,7 +203,7 @@ public: return replace(pos, 0, str.c_str_safe(), str.size()); } - template >> + template >> CString& insert(size_type pos, T str) & noexcept { if (str) { return replace(pos, 0, str, strlen(str)); @@ -212,7 +227,7 @@ public: return std::move(*this); } - template >> + template >> CString&& insert(size_type pos, T str) && noexcept { this->insert(pos, str); return std::move(*this); @@ -233,7 +248,7 @@ public: return insert(length(), str); } - template>> + template>> CString& append(T str) & noexcept { return insert(length(), str); } @@ -254,7 +269,7 @@ public: return std::move(*this); } - template>> + template>> CString&& append(T str) && noexcept { this->append(str); return std::move(*this); @@ -272,7 +287,7 @@ public: CString& operator+=(const StringLiteral& str) & noexcept { return append(str); } - template >> + template >> CString& operator+=(T str) & noexcept { return append(str); } @@ -332,6 +347,13 @@ public: }; private: + static void do_tracking(bool ctor); + static void track(bool ctor) { + if constexpr (TRACK_AND_LOG_ALLOCATIONS) { + do_tracking(ctor); + } + } + CString& replace(size_type pos, size_type len, char const* str, size_t l) & noexcept; #if !defined(NDEBUG) diff --git a/libs/utils/include/utils/ImmutableCString.h b/libs/utils/include/utils/ImmutableCString.h new file mode 100644 index 0000000000..48fbf43071 --- /dev/null +++ b/libs/utils/include/utils/ImmutableCString.h @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TNT_UTILS_IMMUTABLECSTRING_H +#define TNT_UTILS_IMMUTABLECSTRING_H + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace utils { + + +class UTILS_PUBLIC ImmutableCString { + static constexpr bool TRACK_AND_LOG_ALLOCATIONS = false; + + template + static constexpr bool is_char_pointer_v = + std::is_pointer_v && std::is_same_v>>; + +public: + using value_type = char; + using size_type = uint32_t; + using difference_type = int32_t; + using const_reference = const value_type&; + using const_pointer = const value_type*; + using const_iterator = const value_type*; + + ImmutableCString() noexcept { + track(true, mIsStatic); + } + + // The string can't have NULs in it. + template + ImmutableCString(const char (&str)[N]) noexcept : mData(str), mSize(N - 1) { // NOLINT(*-explicit-constructor) + track(true, mIsStatic); + } + + // This constructor can be used if the string has NULs in it. + template + ImmutableCString(const char (&str)[N], size_t const length) noexcept + : mData(str), mSize(length) { + track(true, mIsStatic); + } + + template>> + explicit ImmutableCString(T cstr) { + if (cstr) { + initializeFrom(cstr, strlen(cstr)); + } + track(true, mIsStatic); + } + + ImmutableCString(const char* cstr, size_t const length) { + initializeFrom(cstr, length); + track(true, mIsStatic); + } + + ImmutableCString(StaticString const& str) // NOLINT(*-explicit-constructor) + : mData(str.data()), mSize(str.size()) { + track(true, mIsStatic); + } + + ImmutableCString(const ImmutableCString& other) { + if (other.mIsStatic) { + mIsStatic = other.mIsStatic; + mSize = other.mSize; + mData = other.mData; + } else { + initializeFrom(other.mData, other.mSize); + } + track(true, mIsStatic); + } + + ImmutableCString(ImmutableCString&& other) noexcept { + track(true, mIsStatic); + this->swap(other); + } + + ImmutableCString& operator=(const ImmutableCString& other); + + ImmutableCString& operator=(ImmutableCString&& other) noexcept; + + ~ImmutableCString() { + track(false, mIsStatic); + if (!mIsStatic) { + free(const_cast(mData)); + } + } + + bool isStatic() const noexcept { return mIsStatic; } + bool isDynamic() const noexcept { return !mIsStatic; } + + const_pointer c_str_safe() const noexcept { return mData; } + const_pointer c_str() const noexcept { return mData; } + const_pointer data() const noexcept { return mData; } + size_type size() const noexcept { return mSize; } + size_type length() const noexcept { return mSize; } + bool empty() const noexcept { return mSize == 0; } + + const_iterator begin() const noexcept { return mData; } + const_iterator end() const noexcept { return mData + mSize; } + const_iterator cbegin() const noexcept { return begin(); } + const_iterator cend() const noexcept { return end(); } + + const_reference operator[](size_type const pos) const noexcept { + assert(pos < mSize); + return mData[pos]; + } + + const_reference at(size_type const pos) const noexcept { + assert(pos < mSize); + return mData[pos]; + } + + const_reference front() const noexcept { + assert(mSize > 0); + return mData[0]; + } + + const_reference back() const noexcept { + assert(mSize > 0); + return mData[mSize - 1]; + } + + void swap(ImmutableCString& other) noexcept { + std::swap(mData, other.mData); + std::swap(mSize, other.mSize); + std::swap(mIsStatic, other.mIsStatic); + } + +private: + static void do_tracking(bool ctor, bool is_static); + static void track(bool ctor, bool is_static) { + if constexpr (TRACK_AND_LOG_ALLOCATIONS) { + do_tracking(ctor, is_static); + } + } + +#if !defined(NDEBUG) + friend io::ostream& operator<<(io::ostream& out, const ImmutableCString& rhs); +#endif + + void initializeFrom(const char* cstr, size_t length); + + int compare(const ImmutableCString& rhs) const noexcept { + return std::string_view{ mData, mSize }.compare({ rhs.mData, rhs.mSize }); + } + + char const* mData = ""; + uint32_t mSize = 0; + bool mIsStatic = true; + + friend bool operator==(const ImmutableCString& lhs, const ImmutableCString& rhs) noexcept { + return lhs.compare(rhs) == 0; + } + friend bool operator!=(const ImmutableCString& lhs, const ImmutableCString& rhs) noexcept { + return lhs.compare(rhs) != 0; + } + friend bool operator<(const ImmutableCString& lhs, const ImmutableCString& rhs) noexcept { + return lhs.compare(rhs) < 0; + } + friend bool operator>(const ImmutableCString& lhs, const ImmutableCString& rhs) noexcept { + return lhs.compare(rhs) > 0; + } + friend bool operator<=(const ImmutableCString& lhs, const ImmutableCString& rhs) noexcept { + return lhs.compare(rhs) <= 0; + } + friend bool operator>=(const ImmutableCString& lhs, const ImmutableCString& rhs) noexcept { + return lhs.compare(rhs) >= 0; + } +}; + +static_assert(sizeof(ImmutableCString) <= 16, "ImmutableCString should be 16 bytes or less"); + +} // namespace utils + +#endif //TNT_UTILS_IMMUTABLECSTRING_H diff --git a/libs/utils/include/utils/Logger.h b/libs/utils/include/utils/Logger.h index e08decd1a9..b385c85bfa 100644 --- a/libs/utils/include/utils/Logger.h +++ b/libs/utils/include/utils/Logger.h @@ -46,6 +46,7 @@ using absl::LogSeverity; #else #include +#include namespace utils { @@ -67,7 +68,7 @@ public: LogLine& operator=(const LogLine&) = delete; LogLine& operator=(LogLine&&) = delete; - ~LogLine() noexcept { mStream << utils::io::endl; } + ~LogLine() noexcept { mStream << io::endl; } template LogLine& operator<<(T&& value) { diff --git a/libs/utils/include/utils/StaticString.h b/libs/utils/include/utils/StaticString.h index 2cb56723bf..ae2008cbc7 100644 --- a/libs/utils/include/utils/StaticString.h +++ b/libs/utils/include/utils/StaticString.h @@ -19,10 +19,14 @@ #include +#include + #include namespace utils { +class ImmutableCString; + /** * @brief A lightweight string class that stores a pointer to a string literal and its size, without dynamic allocation. * @@ -41,7 +45,7 @@ public: template constexpr StaticString(const char (&str)[M]) noexcept : mString(str, M - 1) {} // NOLINT(*-explicit-constructor) - constexpr StaticString() noexcept = default; + constexpr StaticString() noexcept : mString("", 0) {} constexpr const_pointer c_str() const noexcept { return mString.data(); } constexpr const_pointer data() const noexcept { return mString.data(); } @@ -75,6 +79,10 @@ public: } private: +#if !defined(NDEBUG) + friend io::ostream& operator<<(io::ostream& out, const ImmutableCString& rhs); +#endif + std::string_view mString; friend constexpr bool operator==(const StaticString& lhs, const StaticString& rhs) noexcept { diff --git a/libs/utils/src/CString.cpp b/libs/utils/src/CString.cpp index 34a998cb23..c6bf648e26 100644 --- a/libs/utils/src/CString.cpp +++ b/libs/utils/src/CString.cpp @@ -17,23 +17,49 @@ #include #include +#include #include #include +#include #include #include -#include -#include -#include +#include #include namespace utils { +namespace { +struct CStringStats { + std::atomic_int32_t alive = { 0 }; + std::atomic_int32_t ctor = { 0 }; +}; + +CStringStats gCStringStats{}; +constexpr size_t CSTRING_LOG_INTERVAL = 10000; +} + +void CString::do_tracking(bool ctor) { + if (ctor) { + gCStringStats.ctor.fetch_add(1, std::memory_order_relaxed); + gCStringStats.alive.fetch_add(1, std::memory_order_relaxed); + } else { + gCStringStats.alive.fetch_sub(1, std::memory_order_relaxed); + } + static std::atomic_int32_t sCtorSinceLastLog = { 0 }; + if (UTILS_UNLIKELY(sCtorSinceLastLog.fetch_add(1, std::memory_order_relaxed) == CSTRING_LOG_INTERVAL)) { + LOG(INFO) << "CString stats: " + << gCStringStats.alive.load(std::memory_order_relaxed) << " alive, " + << gCStringStats.ctor.load(std::memory_order_relaxed) << " ctor"; + sCtorSinceLastLog.store(0, std::memory_order_relaxed); + } +} + UTILS_NOINLINE CString::CString(const char* cstr, size_t const length) { + track(true); if (length && cstr) { - Data* const p = static_cast(std::malloc(sizeof(Data) + length + 1)); p->length = size_type(length); mCStr = reinterpret_cast(p + 1); @@ -44,6 +70,7 @@ CString::CString(const char* cstr, size_t const length) { } CString::CString(size_t const length) { + track(true); if (length) { Data* const p = static_cast(std::malloc(sizeof(Data) + length + 1)); p->length = size_type(length); @@ -59,14 +86,13 @@ CString::CString(const CString& rhs) CString& CString::operator=(const CString& rhs) { if (this != &rhs) { - auto *const p = mData ? mData - 1 : nullptr; - new(this) CString(rhs); - std::free(p); + CString(rhs).swap(*this); } return *this; } CString::~CString() noexcept { + track(false); if (mData) { std::free(mData - 1); } @@ -75,6 +101,10 @@ CString::~CString() noexcept { CString& CString::replace(size_type const pos, size_type len, char const* str, size_t const l) & noexcept { assert(pos <= size()); + if (UTILS_UNLIKELY(!l && !len)) { // nothing to do + return *this; + } + len = std::min(len, size() - pos); const size_type newSize = size() - len + l; diff --git a/libs/utils/src/ImmutableCString.cpp b/libs/utils/src/ImmutableCString.cpp new file mode 100644 index 0000000000..2fdc67af99 --- /dev/null +++ b/libs/utils/src/ImmutableCString.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace utils { + +namespace { +struct ImmutableCStringStats { + std::atomic_int32_t alive = { 0 }; + std::atomic_int32_t ctor = { 0 }; + std::atomic_int32_t staticStrings = { 0 }; + std::atomic_int32_t heapStrings = { 0 }; +}; + +ImmutableCStringStats gImmutableCStringStats{}; +constexpr size_t IMMUTABLECSTRING_LOG_INTERVAL = 10000; +} + +void ImmutableCString::do_tracking(bool ctor, bool is_static) { + if (ctor) { + gImmutableCStringStats.ctor.fetch_add(1, std::memory_order_relaxed); + gImmutableCStringStats.alive.fetch_add(1, std::memory_order_relaxed); + if (is_static) { + gImmutableCStringStats.staticStrings.fetch_add(1, std::memory_order_relaxed); + } else { + gImmutableCStringStats.heapStrings.fetch_add(1, std::memory_order_relaxed); + } + } else { + gImmutableCStringStats.alive.fetch_sub(1, std::memory_order_relaxed); + if (is_static) { + gImmutableCStringStats.staticStrings.fetch_sub(1, std::memory_order_relaxed); + } else { + gImmutableCStringStats.heapStrings.fetch_sub(1, std::memory_order_relaxed); + } + } + static std::atomic_int32_t sCtorSinceLastLog = { 0 }; + if (UTILS_UNLIKELY(sCtorSinceLastLog.fetch_add(1, std::memory_order_relaxed) == IMMUTABLECSTRING_LOG_INTERVAL)) { + LOG(INFO) << "ImmutableCString stats: " + << gImmutableCStringStats.alive.load(std::memory_order_relaxed) << " alive, " + << gImmutableCStringStats.ctor.load(std::memory_order_relaxed) << " ctor, " + << gImmutableCStringStats.staticStrings.load(std::memory_order_relaxed) << " static, " + << gImmutableCStringStats.heapStrings.load(std::memory_order_relaxed) << " heap"; + sCtorSinceLastLog.store(0, std::memory_order_relaxed); + } +} + +ImmutableCString& ImmutableCString::operator=(const ImmutableCString& other) { + if (this != &other) { + ImmutableCString(other).swap(*this); + } + return *this; +} + +ImmutableCString& ImmutableCString::operator=(ImmutableCString&& other) noexcept { + this->swap(other); + return *this; +} + + +void ImmutableCString::initializeFrom(const char* cstr, size_t const length) { + if (length > 0 && cstr) { + char* buffer = static_cast(malloc(length + 1)); + if (UTILS_LIKELY(buffer)) { + memcpy(buffer, cstr, length); + buffer[length] = '\0'; + mData = buffer; + mSize = length; + mIsStatic = false; + return; + } + } + mData = ""; + mSize = 0; + mIsStatic = true; +} + +#if !defined(NDEBUG) +io::ostream& operator<<(io::ostream& out, const ImmutableCString& rhs) { + return out << rhs.c_str(); +} + +io::ostream& operator<<(io::ostream& out, const StaticString& rhs) { + return out << rhs.c_str(); +} +#endif + +} // namespace utils diff --git a/libs/utils/test/test_ImmutableCString.cpp b/libs/utils/test/test_ImmutableCString.cpp new file mode 100644 index 0000000000..a80fb179e3 --- /dev/null +++ b/libs/utils/test/test_ImmutableCString.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include +#include +#include +#include + +using namespace utils; + +TEST(ImmutableCString, EmptyString) { + ImmutableCString const emptyString(""); + EXPECT_STREQ("", emptyString.c_str()); + EXPECT_EQ(0, emptyString.length()); + EXPECT_TRUE(emptyString.empty()); + EXPECT_TRUE(emptyString.isStatic()); +} + +TEST(ImmutableCString, Constructors) { + // ImmutableCString() + { + ImmutableCString const str; + EXPECT_STREQ("", str.c_str()); + EXPECT_EQ(0, str.length()); + EXPECT_TRUE(str.empty()); + EXPECT_TRUE(str.isStatic()); + } + // ImmutableCString(const char* cstr, size_t length) + { + ImmutableCString const str("foobar", 3); + EXPECT_STREQ("foo", str.c_str()); + EXPECT_EQ(3, str.length()); + EXPECT_TRUE(str.isDynamic()); + } + // ImmutableCString(const char* cstr) + { + const char* hello_cstr = "hello"; + ImmutableCString const str(hello_cstr); + EXPECT_STREQ("hello", str.c_str()); + EXPECT_EQ(5, str.length()); + EXPECT_TRUE(str.isDynamic()); + } + // ImmutableCString(StringLiteral) + { + ImmutableCString const str("literal"); // this uses the template constructor + EXPECT_STREQ("literal", str.c_str()); + EXPECT_EQ(7, str.length()); + EXPECT_TRUE(str.isStatic()); + } + // Copy constructor + { + ImmutableCString const s1("copy me"); + EXPECT_TRUE(s1.isStatic()); + ImmutableCString const s2(s1); // NOLINT(*-unnecessary-copy-initialization) + EXPECT_STREQ("copy me", s2.c_str()); + EXPECT_TRUE(s2.isStatic()); + } + // Move constructor + { + ImmutableCString s1("move me"); + EXPECT_TRUE(s1.isStatic()); + ImmutableCString const s2(std::move(s1)); + EXPECT_STREQ("move me", s2.c_str()); + EXPECT_TRUE(s2.isStatic()); + } +} + +TEST(ImmutableCString, Assignment) { + // Copy assignment + { + ImmutableCString const s1("copy"); + ImmutableCString s2; + s2 = s1; + EXPECT_STREQ("copy", s2.c_str()); + EXPECT_TRUE(s2.isStatic()); + } + // Move assignment + { + ImmutableCString s1("move"); + ImmutableCString s2; + s2 = std::move(s1); + EXPECT_STREQ("move", s2.c_str()); + EXPECT_TRUE(s2.isStatic()); + } + // self-copy-assignment + { + ImmutableCString s1("self"); + // This looks strange, but it's an important edge case to test for assignment operators. + s1 = s1; + EXPECT_STREQ("self", s1.c_str()); + EXPECT_TRUE(s1.isStatic()); + } + // self-move-assignment + { + ImmutableCString s1("self-move"); + s1 = std::move(s1); + // A self-move-assignment should leave the object in a valid state. + // Our implementation has a guard against self-move, so the object is unchanged. + EXPECT_STREQ("self-move", s1.c_str()); + EXPECT_TRUE(s1.isStatic()); + } +} + +TEST(ImmutableCString, Swap) { + ImmutableCString s1("first"); + ImmutableCString s2("second"); + + size_t const l1 = s1.length(); + size_t const l2 = s2.length(); + + s1.swap(s2); + + EXPECT_STREQ("second", s1.c_str()); + EXPECT_STREQ("first", s2.c_str()); + EXPECT_EQ(l2, s1.length()); + EXPECT_EQ(l1, s2.length()); +} + +TEST(ImmutableCString, Comparison) { + ImmutableCString const s1("abc"); + ImmutableCString const s2("abc"); + ImmutableCString const s3("def"); + ImmutableCString const s4("ab"); + + EXPECT_TRUE(s1 == s2); + EXPECT_FALSE(s1 == s3); + + EXPECT_TRUE(s1 != s3); + EXPECT_FALSE(s1 != s2); + + EXPECT_TRUE(s1 < s3); + EXPECT_FALSE(s3 < s1); + + EXPECT_TRUE(s3 > s1); + EXPECT_FALSE(s1 > s3); + + EXPECT_TRUE(s1 <= s2); + EXPECT_TRUE(s1 <= s3); + EXPECT_FALSE(s3 <= s1); + + EXPECT_TRUE(s2 >= s1); + EXPECT_TRUE(s3 >= s1); + EXPECT_FALSE(s1 >= s3); + + EXPECT_TRUE(s4 < s1); + EXPECT_TRUE(s1 > s4); +} + +TEST(ImmutableCString, ElementAccess) { + // Test with statically-allocated string + const ImmutableCString cstr("const"); + EXPECT_EQ('c', cstr.front()); + EXPECT_EQ('t', cstr.back()); + EXPECT_EQ('n', cstr[2]); + EXPECT_EQ('s', cstr.at(3)); + + // Test with heap-allocated string + std::string const a_normal_string = "a normal string"; + const ImmutableCString v(a_normal_string.c_str()); // heap allocation + EXPECT_EQ('a', v.front()); + EXPECT_EQ('g', v.back()); + EXPECT_EQ(' ', v[1]); + EXPECT_EQ('n', v.at(2)); + + // iterators + std::string const s(cstr.begin(), cstr.end()); + EXPECT_EQ("const", s); + + EXPECT_TRUE(std::equal(cstr.begin(), cstr.end(), "const")); +} + +TEST(ImmutableCString, NoHeapAllocation) { + ImmutableCString s("hello world"); // no allocation + EXPECT_TRUE(s.isStatic()); + ImmutableCString t(s); // no allocation + EXPECT_TRUE(t.isStatic()); + s = t; // no allocation + EXPECT_TRUE(s.isStatic()); + t = std::move(s); // no allocation and s is now empty + EXPECT_TRUE(t.isStatic()); + EXPECT_STREQ("hello world", t.c_str()); +} + +TEST(ImmutableCString, HeapAllocation) { + std::string const a_normal_string = "a normal string"; + ImmutableCString const v(a_normal_string.c_str()); // heap allocation + EXPECT_TRUE(v.isDynamic()); + EXPECT_STREQ("a normal string", v.c_str()); +}