Compare commits

..
Author SHA1 Message Date
bridgewaterrobbie 3041a7ccc0 Include webgpu matc arg in android builds when appropriate. 2025-04-07 14:36:37 -04:00
Syed Idris Shah 06f8d073da Add Command, RenderPass encoders and other pieces of webgpu 2025-04-04 13:14:35 -04:00
Syed Idris Shah e5b8f91859 Use HandleAllocator for webgpu to implement createVertexBufferInfoS 2025-04-04 13:12:57 -04:00
Andy Hovingh 70f2cda9b6 remove unnecessary third party includes from dawn (Filament already brings them in) 2025-04-03 20:22:28 -04:00
Andy Hovingh c3e4894d49 fix Mac OS 15.4 compile errors: minor changes to reflect webgpu and tint API changes 2025-04-03 20:22:28 -04:00
Andy Hovingh a128d9143a fix Mac OS 15.4 compile errors: ignore clang nullability-extension warnings/errors only for Macs 2025-04-03 20:22:28 -04:00
Andy Hovingh 2cf10999f4 fix Mac OS 15.4 compile errors: upgrade spirv-tools dependency to match dawn (6add4e478f8802d3bbd100120e5ffc6f725ec9fe) 2025-04-03 20:22:28 -04:00
Andy Hovingh e0e44da185 fix Mac OS 15.4 compile errors: upgrade spirv-headers dependency to match dawn (8e82b7cfeca98baae9a01a53511483da7194f854) 2025-04-03 20:22:28 -04:00
Andy Hovingh ce62e0ef06 fix Mac OS 15.4 compile errors: upgrade glslang dependency to match dawn (e57f993cff981c8c3ffd38967e030f04d13781a9) 2025-04-03 20:22:28 -04:00
Andy Hovingh 826b885d0e fix Mac OS 15.4 compile errors: upgrade dawn dependency (chromium/7106 tag/version) 2025-04-03 20:22:28 -04:00
Andy Hovingh 5b9a24edf0 fix Mac OS 15.4 compile errors: upgrade abseil dependency (version Abseil LTS 20250127.1) 2025-04-03 20:22:28 -04:00
Andy Hovingh b651f63e02 update release notes 2025-04-03 20:22:28 -04:00
Andy Hovingh c48273df3c fix Mac OS 15.4 compile errors: invoke printSurfaceConfiguration to avoid an unused error 2025-04-03 20:22:28 -04:00
Andy Hovingh 8397a15914 fix Mac OS 15.4 compile errors: upgrade libpng dependency (v1.6.47) 2025-04-03 20:22:28 -04:00
Andy Hovingh d76567b4a8 fix Mac OS 15.4 compile errors: upgrade libz dependency (v1.3.1) 2025-04-03 20:22:28 -04:00
Konrad Piascik ce62b169cb Fix Windows webGPU build 2025-04-03 14:12:17 -04:00
Powei Feng 9244f8ee21 vk: add YcbcrConversion to VulkanTexture (#8588)
- Refactor VulkanTextureState and VulkanTexture so that most
  state fields are consts.
- Add a field for VkYcbcrConversion.
- Clear the image view cache when YcbcrConversion changes
- Make sure that getAttachmentView and getView are better defined
  and called.
2025-04-03 17:30:40 +00:00
bridgewaterrobbie 3c7a871e7e Avoid running the inline pass without merge return on WebGPU 2025-04-02 17:52:27 -04:00
Jeremy Nelson 31d698e9ca remove resize and refactor GetCurrentTexture
remove resize and refactor GetCurrentTexture

remove resize and refactor GetCurrentTexture
2025-04-02 15:35:50 -05:00
Andy Hovingh 769b0db858 webgpu: select color format, present mode, and composite alpha mode from surface capabilities 2025-04-02 15:35:50 -05:00
Jeremy Nelson b40064b1ab Changed class name to WebGPUSwapChain and comments for handle allocator 2025-04-02 15:35:50 -05:00
Jeremy Nelson 889a62d617 Create WebGPUSurface Class 2025-04-02 15:35:50 -05:00
Mathias Agopian 784b3ce565 Fix subpasses with custom render targets
When Color grading is using the optimized subpass mode, it could fail
if it was the last pass. This is because in that case it renders
directly into the custom rendertarget which doesn't have MRTs (which
is needed). The fix is to issue an extra blit.

FIXES=[406343577]
2025-04-01 15:23:34 -07:00
Powei Feng 4f77547ab3 vk: add ycbcr conversion cache (#8557)
Introduce a cache for Ycbcr conversion, which is needed for
external textures on Android.
2025-04-01 22:12:59 +00:00
Nick Fisher 46c89499d0 Dispose debug.server/debug.fgViewerServer when Engine destroyed (#8563) 2025-04-01 20:52:42 +00:00
Sungun Park 57c782685b Add missing header (#8586) 2025-04-01 11:11:19 -07:00
bridgewaterrobbieandPowei Feng bc799c78f6 Update libs/filamat/src/GLSLPostProcessor.cpp per suggestion
Co-authored-by: Powei Feng <powei@google.com>
2025-03-31 19:39:05 -04:00
bridgewaterrobbieandPowei Feng 86e688a2a3 Update libs/filamat/src/GLSLPostProcessor.cpp per suggestion
Co-authored-by: Powei Feng <powei@google.com>
2025-03-31 19:39:05 -04:00
bridgewaterrobbie 3dead231d4 Output failing processed spir-v on failure to read with tint
Also add a build option to ignore such issues if needed during bringup
2025-03-31 19:39:05 -04:00
bridgewaterrobbie fd382ce219 Split and rebind combined image samplers for WebGPU API target 2025-03-31 19:39:05 -04:00
bridgewaterrobbie 46358572b7 Allow non uniform derivitives 2025-03-31 19:39:05 -04:00
bridgewaterrobbie 546b986107 Hack a workaround for OpConstantLoad issue in Tint to work with most spec constants 2025-03-31 19:39:05 -04:00
bridgewaterrobbie 5245141c46 Workaround Tint issues with texelFetchOffset in dofMedian.mat 2025-03-31 19:39:05 -04:00
bridgewaterrobbie 62b182fe04 Update SPIR-V tools to commit ada1771a9f7a125573aa94fe551fdc44b45769bd to pull in splitter pass 2025-03-31 19:39:05 -04:00
9359 changed files with 352022 additions and 2041731 deletions
+3
View File
@@ -334,6 +334,9 @@ if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} /W0 /Zc:__cplusplus")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_STANDARD} -fstrict-aliasing -Wno-unknown-pragmas -Wno-unused-function -Wno-deprecated-declarations")
if (APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-nullability-extension")
endif()
endif()
if (FILAMENT_USE_EXTERNAL_GLES3)
+2
View File
@@ -7,3 +7,5 @@ for next branch cut* header.
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
## Release notes for next branch cut
- Fix build/compile errors when upgrading to MacOS 15.4
+2 -2
View File
@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.59.1'
implementation 'com.google.android.filament:filament-android:1.59.0'
}
```
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
iOS projects can use CocoaPods to install the latest release:
```shell
pod 'Filament', '~> 1.59.1'
pod 'Filament', '~> 1.59.0'
```
## Documentation
@@ -143,6 +143,15 @@ abstract class MaterialCompiler extends TaskWithBinary {
matcArgs += ['-a', 'vulkan']
}
def include_webgpu = providers
.gradleProperty("com.google.android.filament.include-webgpu")
.forUseAtConfigurationTime().present
if (!include_webgpu) {
matcArgs += ['-a', 'webgpu']
}
def mat_no_opt = providers
.gradleProperty("com.google.android.filament.matnopt")
.forUseAtConfigurationTime().present
+1 -1
View File
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.59.1
VERSION_NAME=1.59.0
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
+11
View File
@@ -233,6 +233,8 @@ if (FILAMENT_SUPPORTS_VULKAN)
src/vulkan/VulkanReadPixels.h
src/vulkan/VulkanTexture.cpp
src/vulkan/VulkanTexture.h
src/vulkan/VulkanYcbcrConversionCache.cpp
src/vulkan/VulkanYcbcrConversionCache.h
)
if (LINUX OR WIN32)
list(APPEND SRCS src/vulkan/platform/VulkanPlatformLinuxWindows.cpp)
@@ -253,6 +255,10 @@ if (FILAMENT_SUPPORTS_WEBGPU)
src/webgpu/WebGPUConstants.h
src/webgpu/WebGPUDriver.cpp
src/webgpu/WebGPUDriver.h
src/webgpu/WebGPUSwapChain.cpp
src/webgpu/WebGPUSwapChain.h
src/webgpu/WebGPUHandles.cpp
src/webgpu/WebGPUHandles.h
)
if (WIN32)
list(APPEND SRCS src/webgpu/platform/WebGPUPlatformWindows.cpp)
@@ -302,6 +308,11 @@ target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
# add this subproject to the Filament folder
set_target_properties(${TARGET} PROPERTIES FOLDER Filament)
# we need to export the headers properly for backend.lib on windows
if (WIN32 AND FILAMENT_SUPPORTS_WEBGPU)
target_compile_definitions(${TARGET} PRIVATE "WGPU_IMPLEMENTATION")
endif()
# ==================================================================================================
# Expose a header-only target to minimize dependencies.
# ==================================================================================================
@@ -361,8 +361,7 @@ public:
VkImageUsageFlags usage);
virtual VkSampler createExternalSampler(SamplerYcbcrConversion chroma,
SamplerParams sampler,
uint32_t internalFormat);
SamplerParams sampler, uint32_t internalFormat);
virtual VkImageView createExternalImageView(SamplerYcbcrConversion chroma,
uint32_t internalFormat, VkImage image, VkImageSubresourceRange range,
@@ -17,9 +17,6 @@
#include "VulkanBlitter.h"
#include "VulkanCommands.h"
#include "VulkanContext.h"
#include "VulkanFboCache.h"
#include "VulkanHandles.h"
#include "VulkanSamplerCache.h"
#include "VulkanTexture.h"
#include "vulkan/utils/Image.h"
@@ -24,13 +24,6 @@
namespace filament::backend {
class VulkanBuffer;
class VulkanFboCache;
class VulkanPipelineCache;
class VulkanSamplerCache;
struct VulkanProgram;
class VulkanBlitter {
public:
VulkanBlitter(VkPhysicalDevice physicalDevice, VulkanCommands* commands) noexcept;
@@ -56,9 +56,9 @@ VkImageView VulkanAttachment::getImageView() {
assert_invariant(texture);
VkImageSubresourceRange range = getSubresourceRange();
if (range.layerCount > 1) {
return texture->getMultiviewAttachmentView(range);
return texture->getAttachmentView(range, VK_IMAGE_VIEW_TYPE_2D_ARRAY);
}
return texture->getAttachmentView(range);
return texture->getAttachmentView(range, VK_IMAGE_VIEW_TYPE_2D);
}
bool VulkanAttachment::isDepth() const {
@@ -68,11 +68,11 @@ bool VulkanAttachment::isDepth() const {
VkImageSubresourceRange VulkanAttachment::getSubresourceRange() const {
assert_invariant(texture);
return {
.aspectMask = texture->getImageAspect(),
.baseMipLevel = uint32_t(level),
.levelCount = 1,
.baseArrayLayer = uint32_t(layer),
.layerCount = layerCount,
.aspectMask = texture->getImageAspect(),
.baseMipLevel = uint32_t(level),
.levelCount = 1,
.baseArrayLayer = uint32_t(layer),
.layerCount = layerCount,
};
}
@@ -17,7 +17,6 @@
#ifndef TNT_FILAMENT_BACKEND_VULKANCONTEXT_H
#define TNT_FILAMENT_BACKEND_VULKANCONTEXT_H
#include "VulkanConstants.h"
#include "vulkan/utils/Image.h"
#include "vulkan/utils/Definitions.h"
@@ -30,8 +29,6 @@
#include <bluevk/BlueVK.h>
#include <memory>
VK_DEFINE_HANDLE(VmaAllocator)
VK_DEFINE_HANDLE(VmaPool)
@@ -260,7 +260,6 @@ VulkanDescriptorSetCache::~VulkanDescriptorSetCache() = default;
void VulkanDescriptorSetCache::terminate() noexcept{
mDescriptorPool.reset();
clearHistory();
}
// bind() is not really binding the set but just stashing until we have all the info
@@ -330,7 +329,6 @@ void VulkanDescriptorSetCache::updateBuffer(fvkmemory::resource_ptr<VulkanDescri
}
VkWriteDescriptorSet const descriptorWrite = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.pNext = nullptr,
.dstSet = set->vkSet,
.dstBinding = binding,
.descriptorCount = 1,
@@ -346,20 +344,19 @@ void VulkanDescriptorSetCache::updateSampler(fvkmemory::resource_ptr<VulkanDescr
VkSampler sampler) noexcept {
VkDescriptorImageInfo info{
.sampler = sampler,
.imageLayout = fvkutils::getVkLayout(texture->getDefaultLayout()),
};
VkImageSubresourceRange const range = texture->getPrimaryViewRange();
VkImageSubresourceRange range = texture->getPrimaryViewRange();
VkImageViewType const expectedType = texture->getViewType();
if (any(texture->usage & TextureUsage::DEPTH_ATTACHMENT) &&
expectedType == VK_IMAGE_VIEW_TYPE_2D) {
// If the sampler is part of a mipmapped depth texture, where one of the level *can* be
// an attachment, then the sampler for this texture has the same view properties as a
// view for an attachment. Therefore, we can use getAttachmentView to get a
// corresponding VkImageView.
info.imageView = texture->getAttachmentView(range);
} else {
info.imageView = texture->getViewForType(range, expectedType);
// an attachment, then the range for this view has exactly one level and one layer.
range.levelCount = 1;
range.layerCount = 1;
}
info.imageLayout = fvkutils::getVkLayout(texture->getDefaultLayout());
info.imageView = texture->getView(range);
VkWriteDescriptorSet const descriptorWrite = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.pNext = nullptr,
@@ -395,7 +392,7 @@ fvkmemory::resource_ptr<VulkanDescriptorSet> VulkanDescriptorSetCache::createSet
});
}
void VulkanDescriptorSetCache::clearHistory() {
void VulkanDescriptorSetCache::gc() {
mStashedSets = {};
}
@@ -68,7 +68,7 @@ public:
fvkmemory::resource_ptr<VulkanDescriptorSet> createSet(Handle<HwDescriptorSet> handle,
fvkmemory::resource_ptr<VulkanDescriptorSetLayout> layout);
void clearHistory();
void gc();
private:
class DescriptorInfinitePool;
+21 -10
View File
@@ -25,10 +25,12 @@
#include "VulkanHandles.h"
#include "VulkanMemory.h"
#include "VulkanTexture.h"
#include "vulkan/VulkanSamplerCache.h"
#include "vulkan/memory/ResourceManager.h"
#include "vulkan/memory/ResourcePointer.h"
#include "vulkan/utils/Conversion.h"
#include "vulkan/utils/Definitions.h"
#include "vulkan/vulkan_core.h"
#include <backend/DriverEnums.h>
#include <backend/platforms/VulkanPlatform.h>
@@ -212,6 +214,7 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& contex
mPipelineCache(mPlatform->getDevice()),
mStagePool(mAllocator, &mCommands),
mFramebufferCache(mPlatform->getDevice()),
mYcbcrConversionCache(mPlatform->getDevice()),
mSamplerCache(mPlatform->getDevice()),
mBlitter(mPlatform->getPhysicalDevice(), &mCommands),
mReadPixels(mPlatform->getDevice()),
@@ -363,7 +366,7 @@ void VulkanDriver::collectGarbage() {
FVK_SYSTRACE_SCOPE();
// Command buffers need to be submitted and completed before other resources can be gc'd.
mCommands.gc();
mDescriptorSetCache.clearHistory();
mDescriptorSetCache.gc();
mStagePool.gc();
mFramebufferCache.gc();
mPipelineCache.gc();
@@ -418,7 +421,11 @@ void VulkanDriver::updateDescriptorSetTexture(
auto set = resource_ptr<VulkanDescriptorSet>::cast(&mResourceManager, dsh);
auto texture = resource_ptr<VulkanTexture>::cast(&mResourceManager, th);
VkSampler const vksampler = mSamplerCache.getSampler(params);
// TODO: YcbcrConversion?
VulkanSamplerCache::Params cacheParams = {
.sampler = params,
};
VkSampler const vksampler = mSamplerCache.getSampler(cacheParams);
mDescriptorSetCache.updateSampler(set, binding, texture, vksampler);
}
@@ -556,7 +563,7 @@ void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th, backend::S
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
Platform::ExternalImageHandleRef externalImage) {
FVK_SYSTRACE_SCOPE();
const auto& metadata = mPlatform->getExternalImageMetadata(externalImage);
auto const& metadata = mPlatform->getExternalImageMetadata(externalImage);
if (metadata.isProtected) {
usage |= backend::TextureUsage::PROTECTED;
}
@@ -566,7 +573,7 @@ void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th, backend::S
vkUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
}
if (any(usage & (TextureUsage::BLIT_DST & TextureUsage::UPLOADABLE))) {
if (any(usage & (TextureUsage::BLIT_DST | TextureUsage::UPLOADABLE))) {
vkUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
@@ -582,13 +589,15 @@ void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th, backend::S
FILAMENT_CHECK_POSTCONDITION(memoryTypeIndex != VK_MAX_MEMORY_TYPES)
<< "failed to find a valid memory type for external image memory.";
const auto& data =
VkImage vkimg;
VkDeviceMemory deviceMemory;
std::tie(vkimg, deviceMemory) =
mPlatform->createExternalImageData(externalImage, metadata, memoryTypeIndex, vkUsage);
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
mAllocator, &mResourceManager, &mCommands, data.first, data.second, metadata.format,
metadata.samples, metadata.width, metadata.height, metadata.layerCount, usage,
mStagePool);
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mContext,
mPlatform->getDevice(), mAllocator, &mResourceManager, &mCommands, vkimg, deviceMemory,
metadata.format, VK_NULL_HANDLE, metadata.samples, metadata.width, metadata.height,
metadata.layerCount, usage, mStagePool);
texture.inc();
}
@@ -597,13 +606,14 @@ void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::Sa
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
void* externalImage) {
FVK_SYSTRACE_SCOPE();
assert_invariant(false && "Not supported in Vulkan backend");
// not supported in this backend
}
void VulkanDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
void* image, uint32_t plane) {
assert_invariant(false && "Not supported in Vulkan backend");
}
void VulkanDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
@@ -611,6 +621,7 @@ void VulkanDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
TextureUsage usage) {
// not supported in this backend
assert_invariant(false && "Not supported in Vulkan backend");
}
void VulkanDriver::destroyTexture(Handle<HwTexture> th) {
@@ -27,6 +27,7 @@
#include "VulkanSamplerCache.h"
#include "VulkanStagePool.h"
#include "VulkanQueryManager.h"
#include "VulkanYcbcrConversionCache.h"
#include "vulkan/VulkanDescriptorSetCache.h"
#include "vulkan/VulkanDescriptorSetLayoutCache.h"
#include "vulkan/VulkanPipelineLayoutCache.h"
@@ -135,6 +136,7 @@ private:
VulkanPipelineCache mPipelineCache;
VulkanStagePool mStagePool;
VulkanFboCache mFramebufferCache;
VulkanYcbcrConversionCache mYcbcrConversionCache;
VulkanSamplerCache mSamplerCache;
VulkanBlitter mBlitter;
VulkanReadPixels mReadPixels;
@@ -18,24 +18,18 @@
#define TNT_FILAMENT_BACKEND_VULKANPIPELINECACHE_H
#include "VulkanCommands.h"
#include "VulkanMemory.h"
#include <backend/DriverEnums.h>
#include <backend/TargetBufferInfo.h>
#include "backend/Program.h"
#include <bluevk/BlueVK.h>
#include <utils/bitset.h>
#include <utils/compiler.h>
#include <utils/Hash.h>
#include <list>
#include <tsl/robin_map.h>
#include <type_traits>
#include <vector>
#include <unordered_map>
namespace filament::backend {
@@ -14,7 +14,9 @@
* limitations under the License.
*/
#include "vulkan/VulkanSamplerCache.h"
#include "VulkanSamplerCache.h"
#include "VulkanConstants.h"
#include "vulkan/utils/Conversion.h"
#include <utils/Panic.h>
@@ -26,41 +28,40 @@ namespace filament::backend {
VulkanSamplerCache::VulkanSamplerCache(VkDevice device)
: mDevice(device) {}
VkSampler VulkanSamplerCache::getSampler(SamplerParams params) noexcept {
VkSampler VulkanSamplerCache::getSampler(Params params) noexcept {
auto iter = mCache.find(params);
if (UTILS_LIKELY(iter != mCache.end())) {
return iter->second;
}
VkSamplerCreateInfo samplerInfo {
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.magFilter = fvkutils::getFilter(params.filterMag),
.minFilter = fvkutils::getFilter(params.filterMin),
.mipmapMode = fvkutils::getMipmapMode(params.filterMin),
.addressModeU = fvkutils::getWrapMode(params.wrapS),
.addressModeV = fvkutils::getWrapMode(params.wrapT),
.addressModeW = fvkutils::getWrapMode(params.wrapR),
.anisotropyEnable = params.anisotropyLog2 == 0 ? VK_FALSE : VK_TRUE,
.maxAnisotropy = (float)(1u << params.anisotropyLog2),
.compareEnable = fvkutils::getCompareEnable(params.compareMode),
.compareOp = fvkutils::getCompareOp(params.compareFunc),
auto const& samplerParams = params.sampler;
VkSamplerCreateInfo samplerInfo{ .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.magFilter = fvkutils::getFilter(samplerParams.filterMag),
.minFilter = fvkutils::getFilter(samplerParams.filterMin),
.mipmapMode = fvkutils::getMipmapMode(samplerParams.filterMin),
.addressModeU = fvkutils::getWrapMode(samplerParams.wrapS),
.addressModeV = fvkutils::getWrapMode(samplerParams.wrapT),
.addressModeW = fvkutils::getWrapMode(samplerParams.wrapR),
.anisotropyEnable = samplerParams.anisotropyLog2 == 0 ? VK_FALSE : VK_TRUE,
.maxAnisotropy = (float) (1u << samplerParams.anisotropyLog2),
.compareEnable = fvkutils::getCompareEnable(samplerParams.compareMode),
.compareOp = fvkutils::getCompareOp(samplerParams.compareFunc),
.minLod = 0.0f,
.maxLod = fvkutils::getMaxLod(params.filterMin),
.maxLod = fvkutils::getMaxLod(samplerParams.filterMin),
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
.unnormalizedCoordinates = VK_FALSE
};
.unnormalizedCoordinates = VK_FALSE };
VkSampler sampler;
VkResult result = vkCreateSampler(mDevice, &samplerInfo, VKALLOC, &sampler);
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "Unable to create sampler."
<< " error=" << static_cast<int32_t>(result);
mCache.insert({params, sampler});
mCache.insert({ params, sampler });
return sampler;
}
void VulkanSamplerCache::terminate() noexcept {
for (auto pair : mCache) {
for (auto pair: mCache) {
vkDestroySampler(mDevice, pair.second, VKALLOC);
}
mCache.clear();
}
} // namespace filament::backend
}// namespace filament::backend
@@ -17,8 +17,11 @@
#ifndef TNT_FILAMENT_BACKEND_VULKANSAMPLERCACHE_H
#define TNT_FILAMENT_BACKEND_VULKANSAMPLERCACHE_H
#include "VulkanContext.h"
#include <backend/DriverEnums.h>
#include <utils/Hash.h>
#include <bluevk/BlueVK.h>
#include <tsl/robin_map.h>
namespace filament::backend {
@@ -26,12 +29,28 @@ namespace filament::backend {
// Simple manager for VkSampler objects.
class VulkanSamplerCache {
public:
struct Params {
SamplerParams sampler = {};
uint32_t padding = 0;
VkSamplerYcbcrConversion conversion = VK_NULL_HANDLE;
};
static_assert(sizeof(Params) == 16);
explicit VulkanSamplerCache(VkDevice device);
VkSampler getSampler(SamplerParams params) noexcept;
VkSampler getSampler(Params params) noexcept;
void terminate() noexcept;
private:
VkDevice mDevice;
tsl::robin_map<SamplerParams, VkSampler, SamplerParams::Hasher, SamplerParams::EqualTo> mCache;
struct SamplerEqualTo {
bool operator()(Params lhs, Params rhs) const noexcept {
SamplerParams::EqualTo equal;
return equal(lhs.sampler, rhs.sampler) && lhs.conversion == rhs.conversion;
}
};
using SamplerHashFn = utils::hash::MurmurHashFn<Params>;
tsl::robin_map<Params, VkSampler, SamplerHashFn, SamplerEqualTo> mCache;
};
} // namespace filament::backend
@@ -32,6 +32,7 @@ VulkanSwapChain::VulkanSwapChain(VulkanPlatform* platform, VulkanContext const&
VulkanCommands* commands, VulkanStagePool& stagePool, void* nativeWindow, uint64_t flags,
VkExtent2D extent)
: mPlatform(platform),
mContext(context),
mResourceManager(resourceManager),
mCommands(commands),
mAllocator(allocator),
@@ -77,16 +78,16 @@ void VulkanSwapChain::update() {
}
for (auto const color: bundle.colors) {
auto colorTexture = fvkmemory::resource_ptr<VulkanTexture>::construct(mResourceManager,
device, mAllocator, mResourceManager, mCommands, color, VK_NULL_HANDLE,
bundle.colorFormat, 1, bundle.extent.width, bundle.extent.height, bundle.layerCount, colorUsage,
mStagePool);
mContext, device, mAllocator, mResourceManager, mCommands, color, VK_NULL_HANDLE,
bundle.colorFormat, VK_NULL_HANDLE /*ycrcb */, 1, bundle.extent.width,
bundle.extent.height, bundle.layerCount, colorUsage, mStagePool);
mColors.push_back(colorTexture);
}
mDepth = fvkmemory::resource_ptr<VulkanTexture>::construct(mResourceManager, device,
mAllocator, mResourceManager, mCommands, bundle.depth, VK_NULL_HANDLE,
bundle.depthFormat, 1, bundle.extent.width, bundle.extent.height, bundle.layerCount, depthUsage,
mStagePool);
mDepth = fvkmemory::resource_ptr<VulkanTexture>::construct(mResourceManager, mContext, device,
mAllocator, mResourceManager, mCommands, bundle.depth, VK_NULL_HANDLE,
bundle.depthFormat, VK_NULL_HANDLE /*ycrcb */, 1, bundle.extent.width,
bundle.extent.height, bundle.layerCount, depthUsage, mStagePool);
mExtent = bundle.extent;
mLayerCount = bundle.layerCount;
@@ -19,6 +19,7 @@
#include "DriverBase.h"
#include "VulkanConstants.h"
#include "VulkanContext.h"
#include "VulkanTexture.h"
#include "vulkan/memory/Resource.h"
@@ -28,7 +29,6 @@
#include <bluevk/BlueVK.h>
#include <utils/FixedCapacityVector.h>
#include <memory>
using namespace bluevk;
@@ -83,6 +83,7 @@ private:
void update();
VulkanPlatform* mPlatform;
VulkanContext const& mContext;
fvkmemory::ResourceManager* mResourceManager;
VulkanCommands* mCommands;
VmaAllocator mAllocator;
+210 -169
View File
@@ -15,6 +15,7 @@
*/
#include "VulkanCommands.h"
#include "VulkanContext.h"
#include "VulkanMemory.h"
#include "VulkanTexture.h"
#include "vulkan/memory/ResourcePointer.h"
@@ -54,7 +55,6 @@ VkComponentMapping composeSwizzle(VkComponentMapping const& prev, VkComponentMap
VK_COMPONENT_SWIZZLE_B,
VK_COMPONENT_SWIZZLE_A,
};
auto const compose = [](VkComponentMapping const& prev,
VkComponentMapping const& next) -> VkComponentMapping {
VkComponentSwizzle vals[4] = { next.r, next.g, next.b, next.a };
@@ -151,35 +151,152 @@ uint8_t getLayerCountFromDepth(uint32_t const depth) {
return getLayerCount(getSamplerTypeFromDepth(depth), depth);
}
VkImageUsageFlags getUsage(VulkanContext const& context, uint8_t samples,
VkPhysicalDevice physicalDevice, VkFormat vkFormat, TextureUsage tusage) {
VkImageUsageFlags usage = {};
if (any(tusage & TextureUsage::BLIT_SRC)) {
usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
}
if (any(tusage & TextureUsage::BLIT_DST)) {
usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
// Determine if we can use the transient usage flag combined with lazily allocated memory.
const bool useTransientAttachment =
// Lazily allocated memory is available.
context.isLazilyAllocatedMemorySupported() &&
// Usage consists of attachment flags only.
none(tusage & ~TextureUsage::ALL_ATTACHMENTS) &&
// Usage contains at least one attachment flag.
any(tusage & TextureUsage::ALL_ATTACHMENTS) &&
// Depth resolve cannot use transient attachment because it uses a custom shader.
// TODO: see VulkanDriver::isDepthStencilResolveSupported() to know when to remove this
// restriction.
// Note that the custom shader does not resolve stencil. We do need to move to vk 1.2
// and above to be able to support stencil resolve (along with depth).
!(any(tusage & TextureUsage::DEPTH_ATTACHMENT) && samples > 1);
const VkImageUsageFlags transientFlag =
useTransientAttachment ? VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT : 0U;
if (any(tusage & TextureUsage::SAMPLEABLE)) {
#if FVK_ENABLED(FVK_DEBUG_TEXTURE)
if (physicalDevice != VK_NULL_HANDLE) {
// Validate that the format is actually sampleable.
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(physicalDevice, vkFormat, &props);
if (!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
FVK_LOGW << "Texture usage is SAMPLEABLE but format " << mState->mVkFormat << " is not "
"sampleable with optimal tiling." << utils::io::endl;
}
}
#endif
usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
}
if (any(tusage & TextureUsage::COLOR_ATTACHMENT)) {
usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | transientFlag;
if (any(tusage & TextureUsage::SUBPASS_INPUT)) {
usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
}
}
if (any(tusage & TextureUsage::STENCIL_ATTACHMENT)) {
usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | transientFlag;
}
if (any(tusage & TextureUsage::UPLOADABLE)) {
usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
if (any(tusage & TextureUsage::DEPTH_ATTACHMENT)) {
usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | transientFlag;
// Depth resolves uses a custom shader and therefore needs to be sampleable.
if (samples > 1) {
usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
}
}
return usage;
}
} // anonymous namespace
VulkanTextureState::VulkanTextureState(VkDevice device, VmaAllocator allocator,
VulkanCommands* commands, VulkanStagePool& stagePool, VkFormat format,
VkImageViewType viewType, uint8_t levels, uint8_t layerCount, VulkanLayout defaultLayout,
VulkanTextureState::VulkanTextureState(VulkanStagePool& stagePool, VulkanCommands* commands,
VmaAllocator allocator, VkDevice device, VkImage image, VkDeviceMemory deviceMemory,
VkFormat format, VkImageViewType viewType, uint8_t levels, uint8_t layerCount,
VkSamplerYcbcrConversion ycbcrConversion, bool isExternalFormat, VkImageUsageFlags usage,
bool isProtected)
: mVkFormat(format),
mViewType(viewType),
mFullViewRange{fvkutils::getImageAspect(format), 0, levels, 0, layerCount},
mDefaultLayout(defaultLayout),
mIsProtected(isProtected),
mStagePool(stagePool),
mDevice(device),
mAllocator(allocator),
: mStagePool(stagePool),
mCommands(commands),
mIsTransientAttachment(false) {}
mAllocator(allocator),
mDevice(device),
mTextureImage(image),
mTextureImageMemory(deviceMemory),
mVkFormat(format),
mViewType(viewType),
mFullViewRange{ fvkutils::getImageAspect(format), 0, levels, 0, layerCount },
mYcbcr{ ycbcrConversion, isExternalFormat },
mDefaultLayout(getDefaultLayoutImpl(usage)),
mUsage(usage),
mIsProtected(isProtected) {}
// Constructor for internally passed VkImage
VulkanTexture::VulkanTexture(VkDevice device, VmaAllocator allocator,
VulkanTextureState::~VulkanTextureState() {
if (mTextureImageMemory != VK_NULL_HANDLE) {
vkDestroyImage(mDevice, mTextureImage, VKALLOC);
vkFreeMemory(mDevice, mTextureImageMemory, VKALLOC);
}
clearCachedImageViews();
}
void VulkanTextureState::clearCachedImageViews() noexcept {
for (auto entry: mCachedImageViews) {
vkDestroyImageView(mDevice, entry.second, VKALLOC);
}
mCachedImageViews.clear();
}
VkImageView VulkanTextureState::getImageView(VkImageSubresourceRange range, VkImageViewType viewType,
VkComponentMapping swizzle) {
ImageViewKey const key{ range, viewType, swizzle };
if (auto iter = mCachedImageViews.find(key); iter != mCachedImageViews.end()) {
return iter->second;
}
VkSamplerYcbcrConversionInfo conversionInfo = {
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
.conversion = mYcbcr.conversion,
};
VkImageViewCreateInfo viewInfo = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = mYcbcr.conversion != VK_NULL_HANDLE ? &conversionInfo : nullptr,
.flags = 0,
.image = mTextureImage,
.viewType = viewType,
.format = mYcbcr.isExternalFormat ? VK_FORMAT_UNDEFINED : mVkFormat,
.components = swizzle,
.subresourceRange = range,
};
VkImageView imageView;
vkCreateImageView(mDevice, &viewInfo, VKALLOC, &imageView);
mCachedImageViews.emplace(key, imageView);
return imageView;
}
// Constructor for internally passed VkImage - including swapchain images and external images.
VulkanTexture::VulkanTexture(VulkanContext const& context, VkDevice device, VmaAllocator allocator,
fvkmemory::ResourceManager* resourceManager, VulkanCommands* commands, VkImage image,
VkDeviceMemory memory, VkFormat format, uint8_t samples, uint32_t width,
uint32_t height, uint32_t depth, TextureUsage tusage, VulkanStagePool& stagePool)
: HwTexture(getSamplerTypeFromDepth(depth), 1, samples, width, height, depth, TextureFormat::UNUSED,
tusage),
mState(fvkmemory::resource_ptr<VulkanTextureState>::construct(resourceManager, device,
allocator, commands, stagePool, format, fvkutils::getViewType(SamplerType::SAMPLER_2D),
/*mipLevels=*/1, getLayerCountFromDepth(depth), getDefaultLayoutImpl(tusage), any(usage & TextureUsage::PROTECTED))) {
mState->mTextureImage = image;
mState->mTextureImageMemory = memory;
VkDeviceMemory memory, VkFormat format, VkSamplerYcbcrConversion conversion,
uint8_t samples, uint32_t width, uint32_t height, uint32_t depth, TextureUsage tusage,
VulkanStagePool& stagePool)
: HwTexture(getSamplerTypeFromDepth(depth), 1, samples, width, height, depth,
TextureFormat::UNUSED, tusage),
mState(fvkmemory::resource_ptr<VulkanTextureState>::construct(resourceManager, stagePool,
commands, allocator, device, image, memory, format,
fvkutils::getViewType(SamplerType::SAMPLER_2D),
/*mipLevels=*/1, getLayerCountFromDepth(depth), conversion,
/*isExternalFormat=*/false,
getUsage(context, samples, VK_NULL_HANDLE, format, tusage),
any(usage & TextureUsage::PROTECTED))) {
mPrimaryViewRange = mState->mFullViewRange;
}
@@ -189,21 +306,19 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
fvkmemory::ResourceManager* resourceManager, VulkanCommands* commands, SamplerType target,
uint8_t levels, TextureFormat tformat, uint8_t samples, uint32_t w, uint32_t h,
uint32_t depth, TextureUsage tusage, VulkanStagePool& stagePool)
: HwTexture(target, levels, samples, w, h, depth, tformat, tusage),
mState(fvkmemory::resource_ptr<VulkanTextureState>::construct(resourceManager, device,
allocator, commands, stagePool, fvkutils::getVkFormat(tformat),
fvkutils::getViewType(target), levels, getLayerCount(target, depth),
VulkanLayout::UNDEFINED, any(usage & TextureUsage::PROTECTED))) {
: HwTexture(target, levels, samples, w, h, depth, tformat, tusage) {
// Create an appropriately-sized device-only VkImage, but do not fill it yet.
VkFormat const vkFormat = fvkutils::getVkFormat(tformat);
bool const isProtected = any(tusage & TextureUsage::PROTECTED);
VkImageCreateInfo imageInfo{
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = target == SamplerType::SAMPLER_3D ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D,
.format = mState->mVkFormat,
.format = vkFormat,
.extent = {w, h, depth},
.mipLevels = levels,
.arrayLayers = 1,
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = 0,
.usage = getUsage(context, samples, physicalDevice, vkFormat, tusage),
};
if (target == SamplerType::SAMPLER_3D && any(tusage & TextureUsage::ALL_ATTACHMENTS)) {
if (context.isImageView2DOn3DImageSupported()) {
@@ -233,79 +348,17 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
imageInfo.arrayLayers = depth * 6;
imageInfo.extent.depth = 1;
}
if (any(usage & TextureUsage::PROTECTED)) {
if (isProtected) {
imageInfo.flags |= VK_IMAGE_CREATE_PROTECTED_BIT;
}
if (any(usage & TextureUsage::BLIT_SRC)) {
imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
}
if (any(usage & TextureUsage::BLIT_DST)) {
imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
// Determine if we can use the transient usage flag combined with lazily allocated memory.
const bool useTransientAttachment =
// Lazily allocated memory is available.
context.isLazilyAllocatedMemorySupported() &&
// Usage consists of attachment flags only.
none(tusage & ~TextureUsage::ALL_ATTACHMENTS) &&
// Usage contains at least one attachment flag.
any(tusage & TextureUsage::ALL_ATTACHMENTS) &&
// Depth resolve cannot use transient attachment because it uses a custom shader.
// TODO: see VulkanDriver::isDepthStencilResolveSupported() to know when to remove this
// restriction.
// Note that the custom shader does not resolve stencil. We do need to move to vk 1.2
// and above to be able to support stencil resolve (along with depth).
!(any(usage & TextureUsage::DEPTH_ATTACHMENT) && samples > 1);
mState->mIsTransientAttachment = useTransientAttachment;
const VkImageUsageFlags transientFlag =
useTransientAttachment ? VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT : 0U;
if (any(usage & TextureUsage::SAMPLEABLE)) {
#if FVK_ENABLED(FVK_DEBUG_TEXTURE)
// Validate that the format is actually sampleable.
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(physicalDevice, mState->mVkFormat, &props);
if (!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
FVK_LOGW << "Texture usage is SAMPLEABLE but format " << mState->mVkFormat << " is not "
"sampleable with optimal tiling." << utils::io::endl;
}
#endif
imageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
}
if (any(usage & TextureUsage::COLOR_ATTACHMENT)) {
imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | transientFlag;
if (any(usage & TextureUsage::SUBPASS_INPUT)) {
imageInfo.usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
}
}
if (any(usage & TextureUsage::STENCIL_ATTACHMENT)) {
imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | transientFlag;
}
if (any(usage & TextureUsage::UPLOADABLE)) {
imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
if (any(usage & TextureUsage::DEPTH_ATTACHMENT)) {
imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | transientFlag;
// Depth resolves uses a custom shader and therefore needs to be sampleable.
if (samples > 1) {
imageInfo.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
}
}
// Constrain the sample count according to the sample count masks in VkPhysicalDeviceProperties.
// Note that VulkanRenderTarget holds a single MSAA count, so we play it safe if this is used as
// any kind of attachment (color or depth).
const auto& limits = context.getPhysicalDeviceLimits();
auto const& limits = context.getPhysicalDeviceLimits();
if (imageInfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
samples = fvkutils::reduceSampleCount(samples,
fvkutils::isVkDepthFormat(mState->mVkFormat)
fvkutils::isVkDepthFormat(vkFormat)
? limits.sampledImageDepthSampleCounts
: limits.sampledImageColorSampleCounts);
}
@@ -319,33 +372,36 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
this->samples = samples;
imageInfo.samples = (VkSampleCountFlagBits) samples;
VkResult result = vkCreateImage(mState->mDevice, &imageInfo, VKALLOC, &mState->mTextureImage);
VkImage textureImage;
VkResult result = vkCreateImage(device, &imageInfo, VKALLOC, &textureImage);
if (result != VK_SUCCESS || FVK_ENABLED(FVK_DEBUG_TEXTURE)) {
FVK_LOGD << "vkCreateImage: "
<< "image = " << mState->mTextureImage << ", "
<< "image = " << textureImage << ", "
<< "result = " << result << ", "
<< "handle = " << utils::io::hex << mState->mTextureImage << utils::io::dec << ", "
<< "handle = " << utils::io::hex << textureImage << utils::io::dec << ", "
<< "extent = " << w << "x" << h << "x"<< depth << ", "
<< "mipLevels = " << int(levels) << ", "
<< "TextureUsage = " << static_cast<int>(usage) << ", "
<< "TextureUsage = " << static_cast<int>(tusage) << ", "
<< "usage = " << imageInfo.usage << ", "
<< "samples = " << imageInfo.samples << ", "
<< "type = " << imageInfo.imageType << ", "
<< "flags = " << imageInfo.flags << ", "
<< "target = " << static_cast<int>(target) <<", "
<< "format = " << mState->mVkFormat << utils::io::endl;
<< "format = " << vkFormat << utils::io::endl;
}
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "Unable to create image."
<< " error=" << static_cast<int32_t>(result);
// Allocate memory for the VkImage and bind it.
VkMemoryRequirements memReqs = {};
vkGetImageMemoryRequirements(mState->mDevice, mState->mTextureImage, &memReqs);
VkMemoryRequirements memReqs;
vkGetImageMemoryRequirements(device, textureImage, &memReqs);
const VkFlags requiredMemoryFlags =
bool const useTransientAttachment = imageInfo.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
VkFlags const requiredMemoryFlags =
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
(useTransientAttachment ? VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT : 0U) |
(mState->mIsProtected ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0U);
(isProtected ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0U);
uint32_t memoryTypeIndex
= context.selectMemoryType(memReqs.memoryTypeBits, requiredMemoryFlags);
@@ -357,21 +413,22 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
.allocationSize = memReqs.size,
.memoryTypeIndex = memoryTypeIndex,
};
result = vkAllocateMemory(mState->mDevice, &allocInfo, nullptr, &mState->mTextureImageMemory);
VkDeviceMemory textureImageMemory;
result = vkAllocateMemory(device, &allocInfo, nullptr, &textureImageMemory);
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "Unable to allocate image memory."
<< " error=" << static_cast<int32_t>(result);
result = vkBindImageMemory(mState->mDevice, mState->mTextureImage, mState->mTextureImageMemory,
0);
result = vkBindImageMemory(device, textureImage, textureImageMemory, 0);
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "Unable to bind image."
<< " error=" << static_cast<int32_t>(result);
mState = fvkmemory::resource_ptr<VulkanTextureState>::construct(resourceManager, stagePool,
commands, allocator, device, textureImage, textureImageMemory, vkFormat,
fvkutils::getViewType(target), levels, getLayerCount(target, depth),
VK_NULL_HANDLE /* ycbcrConversion */, false /*isExternalFormat*/, imageInfo.usage,
isProtected);
// Spec out the "primary" VkImageView that shaders use to sample from the image.
mPrimaryViewRange = mState->mFullViewRange;
// Go ahead and create the primary image view.
getImageView(mPrimaryViewRange, mState->mViewType, mSwizzle);
mState->mDefaultLayout = getDefaultLayoutImpl(imageInfo.usage);
}
// Constructor for creating a texture view
@@ -380,8 +437,8 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
fvkmemory::resource_ptr<VulkanTexture> src, uint8_t baseLevel,
uint8_t levelCount)
: HwTexture(src->target, src->levels, src->samples, src->width, src->height, src->depth,
src->format, src->usage) {
mState = src->mState;
src->format, src->usage),
mState(src->mState) {
mPrimaryViewRange = src->mPrimaryViewRange;
mPrimaryViewRange.baseMipLevel = src->mPrimaryViewRange.baseMipLevel + baseLevel;
mPrimaryViewRange.levelCount = levelCount;
@@ -392,21 +449,10 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
VulkanContext const& context, VmaAllocator allocator, VulkanCommands* commands,
fvkmemory::resource_ptr<VulkanTexture> src, VkComponentMapping swizzle)
: HwTexture(src->target, src->levels, src->samples, src->width, src->height, src->depth,
src->format, src->usage) {
mState = src->mState;
mPrimaryViewRange = src->mPrimaryViewRange;
mSwizzle = composeSwizzle(src->mSwizzle, swizzle);
}
VulkanTextureState::~VulkanTextureState() {
if (mTextureImageMemory != VK_NULL_HANDLE) {
vkDestroyImage(mDevice, mTextureImage, VKALLOC);
vkFreeMemory(mDevice, mTextureImageMemory, VKALLOC);
}
for (auto entry: mCachedImageViews) {
vkDestroyImageView(mDevice, entry.second, VKALLOC);
}
}
src->format, src->usage),
mState(src->mState),
mPrimaryViewRange(src->mPrimaryViewRange),
mSwizzle(composeSwizzle(src->mSwizzle, swizzle)) {}
void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t width, uint32_t height,
uint32_t depth, uint32_t xoffset, uint32_t yoffset, uint32_t zoffset, uint32_t miplevel) {
@@ -513,20 +559,20 @@ void VulkanTexture::updateImageWithBlit(const PixelBufferDescriptor& hostData, u
commands.acquire(fvkmemory::resource_ptr<VulkanTexture>::cast(this));
// TODO: support blit-based format conversion for 3D images and cubemaps.
const int layer = 0;
constexpr int layer = 0;
const VkOffset3D rect[2] { {0, 0, 0}, {int32_t(width), int32_t(height), 1} };
VkOffset3D const rect[2] { {0, 0, 0}, {int32_t(width), int32_t(height), 1} };
const VkImageAspectFlags aspect = getImageAspect();
VkImageAspectFlags const aspect = getImageAspect();
const VkImageBlit blitRegions[1] = {{
VkImageBlit const blitRegions[1] = {{
.srcSubresource = { aspect, 0, 0, 1 },
.srcOffsets = { rect[0], rect[1] },
.dstSubresource = { aspect, uint32_t(miplevel), layer, 1 },
.dstOffsets = { rect[0], rect[1] }
}};
const VkImageSubresourceRange range = { aspect, miplevel, 1, layer, 1 };
VkImageSubresourceRange const range = { aspect, miplevel, 1, layer, 1 };
VulkanLayout const newLayout = VulkanLayout::TRANSFER_DST;
VulkanLayout const oldLayout = getLayout(layer, miplevel);
@@ -542,41 +588,21 @@ VulkanLayout VulkanTexture::getDefaultLayout() const {
return mState->mDefaultLayout;
}
VkImageView VulkanTexture::getAttachmentView(VkImageSubresourceRange range) {
range.levelCount = 1;
range.layerCount = 1;
return getImageView(range, VK_IMAGE_VIEW_TYPE_2D, {});
}
VkImageView VulkanTexture::getMultiviewAttachmentView(VkImageSubresourceRange range) {
return getImageView(range, VK_IMAGE_VIEW_TYPE_2D_ARRAY, {});
}
VkImageView VulkanTexture::getViewForType(VkImageSubresourceRange const& range, VkImageViewType type) {
return getImageView(range, type, mSwizzle);
}
VkImageView VulkanTexture::getImageView(VkImageSubresourceRange range, VkImageViewType viewType,
VkComponentMapping swizzle) {
VulkanTextureState::ImageViewKey const key{ range, viewType, swizzle };
auto iter = mState->mCachedImageViews.find(key);
if (iter != mState->mCachedImageViews.end()) {
return iter->second;
VkImageView VulkanTexture::getAttachmentView(VkImageSubresourceRange const& range, VkImageViewType type) {
assert_invariant(mState->mYcbcr.conversion == VK_NULL_HANDLE &&
"We are not yet supporting external image as attachments.");
if (type == VK_IMAGE_VIEW_TYPE_2D) {
VkImageSubresourceRange copy = range;
copy.levelCount = 1;
copy.layerCount = 1;
return mState->getImageView(copy, type, {});
} else {
return mState->getImageView(range, type, {});
}
VkImageViewCreateInfo viewInfo = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.image = mState->mTextureImage,
.viewType = viewType,
.format = mState->mVkFormat,
.components = swizzle,
.subresourceRange = range,
};
VkImageView imageView;
vkCreateImageView(mState->mDevice, &viewInfo, VKALLOC, &imageView);
mState->mCachedImageViews.emplace(key, imageView);
return imageView;
}
VkImageView VulkanTexture::getView(VkImageSubresourceRange const& range) {
return mState->getImageView(range, mState->mViewType, mSwizzle);
}
VkImageAspectFlags VulkanTexture::getImageAspect() const {
@@ -738,6 +764,21 @@ void VulkanTexture::setLayout(VkImageSubresourceRange const& range, VulkanLayout
}
}
void VulkanTexture::setYcbcrConversion(VkSamplerYcbcrConversion conversion, bool isExternalFormat) {
// Note that this comparison is valid because we only ever create VkSamplerYcbcrConversion from
// a cache. So for each set of parameters, there is exactly one conversion (similar to
// samplers).
VulkanTextureState::Ycbcr ycbcr = {
.conversion = conversion,
.isExternalFormat = isExternalFormat,
};
if (mState->mYcbcr != ycbcr) {
mState->mYcbcr = ycbcr;
mState->clearCachedImageViews();
}
}
VulkanLayout VulkanTexture::getLayout(uint32_t layer, uint32_t level) const {
assert_invariant(level <= 0xffff && layer <= 0xffff);
const uint32_t key = (layer << 16) | level;
+56 -37
View File
@@ -19,7 +19,10 @@
#include "DriverBase.h"
#include "VulkanBuffer.h"
#include "VulkanCommands.h"
#include "VulkanConstants.h"
#include "VulkanMemory.h"
#include "VulkanStagePool.h"
#include "vulkan/memory/Resource.h"
#include "vulkan/memory/ResourcePointer.h"
#include "vulkan/utils/Image.h"
@@ -31,10 +34,14 @@
namespace filament::backend {
struct VulkanTexture;
struct VulkanTextureState : public fvkmemory::Resource {
VulkanTextureState(VkDevice device, VmaAllocator allocator, VulkanCommands* commands,
VulkanStagePool& stagePool, VkFormat format, VkImageViewType viewType, uint8_t levels,
uint8_t layerCount, VulkanLayout defaultLayout, bool isProtected);
VulkanTextureState(VulkanStagePool& stagePool, VulkanCommands* commands, VmaAllocator allocator,
VkDevice device, VkImage image, VkDeviceMemory deviceMemory, VkFormat format,
VkImageViewType viewType, uint8_t levels, uint8_t layerCount,
VkSamplerYcbcrConversion ycbcrConversion, bool isExternalFormat,
VkImageUsageFlags usage, bool isProtected);
~VulkanTextureState();
@@ -57,29 +64,50 @@ struct VulkanTextureState : public fvkmemory::Resource {
// No implicit padding allowed due to it being a hash key.
static_assert(sizeof(ImageViewKey) == 40);
using ImageViewHash = utils::hash::MurmurHashFn<ImageViewKey>;
VkImageView getImageView(VkImageSubresourceRange range, VkImageViewType viewType,
VkComponentMapping swizzle);
private:
void clearCachedImageViews() noexcept;
VulkanStagePool& mStagePool;
VulkanCommands* const mCommands;
VmaAllocator const mAllocator;
VkDevice const mDevice;
// The texture with the sidecar owns the sidecar.
fvkmemory::resource_ptr<VulkanTexture> mSidecarMSAA;
VkDeviceMemory mTextureImageMemory = VK_NULL_HANDLE;
VkImage const mTextureImage;
VkDeviceMemory const mTextureImageMemory;
VkFormat const mVkFormat;
VkImageViewType const mViewType;
VkImageSubresourceRange const mFullViewRange;
VkImage mTextureImage = VK_NULL_HANDLE;
VulkanLayout mDefaultLayout;
bool mIsProtected = false;
// Note that this parameter is not constant due to the fact that AHB can force a change in the
// conversion matrix per-frame.
struct Ycbcr {
VkSamplerYcbcrConversion conversion;
bool isExternalFormat;
bool operator==(Ycbcr const& other) const {
return conversion == other.conversion && isExternalFormat == other.isExternalFormat;
}
bool operator!=(Ycbcr const& other) const {
return !((*this) == other);
}
} mYcbcr;
VulkanLayout const mDefaultLayout;
VkImageUsageFlags const mUsage;
bool const mIsProtected;
// Track the image layout of each subresource using a sparse range map.
utils::RangeMap<uint32_t, VulkanLayout> mSubresourceLayouts;
using ImageViewHash = utils::hash::MurmurHashFn<ImageViewKey>;
std::unordered_map<ImageViewKey, VkImageView, ImageViewHash> mCachedImageViews;
VulkanStagePool& mStagePool;
VkDevice mDevice;
VmaAllocator mAllocator;
VulkanCommands* mCommands;
bool mIsTransientAttachment;
friend struct VulkanTexture;
};
struct VulkanTexture : public HwTexture, fvkmemory::Resource {
@@ -91,10 +119,10 @@ struct VulkanTexture : public HwTexture, fvkmemory::Resource {
VulkanStagePool& stagePool);
// Specialized constructor for internally created textures (e.g. from a swap chain)
// The texture will never destroy the given VkImage, but it does manages its subresources.
VulkanTexture(VkDevice device, VmaAllocator allocator,
VulkanTexture(VulkanContext const& context, VkDevice device, VmaAllocator allocator,
fvkmemory::ResourceManager* resourceManager, VulkanCommands* commands, VkImage image,
VkDeviceMemory memory, VkFormat format, uint8_t samples, uint32_t width, uint32_t height, uint32_t depth,
VkDeviceMemory memory, VkFormat format, VkSamplerYcbcrConversion conversion,
uint8_t samples, uint32_t width, uint32_t height, uint32_t depth,
TextureUsage tusage, VulkanStagePool& stagePool);
// Constructor for creating a texture view for wrt specific mip range
@@ -113,11 +141,6 @@ struct VulkanTexture : public HwTexture, fvkmemory::Resource {
void updateImage(const PixelBufferDescriptor& data, uint32_t width, uint32_t height,
uint32_t depth, uint32_t xoffset, uint32_t yoffset, uint32_t zoffset, uint32_t miplevel);
// Returns the primary image view, which is used for shader sampling.
VkImageView getPrimaryImageView() {
return getImageView(mPrimaryViewRange, mState->mViewType, mSwizzle);
}
VkImageViewType getViewType() const {
return mState->mViewType;
}
@@ -132,20 +155,11 @@ struct VulkanTexture : public HwTexture, fvkmemory::Resource {
// time of the call.
VulkanLayout getDefaultLayout() const;
// Gets or creates a cached VkImageView for a single subresource that can be used as a render
// target attachment. Unlike the primary image view, this always has type VK_IMAGE_VIEW_TYPE_2D
// and the identity swizzle.
VkImageView getAttachmentView(VkImageSubresourceRange range);
// Gets or creates a cached VkImageView for a subresource that can be used as a render
// target attachment. Unlike the primary image view, this always the identity swizzle.
VkImageView getAttachmentView(VkImageSubresourceRange const& range, VkImageViewType type);
// Gets or creates a cached VkImageView for a single subresource that can be used as a render
// target attachment when rendering with multiview.
VkImageView getMultiviewAttachmentView(VkImageSubresourceRange range);
// This is a workaround for the first few frames where we're waiting for the texture to actually
// be uploaded. In that case, we bind the sampler to an empty texture, but the corresponding
// imageView needs to be of the right type. Hence, we provide an option to indicate the
// view type. Swizzle option does not matter in this case.
VkImageView getViewForType(VkImageSubresourceRange const& range, VkImageViewType type);
VkImageView getView(VkImageSubresourceRange const& range);
VkFormat getVkFormat() const {
return mState->mVkFormat;
@@ -165,7 +179,7 @@ struct VulkanTexture : public HwTexture, fvkmemory::Resource {
}
bool isTransientAttachment() const {
return mState->mIsTransientAttachment;
return mState->mUsage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
}
bool getIsProtected() const {
@@ -192,6 +206,11 @@ struct VulkanTexture : public HwTexture, fvkmemory::Resource {
// manually (outside of calls to transitionLayout).
void setLayout(VkImageSubresourceRange const& range, VulkanLayout newLayout);
// This is used in the case of external images and external samplers. AHB might update the
// conversion per-frame. This implies that we need to invalidate the view cache when that
// happens.
void setYcbcrConversion(VkSamplerYcbcrConversion conversion, bool isExternal);
#if FVK_ENABLED(FVK_DEBUG_TEXTURE)
void print() const;
#endif
@@ -0,0 +1,82 @@
/*
* 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 "VulkanYcbcrConversionCache.h"
#include "vulkan/VulkanConstants.h"
#include "vulkan/utils/Conversion.h"
#include <utils/Panic.h>
#if defined(__ANDROID__)
#include <vulkan/vulkan_android.h> // for VkExternalFormatANDROID
#endif
using namespace bluevk;
namespace filament::backend {
VulkanYcbcrConversionCache::VulkanYcbcrConversionCache(VkDevice device)
: mDevice(device) {}
VkSamplerYcbcrConversion VulkanYcbcrConversionCache::getConversion(
VulkanYcbcrConversionCache::Params params) noexcept {
auto iter = mCache.find(params);
if (UTILS_LIKELY(iter != mCache.end())) {
return iter->second;
}
auto const& chroma = params.conversion;
TextureSwizzle const swizzleArray[] = { chroma.r, chroma.g, chroma.b, chroma.a };
VkSamplerYcbcrConversionCreateInfo conversionInfo = {
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
.format = VK_FORMAT_UNDEFINED,
.ycbcrModel = fvkutils::getYcbcrModelConversion(chroma.ycbcrModel),
.ycbcrRange = fvkutils::getYcbcrRange(chroma.ycbcrRange),
.components = fvkutils::getSwizzleMap(swizzleArray),
.xChromaOffset = fvkutils::getChromaLocation(chroma.xChromaOffset),
.yChromaOffset = fvkutils::getChromaLocation(chroma.yChromaOffset),
.chromaFilter = fvkutils::getFilter(chroma.chromaFilter),
};
#if defined(__ANDROID__)
VkExternalFormatANDROID externalFormat = {
.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
.externalFormat = params.externalFormat,
};
if (params.externalFormat) {
conversionInfo.pNext = &externalFormat;
}
#endif
VkSamplerYcbcrConversion conversion;
VkResult result =
vkCreateSamplerYcbcrConversion(mDevice, &conversionInfo, nullptr, &conversion);
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "Unable to create Ycbcr Conversion."
<< " error=" << static_cast<int32_t>(result);
mCache.insert({ params, conversion });
return conversion;
}
void VulkanYcbcrConversionCache::terminate() noexcept {
for (auto& [param, conv]: mCache) {
vkDestroySamplerYcbcrConversion(mDevice, conv, VKALLOC);
}
mCache.clear();
}
} // namespace filament::backend
@@ -0,0 +1,59 @@
/*
* 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_FILAMENT_BACKEND_VULKANYCBCRCONVERSIONCACHE_H
#define TNT_FILAMENT_BACKEND_VULKANYCBCRCONVERSIONCACHE_H
#include <backend/DriverEnums.h>
#include <utils/Hash.h>
#include <bluevk/BlueVK.h>
#include <tsl/robin_map.h>
namespace filament::backend {
// Simple manager for VkSamplerYcbcrConversion objects.
class VulkanYcbcrConversionCache {
public:
struct Params {
SamplerYcbcrConversion conversion = {};
uint32_t padding = 0;
uint64_t externalFormat = 0;
};
static_assert(sizeof(Params) == 16);
explicit VulkanYcbcrConversionCache(VkDevice device);
VkSamplerYcbcrConversion getConversion(Params params) noexcept;
void terminate() noexcept;
private:
VkDevice mDevice;
struct ConversionEqualTo {
bool operator()(Params lhs, Params rhs) const noexcept {
SamplerYcbcrConversion::EqualTo equal;
return equal(lhs.conversion, rhs.conversion) &&
lhs.externalFormat == rhs.externalFormat;
}
};
using ConversionHashFn = utils::hash::MurmurHashFn<Params>;
tsl::robin_map<Params, VkSamplerYcbcrConversion, ConversionHashFn, ConversionEqualTo> mCache;
};
}// namespace filament::backend
#endif// TNT_FILAMENT_BACKEND_VULKANYCBCRCONVERSIONCACHE_H
@@ -295,9 +295,8 @@ VulkanPlatformAndroid::ImageData VulkanPlatformAndroid::createExternalImageData(
VkImageView VulkanPlatform::createExternalImageViewImpl(VkDevice device, SamplerYcbcrConversion chroma,
uint32_t internalFormat, VkImage image, VkImageSubresourceRange range,
VkImageViewType viewType, VkComponentMapping swizzle){
VkExternalFormatANDROID externalFormat = {
VkExternalFormatANDROID externalFormat = {
.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
.pNext = nullptr,
.externalFormat = internalFormat,
};
@@ -322,7 +321,6 @@ VkImageView VulkanPlatform::createExternalImageViewImpl(VkDevice device, Sampler
VkSamplerYcbcrConversionInfo samplerYcbcrConversionInfo = {
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
.pNext = nullptr,
.conversion = conversion,
};
@@ -350,7 +348,6 @@ VkSampler VulkanPlatform::createExternalSamplerImpl(
uint32_t internalFormat) {
VkExternalFormatANDROID externalFormat = {
.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
.pNext = nullptr,
.externalFormat = internalFormat,
};
@@ -18,12 +18,12 @@
#define TNT_FILAMENT_BACKEND_VULKANSWAPCHAIN_IMPL_H
#include "vulkan/VulkanContext.h"
#include "vulkan/VulkanConstants.h"
#include <backend/platforms/VulkanPlatform.h>
#include <bluevk/BlueVK.h>
#include <tuple>
#include <unordered_map>
using namespace bluevk;
+113 -64
View File
@@ -22,6 +22,7 @@
#include "CommandStreamDispatcher.h"
#include "DriverBase.h"
#include "private/backend/Dispatcher.h"
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
@@ -35,6 +36,7 @@
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <sstream>
#include <string_view>
#include <utility>
@@ -116,7 +118,6 @@ void printLimits(wgpu::Limits const& limits) {
printLimit("maxBufferSize", limits.maxBufferSize);
printLimit("maxVertexAttributes", limits.maxVertexAttributes);
printLimit("maxVertexBufferArrayStride", limits.maxVertexBufferArrayStride);
printLimit("maxInterStageShaderComponents", limits.maxInterStageShaderComponents);
printLimit("maxInterStageShaderVariables", limits.maxInterStageShaderVariables);
printLimit("maxColorAttachments", limits.maxColorAttachments);
printLimit("maxColorAttachmentBytesPerSample", limits.maxColorAttachmentBytesPerSample);
@@ -158,8 +159,6 @@ void printAdapterDetails(wgpu::Adapter const& adapter) {
FWGPU_LOGI << " vendor ID: " << adapterInfo.vendorID << utils::io::endl;
FWGPU_LOGI << " subgroup min size: " << adapterInfo.subgroupMinSize << utils::io::endl;
FWGPU_LOGI << " subgroup max size: " << adapterInfo.subgroupMaxSize << utils::io::endl;
FWGPU_LOGI << " compatibility mode: " << bool(adapterInfo.compatibilityMode)
<< utils::io::endl;
FWGPU_LOGI << " power preference: " << powerPreferenceStream.str() << utils::io::endl;
}
wgpu::SupportedFeatures supportedFeatures{};
@@ -175,55 +174,17 @@ void printAdapterDetails(wgpu::Adapter const& adapter) {
FWGPU_LOGI << " " << nameStream.str().data() << utils::io::endl;
});
}
wgpu::SupportedLimits supportedLimits{};
wgpu::Limits supportedLimits{};
if (!adapter.GetLimits(&supportedLimits)) {
FWGPU_LOGW << "Failed to get WebGPU adapter supported limits" << utils::io::endl;
} else {
FWGPU_LOGI << "WebGPU adapter supported limits:" << utils::io::endl;
printLimits(supportedLimits.limits);
printLimits(supportedLimits);
}
}
#endif
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
void printSurfaceCapabilitiesDetails(wgpu::SurfaceCapabilities const& capabilities) {
std::stringstream usages_stream{};
usages_stream << capabilities.usages;
FWGPU_LOGI << "WebGPU surface capabilities:" << utils::io::endl;
FWGPU_LOGI << " surface usages: " << usages_stream.str().data() << utils::io::endl;
FWGPU_LOGI << " surface formats (" << capabilities.formatCount << "):" << utils::io::endl;
if (capabilities.formatCount > 0 && capabilities.formats != nullptr) {
std::for_each(capabilities.formats, capabilities.formats + capabilities.formatCount,
[](wgpu::TextureFormat const format) {
std::stringstream format_stream{};
format_stream << format;
FWGPU_LOGI << " " << format_stream.str().data() << utils::io::endl;
});
}
FWGPU_LOGI << " surface present modes (" << capabilities.presentModeCount
<< "):" << utils::io::endl;
if (capabilities.presentModeCount > 0 && capabilities.presentModes != nullptr) {
std::for_each(capabilities.presentModes,
capabilities.presentModes + capabilities.presentModeCount,
[](wgpu::PresentMode const presentMode) {
std::stringstream present_mode_stream{};
present_mode_stream << presentMode;
FWGPU_LOGI << " " << present_mode_stream.str().data() << utils::io::endl;
});
}
FWGPU_LOGI << " surface alpha modes (" << capabilities.alphaModeCount
<< "):" << utils::io::endl;
if (capabilities.alphaModeCount > 0 && capabilities.alphaModes != nullptr) {
std::for_each(capabilities.alphaModes,
capabilities.alphaModes + capabilities.alphaModeCount,
[](wgpu::CompositeAlphaMode const alphaMode) {
std::stringstream alpha_mode_stream{};
alpha_mode_stream << alphaMode;
FWGPU_LOGI << " " << alpha_mode_stream.str().data() << utils::io::endl;
});
}
}
#endif
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
void printDeviceDetails(wgpu::Device const& device) {
@@ -240,12 +201,12 @@ void printDeviceDetails(wgpu::Device const& device) {
FWGPU_LOGI << " " << nameStream.str().data() << utils::io::endl;
});
}
wgpu::SupportedLimits supportedLimits{};
wgpu::Limits supportedLimits{};
if (!device.GetLimits(&supportedLimits)) {
FWGPU_LOGW << "Failed to get WebGPU supported device limits" << utils::io::endl;
} else {
FWGPU_LOGI << "WebGPU device supported limits:" << utils::io::endl;
printLimits(supportedLimits.limits);
printLimits(supportedLimits);
}
}
#endif
@@ -296,10 +257,14 @@ void WebGPUDriver::terminate() {
}
void WebGPUDriver::tick(int) {
mDevice.Tick();
}
void WebGPUDriver::beginFrame(int64_t monotonic_clock_ns,
int64_t refreshIntervalNs, uint32_t frameId) {
wgpu::CommandEncoderDescriptor commandEncoderDescriptor{};
commandEncoderDescriptor.nextInChain = nullptr;
mCommandEncoder = mDevice.CreateCommandEncoder(&commandEncoderDescriptor);
}
void WebGPUDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch,
@@ -316,6 +281,12 @@ void WebGPUDriver::setPresentationTime(int64_t monotonic_clock_ns) {
}
void WebGPUDriver::endFrame(uint32_t frameId) {
// FWGPU_LOGW << __FUNCTION__<< "\n";
mQueue.Submit(1, &mCommandBuffer);
mCommandEncoder = nullptr;
mCommandBuffer = nullptr;
mTextureView = nullptr;
mSwapChain->Present();
}
void WebGPUDriver::flush(int) {
@@ -349,6 +320,13 @@ void WebGPUDriver::destroyRenderTarget(Handle<HwRenderTarget> rth) {
}
void WebGPUDriver::destroySwapChain(Handle<HwSwapChain> sch) {
mSwapChain = nullptr;
// TODO: use webgpu handle allocator from
// https://github.com/google/filament/pull/8566
// if (sch) {
// HwSwapChain* hwSwapChain = handleCast<HwSwapChain*>(sch);
// destruct(sch, hwSwapChain);
// }
}
void WebGPUDriver::destroyStream(Handle<HwStream> sh) {
@@ -364,6 +342,9 @@ void WebGPUDriver::destroyDescriptorSet(Handle<HwDescriptorSet> tqh) {
}
Handle<HwSwapChain> WebGPUDriver::createSwapChainS() noexcept {
// TODO: use webgpu handle allocator from.
// https://github.com/google/filament/pull/8566
// return allocAndConstructHandle<HwSwapChain>();
return Handle<HwSwapChain>((Handle<HwSwapChain>::HandleId) mNextFakeHandle++);
}
@@ -372,7 +353,7 @@ Handle<HwSwapChain> WebGPUDriver::createSwapChainHeadlessS() noexcept {
}
Handle<HwTexture> WebGPUDriver::createTextureS() noexcept {
return Handle<HwTexture>((Handle<HwTexture>::HandleId) mNextFakeHandle++);
return allocHandle<WGPUTexture>();
}
Handle<HwTexture> WebGPUDriver::importTextureS() noexcept {
@@ -396,19 +377,19 @@ Handle<HwIndexBuffer> WebGPUDriver::createIndexBufferS() noexcept {
}
Handle<HwTexture> WebGPUDriver::createTextureViewS() noexcept {
return Handle<HwTexture>((Handle<HwTexture>::HandleId) mNextFakeHandle++);
return allocHandle<WGPUTexture>();
}
Handle<HwBufferObject> WebGPUDriver::createBufferObjectS() noexcept {
return Handle<HwBufferObject>((Handle<HwBufferObject>::HandleId) mNextFakeHandle++);
return allocHandle<WGPUBufferObject>();
}
Handle<HwRenderTarget> WebGPUDriver::createRenderTargetS() noexcept {
return Handle<HwRenderTarget>((Handle<HwRenderTarget>::HandleId) mNextFakeHandle++);
return allocHandle<WGPURenderTarget>();
}
Handle<HwVertexBuffer> WebGPUDriver::createVertexBufferS() noexcept {
return Handle<HwVertexBuffer>((Handle<HwVertexBuffer>::HandleId) mNextFakeHandle++);
return allocHandle<WGPUVertexBuffer>();
}
Handle<HwDescriptorSet> WebGPUDriver::createDescriptorSetS() noexcept {
@@ -420,15 +401,15 @@ Handle<HwRenderPrimitive> WebGPUDriver::createRenderPrimitiveS() noexcept {
}
Handle<HwVertexBufferInfo> WebGPUDriver::createVertexBufferInfoS() noexcept {
return Handle<HwVertexBufferInfo>((Handle<HwVertexBufferInfo>::HandleId) mNextFakeHandle++);
return allocHandle<WGPUVertexBufferInfo>();
}
Handle<HwTexture> WebGPUDriver::createTextureViewSwizzleS() noexcept {
return Handle<HwTexture>((Handle<HwTexture>::HandleId) mNextFakeHandle++);
return allocHandle<WGPUTexture>();
}
Handle<HwRenderTarget> WebGPUDriver::createDefaultRenderTargetS() noexcept {
return Handle<HwRenderTarget>((Handle<HwRenderTarget>::HandleId) mNextFakeHandle++);
return allocHandle<WGPURenderTarget>();
}
Handle<HwDescriptorSetLayout> WebGPUDriver::createDescriptorSetLayoutS() noexcept {
@@ -449,25 +430,43 @@ Handle<HwTexture> WebGPUDriver::createTextureExternalImagePlaneS() noexcept {
}
void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags) {
mSurface= mPlatform.createSurface(nativeWindow, flags);
mAdapter = mPlatform.requestAdapter(mSurface);
// TODO: use webgpu handle allocator from.
// https://github.com/google/filament/pull/8566
// HwSwapChain* hwSwapChain = handleCast<HwSwapChain*>(sch);
assert_invariant(!mSwapChain);
wgpu::Surface surface = mPlatform.createSurface(nativeWindow, flags);
mAdapter = mPlatform.requestAdapter(surface);
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
printAdapterDetails(mAdapter);
wgpu::SurfaceCapabilities surfaceCapabilities{};
if (!mSurface.GetCapabilities(mAdapter, &surfaceCapabilities)) {
FWGPU_LOGW << "Failed to get WebGPU surface capabilities" << utils::io::endl;
} else {
printSurfaceCapabilitiesDetails(surfaceCapabilities);
}
#endif
mDevice = mPlatform.requestDevice(mAdapter);
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
printDeviceDetails(mDevice);
#endif
mQueue = mDevice.GetQueue();
mSwapChain = std::make_unique<WebGPUSwapChain>(std::move(surface), mAdapter, mDevice, flags);
// TODO configure the surface (maybe before or after creating the swapchain?
// how do we get the surface extent?)
// TODO actually create the swapchain
// auto onQueueWorkDone = [](wgpu::QueueWorkDoneStatus status, void* /* pUserData */) {
// FWGPU_LOGW << "Queued work finished with status: " << status << std::endl;
// };
// mQueue.OnSubmittedWorkDone(wgpu::CallbackMode::WaitAnyOnly, [](wgpu::QueueWorkDoneStatus status, void* pUserdata) {
// FWGPU_LOGW << "Queued work finished with status:\n";
// }, nullptr /* pUserData */);
void* userDataPtr = nullptr;
mQueue.OnSubmittedWorkDone(
wgpu::CallbackMode::AllowProcessEvents,
[](wgpu::QueueWorkDoneStatus status, void* pUserData) {
FWGPU_LOGW << "Queued work finished with status: " << static_cast<int>(status) << "\n";
if (pUserData == nullptr) {
// Expected case
} else {
FWGPU_LOGW << "Unexpected non-null pUserData received.\n";
}
},
userDataPtr /* pUserData */
);
FWGPU_LOGW << "WebGPU support is still essentially a no-op at this point in development (only "
"background components have been instantiated/selected, such as surface/screen, "
"graphics device/GPU, etc.), thus nothing is being drawn to the screen."
@@ -480,6 +479,9 @@ void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
"rebuilding Filament with that flag, e.g. ./build.sh -x "
<< FWGPU_PRINT_SYSTEM << " ..." << utils::io::endl;
#endif
// TODO: use webgpu handle allocator from.
// https://github.com/google/filament/pull/8566
// hwSwapChain->swapChain = mSwapChain.get();
}
void WebGPUDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t width,
@@ -502,7 +504,13 @@ void WebGPUDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
TextureUsage usage) {}
void WebGPUDriver::createTextureViewR(Handle<HwTexture> th, Handle<HwTexture> srch,
uint8_t baseLevel, uint8_t levelCount) {}
uint8_t baseLevel, uint8_t levelCount) {
// FWGPU_LOGW << __FUNCTION__<< "\n";
WGPUTexture const* src = handleCast<WGPUTexture>(srch);
(void) src;
// textures.insert(
// constructHandle<WGPUTexture>(th, src, baseLevel, levelCount));
}
void WebGPUDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
@@ -529,7 +537,11 @@ void WebGPUDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph, Handle<
void WebGPUDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {}
void WebGPUDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int) {}
void WebGPUDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int) {
assert_invariant(!mDefaultRenderTarget);
mDefaultRenderTarget = constructHandle<WGPURenderTarget>(rth);
assert_invariant(mDefaultRenderTarget);
}
void WebGPUDriver::createRenderTargetR(Handle<HwRenderTarget> rth, TargetBufferFlags targets,
uint32_t width, uint32_t height, uint8_t samples, uint8_t layerCount, MRT color,
@@ -690,6 +702,11 @@ void WebGPUDriver::resetBufferObject(Handle<HwBufferObject> boh) {
void WebGPUDriver::setVertexBufferObject(Handle<HwVertexBuffer> vbh, uint32_t index,
Handle<HwBufferObject> boh) {
auto* vertexBuffer = handleCast<WGPUVertexBuffer>(vbh);
auto* bufferObject = handleCast<WGPUBufferObject>(boh);
assert_invariant(index < vertexBuffer->mBuffers.size());
vertexBuffer->setBuffer(bufferObject, index);
}
void WebGPUDriver::update3DImage(Handle<HwTexture> th,
@@ -722,9 +739,33 @@ void WebGPUDriver::compilePrograms(CompilerPriorityQueue priority,
}
void WebGPUDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassParams& params) {
// FWGPU_LOGW << __FUNCTION__<< "\n";
mTextureView = mSwapChain->GetNextSurfaceTextureView(params.viewport.width, params.viewport.height);
wgpu::RenderPassColorAttachment renderPassColorAttachment = {};
renderPassColorAttachment.view = mTextureView;
renderPassColorAttachment.resolveTarget = nullptr;
renderPassColorAttachment.loadOp = wgpu::LoadOp::Clear;
renderPassColorAttachment.storeOp = wgpu::StoreOp::Store;
renderPassColorAttachment.clearValue = wgpu::Color{1, 0 , 0 , 1};
renderPassColorAttachment.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
wgpu::RenderPassDescriptor renderPassDescriptor = {};
renderPassDescriptor.nextInChain = nullptr;
renderPassDescriptor.colorAttachmentCount = 1;
renderPassDescriptor.colorAttachments = &renderPassColorAttachment;
renderPassDescriptor.depthStencilAttachment = nullptr;
renderPassDescriptor.timestampWrites = nullptr;
mRenderPassEncoder = mCommandEncoder.BeginRenderPass(&renderPassDescriptor);
mRenderPassEncoder.SetViewport((float)params.viewport.left, (float)params.viewport.bottom,
(float) params.viewport.width, (float) params.viewport.height, params.depthRange.near, params.depthRange.far);
// (float) 1024/*params.viewport.width*/, (float) 640/*params.viewport.height*/, params.depthRange.near, params.depthRange.far);
}
void WebGPUDriver::endRenderPass(int) {
// FWGPU_LOGW << __FUNCTION__<< "\n";
mRenderPassEncoder.End();
mRenderPassEncoder = nullptr;
}
void WebGPUDriver::nextSubpass(int) {
@@ -734,6 +775,12 @@ void WebGPUDriver::makeCurrent(Handle<HwSwapChain> drawSch, Handle<HwSwapChain>
}
void WebGPUDriver::commit(Handle<HwSwapChain> sch) {
wgpu::CommandBufferDescriptor commandBufferDescriptor = {};
commandBufferDescriptor.nextInChain = nullptr;
mCommandBuffer = mCommandEncoder.Finish(&commandBufferDescriptor);
// mQueue.Submit(1, &mCommandBuffer);
// mCommandBuffer = nullptr;
}
void WebGPUDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
@@ -790,6 +837,8 @@ void WebGPUDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
}
void WebGPUDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t instanceCount) {
// mRenderPassEncoder.DrawIndexed(indexCount, instanceCount, indexOffset, 0, 0);
}
void WebGPUDriver::draw(PipelineState pipelineState, Handle<HwRenderPrimitive> rph,
+20 -3
View File
@@ -17,6 +17,7 @@
#ifndef TNT_FILAMENT_BACKEND_WEBGPUDRIVER_H
#define TNT_FILAMENT_BACKEND_WEBGPUDRIVER_H
#include "webgpu/WebGPUSwapChain.h"
#include <backend/platforms/WebGPUPlatform.h>
#include "DriverBase.h"
@@ -29,7 +30,10 @@
#include <webgpu/webgpu_cpp.h>
#include "WebGPUHandles.h"
#include <cstdint>
#include <memory>
#ifndef FILAMENT_WEBGPU_HANDLE_ARENA_SIZE_IN_MB
# define FILAMENT_WEBGPU_HANDLE_ARENA_SIZE_IN_MB 8
@@ -55,16 +59,20 @@ private:
// the platform (e.g. OS) specific aspects of the WebGPU backend are strictly only
// handled in the WebGPUPlatform
WebGPUPlatform& mPlatform;
wgpu::Surface mSurface = nullptr;
wgpu::Adapter mAdapter = nullptr;
wgpu::Device mDevice = nullptr;
wgpu::Queue mQueue = nullptr;
// TODO consider moving to handle allocator when ready
std::unique_ptr<WebGPUSwapChain> mSwapChain = nullptr;
uint64_t mNextFakeHandle = 1;
wgpu::CommandEncoder mCommandEncoder = nullptr;
wgpu::TextureView mTextureView = nullptr;
wgpu::RenderPassEncoder mRenderPassEncoder = nullptr;
wgpu::CommandBuffer mCommandBuffer = nullptr;
WGPURenderTarget* mDefaultRenderTarget = nullptr;
/*
* Driver interface
*/
template<typename T>
friend class ConcreteDispatcher;
@@ -91,6 +99,15 @@ private:
return mHandleAllocator.allocate<D>();
}
template<typename D, typename B, typename ... ARGS>
D* constructHandle(Handle<B>& handle, ARGS&& ... args) noexcept {
return mHandleAllocator.construct<D>(handle, std::forward<ARGS>(args)...);
}
template<typename D, typename B>
D* handleCast(Handle<B> handle) noexcept {
return mHandleAllocator.handle_cast<D*>(handle);
}
};
}// namespace filament::backend
@@ -0,0 +1,19 @@
//
// Created by Idris Idris Shah on 3/21/25.
//
#include "WebGPUHandles.h"
namespace filament::backend {
WGPUVertexBuffer::WGPUVertexBuffer(uint32_t vextexCount, uint32_t bufferCount,
Handle<WGPUVertexBufferInfo> vbih)
: HwVertexBuffer(vextexCount),
vbih(vbih),
mBuffers(MAX_VERTEX_BUFFER_COUNT) {}
void WGPUVertexBuffer::setBuffer(WGPUBufferObject* bufferObject, uint32_t index) {}
WGPUBufferObject::WGPUBufferObject(BufferObjectBinding bindingType, uint32_t byteCount)
: HwBufferObject(byteCount),
mBindingType(bindingType) {}
}// namespace filament::backend
+109
View File
@@ -0,0 +1,109 @@
//
// Created by Idris Idris Shah on 3/21/25.
//
#ifndef TNT_FILAMENT_BACKEND_WEBGPUHANDLES_H
#define TNT_FILAMENT_BACKEND_WEBGPUHANDLES_H
#include "DriverBase.h"
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <utils/FixedCapacityVector.h>
#include <webgpu/webgpu_cpp.h>
namespace filament::backend {
struct WGPUBufferObject;
struct WGPUVertexBufferInfo : public HwVertexBufferInfo {
WGPUVertexBufferInfo(uint8_t bufferCount, uint8_t attributeCount,
AttributeArray const& attributes)
: HwVertexBufferInfo(bufferCount, attributeCount),
attributes(attributes) {}
AttributeArray attributes;
};
struct WGPUVertexBuffer : public HwVertexBuffer {
WGPUVertexBuffer(uint32_t vextexCount, uint32_t bufferCount, Handle<WGPUVertexBufferInfo> vbih);
void setBuffer(WGPUBufferObject* bufferObject, uint32_t index);
Handle<WGPUVertexBufferInfo> vbih;
utils::FixedCapacityVector<wgpu::Buffer> mBuffers;
};
struct WGPUIndexBuffer : public HwIndexBuffer {
WGPUIndexBuffer(BufferUsage usage, uint8_t elementSize, uint32_t indexCount);
wgpu::Buffer buffer;
};
struct WGPUBufferObject : HwBufferObject {
WGPUBufferObject(BufferObjectBinding bindingType, uint32_t byteCount);
wgpu::Buffer mBuffer;
const BufferObjectBinding mBindingType;
};
class WGPUTexture : public HwTexture {
public:
WGPUTexture(SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples,
uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage) noexcept;
// constructors for creating texture views
WGPUTexture(WGPUTexture const* src, uint8_t baseLevel, uint8_t levelCount) noexcept;
wgpu::Texture texture = nullptr;
};
class WGPURenderTarget : public HwRenderTarget {
public:
class Attachment {
public:
friend class WGPURenderTarget;
Attachment() = default;
Attachment(WGPUTexture* gpuTexture, uint8_t level = 0, uint16_t layer = 0)
: level(level),
layer(layer),
texture(gpuTexture->texture),
mWGPUTexture(gpuTexture) {}
uint8_t level = 0;
uint16_t layer = 0;
private:
wgpu::Texture texture = nullptr;
WGPUTexture* mWGPUTexture = nullptr;
};
WGPURenderTarget(uint32_t width, uint32_t height, uint8_t samples,
Attachment colorAttachments[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT]);
WGPURenderTarget()
: HwRenderTarget(0, 0),
defaultRenderTarget(true) {}
void setUpRenderPassAttachments(wgpu::RenderPassDescriptor* descriptor,
const RenderPassParams& params);
math::uint2 getAttachmentSize() noexcept;
bool isDefaultRenderTarget() const { return defaultRenderTarget; }
uint8_t getSamples() const { return samples; }
Attachment getDrawColorAttachment(size_t index);
Attachment getReadColorAttachment(size_t index);
private:
static wgpu::LoadOp getLoadAction(const RenderPassParams& params, TargetBufferFlags buffer);
static wgpu::LoadOp getStoreAction(const RenderPassParams& params, TargetBufferFlags buffer);
bool defaultRenderTarget = false;
uint8_t samples = 1;
Attachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT] = {};
math::uint2 attachmentSize = {};
};
}// namespace filament::backend
#endif// TNT_FILAMENT_BACKEND_WEBGPUHANDLES_H
@@ -0,0 +1,277 @@
/*
* 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 "webgpu/WebGPUSwapChain.h"
#include "webgpu/WebGPUConstants.h"
#include "backend/DriverEnums.h"
#include <utils/Panic.h>
#include <utils/ostream.h>
#include <dawn/webgpu_cpp_print.h>
#include <webgpu/webgpu_cpp.h>
#include <algorithm>
#include <cstdint>
#include <sstream>
namespace {
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
void printSurfaceCapabilitiesDetails(wgpu::SurfaceCapabilities const& capabilities) {
std::stringstream usagesStream{};
usagesStream << capabilities.usages;
FWGPU_LOGI << "WebGPU surface capabilities:" << utils::io::endl;
FWGPU_LOGI << " surface usages: " << usagesStream.str().data() << utils::io::endl;
FWGPU_LOGI << " surface formats (" << capabilities.formatCount << "):" << utils::io::endl;
if (capabilities.formatCount > 0 && capabilities.formats != nullptr) {
std::for_each(capabilities.formats, capabilities.formats + capabilities.formatCount,
[](wgpu::TextureFormat const format) {
std::stringstream formatStream{};
formatStream << format;
FWGPU_LOGI << " " << formatStream.str().data() << utils::io::endl;
});
}
FWGPU_LOGI << " surface present modes (" << capabilities.presentModeCount
<< "):" << utils::io::endl;
if (capabilities.presentModeCount > 0 && capabilities.presentModes != nullptr) {
std::for_each(capabilities.presentModes,
capabilities.presentModes + capabilities.presentModeCount,
[](wgpu::PresentMode const presentMode) {
std::stringstream presentModeStream{};
presentModeStream << presentMode;
FWGPU_LOGI << " " << presentModeStream.str().data() << utils::io::endl;
});
}
FWGPU_LOGI << " surface alpha modes (" << capabilities.alphaModeCount
<< "):" << utils::io::endl;
if (capabilities.alphaModeCount > 0 && capabilities.alphaModes != nullptr) {
std::for_each(capabilities.alphaModes,
capabilities.alphaModes + capabilities.alphaModeCount,
[](wgpu::CompositeAlphaMode const alphaMode) {
std::stringstream alphaModeStream{};
alphaModeStream << alphaMode;
FWGPU_LOGI << " " << alphaModeStream.str().data() << utils::io::endl;
});
}
}
#endif
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
void printSurfaceConfiguration(wgpu::SurfaceConfiguration const& config) {
std::stringstream formatStream{};
formatStream << config.format;
std::stringstream usageStream{};
usageStream << config.usage;
std::stringstream alphaModeStream{};
alphaModeStream << config.alphaMode;
std::stringstream presentModeStream{};
presentModeStream << config.presentMode;
FWGPU_LOGI << "WebGPU surface configuration:" << utils::io::endl;
FWGPU_LOGI << " surface format: " << formatStream.str() << utils::io::endl;
FWGPU_LOGI << " surface usage: " << usageStream.str() << utils::io::endl;
FWGPU_LOGI << " surface view formats (" << config.viewFormatCount << "):" << utils::io::endl;
if (config.viewFormatCount > 0 && config.viewFormats != nullptr) {
std::for_each(config.viewFormats, config.viewFormats + config.viewFormatCount,
[](wgpu::TextureFormat const viewFormat) {
std::stringstream viewFormatStream{};
viewFormatStream << viewFormat;
FWGPU_LOGI << " " << viewFormatStream.str().data() << utils::io::endl;
});
}
FWGPU_LOGI << " surface alpha mode: " << alphaModeStream.str() << utils::io::endl;
FWGPU_LOGI << " surface width: " << config.width << utils::io::endl;
FWGPU_LOGI << " surface height: " << config.height << utils::io::endl;
FWGPU_LOGI << " surface present mode: " << presentModeStream.str() << utils::io::endl;
}
#endif
wgpu::TextureFormat selectColorFormat(size_t availableFormatsCount,
wgpu::TextureFormat const* availableFormats, bool useSRGBColorSpace) {
const std::array expectedColorFormats =
useSRGBColorSpace ?
std::array{
wgpu::TextureFormat::RGBA8UnormSrgb,
wgpu::TextureFormat::BGRA8UnormSrgb }
: std::array{
wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureFormat::BGRA8Unorm };
auto const firstFoundColorFormat = std::find_first_of(expectedColorFormats.begin(),
expectedColorFormats.end(), availableFormats, availableFormats + availableFormatsCount);
FILAMENT_CHECK_POSTCONDITION(firstFoundColorFormat != expectedColorFormats.end())
<< "Cannot find a suitable WebGPU swapchain "
<< (useSRGBColorSpace ? "sRGB" : "non-standard (e.g. linear) RGB") << " color format";
return *firstFoundColorFormat;
}
wgpu::PresentMode selectPresentMode(size_t availablePresentModesCount,
wgpu::PresentMode const* availablePresentModes) {
// Verify that our chosen present mode is supported. In practice all devices support the FIFO
// mode, but we check for it anyway for completeness. (and to avoid validation warnings)
const wgpu::PresentMode desiredPresentMode = wgpu::PresentMode::Fifo;
FILAMENT_CHECK_POSTCONDITION(
std::any_of(availablePresentModes, availablePresentModes + availablePresentModesCount,
[](const wgpu::PresentMode availablePresentMode) {
return availablePresentMode == desiredPresentMode;
}))
<< "Cannot find a suitable WebGPU swapchain present mode";
return desiredPresentMode;
}
wgpu::CompositeAlphaMode selectAlphaMode(size_t availableAlphaModesCount,
wgpu::CompositeAlphaMode const* availableAlphaModes) {
bool autoAvailable = false;
bool inheritAvailable = false;
bool opaqueAvailable = false;
bool premultipliedAvailable = false;
bool unpremultipliedAvailable = false;
std::for_each(availableAlphaModes, availableAlphaModes + availableAlphaModesCount,
[&](const wgpu::CompositeAlphaMode alphMode) {
switch (alphMode) {
// in practice, the surface capabilities would not list Auto,
// but for completeness and defensive programming we can leverage it
// if it explicitly comes back as available/supported
case wgpu::CompositeAlphaMode::Auto:
autoAvailable = true;
break;
case wgpu::CompositeAlphaMode::Opaque:
opaqueAvailable = true;
break;
case wgpu::CompositeAlphaMode::Premultiplied:
premultipliedAvailable = true;
break;
case wgpu::CompositeAlphaMode::Unpremultiplied:
unpremultipliedAvailable = true;
break;
case wgpu::CompositeAlphaMode::Inherit:
inheritAvailable = true;
break;
}
});
if (autoAvailable || inheritAvailable || opaqueAvailable) {
return wgpu::CompositeAlphaMode::Auto;
} else if (premultipliedAvailable) {
// In practice, we do not expect this to possibly happen, as opaque should be supported,
// which we select first. However, if the underlying system actually does not support
// opaque we allow it to be tested, but warn that this may not likely work as they expect
// (untested territory).
// We prefer premultiplied to unpremuliplied until that assumption should be adjusted.
FWGPU_LOGW << "Auto, Inherit, & Opaque composite alpha modes not supported. Filament has "
"historically used these. Premultiplied alpha composite mode for "
"transparency is being selected as a fallback, but may not work as expected."
<< utils::io::endl;
return wgpu::CompositeAlphaMode::Premultiplied;
} else {
FILAMENT_CHECK_POSTCONDITION(unpremultipliedAvailable)
<< "No available composite alpha modes? Unknown/unhandled composite alpha mode?";
// Again, we don't expect this in practice, but allow if for the same reason as premultiplied.
// We prefer premultiplied to unpremuliplied until that assumption should be adjusted.
FWGPU_LOGW << "Auto, Inherit, & Opaque composite alpha modes not supported. Filament has "
"historically used these. Unpremultiplied alpha composite mode for "
"transparency is being selected as a fallback "
"(premulitipled is not available either), but may not work as expected."
<< utils::io::endl;
return wgpu::CompositeAlphaMode::Unpremultiplied;
}
}
void initConfig(wgpu::SurfaceConfiguration& config, wgpu::Device& device,
wgpu::SurfaceCapabilities const& capabilities, bool useSRGBColorSpace) {
config.device = device;
config.usage = wgpu::TextureUsage::RenderAttachment;
config.format =
selectColorFormat(capabilities.formatCount, capabilities.formats, useSRGBColorSpace);
config.presentMode =
selectPresentMode(capabilities.presentModeCount, capabilities.presentModes);
config.alphaMode = selectAlphaMode(capabilities.alphaModeCount, capabilities.alphaModes);
}
}// namespace
namespace filament::backend {
WebGPUSwapChain::WebGPUSwapChain(wgpu::Surface&& surface, wgpu::Adapter& adapter,
wgpu::Device& device, uint64_t flags)
: mSurface(surface) {
wgpu::SurfaceCapabilities capabilities = {};
if (!mSurface.GetCapabilities(adapter, &capabilities)) {
FWGPU_LOGW << "Failed to get WebGPU surface capabilities" << utils::io::endl;
} else {
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
printSurfaceCapabilitiesDetails(capabilities);
#endif
}
const bool useSRGBColorSpace = (flags & SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0;
initConfig(mConfig, device, capabilities, useSRGBColorSpace);
}
WebGPUSwapChain::~WebGPUSwapChain() {
if (mConfigured) {
mSurface.Unconfigure();
mConfigured = false;
}
}
void WebGPUSwapChain::GetCurrentTexture(uint32_t width, uint32_t height, wgpu::SurfaceTexture* texture) {
if (width < 1 || height < 1) {
PANIC_LOG("WebGPUSwapChain::GetCurrentTexture: Invalid width and/or height requested.");
return;
}
if (mConfig.width != width || mConfig.height != height || !mConfigured) {
mConfig.width = width;
mConfig.height = height;
#if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM)
printSurfaceConfiguration(mConfig);
#endif
mSurface.Configure(&mConfig);
mConfigured = true;
return;
}
mSurface.GetCurrentTexture(texture);
}
wgpu::TextureView WebGPUSwapChain::GetNextSurfaceTextureView(uint32_t width, uint32_t height) {
wgpu::SurfaceTexture surfaceTexture;
GetCurrentTexture(width, height, &surfaceTexture);
if (surfaceTexture.status != wgpu::SurfaceGetCurrentTextureStatus::Success) {
return nullptr;
}
// Create a view for this surface texture
wgpu::TextureViewDescriptor textureViewDescriptor;
textureViewDescriptor.nextInChain = nullptr;
textureViewDescriptor.label = "Surface texture view";
textureViewDescriptor.format = surfaceTexture.texture.GetFormat();
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2D;
textureViewDescriptor.baseMipLevel = 0;
textureViewDescriptor.mipLevelCount = 1;
textureViewDescriptor.baseArrayLayer = 0;
textureViewDescriptor.arrayLayerCount = 1;
textureViewDescriptor.aspect = wgpu::TextureAspect::All;
wgpu::TextureView textureView = surfaceTexture.texture.CreateView(&textureViewDescriptor);
return textureView;
}
void WebGPUSwapChain::Present() {
assert_invariant(mSurface);
mSurface.Present();
}
}// namespace filament::backend
@@ -0,0 +1,46 @@
/*
* 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_FILAMENT_BACKEND_WEBGPUSWAPCHAIN_H
#define TNT_FILAMENT_BACKEND_WEBGPUSWAPCHAIN_H
#include <webgpu/webgpu_cpp.h>
#include <backend/Platform.h>
#include <cstdint>
namespace filament::backend {
class WebGPUSwapChain : public Platform::SwapChain {
public:
WebGPUSwapChain(wgpu::Surface&& surface, wgpu::Adapter& adapter, wgpu::Device& device,
uint64_t flags);
~WebGPUSwapChain();
void GetCurrentTexture(uint32_t width, uint32_t height, wgpu::SurfaceTexture*);
wgpu::TextureView GetNextSurfaceTextureView(uint32_t width, uint32_t height);
void Present();
private:
wgpu::Surface mSurface = {};
wgpu::SurfaceConfiguration mConfig = {};
bool mConfigured = false;
};
} // namespace filament::backend
#endif //TNT_FILAMENT_BACKEND_WEBGPUSWAPCHAIN_H
@@ -22,6 +22,8 @@
#include <cstdint>
#include <Windows.h>
/**
* Windows OS specific implementation aspects of the WebGPU backend
*/
@@ -41,12 +43,12 @@ wgpu::Surface WebGPUPlatform::createSurface(void* nativeWindow, uint64_t /*flags
wgpu::SurfaceSourceWindowsHWND surfaceSourceWin{};
surfaceSourceWin.hinstance = GetModuleHandle(nullptr);
surfaceSourceWin.hwnd = nativeWindow;
wgpu::SurfaceDescriptor surfaceDescriptor{
const wgpu::SurfaceDescriptor surfaceDescriptor{
.nextInChain = &surfaceSourceWin,
.label = "windows_surface"
};
wgpu::Surface surface = mInstance.CreateSurface(&surfaceDescriptor);
FILAMENT_CHECK_POSTCONDITION(surface != nullptr) << "Unable to create Windows-backed surface.";
FILAMENT_CHECK_POSTCONDITION(surface.Get() != nullptr) << "Unable to create Windows-backed surface.";
return surface;
}
+11
View File
@@ -791,6 +791,17 @@ int FEngine::loop() {
}
}
#if FILAMENT_ENABLE_MATDBG
if(debug.server) {
delete debug.server;
}
#endif
#if FILAMENT_ENABLE_FGVIEWER
if(debug.fgviewerServer) {
delete debug.fgviewerServer;
}
#endif
// terminate() is a synchronous API
getDriverApi().terminate();
return 0;
+46 -27
View File
@@ -1364,6 +1364,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
xvp.left = xvp.bottom = 0;
svp = xvp;
}
if (scaled) {
mightNeedFinalBlit = false;
auto viewport = DEBUG_DYNAMIC_SCALING ? xvp : vp;
@@ -1385,34 +1386,59 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
SamplerMagFilter::NEAREST, SamplerMinFilter::NEAREST);
}
// We need to do special processing when rendering directly into the swap-chain, that is when
// the viewRenderTarget is the default render target (mRenderTarget) and we're rendering into
// it.
// * This is because the default render target is not multi-sampled, so we need an
// intermediate buffer when MSAA is enabled.
// * We also need an extra buffer for blending the result to the framebuffer if the view
// is translucent AND we've not already done it as part of upscaling.
// * And we can't use the default rendertarget if MRT is required (e.g. with color grading
// as a subpass)
// * And we also can't use the default rendertarget if frame history is needed (e.g. with
// screen-space reflections)
// * And we also can't use the default rendertarget with refractions, which need to reuse
// the rendertarget due to how the clear flags work.
// * We also need an extra blit if we haven't yet handled "xvp"
// TODO: in that specific scenario it would be better to just not use xvp
// The intermediate buffer is accomplished with a "fake" opaqueBlit (i.e. blit) operation.
if (UTILS_UNLIKELY((input == postProcessInput && viewRenderTarget == mRenderTargetHandle) &&
view.isStencilBufferEnabled())) {
// FIXME: I think this check is incomplete, if we're rendering into a custom rendertarget
// we need to check that it (not the swapchain) has a stencil buffer.
assert_invariant(mSwapChain);
FILAMENT_CHECK_PRECONDITION(mSwapChain->hasStencilBuffer())
<< "View has stencil buffer enabled, but SwapChain does not have "
"SwapChain::CONFIG_HAS_STENCIL_BUFFER flag set.";
}
/*
* Here we're ready to present the output of the framegraph, which is held in `input`.
* The presentation itself happens by forwarding `input` to the render target, which can
* either be the SwapChain's or the View's custom render target. This is done below with
* `forwardResource()`.
*
* There are however a few situations where `input` cannot be forwarded in this manner, and
* an intermediate buffer is needed instead.
*
* 1. Blending is needed (blendModeTranslucent)
* 2. Dimensions don't match, e.g.: because we have guard bands (xvp != svp)
* 3. MRT is needed (colorGradingConfig.asSubpass)
* 4. Frame history is needed (hasScreenSpaceRefraction)
* 5. Refraction is used because how clear flags work (ssReflectionsOptions.enabled)
* 6. `input` and the render target are not compatible:
* - MSAA doesn't match. Note: auto-resolve could work if the SwapChain was configured
* this way.
*
* One complication is that post-processing passes handle some of these issues automatically:
* - each post-processing pass will create an intermediate buffer, which takes care of
* - MSAA (because of auto-resolve)
* - MRT is needed
* - Frame history is needed
* - Refraction
* - the upscaling pass takes care of all the above plus blending and dimensions mismatch.
*
* TODO: we could make this work with custom render targets because we can access the texture
* for those and it could behave just like a regular resource. This would lift
* some (but not all) of those limitations. For instance we could use MRTs.
*/
const bool outputIsSwapChain =
(input == postProcessInput) && (viewRenderTarget == mRenderTargetHandle);
if (mightNeedFinalBlit) {
assert_invariant(!scaled);
// Determine if our `input` is in fact the output of the color pass, in which case
// many of the caveat above apply.
bool const inputIsColorPass = (input == postProcessInput);
if (blendModeTranslucent ||
xvp != svp ||
(outputIsSwapChain &&
(inputIsColorPass &&
(msaaSampleCount > 1 ||
colorGradingConfig.asSubpass ||
hasScreenSpaceRefraction ||
ssReflectionsOptions.enabled))) {
assert_invariant(!scaled);
input = ppm.blit(fg, blendModeTranslucent, input, xvp, {
.width = vp.width, .height = vp.height,
.format = colorGradingConfig.ldrFormat },
@@ -1420,13 +1446,6 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
}
}
if (UTILS_UNLIKELY(outputIsSwapChain && view.isStencilBufferEnabled())) {
assert_invariant(mSwapChain);
FILAMENT_CHECK_PRECONDITION(mSwapChain->hasStencilBuffer())
<< "View has stencil buffer enabled, but SwapChain does not have "
"SwapChain::CONFIG_HAS_STENCIL_BUFFER flag set.";
}
if (UTILS_UNLIKELY(engine.debug.shadowmap.display_shadow_texture)) {
auto shadowmap = blackboard.get<FrameGraphTexture>("shadowmap");
input = ppm.debugDisplayShadowTexture(fg, input, shadowmap,
+5
View File
@@ -88,7 +88,12 @@ void minLeftMaxRight(inout vec4 a, inout vec4 b, inout vec4 c, inout vec4 d, ino
// - we can't use a function because offset must be a constant expression
// - we can't use line continuation because that's not supported on desktop
#ifdef TARGET_WEBGPU_ENVIRONMENT
//WebGPU can not handle texelFetchOffset without an error about "ConstOffset is only permitted...".
#define makeSample(ij, o) vec4(texelFetch(materialParams_dof, ij+o, 0).rgb, texelFetch(materialParams_alpha, ij+o, 0).r)
#else
#define makeSample(ij, o) vec4(texelFetchOffset(materialParams_dof, ij, 0, o).rgb, texelFetchOffset(materialParams_alpha, ij, 0, o).r)
#endif
vec4 median(ivec2 ij) {
vec4 v[9];
+2 -2
View File
@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
spec.version = "1.59.1"
spec.version = "1.59.0"
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
spec.homepage = "https://google.github.io/filament"
spec.authors = "Google LLC."
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
spec.platform = :ios, "11.0"
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.59.1/filament-v1.59.1-ios.tgz" }
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.59.0/filament-v1.59.0-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = {
+95 -21
View File
@@ -518,28 +518,89 @@ void GLSLPostProcessor::spirvToMsl(const SpirvBlob* spirv, std::string* outMsl,
}
}
void GLSLPostProcessor::rebindImageSamplerForWGSL(std::vector<uint32_t> &spirv) {
constexpr size_t HEADER_SIZE = 5;
size_t const dataSize = spirv.size();
uint32_t *data = spirv.data();
std::set<uint32_t> samplerTargetIDs;
auto pass = [&](uint32_t targetOp, std::function<void(uint32_t)> f) {
for (uint32_t cursor = HEADER_SIZE, cursorEnd = dataSize; cursor < cursorEnd;) {
uint32_t const firstWord = data[cursor];
uint32_t const wordCount = firstWord >> 16;
uint32_t const op = firstWord & 0x0000FFFF;
if (targetOp == op) {
f(cursor + 1);
}
cursor += wordCount;
}
};
//Parse through debug name info to determine which bindings are samplers and which are not.
// This is possible because the sampler splitting pass outputs sampler and texture pairs of the form:
// `uniform sampler2D var_x` => `uniform sampler var_sampler` and `uniform texture2D var_texture`;
// TODO: This works, but may limit what optimizations can be done and has the potential to collide with user
// variable names. Ideally, trace usage to determine binding type.
pass(spv::Op::OpName, [&](uint32_t pos) {
auto target = data[pos];
char *name = (char *) &data[pos + 1];
std::string_view view(name);
if (view.find("_sampler") != std::string_view::npos) {
samplerTargetIDs.insert(target);
}
});
// Write out the offset bindings
pass(spv::Op::OpDecorate, [&](uint32_t pos) {
uint32_t const type = data[pos + 1];
if (type == spv::Decoration::DecorationBinding) {
uint32_t const targetVar = data[pos];
if (samplerTargetIDs.find(targetVar) != samplerTargetIDs.end()) {
data[pos + 2] = data[pos + 2] * 2 + 1;
} else {
data[pos + 2] = data[pos + 2] * 2;
}
}
});
}
bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
#if FILAMENT_SUPPORTS_WEBGPU
// We need to remove dead code for our variant-filter workaround for WebGPU to work
// This is especially relevant for removing the push constants that morphing uses when not disabled
spv::spirvbin_t remapper(0);
remapper.remap(*spirv, spv::spirvbin_base_t::DCE_ALL);
//We need to run some opt-passes at all times to transpile to WGSL
auto optimizer = createEmptyOptimizer();
optimizer->RegisterPass(CreateSplitCombinedImageSamplerPass());
optimizeSpirv(optimizer, *spirv);
//Currently no options we want to use
const tint::spirv::reader::Options readerOpts{};
//After splitting the image samplers, we need to remap the bindings to separate them.
rebindImageSamplerForWGSL(*spirv);
//Allow non-uniform derivitives due to our nested shaders. See https://github.com/gpuweb/gpuweb/issues/3479
const tint::spirv::reader::Options readerOpts{true};
tint::wgsl::writer::Options writerOpts{};
tint::Program tintRead = tint::spirv::reader::Read(*spirv, readerOpts);
if (tintRead.Diagnostics().ContainsErrors()) {
//TODO remove this if block once combined image sampler conversion works.
if (tintRead.Diagnostics().Str().rfind("error: WGSL does not support combined image-samplers") != std::string::npos) {
slog.w << "This tint reader error is currently ignored during WebGPU bringup: " << tintRead.Diagnostics().Str() << io::endl;
}
else {
slog.e << "Tint Reader Error: " << tintRead.Diagnostics().Str() << io::endl;
return false;
}
//We know errors can potentially crop up, and want the ability to ignore them if needed for sample bringup
#ifndef FILAMENT_WEBGPU_IGNORE_TNT_READ_ERRORS
slog.e << "Tint Reader Error: " << tintRead.Diagnostics().Str() << io::endl;
spv_context context = spvContextCreate(SPV_ENV_VULKAN_1_1_SPIRV_1_4);
spv_text text = nullptr;
spv_diagnostic diagnostic = nullptr;
spv_result_t result = spvBinaryToText(
context,
spirv->data(),
spirv->size(),
SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_COLOR,
&text,
&diagnostic);
slog.e << "Beginning SpirV-output dump with ret " << result << "\n\n" << text->str << "\n\nEndSPIRV\n" <<
io::endl;
spvTextDestroy(text);
slog.e << "Tint Reader Error: " << tintRead.Diagnostics().Str() << io::endl;
return false;
#endif
}
tint::Result<tint::wgsl::writer::Output> wgslOut = tint::wgsl::writer::Generate(tintRead,writerOpts);
@@ -547,7 +608,7 @@ bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
tint::SuccessType tintSuccess;
if (wgslOut != tintSuccess) {
slog.e << "Tint writer error: " << wgslOut.Failure().reason.Str() << io::endl;
slog.e << "Tint writer error: " << wgslOut.Failure().reason << io::endl;
return false;
}
*outWsl = wgslOut->wgsl;
@@ -887,10 +948,8 @@ bool GLSLPostProcessor::fullOptimization(const TShader& tShader,
return true;
}
std::shared_ptr<spvtools::Optimizer> GLSLPostProcessor::createOptimizer(
MaterialBuilder::Optimization optimization, Config const& config) {
std::shared_ptr<spvtools::Optimizer> GLSLPostProcessor::createEmptyOptimizer() {
auto optimizer = std::make_shared<spvtools::Optimizer>(SPV_ENV_UNIVERSAL_1_3);
optimizer->SetMessageConsumer([](spv_message_level_t level,
const char* source, const spv_position_t& position, const char* message) {
if (!filterSpvOptimizerMessage(level)) {
@@ -899,6 +958,12 @@ std::shared_ptr<spvtools::Optimizer> GLSLPostProcessor::createOptimizer(
slog.e << stringifySpvOptimizerMessage(level, source, position, message)
<< io::endl;
});
return optimizer;
}
std::shared_ptr<spvtools::Optimizer> GLSLPostProcessor::createOptimizer(
MaterialBuilder::Optimization optimization, Config const& config) {
auto optimizer = createEmptyOptimizer();
if (optimization == MaterialBuilder::Optimization::SIZE) {
// When optimizing for size, we don't run the SPIR-V through any size optimization passes
@@ -923,7 +988,7 @@ std::shared_ptr<spvtools::Optimizer> GLSLPostProcessor::createOptimizer(
return optimizer;
}
void GLSLPostProcessor::optimizeSpirv(OptimizerPtr optimizer, SpirvBlob& spirv) const {
void GLSLPostProcessor::optimizeSpirv(OptimizerPtr optimizer, SpirvBlob& spirv) {
if (!optimizer->Run(spirv.data(), spirv.size(), &spirv)) {
slog.e << "SPIR-V optimizer pass failed" << io::endl;
return;
@@ -955,6 +1020,9 @@ void GLSLPostProcessor::fixupClipDistance(
// - triggers a segfault with AMD OpenGL drivers on macOS
// - triggers a crash on some Adreno drivers (b/291140208, b/289401984, b/289393290)
// However Metal requires this pass in order to correctly generate half-precision MSL
// CreateMergeReturnPass() also creates issues with Tint conversion related to the
// bitwise "<<" Operator used in shaders/src/surface_light_directional.fs against
// a signed integer.
//
// CreateSimplificationPass() creates a lot of problems:
// - Adreno GPU show artifacts after running simplification passes (Vulkan)
@@ -965,6 +1033,11 @@ void GLSLPostProcessor::fixupClipDistance(
// However, the simplification passes below are necessary when targeting Metal, otherwise the
// result is mismatched half / float assignments in MSL.
// CreateInlineExhaustivePass() expects CreateMergeReturnPass() to be run beforehand
// (Throwing many warnings if this is not the case), but we don't consistently do so for the above
// reasons. While running it alone may have some value, we will disable it for the new WebGPU backend
// while minimizing other changes.
void GLSLPostProcessor::registerPerformancePasses(Optimizer& optimizer, Config const& config) {
auto RegisterPass = [&](spvtools::Optimizer::PassToken&& pass,
@@ -978,7 +1051,7 @@ void GLSLPostProcessor::registerPerformancePasses(Optimizer& optimizer, Config c
RegisterPass(CreateWrapOpKillPass());
RegisterPass(CreateDeadBranchElimPass());
RegisterPass(CreateMergeReturnPass(), MaterialBuilder::TargetApi::METAL);
RegisterPass(CreateInlineExhaustivePass());
RegisterPass(CreateInlineExhaustivePass(), MaterialBuilder::TargetApi::ALL & ~MaterialBuilder::TargetApi::WEBGPU);
RegisterPass(CreateAggressiveDCEPass());
RegisterPass(CreatePrivateToLocalPass());
RegisterPass(CreateLocalSingleBlockLoadStoreElimPass());
@@ -1022,7 +1095,8 @@ void GLSLPostProcessor::registerSizePasses(Optimizer& optimizer, Config const& c
RegisterPass(CreateWrapOpKillPass());
RegisterPass(CreateDeadBranchElimPass());
RegisterPass(CreateInlineExhaustivePass());
// Disable for WebGPU, see comment above registerPerformancePasses()
RegisterPass(CreateInlineExhaustivePass(), MaterialBuilder::TargetApi::ALL & ~MaterialBuilder::TargetApi::WEBGPU);
RegisterPass(CreateEliminateDeadFunctionsPass());
RegisterPass(CreatePrivateToLocalPass());
RegisterPass(CreateScalarReplacementPass(0));
+7 -1
View File
@@ -114,14 +114,20 @@ private:
* Retrieve an optimizer instance tuned for the given optimization level and shader configuration.
*/
using OptimizerPtr = std::shared_ptr<spvtools::Optimizer>;
static OptimizerPtr createOptimizer(
MaterialBuilder::Optimization optimization,
Config const& config);
static OptimizerPtr createEmptyOptimizer();
static void registerSizePasses(spvtools::Optimizer& optimizer, Config const& config);
static void registerPerformancePasses(spvtools::Optimizer& optimizer, Config const& config);
void optimizeSpirv(OptimizerPtr optimizer, SpirvBlob& spirv) const;
static void optimizeSpirv(OptimizerPtr optimizer, SpirvBlob &spirv);
static void rebindImageSamplerForWGSL(std::vector<uint32_t>& spirv);
void fixupClipDistance(SpirvBlob& spirv, GLSLPostProcessor::Config const& config) const;
@@ -937,6 +937,15 @@ utils::io::sstream& CodeGenerator::generateSpecializationConstant(utils::io::sst
std::string const constantString = std::visit(SpecializationConstantFormatter(), value);
static const char* types[] = { "int", "float", "bool" };
// Spec constants aren't fully supported in Tint,
// workaround until https://issues.chromium.org/issues/42250586 is resolved
if (mTargetApi == TargetApi::WEBGPU) {
out << "layout (constant_id = " << id << ") const "
<< types[value.index()] << " " << name << "_hack = " << constantString << ";\n"
<< types[value.index()] << " " << name << " = " << name << "_hack;\n";
return out;
}
if (mTargetLanguage == MaterialBuilderBase::TargetLanguage::SPIRV) {
out << "layout (constant_id = " << id << ") const "
<< types[value.index()] << " " << name << " = " << constantString << ";\n";
+2
View File
@@ -17,6 +17,8 @@
#ifndef TNT_UTILS_STATICSTRING_H
#define TNT_UTILS_STATICSTRING_H
#include <utils/compiler.h>
#include <type_traits>
#include <string_view>
+17
View File
@@ -0,0 +1,17 @@
# Bzlmod lockfile
MODULE.bazel.lock
# Ignore all bazel-* symlinks.
/bazel-*
# Ignore Bazel verbose explanations
--verbose_explanations
# Ignore CMake usual build directory
build
# Ignore Vim files
*.swp
# Ignore QtCreator Project file
CMakeLists.txt.user
# Ignore VS Code files
.vscode/*
# Ignore generated python artifacts
*.pyc
copts/__pycache__/
-374
View File
@@ -1,374 +0,0 @@
# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Flags specified here must not impact ABI. Code compiled with and without these
# opts will be linked together, and in some cases headers compiled with and
# without these options will be part of the same program.
import("//build/config/c++/c++.gni")
import("//build/config/nacl/config.gni")
import("//build/config/sanitizers/sanitizers.gni")
import("//build/toolchain/toolchain.gni")
import("//build_overrides/build.gni")
import("//third_party/abseil-cpp/absl.gni")
config("absl_component_build") {
defines = [ "ABSL_CONSUME_DLL" ]
}
assert(!is_nacl || is_nacl_saigo,
"base must not be built in most nacl toolchains")
component("absl") {
public_deps = [ ":absl_component_deps" ]
if (is_component_build) {
public_configs = [ ":absl_component_build" ]
if (is_win && is_clang) {
if (current_cpu == "x64") {
if (is_debug) {
sources = [ "symbols_x64_dbg.def" ]
} else {
if (is_asan) {
sources = [ "symbols_x64_rel_asan.def" ]
} else {
sources = [ "symbols_x64_rel.def" ]
}
}
}
if (current_cpu == "x86") {
if (is_debug) {
sources = [ "symbols_x86_dbg.def" ]
} else {
sources = [ "symbols_x86_rel.def" ]
}
}
if (current_cpu == "arm64") {
if (is_debug) {
sources = [ "symbols_arm64_dbg.def" ]
} else {
sources = [ "symbols_arm64_rel.def" ]
}
}
}
}
}
group("absl_component_deps") {
public_deps = [
"//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/base",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/base:no_destructor",
"//third_party/abseil-cpp/absl/base:nullability",
"//third_party/abseil-cpp/absl/base:prefetch",
"//third_party/abseil-cpp/absl/cleanup",
"//third_party/abseil-cpp/absl/container:btree",
"//third_party/abseil-cpp/absl/container:fixed_array",
"//third_party/abseil-cpp/absl/container:flat_hash_map",
"//third_party/abseil-cpp/absl/container:flat_hash_set",
"//third_party/abseil-cpp/absl/container:inlined_vector",
"//third_party/abseil-cpp/absl/container:node_hash_map",
"//third_party/abseil-cpp/absl/container:node_hash_set",
"//third_party/abseil-cpp/absl/debugging:failure_signal_handler",
"//third_party/abseil-cpp/absl/debugging:stacktrace",
"//third_party/abseil-cpp/absl/debugging:symbolize",
"//third_party/abseil-cpp/absl/functional:any_invocable",
"//third_party/abseil-cpp/absl/functional:bind_front",
"//third_party/abseil-cpp/absl/functional:function_ref",
"//third_party/abseil-cpp/absl/functional:overload",
"//third_party/abseil-cpp/absl/hash",
"//third_party/abseil-cpp/absl/log:absl_check",
"//third_party/abseil-cpp/absl/log:absl_log",
"//third_party/abseil-cpp/absl/log:die_if_null",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/abseil-cpp/absl/numeric:bits",
"//third_party/abseil-cpp/absl/numeric:int128",
"//third_party/abseil-cpp/absl/random",
"//third_party/abseil-cpp/absl/random:distributions",
"//third_party/abseil-cpp/absl/status",
"//third_party/abseil-cpp/absl/status:statusor",
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/strings:cord",
"//third_party/abseil-cpp/absl/strings:has_ostream_operator",
"//third_party/abseil-cpp/absl/strings:str_format",
"//third_party/abseil-cpp/absl/strings:string_view",
"//third_party/abseil-cpp/absl/synchronization",
"//third_party/abseil-cpp/absl/time",
"//third_party/abseil-cpp/absl/types:optional",
"//third_party/abseil-cpp/absl/types:span",
"//third_party/abseil-cpp/absl/types:variant",
"//third_party/abseil-cpp/absl/utility",
]
if (is_component_build) {
public_deps += [ ":absl_full_deps" ]
}
# The following dependencies currently don't build with NaCl.
# TODO(https://crbug.com/1114625): Fix build errors and remove this section.
if (is_nacl) {
public_deps -=
[ "//third_party/abseil-cpp/absl/debugging:failure_signal_handler" ]
}
visibility = [ ":absl" ]
}
# Some third-party libraries use additional parts of absl that are banned in
# Chrome (e.g. flags generates static initializers that are undesirable in
# non-test binaries). These third-party libraries can depend on `absl_full`
# instead of `absl` to use those banned subsets of Abseil as well.
source_set("absl_full") {
public_deps = [ ":absl" ]
# In component builds, `absl` itself depends on `absl_full_deps` directly so
# that all of absl is built as a single shared library. This is to prevent
# globals from being duplicated between both `absl` and `absl_full` (e.g.
# inline variables), and the subtle breakage that could cause.
#
# Deps violations will still be enforced by the non-component build.
if (!is_component_build) {
public_deps += [ ":absl_full_deps" ]
}
if (build_with_chromium) {
visibility = [
"//third_party/fuzztest:*",
# GoogleTest doesn't actually need absl_full, but this makes gn check
# happier.
"//third_party/googletest:*",
]
}
}
group("absl_full_deps") {
public_deps = [
# Banned because each flag registration generates a static initializer, and
# the flag registration mechanism is problematic in component builds.
"//third_party/abseil-cpp/absl/flags:config",
"//third_party/abseil-cpp/absl/flags:flag",
"//third_party/abseil-cpp/absl/flags:parse",
"//third_party/abseil-cpp/absl/flags:reflection",
"//third_party/abseil-cpp/absl/flags:usage",
# Banned because the LOG and CHECK macros conflict with Chrome's version of
# those macros.
"//third_party/abseil-cpp/absl/log",
"//third_party/abseil-cpp/absl/log:check",
# TODO(danilchap): Investigate if these targets need to be banned in 3rd party library code.
"//third_party/abseil-cpp/absl/log:globals",
"//third_party/abseil-cpp/absl/log:initialize",
"//third_party/abseil-cpp/absl/random:bit_gen_ref",
]
visibility = [
":absl_component_deps",
":absl_full",
]
public_configs = [ "//third_party/abseil-cpp/absl/flags:absl_flags_config" ]
}
config("absl_include_config") {
include_dirs = [ "." ]
}
config("absl_define_config") {
defines = [ "ABSL_ALLOCATOR_NOTHROW=1" ]
if (is_win && !use_custom_libcxx) {
defines += [
# See crbug.com/1101367: Acknowledge extended alignment when using
# MSVC's standard library.
"_ENABLE_EXTENDED_ALIGNED_STORAGE",
]
}
}
config("absl_default_cflags_cc") {
cflags_cc = []
if (is_clang) {
cflags_cc += [
# TODO(crbug.com/588506): Explicitly enable conversion warnings.
"-Wbool-conversion",
"-Wconstant-conversion",
"-Wenum-conversion",
"-Wint-conversion",
"-Wliteral-conversion",
"-Wnon-literal-null-conversion",
"-Wnull-conversion",
"-Wobjc-literal-conversion",
"-Wstring-conversion",
]
if (!is_nacl) {
cflags_cc += [ "-Wbitfield-enum-conversion" ]
}
}
}
config("absl_public_cflags_cc") {
# Non-chromium users of abseil have more lax style guides and use additional features in
# abseil, Remove a few extra warnings for that use case.
if (!build_with_chromium && is_clang) {
cflags = [
# Allow the use of enable_if()
"-Wno-gcc-compat",
"-Wno-unreachable-code-break",
]
}
}
config("absl_test_cflags_cc") {
cflags_cc = []
if (is_clang || !is_win) {
cflags_cc += [
"-Wno-conversion-null",
"-Wno-missing-declarations",
"-Wno-unused-function",
"-Wno-unused-parameter",
"-Wno-unused-private-field",
]
}
if (is_win) {
cflags_cc += [
"/wd4101", # unreferenced local variable
]
}
}
config("absl_test_config") {
cflags_cc = []
if (is_win && !is_clang) {
cflags_cc += [ "/wd4996" ]
}
if (is_clang) {
cflags_cc += [
"-Wno-deprecated-declarations",
"-Wno-implicit-const-int-float-conversion",
"-Wno-unused-private-field",
"-Wno-unused-function",
]
}
}
if (absl_build_tests) {
import("//testing/test.gni")
if (!is_component_build) {
test("absl_tests") {
testonly = true
deps = [
"absl/algorithm:algorithm_test",
"absl/algorithm:container_test",
"absl/base:config_test",
"absl/base:no_destructor_test",
"absl/base:nullability_test",
"absl/base:prefetch_test",
"absl/cleanup:cleanup_test",
# TODO(mbonadei): Fix issue with EXPECT_DEATH and uncomment.
# "absl/container:btree_test",
"absl/container:common_policy_traits_test",
"absl/container:fixed_array_test",
"absl/container:flat_hash_map_test",
"absl/container:flat_hash_set_test",
"absl/container:hash_function_defaults_test",
"absl/container:inlined_vector_test",
"absl/container:node_slot_policy_test",
"absl/container:raw_hash_set_allocator_test",
"absl/container:raw_hash_set_test",
"absl/container:sample_element_size_test",
"absl/crc:crc32c_test",
"absl/crc:crc_cord_state_test",
"absl/crc:crc_memcpy_test",
"absl/crc:non_temporal_memcpy_test",
"absl/debugging:demangle_rust_test",
"absl/debugging:stacktrace_test",
"absl/flags:flag_test",
"absl/functional:any_invocable_test",
"absl/functional:function_ref_test",
"absl/functional:overload_test",
"absl/hash:hash_instantiated_test",
"absl/hash:hash_test",
"absl/hash:low_level_hash_test",
"absl/log:absl_check_test",
"absl/log:absl_log_basic_test",
"absl/log:die_if_null_test",
"absl/log:flags_test",
"absl/log:globals_test",
"absl/log:log_entry_test",
"absl/log:log_format_test",
"absl/log:log_macro_hygiene_test",
"absl/log:log_modifier_methods_test",
"absl/log:log_sink_test",
"absl/log:log_streamer_test",
"absl/log:scoped_mock_log_test",
"absl/log:stripping_test",
"absl/log:vlog_is_on_test",
"absl/log/internal:fnmatch_test",
"absl/log/internal:stderr_log_sink_test",
"absl/memory:memory_test",
"absl/meta:type_traits_test",
"absl/numeric:int128_test",
"absl/profiling:exponential_biased_test",
"absl/profiling:periodic_sampler_test",
"absl/status:status_matchers_test",
"absl/status:status_test",
"absl/status:statusor_test",
"absl/strings:ascii_test",
"absl/strings:char_formatting_test",
"absl/strings:charset_test",
"absl/strings:cord_buffer_test",
"absl/strings:cord_data_edge_test",
"absl/strings:cord_rep_btree_navigator_test",
"absl/strings:cord_rep_btree_reader_test",
"absl/strings:cord_rep_btree_test",
"absl/strings:cord_rep_crc_test",
"absl/strings:cordz_functions_test",
"absl/strings:cordz_info_statistics_test",
"absl/strings:cordz_info_test",
"absl/strings:cordz_test",
"absl/strings:cordz_update_scope_test",
"absl/strings:cordz_update_tracker_test",
"absl/strings:damerau_levenshtein_distance_test",
"absl/strings:has_absl_stringify_test",
"absl/strings:has_ostream_operator_test",
"absl/strings:match_test",
"absl/strings:str_format_arg_test",
"absl/strings:str_format_bind_test",
"absl/strings:str_format_checker_test",
"absl/strings:str_format_convert_test",
"absl/strings:str_format_extension_test",
"absl/strings:str_format_output_test",
"absl/strings:str_format_parser_test",
"absl/strings:str_format_test",
"absl/strings:str_replace_test",
"absl/strings:string_view_test",
"absl/synchronization:kernel_timeout_internal_test",
"absl/synchronization:waiter_test",
"absl/time:time_test",
"absl/types:optional_test",
"absl/types:span_test",
"absl/types:variant_test",
"absl/utility:if_constexpr_test",
"//third_party/googletest:gtest_main",
]
}
}
test("absl_hardening_tests") {
testonly = true
sources = [ "absl_hardening_test.cc" ]
deps = [
":absl",
"//base/test:run_all_unittests",
"//third_party/googletest:gtest",
]
}
}
+87 -15
View File
@@ -15,6 +15,7 @@ set(ABSL_INTERNAL_DLL_FILES
"base/internal/cycleclock.h"
"base/internal/cycleclock_config.h"
"base/internal/direct_mmap.h"
"base/internal/dynamic_annotations.h"
"base/internal/endian.h"
"base/internal/errno_saver.h"
"base/internal/fast_type_id.h"
@@ -27,6 +28,8 @@ set(ABSL_INTERNAL_DLL_FILES
"base/internal/low_level_scheduling.h"
"base/internal/nullability_impl.h"
"base/internal/per_thread_tls.h"
"base/internal/poison.cc"
"base/internal/poison.h"
"base/prefetch.h"
"base/internal/pretty_function.h"
"base/internal/raw_logging.cc"
@@ -46,6 +49,8 @@ set(ABSL_INTERNAL_DLL_FILES
"base/internal/thread_identity.h"
"base/internal/throw_delegate.cc"
"base/internal/throw_delegate.h"
"base/internal/tracing.cc"
"base/internal/tracing.h"
"base/internal/tsan_mutex_interface.h"
"base/internal/unaligned_access.h"
"base/internal/unscaledcycleclock.cc"
@@ -121,6 +126,9 @@ set(ABSL_INTERNAL_DLL_FILES
"debugging/symbolize.h"
"debugging/internal/address_is_readable.cc"
"debugging/internal/address_is_readable.h"
"debugging/internal/bounded_utf8_length_sequence.h"
"debugging/internal/decode_rust_punycode.cc"
"debugging/internal/decode_rust_punycode.h"
"debugging/internal/demangle.cc"
"debugging/internal/demangle.h"
"debugging/internal/demangle_rust.cc"
@@ -133,6 +141,8 @@ set(ABSL_INTERNAL_DLL_FILES
"debugging/internal/stack_consumption.h"
"debugging/internal/stacktrace_config.h"
"debugging/internal/symbolize.h"
"debugging/internal/utf8_for_code_point.cc"
"debugging/internal/utf8_for_code_point.h"
"debugging/internal/vdso_support.cc"
"debugging/internal/vdso_support.h"
"functional/any_invocable.h"
@@ -183,6 +193,8 @@ set(ABSL_INTERNAL_DLL_FILES
"log/internal/proto.cc"
"log/internal/strip.h"
"log/internal/structured.h"
"log/internal/structured_proto.cc"
"log/internal/structured_proto.h"
"log/internal/vlog_config.cc"
"log/internal/vlog_config.h"
"log/internal/voidify.h"
@@ -313,7 +325,6 @@ set(ABSL_INTERNAL_DLL_FILES
"strings/internal/string_constant.h"
"strings/internal/stringify_sink.h"
"strings/internal/stringify_sink.cc"
"strings/internal/has_absl_stringify.h"
"strings/has_absl_stringify.h"
"strings/has_ostream_operator.h"
"strings/match.cc"
@@ -439,9 +450,47 @@ set(ABSL_INTERNAL_DLL_FILES
"debugging/leak_check.cc"
)
if(NOT MSVC)
list(APPEND ABSL_INTERNAL_DLL_FILES
"flags/commandlineflag.cc"
"flags/commandlineflag.h"
"flags/config.h"
"flags/declare.h"
"flags/flag.h"
"flags/internal/commandlineflag.cc"
"flags/internal/commandlineflag.h"
"flags/internal/flag.cc"
"flags/internal/flag.h"
"flags/internal/parse.h"
"flags/internal/path_util.h"
"flags/internal/private_handle_accessor.cc"
"flags/internal/private_handle_accessor.h"
"flags/internal/program_name.cc"
"flags/internal/program_name.h"
"flags/internal/registry.h"
"flags/internal/sequence_lock.h"
"flags/internal/usage.cc"
"flags/internal/usage.h"
"flags/marshalling.cc"
"flags/marshalling.h"
"flags/parse.cc"
"flags/parse.h"
"flags/reflection.cc"
"flags/reflection.h"
"flags/usage.cc"
"flags/usage.h"
"flags/usage_config.cc"
"flags/usage_config.h"
"log/flags.cc"
"log/flags.h"
"log/internal/flags.h"
)
endif()
set(ABSL_INTERNAL_DLL_TARGETS
"absl_check"
"absl_log"
"absl_vlog_is_on"
"algorithm"
"algorithm_container"
"any"
@@ -507,6 +556,7 @@ set(ABSL_INTERNAL_DLL_TARGETS
"log_internal_check_op"
"log_internal_conditions"
"log_internal_config"
"log_internal_fnmatch"
"log_internal_format"
"log_internal_globals"
"log_internal_log_impl"
@@ -586,6 +636,7 @@ set(ABSL_INTERNAL_DLL_TARGETS
"strerror"
"strings"
"strings_internal"
"string_view"
"symbolize"
"synchronization"
"thread_pool"
@@ -596,8 +647,30 @@ set(ABSL_INTERNAL_DLL_TARGETS
"type_traits"
"utility"
"variant"
"vlog_config_internal"
"vlog_is_on"
)
if(NOT MSVC)
list(APPEND ABSL_INTERNAL_DLL_TARGETS
"flags"
"flags_commandlineflag"
"flags_commandlineflag_internal"
"flags_config"
"flags_internal"
"flags_marshalling"
"flags_parse"
"flags_path_util"
"flags_private_handle_accessor"
"flags_program_name"
"flags_reflection"
"flags_usage"
"flags_usage_internal"
"log_internal_flags"
"log_flags"
)
endif()
set(ABSL_INTERNAL_TEST_DLL_FILES
"hash/hash_testing.h"
"log/scoped_mock_log.cc"
@@ -674,12 +747,7 @@ function(absl_internal_dll_contains)
STRING(REGEX REPLACE "^absl::" "" _target ${ABSL_INTERNAL_DLL_TARGET})
list(FIND
ABSL_INTERNAL_DLL_TARGETS
"${_target}"
_index)
if (${_index} GREATER -1)
if (_target IN_LIST ABSL_INTERNAL_DLL_TARGETS)
set(${ABSL_INTERNAL_DLL_OUTPUT} 1 PARENT_SCOPE)
else()
set(${ABSL_INTERNAL_DLL_OUTPUT} 0 PARENT_SCOPE)
@@ -696,12 +764,7 @@ function(absl_internal_test_dll_contains)
STRING(REGEX REPLACE "^absl::" "" _target ${ABSL_INTERNAL_TEST_DLL_TARGET})
list(FIND
ABSL_INTERNAL_TEST_DLL_TARGETS
"${_target}"
_index)
if (${_index} GREATER -1)
if (_target IN_LIST ABSL_INTERNAL_TEST_DLL_TARGETS)
set(${ABSL_INTERNAL_TEST_DLL_OUTPUT} 1 PARENT_SCOPE)
else()
set(${ABSL_INTERNAL_TEST_DLL_OUTPUT} 0 PARENT_SCOPE)
@@ -753,7 +816,12 @@ function(absl_make_dll)
else()
set(_dll "abseil_dll")
set(_dll_files ${ABSL_INTERNAL_DLL_FILES})
set(_dll_libs "")
set(_dll_libs
Threads::Threads
# TODO(#1495): Use $<LINK_LIBRARY:FRAMEWORK,CoreFoundation> once our
# minimum CMake version >= 3.24
$<$<PLATFORM_ID:Darwin>:-Wl,-framework,CoreFoundation>
)
set(_dll_compile_definitions "")
set(_dll_includes "")
set(_dll_consume "ABSL_CONSUME_DLL")
@@ -770,8 +838,12 @@ function(absl_make_dll)
PRIVATE
${_dll_libs}
${ABSL_DEFAULT_LINKOPTS}
$<$<BOOL:${ANDROID}>:-llog>
)
set_target_properties(${_dll} PROPERTIES
LINKER_LANGUAGE "CXX"
SOVERSION ${ABSL_SOVERSION}
)
set_property(TARGET ${_dll} PROPERTY LINKER_LANGUAGE "CXX")
target_include_directories(
${_dll}
PUBLIC
+16 -9
View File
@@ -186,16 +186,16 @@ function(absl_cc_library)
endif()
endif()
endforeach()
set(skip_next_cflag OFF)
foreach(cflag ${ABSL_CC_LIB_COPTS})
if(skip_next_cflag)
set(skip_next_cflag OFF)
elseif(${cflag} MATCHES "^-Xarch_")
# Strip out the CMake-specific `SHELL:` prefix, which is used to construct
# a group of space-separated options.
# https://cmake.org/cmake/help/v3.30/command/target_compile_options.html#option-de-duplication
string(REGEX REPLACE "^SHELL:" "" cflag "${cflag}")
if(${cflag} MATCHES "^-Xarch_")
# An -Xarch_ flag implies that its successor only applies to the
# specified platform. Filter both of them out before the successor
# reaches the "^-m" filter.
set(skip_next_cflag ON)
elseif(${cflag} MATCHES "^(-Wno|/wd)")
# specified platform. Such option groups are each specified in a single
# `SHELL:`-prefixed string in the COPTS list, which we simply ignore.
elseif(${cflag} MATCHES "^(-Wno-|/wd)")
# These flags are needed to suppress warnings that might fire in our headers.
set(PC_CFLAGS "${PC_CFLAGS} ${cflag}")
elseif(${cflag} MATCHES "^(-W|/w[1234eo])")
@@ -258,6 +258,13 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
elseif(_build_type STREQUAL "static" OR _build_type STREQUAL "shared")
add_library(${_NAME} "")
target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})
if(APPLE)
set_target_properties(${_NAME} PROPERTIES
INSTALL_RPATH "@loader_path")
elseif(UNIX)
set_target_properties(${_NAME} PROPERTIES
INSTALL_RPATH "$ORIGIN")
endif()
target_link_libraries(${_NAME}
PUBLIC ${ABSL_CC_LIB_DEPS}
PRIVATE
@@ -306,7 +313,7 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
if(ABSL_ENABLE_INSTALL)
set_target_properties(${_NAME} PROPERTIES
OUTPUT_NAME "absl_${_NAME}"
SOVERSION 0
SOVERSION "${ABSL_SOVERSION}"
)
endif()
else()
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.16)
project(googletest-external NONE)
+2 -2
View File
@@ -39,7 +39,7 @@ section of your executable or of your library.<br>
Here is a short CMakeLists.txt example of an application project using Abseil.
```cmake
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.16)
project(my_app_project)
# Pick the C++ standard to compile with.
@@ -62,7 +62,7 @@ will control Abseil library targets) is set to at least that minimum. For
example:
```cmake
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.16)
project(my_lib_project)
# Leave C++ standard up to the root application, so set it only if this is the
@@ -15,7 +15,7 @@
# A simple CMakeLists.txt for testing cmake installation
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.16)
project(absl_cmake_testing CXX)
add_executable(simple simple.cc)
+5 -4
View File
@@ -22,7 +22,8 @@ set -euox pipefail
absl_dir=/abseil-cpp
absl_build_dir=/buildfs
googletest_builddir=/googletest_builddir
project_dir="${absl_dir}"/CMake/install_test_project
googletest_archive="googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz"
project_dir="${absl_dir}/CMake/install_test_project"
project_build_dir=/buildfs/project-build
build_shared_libs="OFF"
@@ -33,9 +34,9 @@ fi
# Build and install GoogleTest
mkdir "${googletest_builddir}"
pushd "${googletest_builddir}"
curl -L "${ABSL_GOOGLETEST_DOWNLOAD_URL}" --output "${ABSL_GOOGLETEST_COMMIT}".zip
unzip "${ABSL_GOOGLETEST_COMMIT}".zip
pushd "googletest-${ABSL_GOOGLETEST_COMMIT}"
curl -L "${ABSL_GOOGLETEST_DOWNLOAD_URL}" --output "${googletest_archive}"
tar -xz -f "${googletest_archive}"
pushd "googletest-${ABSL_GOOGLETEST_VERSION}"
mkdir build
pushd build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS="${build_shared_libs}" ..
+44 -54
View File
@@ -15,50 +15,16 @@
#
# https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md
# As of 2022-09-06, CMake 3.10 is the minimum supported version.
cmake_minimum_required(VERSION 3.10)
# Compiler id for Apple Clang is now AppleClang.
if (POLICY CMP0025)
cmake_policy(SET CMP0025 NEW)
endif (POLICY CMP0025)
# if command can use IN_LIST
if (POLICY CMP0057)
cmake_policy(SET CMP0057 NEW)
endif (POLICY CMP0057)
# Project version variables are the empty string if version is unspecified
if (POLICY CMP0048)
cmake_policy(SET CMP0048 NEW)
endif (POLICY CMP0048)
# Honor the GTest_ROOT variable if specified
if (POLICY CMP0074)
cmake_policy(SET CMP0074 NEW)
endif (POLICY CMP0074)
# option() honor variables
if (POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif (POLICY CMP0077)
# Allow the user to specify the MSVC runtime
if (POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif (POLICY CMP0091)
# try_compile() honors the CMAKE_CXX_STANDARD value
if (POLICY CMP0067)
cmake_policy(SET CMP0067 NEW)
endif (POLICY CMP0067)
# As of 2024-07-01, CMake 3.16 is the minimum supported version.
cmake_minimum_required(VERSION 3.16)
# Allow the user to specify the CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
if (POLICY CMP0141)
cmake_policy(SET CMP0141 NEW)
endif (POLICY CMP0141)
project(absl LANGUAGES CXX)
project(absl LANGUAGES CXX VERSION 20250127)
set(ABSL_SOVERSION "2501.0.0")
include(CTest)
# Output directory is correct by default for most build setups. However, when
@@ -75,12 +41,13 @@ else()
option(ABSL_ENABLE_INSTALL "Enable install rule" ON)
endif()
set(CMAKE_INSTALL_RPATH "$ORIGIN")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON)
set(CMAKE_BUILD_RPATH_USE_ORIGIN ON)
option(ABSL_PROPAGATE_CXX_STD
"Use CMake C++ standard meta features (e.g. cxx_std_14) that propagate to targets that link to Abseil"
OFF) # TODO: Default to ON for CMake 3.8 and greater.
if(NOT ABSL_PROPAGATE_CXX_STD)
message(WARNING "A future Abseil release will default ABSL_PROPAGATE_CXX_STD to ON for CMake 3.8 and up. We recommend enabling this option to ensure your project still builds correctly.")
endif()
ON)
option(ABSL_USE_SYSTEM_INCLUDES
"Silence warnings in Abseil headers by marking them as SYSTEM includes"
@@ -91,6 +58,15 @@ list(APPEND CMAKE_MODULE_PATH
${CMAKE_CURRENT_LIST_DIR}/absl/copts
)
option(ABSL_MSVC_STATIC_RUNTIME
"Link static runtime libraries"
OFF)
if(ABSL_MSVC_STATIC_RUNTIME)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
else()
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
endif()
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
include(AbseilDll)
@@ -149,6 +125,14 @@ set(ABSL_LOCAL_GOOGLETEST_DIR "/usr/src/googletest" CACHE PATH
"If ABSL_USE_GOOGLETEST_HEAD is OFF and ABSL_GOOGLETEST_URL is not set, specifies the directory of a local GoogleTest checkout."
)
option(ABSL_BUILD_MONOLITHIC_SHARED_LIBS
"Build Abseil as a single shared library (always enabled for Windows)"
OFF
)
if(NOT BUILD_SHARED_LIBS AND ABSL_BUILD_MONOLITHIC_SHARED_LIBS)
message(WARNING "Not building a shared library because BUILD_SHARED_LIBS is not set. Ignoring ABSL_BUILD_MONOLITHIC_SHARED_LIBS.")
endif()
if((BUILD_TESTING AND ABSL_BUILD_TESTING) OR ABSL_BUILD_TEST_HELPERS)
if (ABSL_USE_EXTERNAL_GOOGLETEST)
if (ABSL_FIND_GOOGLETEST)
@@ -186,17 +170,7 @@ endif()
add_subdirectory(absl)
if(ABSL_ENABLE_INSTALL)
# absl:lts-remove-begin(system installation is supported for LTS releases)
# We don't support system-wide installation
list(APPEND SYSTEM_INSTALL_DIRS "/usr/local" "/usr" "/opt/" "/opt/local" "c:/Program Files/${PROJECT_NAME}")
if(NOT DEFINED CMAKE_INSTALL_PREFIX OR CMAKE_INSTALL_PREFIX IN_LIST SYSTEM_INSTALL_DIRS)
message(WARNING "\
The default and system-level install directories are unsupported except in LTS \
releases of Abseil. Please set CMAKE_INSTALL_PREFIX to install Abseil in your \
source or build tree directly.\
")
endif()
# absl:lts-remove-end
# install as a subdirectory only
install(EXPORT ${PROJECT_NAME}Targets
@@ -227,11 +201,13 @@ if(ABSL_ENABLE_INSTALL)
)
endif() # absl_VERSION
# Install the headers except for "options.h" which is installed separately.
install(DIRECTORY absl
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING
PATTERN "*.inc"
PATTERN "*.h"
PATTERN "options.h" EXCLUDE
PATTERN "copts" EXCLUDE
PATTERN "testdata" EXCLUDE
)
@@ -271,7 +247,21 @@ if(ABSL_ENABLE_INSTALL)
ABSL_INTERNAL_OPTIONS_H_PINNED
"${ABSL_INTERNAL_OPTIONS_H_CONTENTS}")
file(WRITE "${CMAKE_BINARY_DIR}/options-pinned.h" "${ABSL_INTERNAL_OPTIONS_H_PINNED}")
# If the file already exists, check if it matches the new contents.
# This avoids writing the file if it is already up-to-date when the CMake
# generation is triggered and triggering unnecessary rebuilds.
set(ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE TRUE)
if (EXISTS "${CMAKE_BINARY_DIR}/options-pinned.h")
file(READ "${CMAKE_BINARY_DIR}/options-pinned.h" ABSL_INTERNAL_OPTIONS_PINNED_H_CONTENTS)
if ("${ABSL_INTERNAL_OPTIONS_H_PINNED}" STREQUAL "${ABSL_INTERNAL_OPTIONS_PINNED_H_CONTENTS}")
set(ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE FALSE)
endif()
endif()
# If the file needs an update, generate it.
if (ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE)
file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/options-pinned.h" CONTENT "${ABSL_INTERNAL_OPTIONS_H_PINNED}")
endif()
install(FILES "${CMAKE_BINARY_DIR}/options-pinned.h"
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/absl/base
-6
View File
@@ -1,6 +0,0 @@
monorail: {
component: "Internals>Core"
}
buganizer_public: {
component_id: 1456128
}
+18 -14
View File
@@ -16,27 +16,31 @@
module(
name = "abseil-cpp",
version = "head",
version = "20250127.1",
compatibility_level = 1,
)
cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
cc_configure = use_extension("@rules_cc//cc:extensions.bzl",
"cc_configure_extension",
dev_dependency = True)
use_repo(cc_configure, "local_config_cc")
# Only direct dependencies need to be listed below.
# Please keep the versions in sync with the versions in the WORKSPACE file.
bazel_dep(name = "bazel_skylib",
version = "1.5.0")
bazel_dep(name = "rules_cc", version = "0.0.17")
bazel_dep(name = "bazel_skylib", version = "1.7.1")
bazel_dep(name = "platforms", version = "0.0.10")
bazel_dep(name = "google_benchmark",
version = "1.8.3",
repo_name = "com_github_google_benchmark",
dev_dependency = True)
bazel_dep(
name = "google_benchmark",
version = "1.8.5",
dev_dependency = True,
)
bazel_dep(name = "googletest",
version = "1.14.0.bcr.1",
repo_name = "com_google_googletest")
bazel_dep(name = "platforms",
version = "0.0.8")
# Note: Googletest is NOT a dev_dependency. Some Abseil test utilities
# intended to be used by Abseil users depend on GoogleTest.
bazel_dep(
name = "googletest",
version = "1.15.2",
)
-5
View File
@@ -1,5 +0,0 @@
danilchap@chromium.org
mbonadei@chromium.org
# For .def files updates:
hans@chromium.org
-43
View File
@@ -1,43 +0,0 @@
Name: Abseil
Short Name: absl
URL: https://github.com/abseil/abseil-cpp
License: Apache 2.0
License File: LICENSE
Version: N/A
Revision: eba8db7baf6c326870f28e58977075b7b2fb243d
Security Critical: yes
Shipped: yes
Description:
This directory contains the source code of Abseil for C++. This can be used by
Chromium, subject to the guidance at
https://chromium.googlesource.com/chromium/src/+/main/styleguide/c++/c++-features.md;
it can be used without restriction by Chromium's dependencies, except that
objects compiled into Chromium itself cannot use anything relying on
absl::base_internal::FastTypeId (see https://crbug.com/1096380).
How to update Abseil:
1. From your source root run third_party/abseil-cpp/roll_abseil.py to download the code from the Abseil git repository and apply chromium specific patches.
2. Update BUILD.gn files to match changes in BUILD.bazel
If there is a new test, add dependcy on it from absl_tests in the
third_party/abseil-cpp/BUILD.gn target
3. From your source root run third_party/abseil-cpp/generate_def_files.py to
regenerate Windows symbol definition files.
4. If abseil adds new features, update styleguide/c++/c++-features.md and add headers for that feature into exclude list in root DEPS
Local Modifications:
* absl/copts.bzl has been translated to //third_party/absl-cpp/BUILD.gn. Both
files contain lists of compiler flags in order to reduce duplication.
* All the BUILD.bazel files have been translated to BUILD.gn files.
* Patches from //third_party/abseil-cpp/patches have been applied.
* Increment this number to silence presubmits about modifying files in
third_party when regenerating absl .def files: 2
+37 -20
View File
@@ -14,46 +14,63 @@
# limitations under the License.
#
workspace(name = "com_google_absl")
workspace(name = "abseil-cpp")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# GoogleTest/GoogleMock framework. Used by most unit-tests.
http_archive(
name = "com_google_googletest",
sha256 = "8ad598c73ad796e0d8280b082cebd82a630d73e73cd3c70057938a6501bba5d7",
strip_prefix = "googletest-1.14.0",
# Keep this URL in sync with ABSL_GOOGLETEST_COMMIT in ci/cmake_common.sh and
# ci/windows_msvc_cmake.bat.
urls = ["https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz"],
name = "googletest",
sha256 = "7b42b4d6ed48810c5362c265a17faebe90dc2373c885e5216439d37927f02926",
strip_prefix = "googletest-1.15.2",
# Keep this URL in sync with the version in ci/cmake_common.sh and
# ci/windows_msvc_cmake.bat.
urls = ["https://github.com/google/googletest/releases/download/v1.15.2/googletest-1.15.2.tar.gz"],
# Now that Abseil is using the canonical names from the Bazel Central Registry, map
# GoogleTest's old names to the new canonical names.
repo_mapping = {
"@com_google_absl": "@",
"@com_googlesource_code_re2": "@re2",
},
)
# RE2 (the regular expression library used by GoogleTest)
http_archive(
name = "com_googlesource_code_re2",
sha256 = "828341ad08524618a626167bd320b0c2acc97bd1c28eff693a9ea33a7ed2a85f",
strip_prefix = "re2-2023-11-01",
urls = ["https://github.com/google/re2/releases/download/2023-11-01/re2-2023-11-01.zip"],
name = "re2",
sha256 = "eb2df807c781601c14a260a507a5bb4509be1ee626024cb45acbd57cb9d4032b",
strip_prefix = "re2-2024-07-02",
urls = ["https://github.com/google/re2/releases/download/2024-07-02/re2-2024-07-02.tar.gz"],
)
# Google benchmark.
http_archive(
name = "com_github_google_benchmark",
sha256 = "6bc180a57d23d4d9515519f92b0c83d61b05b5bab188961f36ac7b06b0d9e9ce",
strip_prefix = "benchmark-1.8.3",
urls = ["https://github.com/google/benchmark/archive/refs/tags/v1.8.3.tar.gz"],
name = "google_benchmark",
sha256 = "d26789a2b46d8808a48a4556ee58ccc7c497fcd4c0af9b90197674a81e04798a",
strip_prefix = "benchmark-1.8.5",
urls = ["https://github.com/google/benchmark/archive/refs/tags/v1.8.5.tar.gz"],
)
# Bazel Skylib.
http_archive(
name = "bazel_skylib",
sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz"],
name = "bazel_skylib",
sha256 = "bc283cdfcd526a52c3201279cda4bc298652efa898b10b4db0837dc51652756f",
urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.7.1/bazel-skylib-1.7.1.tar.gz"],
)
# C++ rules for Bazel
http_archive(
name = "rules_cc",
urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.1.0/rules_cc-0.1.0.tar.gz"],
sha256 = "4b12149a041ddfb8306a8fd0e904e39d673552ce82e4296e96fac9cbf0780e59",
strip_prefix = "rules_cc-0.1.0",
)
# Bazel platform rules.
http_archive(
name = "platforms",
sha256 = "8150406605389ececb6da07cbcb509d5637a3ab9a24bc69b1101531367d89d74",
urls = ["https://github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz"],
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
"https://github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
],
sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee",
)
-128
View File
@@ -1,128 +0,0 @@
# Copyright 2020 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This file contains the definition of the template absl_source_set which
# should be the only type of target needed in abseil's BUILD.gn files.
# This template will correctly set "configs" and "public_configs" in order
# to correctly compile abseil in Chromium.
#
# Usage:
# Most of the times its usage will be similar to the example below but all
# the arguments avilable in source_set are also available for absl_source_set.
#
# absl_source_set("foo") {
# sources = [ "foo.cc" ]
# public = [ "foo.h" ]
# deps = [ ":bar" ]
# }
import("//build_overrides/build.gni")
declare_args() {
absl_build_tests = build_with_chromium
}
template("absl_source_set") {
source_set(target_name) {
if (defined(invoker.testonly) && invoker.testonly && !absl_build_tests) {
not_needed(invoker, "*")
} else {
forward_variables_from(invoker, "*")
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [
"//build/config/compiler:no_chromium_code",
"//build/config/compiler:prevent_unsafe_narrowing",
"//third_party/abseil-cpp:absl_default_cflags_cc",
"//third_party/abseil-cpp:absl_define_config",
]
if (is_component_build) {
defines = [ "ABSL_BUILD_DLL" ]
if (!is_win && current_os != "aix") {
configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
configs += [ "//build/config/gcc:symbol_visibility_default" ]
}
}
if (!defined(public_configs)) {
public_configs = []
}
public_configs += [
"//third_party/abseil-cpp:absl_include_config",
"//third_party/abseil-cpp:absl_public_cflags_cc",
]
if (!defined(visibility)) {
# Within Chromium builds, restrict direct visibility of Abseil sources, so
# users must depend on //third_party/abseil-cpp:absl. This prevents use of
# banned targets like absl/types:any. A few targets require exceptions.
# TODO(crbug.com/1096380): Consider replacing build_with_chromium with
# is_component_build for a narrower, more accurate condition.
if (build_with_chromium) {
visibility = [
# Abseil itself.
"//third_party/abseil-cpp/*",
# GTest. It unconditionally #includes any.h if pretty-print support
# for absl types is enabled.
"//third_party/googletest/*",
# WebRTC binary to run PSNR and SSIM video quality analysis. It
# statically links absl and it is used by "browser_tests" when
# is_component_build=false but it cannot depend on the absl
# component because it uses absl/flags.
"//third_party/webrtc/rtc_tools:frame_analyzer",
# WebRTC binaries used by //:chromium_builder_asan. They both
# statically link absl (because they depend on absl/flags) and are
# used by Chromium only when is_component_build=false.
"//third_party/webrtc/rtc_tools:rtp_generator",
"//third_party/webrtc/rtc_tools:video_replay",
# Not used by Chromium directly.
"//chromecast/internal/*",
"//libassistant/*",
# Not built into Chrome.
"//components/optimization_guide/internal/*",
]
} else {
visibility = [ "*" ]
}
}
}
}
}
template("absl_test") {
source_set(target_name) {
if (!absl_build_tests) {
not_needed(invoker, "*")
} else {
forward_variables_from(invoker, "*")
testonly = true
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [
"//build/config/compiler:no_chromium_code",
"//third_party/abseil-cpp:absl_default_cflags_cc",
"//third_party/abseil-cpp:absl_define_config",
"//third_party/abseil-cpp:absl_test_config",
]
if (!defined(public_configs)) {
public_configs = []
}
public_configs += [
"//third_party/abseil-cpp:absl_include_config",
"//third_party/abseil-cpp:absl_public_cflags_cc",
]
visibility = [ "//third_party/abseil-cpp/:*" ]
deps += [
"//third_party/googletest:gmock",
"//third_party/googletest:gtest",
]
}
}
}
+3 -92
View File
@@ -28,14 +28,6 @@ config_setting(
visibility = [":__subpackages__"],
)
config_setting(
name = "gcc_compiler",
flag_values = {
"@bazel_tools//tools/cpp:compiler": "gcc",
},
visibility = [":__subpackages__"],
)
config_setting(
name = "mingw_unspecified_compiler",
flag_values = {
@@ -52,92 +44,11 @@ config_setting(
visibility = [":__subpackages__"],
)
config_setting(
name = "msvc_compiler",
flag_values = {
"@bazel_tools//tools/cpp:compiler": "msvc-cl",
},
visibility = [":__subpackages__"],
)
config_setting(
name = "clang-cl_compiler",
flag_values = {
"@bazel_tools//tools/cpp:compiler": "clang-cl",
},
visibility = [":__subpackages__"],
)
config_setting(
name = "osx",
constraint_values = [
"@platforms//os:osx",
],
)
config_setting(
name = "ios",
constraint_values = [
"@platforms//os:ios",
],
)
config_setting(
name = "ppc",
values = {
"cpu": "ppc",
},
visibility = [":__subpackages__"],
)
config_setting(
name = "cpu_wasm",
values = {
"cpu": "wasm",
},
visibility = [":__subpackages__"],
)
config_setting(
name = "cpu_wasm32",
values = {
"cpu": "wasm32",
},
visibility = [":__subpackages__"],
)
config_setting(
name = "platforms_wasm32",
constraint_values = [
"@platforms//cpu:wasm32",
],
visibility = [":__subpackages__"],
)
config_setting(
name = "platforms_wasm64",
constraint_values = [
"@platforms//cpu:wasm64",
],
visibility = [":__subpackages__"],
)
selects.config_setting_group(
name = "wasm",
match_any = [
":cpu_wasm",
":cpu_wasm32",
":platforms_wasm32",
":platforms_wasm64",
],
visibility = [":__subpackages__"],
)
config_setting(
name = "fuchsia",
values = {
"cpu": "fuchsia",
},
constraint_values = [
"@platforms//os:fuchsia",
],
visibility = [":__subpackages__"],
)
+2 -2
View File
@@ -36,9 +36,9 @@ add_subdirectory(time)
add_subdirectory(types)
add_subdirectory(utility)
if (${ABSL_BUILD_DLL})
if (ABSL_BUILD_DLL)
absl_make_dll()
if (${ABSL_BUILD_TEST_HELPERS})
if ((BUILD_TESTING AND ABSL_BUILD_TESTING) OR ABSL_BUILD_TEST_HELPERS)
absl_make_dll(TEST ON)
endif()
endif()
+6 -4
View File
@@ -51,8 +51,8 @@ cc_test(
deps = [
":algorithm",
"//absl/base:config",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -65,6 +65,7 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":algorithm",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:nullability",
"//absl/meta:type_traits",
@@ -79,10 +80,11 @@ cc_test(
deps = [
":container",
"//absl/base",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/memory",
"//absl/types:span",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
-39
View File
@@ -1,39 +0,0 @@
# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//third_party/abseil-cpp/absl.gni")
absl_source_set("algorithm") {
public = [ "algorithm.h" ]
deps = [ "//third_party/abseil-cpp/absl/base:config" ]
}
absl_source_set("container") {
public = [ "container.h" ]
deps = [
":algorithm",
"//third_party/abseil-cpp/absl/base:nullability",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/meta:type_traits",
]
}
absl_test("algorithm_test") {
sources = [ "algorithm_test.cc" ]
deps = [
":algorithm",
"//third_party/abseil-cpp/absl/base:config",
]
}
absl_test("container_test") {
sources = [ "container_test.cc" ]
deps = [
":container",
"//third_party/abseil-cpp/absl/base",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/types:span",
]
}
+2
View File
@@ -48,6 +48,7 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
DEPS
absl::algorithm
absl::config
absl::core_headers
absl::meta
absl::nullability
@@ -64,6 +65,7 @@ absl_cc_test(
DEPS
absl::algorithm_container
absl::base
absl::config
absl::core_headers
absl::memory
absl::span
+2 -2
View File
@@ -53,8 +53,8 @@ using std::rotate;
// n = (`last` - `first`) comparisons. A linear search over short containers
// may be faster than a binary search, even when the container is sorted.
template <typename InputIterator, typename EqualityComparable>
bool linear_search(InputIterator first, InputIterator last,
const EqualityComparable& value) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool linear_search(
InputIterator first, InputIterator last, const EqualityComparable& value) {
return std::find(first, last, value) != last;
}
+13 -3
View File
@@ -14,11 +14,9 @@
#include "absl/algorithm/algorithm.h"
#include <algorithm>
#include <list>
#include <array>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/config.h"
@@ -47,4 +45,16 @@ TEST_F(LinearSearchTest, linear_searchConst) {
absl::linear_search(const_container->begin(), const_container->end(), 4));
}
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
TEST_F(LinearSearchTest, Constexpr) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(absl::linear_search(kArray.begin(), kArray.end(), 3));
static_assert(!absl::linear_search(kArray.begin(), kArray.end(), 4));
}
#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
// ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
} // namespace
+132 -62
View File
@@ -44,6 +44,7 @@
#include <cassert>
#include <iterator>
#include <numeric>
#include <random>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
@@ -51,6 +52,7 @@
#include <vector>
#include "absl/algorithm/algorithm.h"
#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/meta/type_traits.h"
@@ -92,17 +94,17 @@ using ContainerPointerType =
// using std::end;
// std::foo(begin(c), end(c));
// becomes
// std::foo(container_algorithm_internal::begin(c),
// container_algorithm_internal::end(c));
// std::foo(container_algorithm_internal::c_begin(c),
// container_algorithm_internal::c_end(c));
// These are meant for internal use only.
template <typename C>
ContainerIter<C> c_begin(C& c) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_begin(C& c) {
return begin(c);
}
template <typename C>
ContainerIter<C> c_end(C& c) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_end(C& c) {
return end(c);
}
@@ -129,11 +131,14 @@ struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
//
// Container-based version of absl::linear_search() for performing a linear
// search within a container.
//
// For a generalization that uses a predicate, see absl::c_any_of().
template <typename C, typename EqualityComparable>
bool c_linear_search(const C& c, EqualityComparable&& value) {
return linear_search(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<EqualityComparable>(value));
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_linear_search(
const C& c, EqualityComparable&& value) {
return absl::linear_search(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<EqualityComparable>(value));
}
//------------------------------------------------------------------------------
@@ -145,8 +150,9 @@ bool c_linear_search(const C& c, EqualityComparable&& value) {
// Container-based version of the <iterator> `std::distance()` function to
// return the number of elements within a container.
template <typename C>
container_algorithm_internal::ContainerDifferenceType<const C> c_distance(
const C& c) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
container_algorithm_internal::ContainerDifferenceType<const C>
c_distance(const C& c) {
return std::distance(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c));
}
@@ -160,7 +166,7 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_distance(
// Container-based version of the <algorithm> `std::all_of()` function to
// test if all elements within a container satisfy a condition.
template <typename C, typename Pred>
bool c_all_of(const C& c, Pred&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_all_of(const C& c, Pred&& pred) {
return std::all_of(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<Pred>(pred));
@@ -171,7 +177,7 @@ bool c_all_of(const C& c, Pred&& pred) {
// Container-based version of the <algorithm> `std::any_of()` function to
// test if any element in a container fulfills a condition.
template <typename C, typename Pred>
bool c_any_of(const C& c, Pred&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_any_of(const C& c, Pred&& pred) {
return std::any_of(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<Pred>(pred));
@@ -182,7 +188,7 @@ bool c_any_of(const C& c, Pred&& pred) {
// Container-based version of the <algorithm> `std::none_of()` function to
// test if no elements in a container fulfill a condition.
template <typename C, typename Pred>
bool c_none_of(const C& c, Pred&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_none_of(const C& c, Pred&& pred) {
return std::none_of(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<Pred>(pred));
@@ -193,7 +199,8 @@ bool c_none_of(const C& c, Pred&& pred) {
// Container-based version of the <algorithm> `std::for_each()` function to
// apply a function to a container's elements.
template <typename C, typename Function>
decay_t<Function> c_for_each(C&& c, Function&& f) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<Function> c_for_each(C&& c,
Function&& f) {
return std::for_each(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<Function>(f));
@@ -204,18 +211,33 @@ decay_t<Function> c_for_each(C&& c, Function&& f) {
// Container-based version of the <algorithm> `std::find()` function to find
// the first element containing the passed value within a container value.
template <typename C, typename T>
container_algorithm_internal::ContainerIter<C> c_find(C& c, T&& value) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<C>
c_find(C& c, T&& value) {
return std::find(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<T>(value));
}
// c_contains()
//
// Container-based version of the <algorithm> `std::ranges::contains()` C++23
// function to search a container for a value.
template <typename Sequence, typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains(const Sequence& sequence,
T&& value) {
return absl::c_find(sequence, std::forward<T>(value)) !=
container_algorithm_internal::c_end(sequence);
}
// c_find_if()
//
// Container-based version of the <algorithm> `std::find_if()` function to find
// the first element in a container matching the given condition.
template <typename C, typename Pred>
container_algorithm_internal::ContainerIter<C> c_find_if(C& c, Pred&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<C>
c_find_if(C& c, Pred&& pred) {
return std::find_if(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<Pred>(pred));
@@ -226,8 +248,9 @@ container_algorithm_internal::ContainerIter<C> c_find_if(C& c, Pred&& pred) {
// Container-based version of the <algorithm> `std::find_if_not()` function to
// find the first element in a container not matching the given condition.
template <typename C, typename Pred>
container_algorithm_internal::ContainerIter<C> c_find_if_not(C& c,
Pred&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<C>
c_find_if_not(C& c, Pred&& pred) {
return std::find_if_not(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<Pred>(pred));
@@ -238,8 +261,9 @@ container_algorithm_internal::ContainerIter<C> c_find_if_not(C& c,
// Container-based version of the <algorithm> `std::find_end()` function to
// find the last subsequence within a container.
template <typename Sequence1, typename Sequence2>
container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
Sequence1& sequence, Sequence2& subsequence) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence1>
c_find_end(Sequence1& sequence, Sequence2& subsequence) {
return std::find_end(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
container_algorithm_internal::c_begin(subsequence),
@@ -249,8 +273,10 @@ container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
// Overload of c_find_end() for using a predicate evaluation other than `==` as
// the function's test condition.
template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence1>
c_find_end(Sequence1& sequence, Sequence2& subsequence,
BinaryPredicate&& pred) {
return std::find_end(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
container_algorithm_internal::c_begin(subsequence),
@@ -264,8 +290,9 @@ container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
// find the first element within the container that is also within the options
// container.
template <typename C1, typename C2>
container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container,
C2& options) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<C1>
c_find_first_of(C1& container, const C2& options) {
return std::find_first_of(container_algorithm_internal::c_begin(container),
container_algorithm_internal::c_end(container),
container_algorithm_internal::c_begin(options),
@@ -275,8 +302,9 @@ container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container,
// Overload of c_find_first_of() for using a predicate evaluation other than
// `==` as the function's test condition.
template <typename C1, typename C2, typename BinaryPredicate>
container_algorithm_internal::ContainerIter<C1> c_find_first_of(
C1& container, C2& options, BinaryPredicate&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<C1>
c_find_first_of(C1& container, const C2& options, BinaryPredicate&& pred) {
return std::find_first_of(container_algorithm_internal::c_begin(container),
container_algorithm_internal::c_end(container),
container_algorithm_internal::c_begin(options),
@@ -289,8 +317,9 @@ container_algorithm_internal::ContainerIter<C1> c_find_first_of(
// Container-based version of the <algorithm> `std::adjacent_find()` function to
// find equal adjacent elements within a container.
template <typename Sequence>
container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
Sequence& sequence) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence>
c_adjacent_find(Sequence& sequence) {
return std::adjacent_find(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence));
}
@@ -298,8 +327,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
// Overload of c_adjacent_find() for using a predicate evaluation other than
// `==` as the function's test condition.
template <typename Sequence, typename BinaryPredicate>
container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
Sequence& sequence, BinaryPredicate&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence>
c_adjacent_find(Sequence& sequence, BinaryPredicate&& pred) {
return std::adjacent_find(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<BinaryPredicate>(pred));
@@ -310,8 +340,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
// Container-based version of the <algorithm> `std::count()` function to count
// values that match within a container.
template <typename C, typename T>
container_algorithm_internal::ContainerDifferenceType<const C> c_count(
const C& c, T&& value) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerDifferenceType<const C>
c_count(const C& c, T&& value) {
return std::count(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<T>(value));
@@ -322,8 +353,9 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count(
// Container-based version of the <algorithm> `std::count_if()` function to
// count values matching a condition within a container.
template <typename C, typename Pred>
container_algorithm_internal::ContainerDifferenceType<const C> c_count_if(
const C& c, Pred&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerDifferenceType<const C>
c_count_if(const C& c, Pred&& pred) {
return std::count_if(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<Pred>(pred));
@@ -335,8 +367,9 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count_if(
// return the first element where two ordered containers differ. Applies `==` to
// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
template <typename C1, typename C2>
container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1,
C2& c2) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIterPairType<C1, C2>
c_mismatch(C1& c1, C2& c2) {
return std::mismatch(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
@@ -347,8 +380,9 @@ container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1,
// the function's test condition. Applies `pred`to the first N elements of `c1`
// and `c2`, where N = min(size(c1), size(c2)).
template <typename C1, typename C2, typename BinaryPredicate>
container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(
C1& c1, C2& c2, BinaryPredicate pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIterPairType<C1, C2>
c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) {
return std::mismatch(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
@@ -360,7 +394,7 @@ container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(
// Container-based version of the <algorithm> `std::equal()` function to
// test whether two containers are equal.
template <typename C1, typename C2>
bool c_equal(const C1& c1, const C2& c2) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2) {
return std::equal(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
@@ -370,7 +404,8 @@ bool c_equal(const C1& c1, const C2& c2) {
// Overload of c_equal() for using a predicate evaluation other than `==` as
// the function's test condition.
template <typename C1, typename C2, typename BinaryPredicate>
bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2,
BinaryPredicate&& pred) {
return std::equal(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
@@ -383,7 +418,8 @@ bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
// Container-based version of the <algorithm> `std::is_permutation()` function
// to test whether a container is a permutation of another.
template <typename C1, typename C2>
bool c_is_permutation(const C1& c1, const C2& c2) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(const C1& c1,
const C2& c2) {
return std::is_permutation(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
@@ -393,7 +429,8 @@ bool c_is_permutation(const C1& c1, const C2& c2) {
// Overload of c_is_permutation() for using a predicate evaluation other than
// `==` as the function's test condition.
template <typename C1, typename C2, typename BinaryPredicate>
bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(
const C1& c1, const C2& c2, BinaryPredicate&& pred) {
return std::is_permutation(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
@@ -406,8 +443,9 @@ bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
// Container-based version of the <algorithm> `std::search()` function to search
// a container for a subsequence.
template <typename Sequence1, typename Sequence2>
container_algorithm_internal::ContainerIter<Sequence1> c_search(
Sequence1& sequence, Sequence2& subsequence) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence1>
c_search(Sequence1& sequence, Sequence2& subsequence) {
return std::search(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
container_algorithm_internal::c_begin(subsequence),
@@ -417,8 +455,10 @@ container_algorithm_internal::ContainerIter<Sequence1> c_search(
// Overload of c_search() for using a predicate evaluation other than
// `==` as the function's test condition.
template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
container_algorithm_internal::ContainerIter<Sequence1> c_search(
Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence1>
c_search(Sequence1& sequence, Sequence2& subsequence,
BinaryPredicate&& pred) {
return std::search(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
container_algorithm_internal::c_begin(subsequence),
@@ -426,13 +466,35 @@ container_algorithm_internal::ContainerIter<Sequence1> c_search(
std::forward<BinaryPredicate>(pred));
}
// c_contains_subrange()
//
// Container-based version of the <algorithm> `std::ranges::contains_subrange()`
// C++23 function to search a container for a subsequence.
template <typename Sequence1, typename Sequence2>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange(
Sequence1& sequence, Sequence2& subsequence) {
return absl::c_search(sequence, subsequence) !=
container_algorithm_internal::c_end(sequence);
}
// Overload of c_contains_subrange() for using a predicate evaluation other than
// `==` as the function's test condition.
template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange(
Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
return absl::c_search(sequence, subsequence,
std::forward<BinaryPredicate>(pred)) !=
container_algorithm_internal::c_end(sequence);
}
// c_search_n()
//
// Container-based version of the <algorithm> `std::search_n()` function to
// search a container for the first sequence of N elements.
template <typename Sequence, typename Size, typename T>
container_algorithm_internal::ContainerIter<Sequence> c_search_n(
Sequence& sequence, Size count, T&& value) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence>
c_search_n(Sequence& sequence, Size count, T&& value) {
return std::search_n(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence), count,
std::forward<T>(value));
@@ -442,8 +504,10 @@ container_algorithm_internal::ContainerIter<Sequence> c_search_n(
// `==` as the function's test condition.
template <typename Sequence, typename Size, typename T,
typename BinaryPredicate>
container_algorithm_internal::ContainerIter<Sequence> c_search_n(
Sequence& sequence, Size count, T&& value, BinaryPredicate&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence>
c_search_n(Sequence& sequence, Size count, T&& value,
BinaryPredicate&& pred) {
return std::search_n(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence), count,
std::forward<T>(value),
@@ -1500,8 +1564,9 @@ c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) {
// to return an iterator pointing to the element with the smallest value, using
// `operator<` to make the comparisons.
template <typename Sequence>
container_algorithm_internal::ContainerIter<Sequence> c_min_element(
Sequence& sequence) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
container_algorithm_internal::ContainerIter<Sequence>
c_min_element(Sequence& sequence) {
return std::min_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence));
}
@@ -1509,8 +1574,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_min_element(
// Overload of c_min_element() for performing a `comp` comparison other than
// `operator<`.
template <typename Sequence, typename LessThan>
container_algorithm_internal::ContainerIter<Sequence> c_min_element(
Sequence& sequence, LessThan&& comp) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
container_algorithm_internal::ContainerIter<Sequence>
c_min_element(Sequence& sequence, LessThan&& comp) {
return std::min_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<LessThan>(comp));
@@ -1522,8 +1588,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_min_element(
// to return an iterator pointing to the element with the largest value, using
// `operator<` to make the comparisons.
template <typename Sequence>
container_algorithm_internal::ContainerIter<Sequence> c_max_element(
Sequence& sequence) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
container_algorithm_internal::ContainerIter<Sequence>
c_max_element(Sequence& sequence) {
return std::max_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence));
}
@@ -1531,8 +1598,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element(
// Overload of c_max_element() for performing a `comp` comparison other than
// `operator<`.
template <typename Sequence, typename LessThan>
container_algorithm_internal::ContainerIter<Sequence> c_max_element(
Sequence& sequence, LessThan&& comp) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
container_algorithm_internal::ContainerIter<Sequence>
c_max_element(Sequence& sequence, LessThan&& comp) {
return std::max_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<LessThan>(comp));
@@ -1545,8 +1613,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element(
// smallest and largest values, respectively, using `operator<` to make the
// comparisons.
template <typename C>
container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
C& c) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
container_algorithm_internal::ContainerIterPairType<C, C>
c_minmax_element(C& c) {
return std::minmax_element(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c));
}
@@ -1554,8 +1623,9 @@ container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
// Overload of c_minmax_element() for performing `comp` comparisons other than
// `operator<`.
template <typename C, typename LessThan>
container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
C& c, LessThan&& comp) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
container_algorithm_internal::ContainerIterPairType<C, C>
c_minmax_element(C& c, LessThan&& comp) {
return std::minmax_element(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<LessThan>(comp));
+274
View File
@@ -15,6 +15,7 @@
#include "absl/algorithm/container.h"
#include <algorithm>
#include <array>
#include <functional>
#include <initializer_list>
#include <iterator>
@@ -31,6 +32,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/casts.h"
#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/memory/memory.h"
#include "absl/types/span.h"
@@ -113,6 +115,11 @@ TEST_F(NonMutatingTest, FindReturnsCorrectType) {
absl::c_find(absl::implicit_cast<const std::list<int>&>(sequence_), 3);
}
TEST_F(NonMutatingTest, Contains) {
EXPECT_TRUE(absl::c_contains(container_, 3));
EXPECT_FALSE(absl::c_contains(container_, 4));
}
TEST_F(NonMutatingTest, FindIf) { absl::c_find_if(container_, Predicate); }
TEST_F(NonMutatingTest, FindIfNot) {
@@ -132,11 +139,13 @@ TEST_F(NonMutatingTest, FindEndWithPredicate) {
TEST_F(NonMutatingTest, FindFirstOf) {
absl::c_find_first_of(container_, sequence_);
absl::c_find_first_of(sequence_, container_);
absl::c_find_first_of(sequence_, std::array<int, 2>{1, 2});
}
TEST_F(NonMutatingTest, FindFirstOfWithPredicate) {
absl::c_find_first_of(container_, sequence_, BinPredicate);
absl::c_find_first_of(sequence_, container_, BinPredicate);
absl::c_find_first_of(sequence_, std::array<int, 2>{1, 2}, BinPredicate);
}
TEST_F(NonMutatingTest, AdjacentFind) { absl::c_adjacent_find(sequence_); }
@@ -305,6 +314,17 @@ TEST_F(NonMutatingTest, SearchWithPredicate) {
absl::c_search(vector_, sequence_, BinPredicate);
}
TEST_F(NonMutatingTest, ContainsSubrange) {
EXPECT_TRUE(absl::c_contains_subrange(sequence_, vector_));
EXPECT_TRUE(absl::c_contains_subrange(vector_, sequence_));
EXPECT_TRUE(absl::c_contains_subrange(array_, sequence_));
}
TEST_F(NonMutatingTest, ContainsSubrangeWithPredicate) {
EXPECT_TRUE(absl::c_contains_subrange(sequence_, vector_, Equals));
EXPECT_TRUE(absl::c_contains_subrange(vector_, sequence_, Equals));
}
TEST_F(NonMutatingTest, SearchN) { absl::c_search_n(sequence_, 3, 1); }
TEST_F(NonMutatingTest, SearchNWithPredicate) {
@@ -1144,4 +1164,258 @@ TEST(MutatingTest, PermutationOperations) {
EXPECT_EQ(initial, permuted);
}
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
TEST(ConstexprTest, Distance) {
// Works at compile time with constexpr containers.
static_assert(absl::c_distance(std::array<int, 3>()) == 3);
}
TEST(ConstexprTest, MinElement) {
constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(*absl::c_min_element(kArray) == 1);
}
TEST(ConstexprTest, MinElementWithPredicate) {
constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(*absl::c_min_element(kArray, std::greater<int>()) == 3);
}
TEST(ConstexprTest, MaxElement) {
constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(*absl::c_max_element(kArray) == 3);
}
TEST(ConstexprTest, MaxElementWithPredicate) {
constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(*absl::c_max_element(kArray, std::greater<int>()) == 1);
}
TEST(ConstexprTest, MinMaxElement) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
constexpr auto kMinMaxPair = absl::c_minmax_element(kArray);
static_assert(*kMinMaxPair.first == 1);
static_assert(*kMinMaxPair.second == 3);
}
TEST(ConstexprTest, MinMaxElementWithPredicate) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
constexpr auto kMinMaxPair =
absl::c_minmax_element(kArray, std::greater<int>());
static_assert(*kMinMaxPair.first == 3);
static_assert(*kMinMaxPair.second == 1);
}
#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
// ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
TEST(ConstexprTest, LinearSearch) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(absl::c_linear_search(kArray, 3));
static_assert(!absl::c_linear_search(kArray, 4));
}
TEST(ConstexprTest, AllOf) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(!absl::c_all_of(kArray, [](int x) { return x > 1; }));
static_assert(absl::c_all_of(kArray, [](int x) { return x > 0; }));
}
TEST(ConstexprTest, AnyOf) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(absl::c_any_of(kArray, [](int x) { return x > 2; }));
static_assert(!absl::c_any_of(kArray, [](int x) { return x > 5; }));
}
TEST(ConstexprTest, NoneOf) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(!absl::c_none_of(kArray, [](int x) { return x > 2; }));
static_assert(absl::c_none_of(kArray, [](int x) { return x > 5; }));
}
TEST(ConstexprTest, ForEach) {
static constexpr std::array<int, 3> kArray = [] {
std::array<int, 3> array = {1, 2, 3};
absl::c_for_each(array, [](int& x) { x += 1; });
return array;
}();
static_assert(kArray == std::array{2, 3, 4});
}
TEST(ConstexprTest, Find) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(absl::c_find(kArray, 1) == kArray.begin());
static_assert(absl::c_find(kArray, 4) == kArray.end());
}
TEST(ConstexprTest, Contains) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(absl::c_contains(kArray, 1));
static_assert(!absl::c_contains(kArray, 4));
}
TEST(ConstexprTest, FindIf) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(absl::c_find_if(kArray, [](int x) { return x > 2; }) ==
kArray.begin() + 2);
static_assert(absl::c_find_if(kArray, [](int x) { return x > 5; }) ==
kArray.end());
}
TEST(ConstexprTest, FindIfNot) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(absl::c_find_if_not(kArray, [](int x) { return x > 1; }) ==
kArray.begin());
static_assert(absl::c_find_if_not(kArray, [](int x) { return x > 0; }) ==
kArray.end());
}
TEST(ConstexprTest, FindEnd) {
static constexpr std::array<int, 5> kHaystack = {1, 2, 3, 2, 3};
static constexpr std::array<int, 2> kNeedle = {2, 3};
static_assert(absl::c_find_end(kHaystack, kNeedle) == kHaystack.begin() + 3);
}
TEST(ConstexprTest, FindFirstOf) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(absl::c_find_first_of(kArray, kArray) == kArray.begin());
}
TEST(ConstexprTest, AdjacentFind) {
static constexpr std::array<int, 4> kArray = {1, 2, 2, 3};
static_assert(absl::c_adjacent_find(kArray) == kArray.begin() + 1);
}
TEST(ConstexprTest, AdjacentFindWithPredicate) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(absl::c_adjacent_find(kArray, std::less<int>()) ==
kArray.begin());
}
TEST(ConstexprTest, Count) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(absl::c_count(kArray, 1) == 1);
static_assert(absl::c_count(kArray, 2) == 1);
static_assert(absl::c_count(kArray, 3) == 1);
static_assert(absl::c_count(kArray, 4) == 0);
}
TEST(ConstexprTest, CountIf) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(absl::c_count_if(kArray, [](int x) { return x > 0; }) == 3);
static_assert(absl::c_count_if(kArray, [](int x) { return x > 1; }) == 2);
}
TEST(ConstexprTest, Mismatch) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(absl::c_mismatch(kArray1, kArray2) ==
std::pair{kArray1.end(), kArray2.end()});
static_assert(absl::c_mismatch(kArray1, kArray3) ==
std::pair{kArray1.begin(), kArray3.begin()});
}
TEST(ConstexprTest, MismatchWithPredicate) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(absl::c_mismatch(kArray1, kArray2, std::not_equal_to<int>()) ==
std::pair{kArray1.begin(), kArray2.begin()});
static_assert(absl::c_mismatch(kArray1, kArray3, std::not_equal_to<int>()) ==
std::pair{kArray1.end(), kArray3.end()});
}
TEST(ConstexprTest, Equal) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(absl::c_equal(kArray1, kArray2));
static_assert(!absl::c_equal(kArray1, kArray3));
}
TEST(ConstexprTest, EqualWithPredicate) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(!absl::c_equal(kArray1, kArray2, std::not_equal_to<int>()));
static_assert(absl::c_equal(kArray1, kArray3, std::not_equal_to<int>()));
}
TEST(ConstexprTest, IsPermutation) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {3, 2, 1};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(absl::c_is_permutation(kArray1, kArray2));
static_assert(!absl::c_is_permutation(kArray1, kArray3));
}
TEST(ConstexprTest, IsPermutationWithPredicate) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {3, 2, 1};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(absl::c_is_permutation(kArray1, kArray2, std::equal_to<int>()));
static_assert(
!absl::c_is_permutation(kArray1, kArray3, std::equal_to<int>()));
}
TEST(ConstexprTest, Search) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(absl::c_search(kArray1, kArray2) == kArray1.begin());
static_assert(absl::c_search(kArray1, kArray3) == kArray1.end());
}
TEST(ConstexprTest, SearchWithPredicate) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(absl::c_search(kArray1, kArray2, std::not_equal_to<int>()) ==
kArray1.end());
static_assert(absl::c_search(kArray1, kArray3, std::not_equal_to<int>()) ==
kArray1.begin());
}
TEST(ConstexprTest, ContainsSubrange) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(absl::c_contains_subrange(kArray1, kArray2));
static_assert(!absl::c_contains_subrange(kArray1, kArray3));
}
TEST(ConstexprTest, ContainsSubrangeWithPredicate) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(
!absl::c_contains_subrange(kArray1, kArray2, std::not_equal_to<>()));
static_assert(
absl::c_contains_subrange(kArray1, kArray3, std::not_equal_to<>()));
}
TEST(ConstexprTest, SearchN) {
static constexpr std::array<int, 4> kArray = {1, 2, 2, 3};
static_assert(absl::c_search_n(kArray, 1, 1) == kArray.begin());
static_assert(absl::c_search_n(kArray, 2, 2) == kArray.begin() + 1);
static_assert(absl::c_search_n(kArray, 1, 4) == kArray.end());
}
TEST(ConstexprTest, SearchNWithPredicate) {
static constexpr std::array<int, 4> kArray = {1, 2, 2, 3};
static_assert(absl::c_search_n(kArray, 1, 1, std::not_equal_to<int>()) ==
kArray.begin() + 1);
static_assert(absl::c_search_n(kArray, 2, 2, std::not_equal_to<int>()) ==
kArray.end());
static_assert(absl::c_search_n(kArray, 1, 4, std::not_equal_to<int>()) ==
kArray.begin());
}
#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
// ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
} // namespace
+162 -60
View File
@@ -87,6 +87,7 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":config",
":core_headers",
"//absl/meta:type_traits",
],
@@ -162,6 +163,9 @@ cc_library(
cc_library(
name = "dynamic_annotations",
srcs = [
"internal/dynamic_annotations.h",
],
hdrs = [
"dynamic_annotations.h",
],
@@ -203,9 +207,9 @@ cc_library(
"//conditions:default": [],
}),
linkopts = select({
"//absl:msvc_compiler": [],
"//absl:clang-cl_compiler": [],
"//absl:wasm": [],
"@rules_cc//cc/compiler:msvc-cl": [],
"@rules_cc//cc/compiler:clang-cl": [],
"@rules_cc//cc/compiler:emscripten": [],
"//conditions:default": ["-pthread"],
}) + ABSL_DEFAULT_LINKOPTS,
visibility = [
@@ -264,17 +268,17 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
linkopts = select({
"//absl:msvc_compiler": [
"@rules_cc//cc/compiler:msvc-cl": [
"-DEFAULTLIB:advapi32.lib",
],
"//absl:clang-cl_compiler": [
"@rules_cc//cc/compiler:clang-cl": [
"-DEFAULTLIB:advapi32.lib",
],
"//absl:mingw_compiler": [
"-DEFAULTLIB:advapi32.lib",
"-ladvapi32",
],
"//absl:wasm": [],
"@rules_cc//cc/compiler:emscripten": [],
"//conditions:default": ["-pthread"],
}) + ABSL_DEFAULT_LINKOPTS,
deps = [
@@ -315,8 +319,8 @@ cc_test(
":atomic_hook",
":atomic_hook_test_helper",
":core_headers",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -331,8 +335,20 @@ cc_test(
deps = [
":base",
":core_headers",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
cc_test(
name = "c_header_test",
srcs = ["c_header_test.c"],
tags = [
"no_test_wasm",
],
deps = [
":config",
":core_headers",
],
)
@@ -359,8 +375,8 @@ cc_test(
deps = [
":config",
":throw_delegate",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -373,8 +389,8 @@ cc_test(
deps = [
":errno_saver",
":strerror",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -389,7 +405,7 @@ cc_library(
],
deps = [
":config",
"@com_google_googletest//:gtest",
"@googletest//:gtest",
],
)
@@ -416,7 +432,7 @@ cc_library(
"//absl/meta:type_traits",
"//absl/strings",
"//absl/utility",
"@com_google_googletest//:gtest",
"@googletest//:gtest",
],
)
@@ -428,8 +444,8 @@ cc_test(
deps = [
":exception_safety_testing",
"//absl/memory",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -446,8 +462,8 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":base_internal",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -461,8 +477,8 @@ cc_test(
":base_internal",
"//absl/memory",
"//absl/strings",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -480,7 +496,7 @@ cc_library(
":config",
":core_headers",
"//absl/synchronization",
"@com_google_googletest//:gtest",
"@googletest//:gtest",
],
alwayslink = 1,
)
@@ -500,8 +516,8 @@ cc_test(
":config",
":core_headers",
"//absl/synchronization",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -520,7 +536,7 @@ cc_library(
":no_destructor",
":raw_logging_internal",
"//absl/synchronization",
"@com_github_google_benchmark//:benchmark_main",
"@google_benchmark//:benchmark_main",
],
alwayslink = 1,
)
@@ -560,8 +576,8 @@ cc_test(
deps = [
":config",
":endian",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -573,8 +589,8 @@ cc_test(
deps = [
":config",
"//absl/synchronization:thread_pool",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -587,8 +603,8 @@ cc_test(
":base",
":core_headers",
"//absl/synchronization",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -601,8 +617,8 @@ cc_test(
":config",
":no_destructor",
":raw_logging_internal",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -617,7 +633,7 @@ cc_binary(
deps = [
":no_destructor",
":raw_logging_internal",
"@com_github_google_benchmark//:benchmark_main",
"@google_benchmark//:benchmark_main",
],
)
@@ -627,8 +643,18 @@ cc_test(
deps = [
":core_headers",
":nullability",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
cc_test(
name = "nullability_default_nonnull_test",
srcs = ["nullability_default_nonnull_test.cc"],
deps = [
":nullability",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -640,8 +666,8 @@ cc_test(
deps = [
":raw_logging_internal",
"//absl/strings",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -654,8 +680,8 @@ cc_test(
deps = [
":base",
"//absl/synchronization",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -688,8 +714,8 @@ cc_test(
":base",
":core_headers",
"//absl/synchronization",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -703,8 +729,8 @@ cc_test(
deps = [
":base",
"//absl/synchronization",
"@com_github_google_benchmark//:benchmark_main",
"@com_google_googletest//:gtest",
"@google_benchmark//:benchmark_main",
"@googletest//:gtest",
],
)
@@ -731,8 +757,8 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":scoped_set_env",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -747,8 +773,8 @@ cc_test(
"//absl/flags:flag_internal",
"//absl/flags:marshalling",
"//absl/strings",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -777,8 +803,8 @@ cc_test(
deps = [
":strerror",
"//absl/strings",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -792,7 +818,7 @@ cc_binary(
visibility = ["//visibility:private"],
deps = [
":strerror",
"@com_github_google_benchmark//:benchmark_main",
"@google_benchmark//:benchmark_main",
],
)
@@ -817,8 +843,8 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":fast_type_id",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -845,8 +871,43 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":prefetch",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
cc_library(
name = "poison",
srcs = [
"internal/poison.cc",
],
hdrs = ["internal/poison.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl:__subpackages__",
],
deps = [
":config",
":core_headers",
":malloc_internal",
],
)
cc_test(
name = "poison_test",
size = "small",
timeout = "short",
srcs = [
"internal/poison_test.cc",
],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":config",
":poison",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -860,8 +921,8 @@ cc_test(
deps = [
":core_headers",
"//absl/strings",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -874,7 +935,48 @@ cc_test(
deps = [
":core_headers",
"//absl/types:optional",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
cc_library(
name = "tracing_internal",
srcs = ["internal/tracing.cc"],
hdrs = ["internal/tracing.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl:__subpackages__",
],
deps = [
"//absl/base:config",
"//absl/base:core_headers",
],
)
cc_test(
name = "tracing_internal_weak_test",
srcs = ["internal/tracing_weak_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":tracing_internal",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
cc_test(
name = "tracing_internal_strong_test",
srcs = ["internal/tracing_strong_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":config",
":core_headers",
":tracing_internal",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
-329
View File
@@ -1,329 +0,0 @@
# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//third_party/abseil-cpp/absl.gni")
absl_source_set("atomic_hook") {
public = [ "internal/atomic_hook.h" ]
public_deps = [
":config",
":core_headers",
]
visibility = [ "//third_party/abseil-cpp/absl/*" ]
}
absl_source_set("errno_saver") {
public = [ "internal/errno_saver.h" ]
public_deps = [ ":config" ]
visibility = [ "//third_party/abseil-cpp/absl/*" ]
}
absl_source_set("log_severity") {
sources = [ "log_severity.cc" ]
public = [ "log_severity.h" ]
public_deps = [
":config",
":core_headers",
]
}
absl_source_set("no_destructor") {
public = [ "no_destructor.h" ]
deps = [
":config",
":nullability",
]
}
absl_source_set("nullability") {
sources = [ "internal/nullability_impl.h" ]
public = [ "nullability.h" ]
deps = [
":core_headers",
"//third_party/abseil-cpp/absl/meta:type_traits",
]
}
absl_source_set("raw_logging_internal") {
sources = [ "internal/raw_logging.cc" ]
public = [ "internal/raw_logging.h" ]
public_deps = [
":atomic_hook",
":config",
":core_headers",
":errno_saver",
":log_severity",
]
visibility = [ "//third_party/abseil-cpp/absl/*" ]
}
absl_source_set("spinlock_wait") {
sources = [
"internal/spinlock_akaros.inc",
"internal/spinlock_linux.inc",
"internal/spinlock_posix.inc",
"internal/spinlock_wait.cc",
"internal/spinlock_win32.inc",
]
public = [ "internal/spinlock_wait.h" ]
deps = [
":base_internal",
":core_headers",
":errno_saver",
]
visibility = [ "//third_party/abseil-cpp/absl/base:*" ]
}
absl_source_set("config") {
public = [
"config.h",
"options.h",
"policy_checks.h",
]
}
absl_source_set("cycleclock_internal") {
public = [
"internal/cycleclock_config.h",
"internal/unscaledcycleclock_config.h",
]
visibility = [ "//third_party/abseil-cpp/absl/*" ]
deps = [
":base_internal",
":config",
]
}
absl_source_set("dynamic_annotations") {
public = [ "dynamic_annotations.h" ]
# Abseil's dynamic annotations are only visible inside Abseil because
# their usage is deprecated in Chromium (see README.chromium for more info).
visibility = [ "//third_party/abseil-cpp/absl/*" ]
deps = [
":config",
":core_headers",
]
}
absl_source_set("core_headers") {
public = [
"attributes.h",
"const_init.h",
"macros.h",
"optimization.h",
"port.h",
"thread_annotations.h",
]
public_deps = [ ":config" ]
}
absl_source_set("malloc_internal") {
sources = [ "internal/low_level_alloc.cc" ]
public = [
"internal/direct_mmap.h",
"internal/low_level_alloc.h",
]
public_deps = [
":base",
":base_internal",
":config",
":core_headers",
":dynamic_annotations",
":raw_logging_internal",
]
}
absl_source_set("base_internal") {
public = [
"internal/hide_ptr.h",
"internal/identity.h",
"internal/inline_variable.h",
"internal/invoke.h",
"internal/scheduling_mode.h",
]
public_deps = [
":config",
"//third_party/abseil-cpp/absl/meta:type_traits",
]
visibility = [ "//third_party/abseil-cpp/absl/*" ]
}
absl_source_set("base") {
sources = [
"internal/cycleclock.cc",
"internal/spinlock.cc",
"internal/sysinfo.cc",
"internal/thread_identity.cc",
"internal/unscaledcycleclock.cc",
]
public = [
"call_once.h",
"casts.h",
"internal/cycleclock.h",
"internal/low_level_scheduling.h",
"internal/per_thread_tls.h",
"internal/spinlock.h",
"internal/sysinfo.h",
"internal/thread_identity.h",
"internal/tsan_mutex_interface.h",
"internal/unscaledcycleclock.h",
]
# TODO(mbonadei): The bazel file has:
# "-DEFAULTLIB:advapi32.lib"
# understand if this is needed here as well.
public_deps = [
":atomic_hook",
":base_internal",
":config",
":core_headers",
":cycleclock_internal",
":dynamic_annotations",
":log_severity",
":nullability",
":raw_logging_internal",
":spinlock_wait",
"//third_party/abseil-cpp/absl/meta:type_traits",
]
}
absl_source_set("throw_delegate") {
sources = [ "internal/throw_delegate.cc" ]
public = [ "internal/throw_delegate.h" ]
public_deps = [
":config",
":raw_logging_internal",
]
visibility = [ "//third_party/abseil-cpp/absl/*" ]
}
absl_source_set("exception_testing") {
testonly = true
public = [ "internal/exception_testing.h" ]
public_deps = [ ":config" ]
visibility = [ "//third_party/abseil-cpp/absl/*" ]
}
absl_source_set("pretty_function") {
public = [ "internal/pretty_function.h" ]
visibility = [ "//third_party/abseil-cpp/absl/*" ]
}
# TODO(mbonadei): This target throws by design. We should probably
# just remove it.
# source_set("exception_safety_testing") {
# testonly = true
# configs -= [ "//build/config/compiler:chromium_code" ]
# configs += [
# "//build/config/compiler:no_chromium_code",
# "//third_party/abseil-cpp:absl_test_cflags_cc",
# ]
# public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
# sources = [
# "internal/exception_safety_testing.cc",
# ]
# public = [
# "internal/exception_safety_testing.h",
# ]
# deps = [
# ":config",
# ":pretty_function",
# "//third_party/abseil-cpp/absl/memory",
# "//third_party/abseil-cpp/absl/meta:type_traits",
# "//third_party/abseil-cpp/absl/strings",
# "//third_party/abseil-cpp/absl/utility",
# "//third_party/googletest:gtest",
# ]
# }
absl_source_set("spinlock_test_common") {
testonly = true
sources = [ "spinlock_test_common.cc" ]
deps = [
":base",
":base_internal",
":config",
":core_headers",
"//third_party/abseil-cpp/absl/synchronization",
"//third_party/googletest:gtest",
]
}
absl_source_set("endian") {
public = [
"internal/endian.h",
"internal/unaligned_access.h",
]
public_deps = [
":base",
":config",
":core_headers",
":nullability",
]
}
absl_source_set("scoped_set_env") {
testonly = true
public = [ "internal/scoped_set_env.h" ]
sources = [ "internal/scoped_set_env.cc" ]
public_deps = [ ":config" ]
deps = [ ":raw_logging_internal" ]
visibility = [ "//third_party/abseil-cpp/absl/*" ]
}
absl_source_set("strerror") {
sources = [ "internal/strerror.cc" ]
public = [ "internal/strerror.h" ]
public_deps = [ ":config" ]
deps = [
":core_headers",
":errno_saver",
]
visibility = [ "//third_party/abseil-cpp/absl/*" ]
}
absl_source_set("fast_type_id") {
public = [ "internal/fast_type_id.h" ]
public_deps = [ ":config" ]
visibility = [ "//third_party/abseil-cpp/absl/*" ]
}
absl_source_set("prefetch") {
public = [ "prefetch.h" ]
deps = [
":config",
":core_headers",
]
}
absl_test("prefetch_test") {
sources = [ "prefetch_test.cc" ]
deps = [ ":prefetch" ]
}
absl_test("config_test") {
sources = [ "config_test.cc" ]
deps = [
":config",
"//third_party/abseil-cpp/absl/synchronization:thread_pool",
]
}
absl_test("no_destructor_test") {
sources = [ "no_destructor_test.cc" ]
deps = [
":config",
":no_destructor",
":raw_logging_internal",
]
}
absl_test("nullability_test") {
sources = [ "nullability_test.cc" ]
deps = [
":core_headers",
":nullability",
]
}
+85
View File
@@ -75,6 +75,7 @@ absl_cc_library(
SRCS
"internal/nullability_impl.h"
DEPS
absl::config
absl::core_headers
absl::type_traits
COPTS
@@ -94,6 +95,18 @@ absl_cc_test(
GTest::gtest_main
)
absl_cc_test(
NAME
nullability_default_nonnull_test
SRCS
"nullability_default_nonnull_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
absl::nullability
GTest::gtest_main
)
# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
@@ -149,6 +162,8 @@ absl_cc_library(
dynamic_annotations
HDRS
"dynamic_annotations.h"
SRCS
"internal/dynamic_annotations.h"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
@@ -531,6 +546,7 @@ absl_cc_test(
absl::no_destructor
absl::config
absl::raw_logging_internal
GTest::gmock
GTest::gtest_main
)
@@ -736,3 +752,72 @@ absl_cc_test(
absl::optional
GTest::gtest_main
)
absl_cc_library(
NAME
poison
SRCS
"internal/poison.cc"
HDRS
"internal/poison.h"
COPTS
${ABSL_DEFAULT_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::config
absl::core_headers
absl::malloc_internal
)
absl_cc_test(
NAME
poison_test
SRCS
"internal/poison_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
absl::config
absl::poison
GTest::gtest_main
)
absl_cc_library(
NAME
tracing_internal
HDRS
"internal/tracing.h"
SRCS
"internal/tracing.cc"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
absl::base
)
absl_cc_test(
NAME
tracing_internal_weak_test
SRCS
"internal/tracing_weak_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
absl::base
absl::tracing_internal
GTest::gtest_main
)
absl_cc_test(
NAME
tracing_internal_strong_test
SRCS
"internal/tracing_strong_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
absl::base
absl::tracing_internal
GTest::gtest_main
)
+86 -4
View File
@@ -31,6 +31,8 @@
// `__has_attribute()` first. If the check fails, we check if we are on GCC and
// assume the attribute exists on GCC (which is verified on GCC 4.7).
// SKIP_ABSL_INLINE_NAMESPACE_CHECK
#ifndef ABSL_BASE_ATTRIBUTES_H_
#define ABSL_BASE_ATTRIBUTES_H_
@@ -133,12 +135,14 @@
// Tags a function as weak for the purposes of compilation and linking.
// Weak attributes did not work properly in LLVM's Windows backend before
// 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
// for further information.
// for further information. Weak attributes do not work across DLL boundary.
// The MinGW compiler doesn't complain about the weak attribute until the link
// step, presumably because Windows doesn't use ELF binaries.
#if (ABSL_HAVE_ATTRIBUTE(weak) || \
(defined(__GNUC__) && !defined(__clang__))) && \
(!defined(_WIN32) || (defined(__clang__) && __clang_major__ >= 9)) && \
#if (ABSL_HAVE_ATTRIBUTE(weak) || \
(defined(__GNUC__) && !defined(__clang__))) && \
(!defined(_WIN32) || \
(defined(__clang__) && __clang_major__ >= 9 && \
!defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL))) && \
!defined(__MINGW32__)
#undef ABSL_ATTRIBUTE_WEAK
#define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
@@ -195,6 +199,9 @@
// ABSL_ATTRIBUTE_NORETURN
//
// Tells the compiler that a given function never returns.
//
// Deprecated: Prefer the `[[noreturn]]` attribute standardized by C++11 over
// this macro.
#if ABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_NORETURN __attribute__((noreturn))
#elif defined(_MSC_VER)
@@ -813,14 +820,89 @@
//
// See also the upstream documentation:
// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
// https://learn.microsoft.com/en-us/cpp/code-quality/c26816?view=msvc-170
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound)
#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]]
#elif ABSL_HAVE_CPP_ATTRIBUTE(msvc::lifetimebound)
#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[msvc::lifetimebound]]
#elif ABSL_HAVE_ATTRIBUTE(lifetimebound)
#define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound))
#else
#define ABSL_ATTRIBUTE_LIFETIME_BOUND
#endif
// Internal attribute; name and documentation TBD.
//
// See the upstream documentation:
// https://clang.llvm.org/docs/AttributeReference.html#lifetime_capture_by
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetime_capture_by)
#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner) \
[[clang::lifetime_capture_by(Owner)]]
#else
#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner)
#endif
// ABSL_ATTRIBUTE_VIEW indicates that a type is solely a "view" of data that it
// points to, similarly to a span, string_view, or other non-owning reference
// type.
// This enables diagnosing certain lifetime issues similar to those enabled by
// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as:
//
// struct ABSL_ATTRIBUTE_VIEW StringView {
// template<class R>
// StringView(const R&);
// };
//
// StringView f(std::string s) {
// return s; // warning: address of stack memory returned
// }
//
// We disable this on Clang versions < 13 because of the following
// false-positive:
//
// absl::string_view f(absl::optional<absl::string_view> sv) { return *sv; }
//
// See the following links for details:
// https://reviews.llvm.org/D64448
// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html
#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Pointer) && \
(!defined(__clang_major__) || __clang_major__ >= 13)
#define ABSL_ATTRIBUTE_VIEW [[gsl::Pointer]]
#else
#define ABSL_ATTRIBUTE_VIEW
#endif
// ABSL_ATTRIBUTE_OWNER indicates that a type is a container, smart pointer, or
// similar class that owns all the data that it points to.
// This enables diagnosing certain lifetime issues similar to those enabled by
// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as:
//
// struct ABSL_ATTRIBUTE_VIEW StringView {
// template<class R>
// StringView(const R&);
// };
//
// struct ABSL_ATTRIBUTE_OWNER String {};
//
// StringView f(String s) {
// return s; // warning: address of stack memory returned
// }
//
// We disable this on Clang versions < 13 because of the following
// false-positive:
//
// absl::string_view f(absl::optional<absl::string_view> sv) { return *sv; }
//
// See the following links for details:
// https://reviews.llvm.org/D64448
// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html
#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Owner) && \
(!defined(__clang_major__) || __clang_major__ >= 13)
#define ABSL_ATTRIBUTE_OWNER [[gsl::Owner]]
#else
#define ABSL_ATTRIBUTE_OWNER
#endif
// ABSL_ATTRIBUTE_TRIVIAL_ABI
// Indicates that a type is "trivially relocatable" -- meaning it can be
// relocated without invoking the constructor/destructor, using a form of move
+30
View File
@@ -0,0 +1,30 @@
// Copyright 2024 The Abseil Authors
//
// 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
//
// https://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.
#ifdef __cplusplus
#error This is a C compile test
#endif
// This test ensures that headers that are included in legacy C code are
// compatible with C. Abseil is a C++ library. We do not desire to expand C
// compatibility or keep C compatibility forever. This test only exists to
// ensure C compatibility until it is no longer required. Do not add new code
// that requires C compatibility.
#include "absl/base/attributes.h" // IWYU pragma: keep
#include "absl/base/config.h" // IWYU pragma: keep
#include "absl/base/optimization.h" // IWYU pragma: keep
#include "absl/base/policy_checks.h" // IWYU pragma: keep
#include "absl/base/port.h" // IWYU pragma: keep
int main() { return 0; }
+8 -5
View File
@@ -31,6 +31,8 @@
#include <type_traits>
#include <utility>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/invoke.h"
#include "absl/base/internal/low_level_scheduling.h"
#include "absl/base/internal/raw_logging.h"
@@ -147,10 +149,10 @@ enum {
};
template <typename Callable, typename... Args>
ABSL_ATTRIBUTE_NOINLINE void CallOnceImpl(
absl::Nonnull<std::atomic<uint32_t>*> control,
base_internal::SchedulingMode scheduling_mode, Callable&& fn,
Args&&... args) {
void
CallOnceImpl(absl::Nonnull<std::atomic<uint32_t>*> control,
base_internal::SchedulingMode scheduling_mode, Callable&& fn,
Args&&... args) {
#ifndef NDEBUG
{
uint32_t old_control = control->load(std::memory_order_relaxed);
@@ -209,7 +211,8 @@ void LowLevelCallOnce(absl::Nonnull<absl::once_flag*> flag, Callable&& fn,
} // namespace base_internal
template <typename Callable, typename... Args>
void call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) {
void
call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) {
std::atomic<uint32_t>* once = base_internal::ControlWord(&flag);
uint32_t s = once->load(std::memory_order_acquire);
if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) {
+32 -47
View File
@@ -117,8 +117,8 @@
//
// LTS releases can be obtained from
// https://github.com/abseil/abseil-cpp/releases.
#undef ABSL_LTS_RELEASE_VERSION
#undef ABSL_LTS_RELEASE_PATCH_LEVEL
#define ABSL_LTS_RELEASE_VERSION 20250127
#define ABSL_LTS_RELEASE_PATCH_LEVEL 1
// Helper macro to convert a CPP variable to a string literal.
#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x
@@ -231,12 +231,11 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#endif
// ABSL_HAVE_TLS is defined to 1 when __thread should be supported.
// We assume __thread is supported on Linux or Asylo when compiled with Clang or
// We assume __thread is supported on Linux when compiled with Clang or
// compiled against libstdc++ with _GLIBCXX_HAVE_TLS defined.
#ifdef ABSL_HAVE_TLS
#error ABSL_HAVE_TLS cannot be directly set
#elif (defined(__linux__) || defined(__ASYLO__)) && \
(defined(__clang__) || defined(_GLIBCXX_HAVE_TLS))
#elif (defined(__linux__)) && (defined(__clang__) || defined(_GLIBCXX_HAVE_TLS))
#define ABSL_HAVE_TLS 1
#endif
@@ -275,52 +274,17 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE 1
#endif
// ABSL_HAVE_THREAD_LOCAL
//
// DEPRECATED - `thread_local` is available on all supported platforms.
// Checks whether C++11's `thread_local` storage duration specifier is
// supported.
#ifdef ABSL_HAVE_THREAD_LOCAL
#error ABSL_HAVE_THREAD_LOCAL cannot be directly set
#elif defined(__APPLE__)
// Notes:
// * Xcode's clang did not support `thread_local` until version 8, and
// even then not for all iOS < 9.0.
// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator
// targeting iOS 9.x.
// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time
// making ABSL_HAVE_FEATURE unreliable there.
//
#if ABSL_HAVE_FEATURE(cxx_thread_local) && \
!(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
#else
#define ABSL_HAVE_THREAD_LOCAL 1
#endif
#else // !defined(__APPLE__)
#define ABSL_HAVE_THREAD_LOCAL 1
#endif
// There are platforms for which TLS should not be used even though the compiler
// makes it seem like it's supported (Android NDK < r12b for example).
// This is primarily because of linker problems and toolchain misconfiguration:
// Abseil does not intend to support this indefinitely. Currently, the newest
// toolchain that we intend to support that requires this behavior is the
// r11 NDK - allowing for a 5 year support window on that means this option
// is likely to be removed around June of 2021.
// TLS isn't supported until NDK r12b per
// https://developer.android.com/ndk/downloads/revision_history.html
// Since NDK r16, `__NDK_MAJOR__` and `__NDK_MINOR__` are defined in
// <android/ndk-version.h>. For NDK < r16, users should define these macros,
// e.g. `-D__NDK_MAJOR__=11 -D__NKD_MINOR__=0` for NDK r11.
#if defined(__ANDROID__) && defined(__clang__)
#if __has_include(<android/ndk-version.h>)
#include <android/ndk-version.h>
#endif // __has_include(<android/ndk-version.h>)
#if defined(__ANDROID__) && defined(__clang__) && defined(__NDK_MAJOR__) && \
defined(__NDK_MINOR__) && \
((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1)))
#undef ABSL_HAVE_TLS
#undef ABSL_HAVE_THREAD_LOCAL
#endif
#endif // defined(__ANDROID__) && defined(__clang__)
// ABSL_HAVE_INTRINSIC_INT128
//
@@ -414,9 +378,9 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
defined(_AIX) || defined(__ros__) || defined(__native_client__) || \
defined(__asmjs__) || defined(__EMSCRIPTEN__) || defined(__Fuchsia__) || \
defined(__sun) || defined(__ASYLO__) || defined(__myriad2__) || \
defined(__HAIKU__) || defined(__OpenBSD__) || defined(__NetBSD__) || \
defined(__QNX__) || defined(__VXWORKS__) || defined(__hexagon__)
defined(__sun) || defined(__myriad2__) || defined(__HAIKU__) || \
defined(__OpenBSD__) || defined(__NetBSD__) || defined(__QNX__) || \
defined(__VXWORKS__) || defined(__hexagon__) || defined(__XTENSA__)
#define ABSL_HAVE_MMAP 1
#endif
@@ -962,7 +926,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// https://llvm.org/docs/CompileCudaWithLLVM.html#detecting-clang-vs-nvcc-from-code
#ifdef ABSL_INTERNAL_HAVE_ARM_NEON
#error ABSL_INTERNAL_HAVE_ARM_NEON cannot be directly set
#elif defined(__ARM_NEON) && !defined(__CUDA_ARCH__)
#elif defined(__ARM_NEON) && !(defined(__NVCC__) && defined(__CUDACC__))
#define ABSL_INTERNAL_HAVE_ARM_NEON 1
#endif
@@ -977,6 +941,27 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_HAVE_CONSTANT_EVALUATED 1
#endif
// ABSL_INTERNAL_CONSTEXPR_SINCE_CXXYY is used to conditionally define constexpr
// for different C++ versions.
//
// These macros are an implementation detail and will be unconditionally removed
// once the minimum supported C++ version catches up to a given version.
//
// For this reason, this symbol is considered INTERNAL and code outside of
// Abseil must not use it.
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 constexpr
#else
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
#endif
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 constexpr
#else
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
#endif
// ABSL_INTERNAL_EMSCRIPTEN_VERSION combines Emscripten's three version macros
// into an integer that can be compared against.
#ifdef ABSL_INTERNAL_EMSCRIPTEN_VERSION
+3
View File
@@ -58,6 +58,9 @@
#include <sanitizer/hwasan_interface.h>
#endif
// TODO(rogeeff): Remove after the backward compatibility period.
#include "absl/base/internal/dynamic_annotations.h" // IWYU pragma: export
// -------------------------------------------------------------------------
// Decide which features are enabled.
@@ -0,0 +1,398 @@
// Copyright 2017 The Abseil Authors.
//
// 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
//
// https://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.
// This file defines dynamic annotations for use with dynamic analysis tool
// such as valgrind, PIN, etc.
//
// Dynamic annotation is a source code annotation that affects the generated
// code (that is, the annotation is not a comment). Each such annotation is
// attached to a particular instruction and/or to a particular object (address)
// in the program.
//
// The annotations that should be used by users are macros in all upper-case
// (e.g., ANNOTATE_THREAD_NAME).
//
// Actual implementation of these macros may differ depending on the dynamic
// analysis tool being used.
//
// This file supports the following configurations:
// - Dynamic Annotations enabled (with static thread-safety warnings disabled).
// In this case, macros expand to functions implemented by Thread Sanitizer,
// when building with TSan. When not provided an external implementation,
// dynamic_annotations.cc provides no-op implementations.
//
// - Static Clang thread-safety warnings enabled.
// When building with a Clang compiler that supports thread-safety warnings,
// a subset of annotations can be statically-checked at compile-time. We
// expand these macros to static-inline functions that can be analyzed for
// thread-safety, but afterwards elided when building the final binary.
//
// - All annotations are disabled.
// If neither Dynamic Annotations nor Clang thread-safety warnings are
// enabled, then all annotation-macros expand to empty.
#ifndef ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
#define ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
#include <stddef.h>
#include "absl/base/config.h"
// -------------------------------------------------------------------------
// Decide which features are enabled
#ifndef DYNAMIC_ANNOTATIONS_ENABLED
#define DYNAMIC_ANNOTATIONS_ENABLED 0
#endif
#if defined(__clang__) && !defined(SWIG)
#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
#endif
#if DYNAMIC_ANNOTATIONS_ENABLED != 0
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1
#else
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
// Clang provides limited support for static thread-safety analysis through a
// feature called Annotalysis. We configure macro-definitions according to
// whether Annotalysis support is available. When running in opt-mode, GCC
// will issue a warning, if these attributes are compiled. Only include them
// when compiling using Clang.
// ANNOTALYSIS_ENABLED == 1 when IGNORE_READ_ATTRIBUTE_ENABLED == 1
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED \
defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
ABSL_INTERNAL_ANNOTALYSIS_ENABLED
#endif
// Memory annotations are also made available to LLVM's Memory Sanitizer
#if defined(ABSL_HAVE_MEMORY_SANITIZER) && !defined(__native_client__)
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 1
#endif
#ifndef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 0
#endif
#ifdef __cplusplus
#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
#define ABSL_INTERNAL_END_EXTERN_C } // extern "C"
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F
#define ABSL_INTERNAL_STATIC_INLINE inline
#else
#define ABSL_INTERNAL_BEGIN_EXTERN_C // empty
#define ABSL_INTERNAL_END_EXTERN_C // empty
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F
#define ABSL_INTERNAL_STATIC_INLINE static inline
#endif
// -------------------------------------------------------------------------
// Define race annotations.
#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
// -------------------------------------------------------------
// Annotations that suppress errors. It is usually better to express the
// program's synchronization using the other annotations, but these can be used
// when all else fails.
// Report that we may have a benign race at `pointer`, with size
// "sizeof(*(pointer))". `pointer` must be a non-void* pointer. Insert at the
// point where `pointer` has been allocated, preferably close to the point
// where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC.
#define ANNOTATE_BENIGN_RACE(pointer, description) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
(__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
// Same as ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to
// the memory range [`address`, `address`+`size`).
#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
(__FILE__, __LINE__, address, size, description)
// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.
// This annotation could be useful if you want to skip expensive race analysis
// during some period of program execution, e.g. during initialization.
#define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \
(__FILE__, __LINE__, enable)
// -------------------------------------------------------------
// Annotations useful for debugging.
// Report the current thread `name` to a race detector.
#define ANNOTATE_THREAD_NAME(name) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)
// -------------------------------------------------------------
// Annotations useful when implementing locks. They are not normally needed by
// modules that merely use locks. The `lock` argument is a pointer to the lock
// object.
// Report that a lock has been created at address `lock`.
#define ANNOTATE_RWLOCK_CREATE(lock) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
// Report that a linker initialized lock has been created at address `lock`.
#ifdef ABSL_HAVE_THREAD_SANITIZER
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
(__FILE__, __LINE__, lock)
#else
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) ANNOTATE_RWLOCK_CREATE(lock)
#endif
// Report that the lock at address `lock` is about to be destroyed.
#define ANNOTATE_RWLOCK_DESTROY(lock) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
// Report that the lock at address `lock` has been acquired.
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \
(__FILE__, __LINE__, lock, is_w)
// Report that the lock at address `lock` is about to be released.
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \
(__FILE__, __LINE__, lock, is_w)
// Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.
#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
namespace { \
class static_var##_annotator { \
public: \
static_var##_annotator() { \
ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
#static_var ": " description); \
} \
}; \
static static_var##_annotator the##static_var##_annotator; \
} // namespace
#else // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0
#define ANNOTATE_RWLOCK_CREATE(lock) // empty
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) // empty
#define ANNOTATE_RWLOCK_DESTROY(lock) // empty
#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) // empty
#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) // empty
#define ANNOTATE_BENIGN_RACE(address, description) // empty
#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) // empty
#define ANNOTATE_THREAD_NAME(name) // empty
#define ANNOTATE_ENABLE_RACE_DETECTION(enable) // empty
#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) // empty
#endif // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
// -------------------------------------------------------------------------
// Define memory annotations.
#if ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 1
#include <sanitizer/msan_interface.h>
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
__msan_unpoison(address, size)
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
__msan_allocated_memory(address, size)
#else // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 0
#if DYNAMIC_ANNOTATIONS_ENABLED == 1
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
do { \
(void)(address); \
(void)(size); \
} while (0)
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
do { \
(void)(address); \
(void)(size); \
} while (0)
#else
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty
#endif
#endif // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
// -------------------------------------------------------------------------
// Define IGNORE_READS_BEGIN/_END attributes.
#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
__attribute((exclusive_lock_function("*")))
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
__attribute((unlock_function("*")))
#else // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE // empty
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE // empty
#endif // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
// -------------------------------------------------------------------------
// Define IGNORE_READS_BEGIN/_END annotations.
#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1
// Request the analysis tool to ignore all reads in the current thread until
// ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey
// reads, while still checking other reads and all writes.
// See also ANNOTATE_UNPROTECTED_READ.
#define ANNOTATE_IGNORE_READS_BEGIN() \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)
// Stop ignoring reads.
#define ANNOTATE_IGNORE_READS_END() \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)
#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
// When Annotalysis is enabled without Dynamic Annotations, the use of
// static-inline functions allows the annotations to be read at compile-time,
// while still letting the compiler elide the functions from the final build.
//
// TODO(delesley) -- The exclusive lock here ignores writes as well, but
// allows IGNORE_READS_AND_WRITES to work properly.
#define ANNOTATE_IGNORE_READS_BEGIN() \
ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsBegin)()
#define ANNOTATE_IGNORE_READS_END() \
ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsEnd)()
#else
#define ANNOTATE_IGNORE_READS_BEGIN() // empty
#define ANNOTATE_IGNORE_READS_END() // empty
#endif
// -------------------------------------------------------------------------
// Define IGNORE_WRITES_BEGIN/_END annotations.
#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1
// Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.
#define ANNOTATE_IGNORE_WRITES_BEGIN() \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
// Stop ignoring writes.
#define ANNOTATE_IGNORE_WRITES_END() \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
#else
#define ANNOTATE_IGNORE_WRITES_BEGIN() // empty
#define ANNOTATE_IGNORE_WRITES_END() // empty
#endif
// -------------------------------------------------------------------------
// Define the ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
// primitive annotations defined above.
//
// Instead of doing
// ANNOTATE_IGNORE_READS_BEGIN();
// ... = x;
// ANNOTATE_IGNORE_READS_END();
// one can use
// ... = ANNOTATE_UNPROTECTED_READ(x);
#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)
// Start ignoring all memory accesses (both reads and writes).
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
do { \
ANNOTATE_IGNORE_READS_BEGIN(); \
ANNOTATE_IGNORE_WRITES_BEGIN(); \
} while (0)
// Stop ignoring both reads and writes.
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
do { \
ANNOTATE_IGNORE_WRITES_END(); \
ANNOTATE_IGNORE_READS_END(); \
} while (0)
#ifdef __cplusplus
// ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
#define ANNOTATE_UNPROTECTED_READ(x) \
absl::base_internal::AnnotateUnprotectedRead(x)
#endif
#else
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() // empty
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() // empty
#define ANNOTATE_UNPROTECTED_READ(x) (x)
#endif
// -------------------------------------------------------------------------
// Address sanitizer annotations
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
// Describe the current state of a contiguous container such as e.g.
// std::vector or std::string. For more details see
// sanitizer/common_interface_defs.h, which is provided by the compiler.
#include <sanitizer/common_interface_defs.h>
#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
#define ADDRESS_SANITIZER_REDZONE(name) \
struct { \
char x[8] __attribute__((aligned(8))); \
} name
#else
#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
#endif // ABSL_HAVE_ADDRESS_SANITIZER
// -------------------------------------------------------------------------
// Undefine the macros intended only for this file.
#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED
#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_BEGIN_EXTERN_C
#undef ABSL_INTERNAL_END_EXTERN_C
#undef ABSL_INTERNAL_STATIC_INLINE
#endif // ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
+20 -57
View File
@@ -19,88 +19,51 @@
#include <type_traits>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace nullability_internal {
// `IsNullabilityCompatible` checks whether its first argument is a class
// explicitly tagged as supporting nullability annotations. The tag is the type
// declaration `absl_nullability_compatible`.
template <typename, typename = void>
struct IsNullabilityCompatible : std::false_type {};
template <typename T>
struct IsNullabilityCompatible<
T, absl::void_t<typename T::absl_nullability_compatible>> : std::true_type {
};
template <typename T>
constexpr bool IsSupportedType = IsNullabilityCompatible<T>::value;
template <typename T>
constexpr bool IsSupportedType<T*> = true;
template <typename T, typename U>
constexpr bool IsSupportedType<T U::*> = true;
template <typename T, typename... Deleter>
constexpr bool IsSupportedType<std::unique_ptr<T, Deleter...>> = true;
template <typename T>
constexpr bool IsSupportedType<std::shared_ptr<T>> = true;
template <typename T>
struct EnableNullable {
static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
"Template argument must be a raw or supported smart pointer "
"type. See absl/base/nullability.h.");
using type = T;
};
template <typename T>
struct EnableNonnull {
static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
"Template argument must be a raw or supported smart pointer "
"type. See absl/base/nullability.h.");
using type = T;
};
template <typename T>
struct EnableNullabilityUnknown {
static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
"Template argument must be a raw or supported smart pointer "
"type. See absl/base/nullability.h.");
using type = T;
};
// Note: we do not apply Clang nullability attributes (e.g. _Nullable). These
// only support raw pointers, and conditionally enabling them only for raw
// pointers inhibits template arg deduction. Ideally, they would support all
// pointer-like types.
template <typename T, typename = typename EnableNullable<T>::type>
using NullableImpl
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
[[clang::annotate("Nullable")]]
#endif
// Don't add the _Nullable attribute in Objective-C compiles. Many Objective-C
// projects enable the `-Wnullable-to-nonnull-conversion warning`, which is
// liable to produce false positives.
#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__)
= T _Nullable;
#else
= T;
#endif
template <typename T, typename = typename EnableNonnull<T>::type>
template <typename T>
using NonnullImpl
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
[[clang::annotate("Nonnull")]]
#endif
#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__)
= T _Nonnull;
#else
= T;
#endif
template <typename T, typename = typename EnableNullabilityUnknown<T>::type>
template <typename T>
using NullabilityUnknownImpl
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
[[clang::annotate("Nullability_Unspecified")]]
#endif
#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__)
= T _Null_unspecified;
#else
= T;
#endif
} // namespace nullability_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_
+84
View File
@@ -0,0 +1,84 @@
// Copyright 2024 The Abseil Authors
//
// 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
//
// https://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 "absl/base/internal/poison.h"
#include <cstdlib>
#include "absl/base/config.h"
#include "absl/base/internal/direct_mmap.h"
#ifndef _WIN32
#include <unistd.h>
#endif
#if defined(ABSL_HAVE_ADDRESS_SANITIZER)
#include <sanitizer/asan_interface.h>
#elif defined(ABSL_HAVE_MEMORY_SANITIZER)
#include <sanitizer/msan_interface.h>
#elif defined(ABSL_HAVE_MMAP)
#include <sys/mman.h>
#endif
#if defined(_WIN32)
#include <windows.h>
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
namespace {
size_t GetPageSize() {
#ifdef _WIN32
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
return system_info.dwPageSize;
#elif defined(__wasm__) || defined(__asmjs__) || defined(__hexagon__)
return getpagesize();
#else
return static_cast<size_t>(sysconf(_SC_PAGESIZE));
#endif
}
} // namespace
void* InitializePoisonedPointerInternal() {
const size_t block_size = GetPageSize();
#if defined(ABSL_HAVE_ADDRESS_SANITIZER)
void* data = malloc(block_size);
ASAN_POISON_MEMORY_REGION(data, block_size);
#elif defined(ABSL_HAVE_MEMORY_SANITIZER)
void* data = malloc(block_size);
__msan_poison(data, block_size);
#elif defined(ABSL_HAVE_MMAP)
void* data = DirectMmap(nullptr, block_size, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (data == MAP_FAILED) return GetBadPointerInternal();
#elif defined(_WIN32)
void* data = VirtualAlloc(nullptr, block_size, MEM_RESERVE | MEM_COMMIT,
PAGE_NOACCESS);
if (data == nullptr) return GetBadPointerInternal();
#else
return GetBadPointerInternal();
#endif
// Return the middle of the block so that dereferences before and after the
// pointer will both crash.
return static_cast<char*>(data) + block_size / 2;
}
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
+59
View File
@@ -0,0 +1,59 @@
// Copyright 2024 The Abseil Authors
//
// 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
//
// https://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 ABSL_BASE_INTERNAL_POISON_H_
#define ABSL_BASE_INTERNAL_POISON_H_
#include <cstdint>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
inline void* GetBadPointerInternal() {
// A likely bad pointer. Pointers are required to have high bits that are all
// zero or all one for certain 64-bit CPUs. This pointer value will hopefully
// cause a crash on dereference and also be clearly recognizable as invalid.
constexpr uint64_t kBadPtr = 0xBAD0BAD0BAD0BAD0;
auto ret = reinterpret_cast<void*>(static_cast<uintptr_t>(kBadPtr));
#ifndef _MSC_VER // MSVC doesn't support inline asm with `volatile`.
// Try to prevent the compiler from optimizing out the undefined behavior.
asm volatile("" : : "r"(ret) :); // NOLINT
#endif
return ret;
}
void* InitializePoisonedPointerInternal();
inline void* get_poisoned_pointer() {
#if defined(NDEBUG) && !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \
!defined(ABSL_HAVE_MEMORY_SANITIZER)
// In optimized non-sanitized builds, avoid the function-local static because
// of the codegen and runtime cost.
return GetBadPointerInternal();
#else
// Non-optimized builds may use more robust implementation. Note that we can't
// use a static global because Chromium doesn't allow non-constinit globals.
static void* ptr = InitializePoisonedPointerInternal();
return ptr;
#endif
}
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_POISON_H_
+41
View File
@@ -0,0 +1,41 @@
// Copyright 2024 The Abseil Authors
//
// 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
//
// https://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 "absl/base/internal/poison.h"
#include <iostream>
#include "gtest/gtest.h"
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
namespace {
TEST(PoisonTest, CrashesOnDereference) {
#ifdef __ANDROID__
GTEST_SKIP() << "On Android, poisoned pointer dereference times out instead "
"of crashing.";
#endif
int* poisoned_ptr = static_cast<int*>(get_poisoned_pointer());
EXPECT_DEATH_IF_SUPPORTED(std::cout << *poisoned_ptr, "");
EXPECT_DEATH_IF_SUPPORTED(std::cout << *(poisoned_ptr - 10), "");
EXPECT_DEATH_IF_SUPPORTED(std::cout << *(poisoned_ptr + 10), "");
}
} // namespace
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
+1 -1
View File
@@ -175,7 +175,7 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line,
} else {
DoRawLog(&buf, &size, "%s", kTruncated);
}
AsyncSignalSafeWriteError(buffer, strlen(buffer));
AsyncSignalSafeWriteError(buffer, static_cast<size_t>(buf - buffer));
}
#else
static_cast<void>(format);
+14
View File
@@ -46,6 +46,10 @@
#include <rtems.h>
#endif
#if defined(__Fuchsia__)
#include <zircon/process.h>
#endif
#include <string.h>
#include <cassert>
@@ -461,6 +465,16 @@ pid_t GetTID() {
return reinterpret_cast<pid_t>(thread);
}
#elif defined(__Fuchsia__)
pid_t GetTID() {
// Use our thread handle as the TID, which should be unique within this
// process (but may not be globally unique). The handle value was chosen over
// a kernel object ID (KOID) because zx_handle_t (32-bits) can be cast to a
// pid_t type without loss of precision, but a zx_koid_t (64-bits) cannot.
return static_cast<pid_t>(zx_thread_self());
}
#else
// Fallback implementation of `GetTID` using `pthread_self`.
+5 -1
View File
@@ -130,7 +130,11 @@ struct PerThreadSynch {
};
// The instances of this class are allocated in NewThreadIdentity() with an
// alignment of PerThreadSynch::kAlignment.
// alignment of PerThreadSynch::kAlignment and never destroyed. Initialization
// should happen in OneTimeInitThreadIdentity().
//
// Instances may be reused by new threads - fields should be reset in
// ResetThreadIdentityBetweenReuse().
//
// NOTE: The layout of fields in this structure is critical, please do not
// add, remove, or modify the field placements without fully auditing the
+39
View File
@@ -0,0 +1,39 @@
// Copyright 2024 The Abseil Authors
//
// 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
//
// https://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 "absl/base/internal/tracing.h"
#include "absl/base/attributes.h"
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
extern "C" {
ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(
const void*, ObjectKind) {}
ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(
const void*, ObjectKind) {}
ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(
const void*, ObjectKind) {}
ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(
const void*, ObjectKind) {}
} // extern "C"
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
+81
View File
@@ -0,0 +1,81 @@
// Copyright 2024 The Abseil Authors
//
// 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
//
// https://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 ABSL_BASE_INTERNAL_TRACING_H_
#define ABSL_BASE_INTERNAL_TRACING_H_
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
// Well known Abseil object types that have causality.
enum class ObjectKind { kUnknown, kBlockingCounter, kNotification };
// `TraceWait` and `TraceContinue` record the start and end of a potentially
// blocking wait operation on `object`. `object` typically represents a higher
// level synchronization object such as `absl::Notification`.
void TraceWait(const void* object, ObjectKind kind);
void TraceContinue(const void* object, ObjectKind kind);
// `TraceSignal` records a signal on `object`.
void TraceSignal(const void* object, ObjectKind kind);
// `TraceObserved` records the non-blocking observation of a signaled object.
void TraceObserved(const void* object, ObjectKind kind);
// ---------------------------------------------------------------------------
// Weak implementation detail:
//
// We define the weak API as extern "C": in some build configurations we pass
// `--detect-odr-violations` to the gold linker. This causes it to flag weak
// symbol overrides as ODR violations. Because ODR only applies to C++ and not
// C, `--detect-odr-violations` ignores symbols not mangled with C++ names.
// By changing our extension points to be extern "C", we dodge this check.
// ---------------------------------------------------------------------------
extern "C" {
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,
ObjectKind kind);
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,
ObjectKind kind);
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,
ObjectKind kind);
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,
ObjectKind kind);
} // extern "C"
inline void TraceWait(const void* object, ObjectKind kind) {
ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(object, kind);
}
inline void TraceContinue(const void* object, ObjectKind kind) {
ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(object, kind);
}
inline void TraceSignal(const void* object, ObjectKind kind) {
ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(object, kind);
}
inline void TraceObserved(const void* object, ObjectKind kind) {
ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(object, kind);
}
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_TRACING_H_
@@ -0,0 +1,117 @@
// Copyright 2024 The Abseil Authors
//
// 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
//
// https://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 <tuple>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/tracing.h"
#if ABSL_HAVE_ATTRIBUTE_WEAK
namespace {
using ::testing::ElementsAre;
using ::absl::base_internal::ObjectKind;
enum Function { kWait, kContinue, kSignal, kObserved };
using Record = std::tuple<Function, const void*, ObjectKind>;
thread_local std::vector<Record>* tls_records = nullptr;
} // namespace
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
// Strong extern "C" implementation.
extern "C" {
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,
ObjectKind kind) {
if (tls_records != nullptr) {
tls_records->push_back({kWait, object, kind});
}
}
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,
ObjectKind kind) {
if (tls_records != nullptr) {
tls_records->push_back({kContinue, object, kind});
}
}
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,
ObjectKind kind) {
if (tls_records != nullptr) {
tls_records->push_back({kSignal, object, kind});
}
}
void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,
ObjectKind kind) {
if (tls_records != nullptr) {
tls_records->push_back({kObserved, object, kind});
}
}
} // extern "C"
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
namespace {
TEST(TracingInternal, InvokesStrongFunctionWithNullptr) {
std::vector<Record> records;
tls_records = &records;
auto kind = absl::base_internal::ObjectKind::kUnknown;
absl::base_internal::TraceWait(nullptr, kind);
absl::base_internal::TraceContinue(nullptr, kind);
absl::base_internal::TraceSignal(nullptr, kind);
absl::base_internal::TraceObserved(nullptr, kind);
tls_records = nullptr;
EXPECT_THAT(records, ElementsAre(Record{kWait, nullptr, kind},
Record{kContinue, nullptr, kind},
Record{kSignal, nullptr, kind},
Record{kObserved, nullptr, kind}));
}
TEST(TracingInternal, InvokesStrongFunctionWithObjectAddress) {
int object = 0;
std::vector<Record> records;
tls_records = &records;
auto kind = absl::base_internal::ObjectKind::kUnknown;
absl::base_internal::TraceWait(&object, kind);
absl::base_internal::TraceContinue(&object, kind);
absl::base_internal::TraceSignal(&object, kind);
absl::base_internal::TraceObserved(&object, kind);
tls_records = nullptr;
EXPECT_THAT(records, ElementsAre(Record{kWait, &object, kind},
Record{kContinue, &object, kind},
Record{kSignal, &object, kind},
Record{kObserved, &object, kind}));
}
} // namespace
#endif // ABSL_HAVE_ATTRIBUTE_WEAK
@@ -0,0 +1,34 @@
// Copyright 2024 The Abseil Authors
//
// 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
//
// https://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 "gtest/gtest.h"
#include "absl/base/internal/tracing.h"
namespace {
TEST(TracingInternal, HasDefaultImplementation) {
auto kind = absl::base_internal::ObjectKind::kUnknown;
absl::base_internal::TraceWait(nullptr, kind);
absl::base_internal::TraceContinue(nullptr, kind);
absl::base_internal::TraceSignal(nullptr, kind);
absl::base_internal::TraceObserved(nullptr, kind);
int object = 0;
absl::base_internal::TraceWait(&object, kind);
absl::base_internal::TraceContinue(&object, kind);
absl::base_internal::TraceSignal(&object, kind);
absl::base_internal::TraceObserved(&object, kind);
}
} // namespace
@@ -105,16 +105,6 @@ double UnscaledCycleClock::Frequency() {
#elif defined(__aarch64__)
// System timer of ARMv8 runs at a different frequency than the CPU's.
// The frequency is fixed, typically in the range 1-50MHz. It can be
// read at CNTFRQ special register. We assume the OS has set up
// the virtual timer properly.
int64_t UnscaledCycleClock::Now() {
int64_t virtual_timer_value;
asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
return virtual_timer_value;
}
double UnscaledCycleClock::Frequency() {
uint64_t aarch64_timer_frequency;
asm volatile("mrs %0, cntfrq_el0" : "=r"(aarch64_timer_frequency));
@@ -85,6 +85,18 @@ inline int64_t UnscaledCycleClock::Now() {
return static_cast<int64_t>((high << 32) | low);
}
#elif defined(__aarch64__)
// System timer of ARMv8 runs at a different frequency than the CPU's.
// The frequency is fixed, typically in the range 1-50MHz. It can be
// read at CNTFRQ special register. We assume the OS has set up
// the virtual timer properly.
inline int64_t UnscaledCycleClock::Now() {
int64_t virtual_timer_value;
asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
return virtual_timer_value;
}
#endif
} // namespace base_internal
+35 -4
View File
@@ -34,6 +34,7 @@
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/optimization.h"
#include "absl/base/options.h"
#include "absl/base/port.h"
// ABSL_ARRAYSIZE()
@@ -81,8 +82,9 @@ ABSL_NAMESPACE_END
// ABSL_ASSERT()
//
// In C++11, `assert` can't be used portably within constexpr functions.
// `assert` also generates spurious unused-symbol warnings.
// ABSL_ASSERT functions as a runtime assert but works in C++11 constexpr
// functions. Example:
// functions, and maintains references to symbols. Example:
//
// constexpr double Divide(double a, double b) {
// return ABSL_ASSERT(b != 0), a / b;
@@ -91,8 +93,18 @@ ABSL_NAMESPACE_END
// This macro is inspired by
// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/
#if defined(NDEBUG)
#define ABSL_ASSERT(expr) \
(false ? static_cast<void>(expr) : static_cast<void>(0))
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
// We use `decltype` here to avoid generating unnecessary code that the
// optimizer then has to optimize away.
// This not only improves compilation performance by reducing codegen bloat
// and optimization work, but also guarantees fast run-time performance without
// having to rely on the optimizer.
#define ABSL_ASSERT(expr) (decltype((expr) ? void() : void())())
#else
// Pre-C++20, lambdas can't be inside unevaluated operands, so we're forced to
// rely on the optimizer.
#define ABSL_ASSERT(expr) (false ? ((expr) ? void() : void()) : void())
#endif
#else
#define ABSL_ASSERT(expr) \
(ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
@@ -120,7 +132,7 @@ ABSL_NAMESPACE_END
//
// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on
// hardened mode.
#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
#if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG)
#define ABSL_HARDENING_ASSERT(expr) \
(ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
: [] { ABSL_INTERNAL_HARDENING_ABORT(); }())
@@ -128,6 +140,25 @@ ABSL_NAMESPACE_END
#define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr)
#endif
// ABSL_HARDENING_ASSERT_SLOW()
//
// `ABSL_HARDENING_ASSERT()` is like `ABSL_HARDENING_ASSERT()`,
// but specifically for assertions whose predicates are too slow
// to be enabled in many applications.
//
// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT_SLOW()` is identical to
// `ABSL_ASSERT()`.
//
// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on
// hardened mode.
#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
#define ABSL_HARDENING_ASSERT_SLOW(expr) \
(ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
: [] { ABSL_INTERNAL_HARDENING_ABORT(); }())
#else
#define ABSL_HARDENING_ASSERT_SLOW(expr) ABSL_ASSERT(expr)
#endif
#ifdef ABSL_HAVE_EXCEPTIONS
#define ABSL_INTERNAL_TRY try
#define ABSL_INTERNAL_CATCH_ANY catch (...)
+25 -31
View File
@@ -21,14 +21,13 @@
// such an object survives during program exit (and can be safely accessed at
// any time).
//
// Objects of such type, if constructed safely and under the right conditions,
// provide two main benefits over other alternatives:
//
// * Global objects not normally allowed due to concerns of destruction order
// (i.e. no "complex globals") can be safely allowed, provided that such
// objects can be constant initialized.
// * Function scope static objects can be optimized to avoid heap allocation,
// pointer chasing, and allow lazy construction.
// absl::NoDestructor<T> is useful when when a variable has static storage
// duration but its type has a non-trivial destructor. Global constructors are
// not recommended because of the C++'s static initialization order fiasco (See
// https://en.cppreference.com/w/cpp/language/siof). Global destructors are not
// allowed due to similar concerns about destruction ordering. Using
// absl::NoDestructor<T> as a function-local static prevents both of these
// issues.
//
// See below for complete details.
@@ -50,8 +49,8 @@ ABSL_NAMESPACE_BEGIN
//
// NoDestructor<T> is a wrapper around an object of type T that behaves as an
// object of type T but never calls T's destructor. NoDestructor<T> makes it
// safer and/or more efficient to use such objects in static storage contexts:
// as global or function scope static variables.
// safer and/or more efficient to use such objects in static storage contexts,
// ideally as function scope static variables.
//
// An instance of absl::NoDestructor<T> has similar type semantics to an
// instance of T:
@@ -62,9 +61,6 @@ ABSL_NAMESPACE_BEGIN
// `->`, `*`, and `get()`.
// (Note that `const NoDestructor<T>` works like a pointer to const `T`.)
//
// An object of type NoDestructor<T> should be defined in static storage:
// as either a global static object, or as a function scope static variable.
//
// Additionally, NoDestructor<T> provides the following benefits:
//
// * Never calls T's destructor for the object
@@ -72,24 +68,7 @@ ABSL_NAMESPACE_BEGIN
// lazily constructed.
//
// An object of type NoDestructor<T> is "trivially destructible" in the notion
// that its destructor is never run. Provided that an object of this type can be
// safely initialized and does not need to be cleaned up on program shutdown,
// NoDestructor<T> allows you to define global static variables, since Google's
// C++ style guide ban on such objects doesn't apply to objects that are
// trivially destructible.
//
// Usage as Global Static Variables
//
// NoDestructor<T> allows declaration of a global object with a non-trivial
// constructor in static storage without needing to add a destructor.
// However, such objects still need to worry about initialization order, so
// such objects should be const initialized:
//
// // Global or namespace scope.
// constinit absl::NoDestructor<MyRegistry> reg{"foo", "bar", 8008};
//
// Note that if your object already has a trivial destructor, you don't need to
// use NoDestructor<T>.
// that its destructor is never run.
//
// Usage as Function Scope Static Variables
//
@@ -115,6 +94,21 @@ ABSL_NAMESPACE_BEGIN
// return *x;
// }
//
// Usage as Global Static Variables
//
// NoDestructor<T> allows declaration of a global object of type T that has a
// non-trivial destructor since its destructor is never run. However, such
// objects still need to worry about initialization order, so such use is not
// recommended, strongly discouraged by the Google C++ Style Guide, and outright
// banned in Chromium.
// See https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
//
// // Global or namespace scope.
// absl::NoDestructor<MyRegistry> reg{"foo", "bar", 8008};
//
// Note that if your object already has a trivial destructor, you don't need to
// use NoDestructor<T>.
//
template <typename T>
class NoDestructor {
public:
+95 -13
View File
@@ -128,17 +128,17 @@
//
// By default, nullability annotations are applicable to raw and smart
// pointers. User-defined types can indicate compatibility with nullability
// annotations by providing an `absl_nullability_compatible` nested type. The
// actual definition of this inner type is not relevant as it is used merely as
// a marker. It is common to use a using declaration of
// `absl_nullability_compatible` set to void.
// annotations by adding the ABSL_NULLABILITY_COMPATIBLE attribute.
//
// // Example:
// struct MyPtr {
// using absl_nullability_compatible = void;
// struct ABSL_NULLABILITY_COMPATIBLE MyPtr {
// ...
// };
//
// Note: Compilers that don't support the `nullability_on_classes` feature will
// allow nullability annotations to be applied to any type, not just ones
// marked with `ABSL_NULLABILITY_COMPATIBLE`.
//
// DISCLAIMER:
// ===========================================================================
// These nullability annotations are primarily a human readable signal about the
@@ -150,14 +150,53 @@
#ifndef ABSL_BASE_NULLABILITY_H_
#define ABSL_BASE_NULLABILITY_H_
#include "absl/base/config.h"
#include "absl/base/internal/nullability_impl.h"
namespace absl {
// ABSL_POINTERS_DEFAULT_NONNULL
//
// This macro specifies that all unannotated pointer types within the given
// file are designated as nonnull (instead of the default "unknown"). This macro
// exists as a standalone statement and applies default nonnull behavior to all
// subsequent pointers; as a result, place this macro as the first non-comment,
// non-`#include` line in a file.
//
// Example:
//
// #include "absl/base/nullability.h"
//
// ABSL_POINTERS_DEFAULT_NONNULL
//
// void FillMessage(Message *m); // implicitly non-null
// absl::Nullable<T*> GetNullablePtr(); // explicitly nullable
// absl::NullabilityUnknown<T*> GetUnknownPtr(); // explicitly unknown
//
// The macro can be safely used in header files -- it will not affect any files
// that include it.
//
// In files with the macro, plain `T*` syntax means `absl::Nonnull<T*>`, and the
// exceptions (`Nullable` and `NullabilityUnknown`) must be marked
// explicitly. The same holds, correspondingly, for smart pointer types.
//
// For comparison, without the macro, all unannotated pointers would default to
// unknown, and otherwise require explicit annotations to change this behavior:
//
// #include "absl/base/nullability.h"
//
// void FillMessage(absl::Nonnull<Message*> m); // explicitly non-null
// absl::Nullable<T*> GetNullablePtr(); // explicitly nullable
// T* GetUnknownPtr(); // implicitly unknown
//
// No-op except for being a human readable signal.
#define ABSL_POINTERS_DEFAULT_NONNULL
// absl::Nonnull
namespace absl {
ABSL_NAMESPACE_BEGIN
// absl::Nonnull (default with `ABSL_POINTERS_DEFAULT_NONNULL`)
//
// The indicated pointer is never null. It is the responsibility of the provider
// of this pointer across an API boundary to ensure that the pointer is never be
// of this pointer across an API boundary to ensure that the pointer is never
// set to null. Consumers of this pointer across an API boundary may safely
// dereference the pointer.
//
@@ -187,7 +226,7 @@ using Nonnull = nullability_internal::NonnullImpl<T>;
template <typename T>
using Nullable = nullability_internal::NullableImpl<T>;
// absl::NullabilityUnknown (default)
// absl::NullabilityUnknown (default without `ABSL_POINTERS_DEFAULT_NONNULL`)
//
// The indicated pointer has not yet been determined to be definitively
// "non-null" or "nullable." Providers of such pointers across API boundaries
@@ -198,9 +237,10 @@ using Nullable = nullability_internal::NullableImpl<T>;
// migrated into one of the above two nullability states: `Nonnull<T>` or
// `Nullable<T>`.
//
// NOTE: Because this annotation is the global default state, pointers without
// any annotation are assumed to have "unknown" semantics. This assumption is
// designed to minimize churn and reduce clutter within the codebase.
// NOTE: For files that do not specify `ABSL_POINTERS_DEFAULT_NONNULL`,
// because this annotation is the global default state, unannotated pointers are
// are assumed to have "unknown" semantics. This assumption is designed to
// minimize churn and reduce clutter within the codebase.
//
// Example:
//
@@ -219,6 +259,48 @@ using Nullable = nullability_internal::NullableImpl<T>;
template <typename T>
using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl<T>;
ABSL_NAMESPACE_END
} // namespace absl
// ABSL_NULLABILITY_COMPATIBLE
//
// Indicates that a class is compatible with nullability annotations.
//
// For example:
//
// struct ABSL_NULLABILITY_COMPATIBLE MyPtr {
// ...
// };
//
// Note: Compilers that don't support the `nullability_on_classes` feature will
// allow nullability annotations to be applied to any type, not just ones marked
// with `ABSL_NULLABILITY_COMPATIBLE`.
#if ABSL_HAVE_FEATURE(nullability_on_classes)
#define ABSL_NULLABILITY_COMPATIBLE _Nullable
#else
#define ABSL_NULLABILITY_COMPATIBLE
#endif
// ABSL_NONNULL
// ABSL_NULLABLE
// ABSL_NULLABILITY_UNKNOWN
//
// These macros are analogues of the alias template nullability annotations
// above.
//
// Example:
// int* ABSL_NULLABLE foo;
// Is equivalent to:
// absl::Nullable<int*> foo;
#if defined(__clang__) && !defined(__OBJC__) && \
ABSL_HAVE_FEATURE(nullability_on_classes)
#define ABSL_NONNULL _Nonnull
#define ABSL_NULLABLE _Nullable
#define ABSL_NULLABILITY_UNKNOWN _Null_unspecified
#else
#define ABSL_NONNULL
#define ABSL_NULLABLE
#define ABSL_NULLABILITY_UNKNOWN
#endif
#endif // ABSL_BASE_NULLABILITY_H_
@@ -0,0 +1,44 @@
// Copyright 2024 The Abseil Authors.
//
// 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
//
// https://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 <cassert>
#include "gtest/gtest.h"
#include "absl/base/nullability.h"
ABSL_POINTERS_DEFAULT_NONNULL
namespace {
void FuncWithDefaultNonnullArg(int* /*arg*/) {}
template <typename T>
void FuncWithDeducedDefaultNonnullArg(T* /*arg*/) {}
TEST(DefaultNonnullTest, NonnullArgument) {
int var = 0;
FuncWithDefaultNonnullArg(&var);
FuncWithDeducedDefaultNonnullArg<int>(&var);
}
int* FuncWithDefaultNonnullReturn() {
static int var = 0;
return &var;
}
TEST(DefaultNonnullTest, NonnullReturn) {
auto var = FuncWithDefaultNonnullReturn();
(void)var;
}
} // namespace
+19 -12
View File
@@ -18,12 +18,25 @@
// -----------------------------------------------------------------------------
//
// This header file defines portable macros for performance optimization.
//
// This header is included in both C++ code and legacy C code and thus must
// remain compatible with both C and C++. C compatibility will be removed if
// the legacy code is removed or converted to C++. Do not include this header in
// new code that requires C compatibility or assume C compatibility will remain
// indefinitely.
// SKIP_ABSL_INLINE_NAMESPACE_CHECK
#ifndef ABSL_BASE_OPTIMIZATION_H_
#define ABSL_BASE_OPTIMIZATION_H_
#include <assert.h>
#ifdef __cplusplus
// Included for std::unreachable()
#include <utility>
#endif // __cplusplus
#include "absl/base/config.h"
#include "absl/base/options.h"
@@ -260,20 +273,14 @@
#elif defined(_MSC_VER)
#define ABSL_ASSUME(cond) __assume(cond)
#elif defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L
#define ABSL_ASSUME(cond) \
do { \
if (!(cond)) std::unreachable(); \
} while (false)
#define ABSL_ASSUME(cond) ((cond) ? void() : std::unreachable())
#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
#define ABSL_ASSUME(cond) \
do { \
if (!(cond)) __builtin_unreachable(); \
} while (false)
#define ABSL_ASSUME(cond) ((cond) ? void() : __builtin_unreachable())
#elif ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
// Unimplemented. Uses the same definition as ABSL_ASSERT in the NDEBUG case.
#define ABSL_ASSUME(expr) (decltype((expr) ? void() : void())())
#else
#define ABSL_ASSUME(cond) \
do { \
static_cast<void>(false && (cond)); \
} while (false)
#define ABSL_ASSUME(expr) (false ? ((expr) ? void() : void()) : void())
#endif
// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond)
+20 -8
View File
@@ -88,9 +88,9 @@ TEST(PredictTest, Optional) {
EXPECT_FALSE(ABSL_PREDICT_FALSE(no_value));
}
class ImplictlyConvertibleToBool {
class ImplicitlyConvertibleToBool {
public:
explicit ImplictlyConvertibleToBool(bool value) : value_(value) {}
explicit ImplicitlyConvertibleToBool(bool value) : value_(value) {}
operator bool() const { // NOLINT(google-explicit-constructor)
return value_;
}
@@ -100,17 +100,17 @@ class ImplictlyConvertibleToBool {
};
TEST(PredictTest, ImplicitBoolConversion) {
const ImplictlyConvertibleToBool is_true(true);
const ImplictlyConvertibleToBool is_false(false);
const ImplicitlyConvertibleToBool is_true(true);
const ImplicitlyConvertibleToBool is_false(false);
if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
}
class ExplictlyConvertibleToBool {
class ExplicitlyConvertibleToBool {
public:
explicit ExplictlyConvertibleToBool(bool value) : value_(value) {}
explicit ExplicitlyConvertibleToBool(bool value) : value_(value) {}
explicit operator bool() const { return value_; }
private:
@@ -118,12 +118,24 @@ class ExplictlyConvertibleToBool {
};
TEST(PredictTest, ExplicitBoolConversion) {
const ExplictlyConvertibleToBool is_true(true);
const ExplictlyConvertibleToBool is_false(false);
const ExplicitlyConvertibleToBool is_true(true);
const ExplicitlyConvertibleToBool is_false(false);
if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
}
// This verifies that ABSL_ASSUME compiles in a variety of contexts.
// It does not test optimization.
TEST(AbslAssume, Compiles) {
int x = 0;
ABSL_ASSUME(x >= 0);
EXPECT_EQ(x, 0);
// https://github.com/abseil/abseil-cpp/issues/1814
ABSL_ASSUME(x >= 0), (x >= 0) ? ++x : --x;
EXPECT_EQ(x, 1);
}
} // namespace
+8 -5
View File
@@ -174,7 +174,7 @@
// absl::variant is a typedef of std::variant, use the feature macro
// ABSL_USES_STD_VARIANT.
#define ABSL_OPTION_USE_STD_VARIANT 0
#define ABSL_OPTION_USE_STD_VARIANT 2
// ABSL_OPTION_USE_STD_ORDERING
//
@@ -225,8 +225,8 @@
// be changed to a new, unique identifier name. In particular "head" is not
// allowed.
#define ABSL_OPTION_USE_INLINE_NAMESPACE 0
#define ABSL_OPTION_INLINE_NAMESPACE_NAME head
#define ABSL_OPTION_USE_INLINE_NAMESPACE 1
#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20250127
// ABSL_OPTION_HARDENED
//
@@ -235,7 +235,10 @@
//
// A value of 0 means that "hardened" mode is not enabled.
//
// A value of 1 means that "hardened" mode is enabled.
// A value of 1 means that "hardened" mode is enabled with all checks.
//
// A value of 2 means that "hardened" mode is partially enabled, with
// only a subset of checks chosen to minimize performance impact.
//
// Hardened builds have additional security checks enabled when `NDEBUG` is
// defined. Defining `NDEBUG` is normally used to turn `assert()` macro into a
@@ -253,6 +256,6 @@
// checks enabled by this option may abort the program in a different way and
// log additional information when `NDEBUG` is not defined.
#define ABSL_OPTION_HARDENED 1
#define ABSL_OPTION_HARDENED 0
#endif // ABSL_BASE_OPTIONS_H_
+2
View File
@@ -21,6 +21,8 @@
// reported with `#error`. This enforcement is best effort, so successfully
// compiling this header does not guarantee a supported configuration.
// SKIP_ABSL_INLINE_NAMESPACE_CHECK
#ifndef ABSL_BASE_POLICY_CHECKS_H_
#define ABSL_BASE_POLICY_CHECKS_H_
+4
View File
@@ -35,6 +35,10 @@ TEST(RawLoggingCompilationTest, Log) {
ABSL_RAW_LOG(ERROR, "RAW ERROR: %d", 1);
}
TEST(RawLoggingCompilationTest, LogWithNulls) {
ABSL_RAW_LOG(INFO, "RAW INFO: %s%c%s", "Hello", 0, "World");
}
TEST(RawLoggingCompilationTest, PassingCheck) {
ABSL_RAW_CHECK(true, "RAW CHECK");
}
+2 -2
View File
@@ -67,7 +67,7 @@ cc_test(
":cleanup",
"//absl/base:config",
"//absl/utility",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
-33
View File
@@ -1,33 +0,0 @@
# Copyright 2021 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//third_party/abseil-cpp/absl.gni")
absl_source_set("cleanup_internal") {
public = [ "internal/cleanup.h" ]
deps = [
"//third_party/abseil-cpp/absl/base:base_internal",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/utility",
]
visibility = [ "//third_party/abseil-cpp/absl/*" ]
}
absl_source_set("cleanup") {
public = [ "cleanup.h" ]
deps = [
":cleanup_internal",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/base:core_headers",
]
}
absl_test("cleanup_test") {
sources = [ "cleanup_test.cc" ]
deps = [
":cleanup",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/utility",
]
}
+81 -64
View File
@@ -54,8 +54,8 @@ cc_test(
"//absl/types:any",
"//absl/types:optional",
"//absl/utility",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -87,8 +87,8 @@ cc_test(
"//absl/base:exception_testing",
"//absl/hash:hash_testing",
"//absl/memory",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -101,8 +101,8 @@ cc_test(
":fixed_array",
"//absl/base:config",
"//absl/base:exception_safety_testing",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -115,7 +115,7 @@ cc_binary(
tags = ["benchmark"],
deps = [
":fixed_array",
"@com_github_google_benchmark//:benchmark_main",
"@google_benchmark//:benchmark_main",
],
)
@@ -175,8 +175,8 @@ cc_test(
"//absl/log:check",
"//absl/memory",
"//absl/strings",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -192,7 +192,7 @@ cc_binary(
"//absl/base:core_headers",
"//absl/base:raw_logging_internal",
"//absl/strings",
"@com_github_google_benchmark//:benchmark_main",
"@google_benchmark//:benchmark_main",
],
)
@@ -204,8 +204,8 @@ cc_test(
":inlined_vector",
"//absl/base:config",
"//absl/base:exception_safety_testing",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -229,8 +229,8 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":test_instance_tracker",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -252,7 +252,7 @@ cc_library(
":raw_hash_map",
"//absl/algorithm:container",
"//absl/base:core_headers",
"//absl/memory",
"//absl/meta:type_traits",
],
)
@@ -265,16 +265,18 @@ cc_test(
deps = [
":flat_hash_map",
":hash_generator_testing",
":hash_policy_testing",
":test_allocator",
":unordered_map_constructor_test",
":unordered_map_lookup_test",
":unordered_map_members_test",
":unordered_map_modifiers_test",
"//absl/base:config",
"//absl/log:check",
"//absl/meta:type_traits",
"//absl/types:any",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -290,6 +292,7 @@ cc_library(
"//absl/algorithm:container",
"//absl/base:core_headers",
"//absl/memory",
"//absl/meta:type_traits",
],
)
@@ -302,6 +305,7 @@ cc_test(
deps = [
":container_memory",
":flat_hash_set",
":hash_container_defaults",
":hash_generator_testing",
":test_allocator",
":unordered_set_constructor_test",
@@ -309,11 +313,12 @@ cc_test(
":unordered_set_members_test",
":unordered_set_modifiers_test",
"//absl/base:config",
"//absl/hash",
"//absl/log:check",
"//absl/memory",
"//absl/strings",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -330,6 +335,7 @@ cc_library(
"//absl/algorithm:container",
"//absl/base:core_headers",
"//absl/memory",
"//absl/meta:type_traits",
],
)
@@ -340,15 +346,16 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
tags = ["no_test_loonix"],
deps = [
":hash_generator_testing",
":hash_policy_testing",
":node_hash_map",
":tracked",
":unordered_map_constructor_test",
":unordered_map_lookup_test",
":unordered_map_members_test",
":unordered_map_modifiers_test",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"//absl/base:config",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -365,6 +372,7 @@ cc_library(
"//absl/algorithm:container",
"//absl/base:core_headers",
"//absl/memory",
"//absl/meta:type_traits",
],
)
@@ -375,13 +383,17 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
tags = ["no_test_loonix"],
deps = [
":hash_generator_testing",
":hash_policy_testing",
":node_hash_set",
":unordered_set_constructor_test",
":unordered_set_lookup_test",
":unordered_set_members_test",
":unordered_set_modifiers_test",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"//absl/base:config",
"//absl/memory",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -410,8 +422,8 @@ cc_test(
"//absl/base:no_destructor",
"//absl/meta:type_traits",
"//absl/strings",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -459,8 +471,8 @@ cc_test(
"//absl/strings",
"//absl/strings:cord",
"//absl/strings:cord_test_helpers",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -499,8 +511,8 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash_policy_testing",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -523,8 +535,8 @@ cc_test(
deps = [
":container_memory",
":hash_policy_traits",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -545,8 +557,8 @@ cc_test(
deps = [
":common_policy_traits",
"//absl/base:config",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -610,8 +622,8 @@ cc_test(
"//absl/synchronization",
"//absl/synchronization:thread_pool",
"//absl/time",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -632,8 +644,8 @@ cc_test(
":hash_policy_traits",
":node_slot_policy",
"//absl/base:config",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -670,8 +682,10 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":common",
":common_policy_traits",
":compressed_tuple",
":container_memory",
":hash_function_defaults",
":hash_policy_traits",
":hashtable_debug_hooks",
":hashtablez_sampler",
@@ -707,8 +721,10 @@ cc_test(
":hash_policy_testing",
":hashtable_debug",
":hashtablez_sampler",
":node_hash_set",
":raw_hash_set",
":test_allocator",
":test_instance_tracker",
"//absl/base",
"//absl/base:config",
"//absl/base:core_headers",
@@ -720,8 +736,9 @@ cc_test(
"//absl/memory",
"//absl/meta:type_traits",
"//absl/strings",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"//absl/types:optional",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -740,7 +757,7 @@ cc_binary(
"//absl/base:raw_logging_internal",
"//absl/random",
"//absl/strings:str_format",
"@com_github_google_benchmark//:benchmark_main",
"@google_benchmark//:benchmark_main",
],
)
@@ -779,8 +796,8 @@ cc_test(
":raw_hash_set",
":tracked",
"//absl/base:config",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -814,8 +831,8 @@ cc_test(
"//absl/log:check",
"//absl/types:span",
"//absl/utility",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -831,7 +848,7 @@ cc_binary(
":layout",
"//absl/base:core_headers",
"//absl/base:raw_logging_internal",
"@com_github_google_benchmark//:benchmark_main",
"@google_benchmark//:benchmark_main",
],
)
@@ -855,7 +872,7 @@ cc_library(
deps = [
":hash_generator_testing",
":hash_policy_testing",
"@com_google_googletest//:gtest",
"@googletest//:gtest",
],
)
@@ -868,7 +885,7 @@ cc_library(
deps = [
":hash_generator_testing",
":hash_policy_testing",
"@com_google_googletest//:gtest",
"@googletest//:gtest",
],
)
@@ -881,7 +898,7 @@ cc_library(
deps = [
":hash_generator_testing",
":hash_policy_testing",
"@com_google_googletest//:gtest",
"@googletest//:gtest",
],
)
@@ -895,7 +912,7 @@ cc_library(
":hash_generator_testing",
":hash_policy_testing",
"//absl/meta:type_traits",
"@com_google_googletest//:gtest",
"@googletest//:gtest",
],
)
@@ -907,7 +924,7 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/meta:type_traits",
"@com_google_googletest//:gtest",
"@googletest//:gtest",
],
)
@@ -919,7 +936,7 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/meta:type_traits",
"@com_google_googletest//:gtest",
"@googletest//:gtest",
],
)
@@ -932,7 +949,7 @@ cc_library(
deps = [
":hash_generator_testing",
":hash_policy_testing",
"@com_google_googletest//:gtest",
"@googletest//:gtest",
],
)
@@ -945,7 +962,7 @@ cc_library(
deps = [
":hash_generator_testing",
":hash_policy_testing",
"@com_google_googletest//:gtest",
"@googletest//:gtest",
],
)
@@ -960,8 +977,8 @@ cc_test(
":unordered_set_lookup_test",
":unordered_set_members_test",
":unordered_set_modifiers_test",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -976,8 +993,8 @@ cc_test(
":unordered_map_lookup_test",
":unordered_map_members_test",
":unordered_map_modifiers_test",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -993,8 +1010,8 @@ cc_test(
":flat_hash_set",
":node_hash_map",
":node_hash_set",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -1075,8 +1092,8 @@ cc_test(
"//absl/strings",
"//absl/types:compare",
"//absl/types:optional",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
"@googletest//:gtest",
"@googletest//:gtest_main",
],
)
@@ -1105,7 +1122,7 @@ cc_binary(
"//absl/strings:cord",
"//absl/strings:str_format",
"//absl/time",
"@com_github_google_benchmark//:benchmark_main",
"@com_google_googletest//:gtest",
"@google_benchmark//:benchmark_main",
"@googletest//:gtest",
],
)
-585
View File
@@ -1,585 +0,0 @@
# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//third_party/abseil-cpp/absl.gni")
absl_source_set("compressed_tuple") {
public = [ "internal/compressed_tuple.h" ]
deps = [ "//third_party/abseil-cpp/absl/utility" ]
}
absl_source_set("fixed_array") {
public = [ "fixed_array.h" ]
deps = [
":compressed_tuple",
"//third_party/abseil-cpp/absl/algorithm",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/base:dynamic_annotations",
"//third_party/abseil-cpp/absl/base:throw_delegate",
"//third_party/abseil-cpp/absl/memory",
]
}
absl_test("fixed_array_test") {
sources = [ "fixed_array_test.cc" ]
deps = [
":fixed_array",
":test_allocator",
":test_instance_tracker",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/base:exception_testing",
"//third_party/abseil-cpp/absl/hash:hash_testing",
"//third_party/abseil-cpp/absl/memory",
]
}
absl_source_set("inlined_vector_internal") {
public = [ "internal/inlined_vector.h" ]
deps = [
":compressed_tuple",
"//third_party/abseil-cpp/absl/base:base_internal",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/abseil-cpp/absl/types:span",
]
}
absl_source_set("inlined_vector") {
public = [ "inlined_vector.h" ]
deps = [
":inlined_vector_internal",
"//third_party/abseil-cpp/absl/algorithm",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/base:throw_delegate",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/meta:type_traits",
]
}
absl_source_set("test_allocator") {
testonly = true
public = [ "internal/test_allocator.h" ]
deps = [
"//third_party/abseil-cpp/absl/base:config",
"//third_party/googletest:gtest",
]
visibility = [ ":*" ]
}
absl_test("inlined_vector_test") {
sources = [ "inlined_vector_test.cc" ]
deps = [
":inlined_vector",
":test_allocator",
":test_instance_tracker",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/base:exception_testing",
"//third_party/abseil-cpp/absl/hash:hash_testing",
"//third_party/abseil-cpp/absl/log:check",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/strings",
]
}
absl_source_set("test_instance_tracker") {
testonly = true
sources = [ "internal/test_instance_tracker.cc" ]
public = [ "internal/test_instance_tracker.h" ]
deps = [ "//third_party/abseil-cpp/absl/types:compare" ]
visibility = [ "//third_party/abseil-cpp/absl/*" ]
}
absl_source_set("flat_hash_map") {
public = [ "flat_hash_map.h" ]
deps = [
":container_memory",
":hash_container_defaults",
":raw_hash_map",
"//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/memory",
]
}
absl_test("flat_hash_map_test") {
sources = [ "flat_hash_map_test.cc" ]
deps = [
":flat_hash_map",
":hash_generator_testing",
":test_allocator",
":unordered_map_constructor_test",
":unordered_map_lookup_test",
":unordered_map_members_test",
":unordered_map_modifiers_test",
"//third_party/abseil-cpp/absl/log:check",
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/abseil-cpp/absl/types:any",
]
}
absl_source_set("flat_hash_set") {
public = [ "flat_hash_set.h" ]
deps = [
":container_memory",
":hash_container_defaults",
":raw_hash_set",
"//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/memory",
]
}
absl_test("flat_hash_set_test") {
sources = [ "flat_hash_set_test.cc" ]
deps = [
":container_memory",
":flat_hash_set",
":hash_generator_testing",
":test_allocator",
":unordered_set_constructor_test",
":unordered_set_lookup_test",
":unordered_set_members_test",
":unordered_set_modifiers_test",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/log:check",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/strings",
]
}
absl_source_set("node_hash_map") {
public = [ "node_hash_map.h" ]
deps = [
":container_memory",
":hash_container_defaults",
":node_slot_policy",
":raw_hash_map",
"//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/memory",
]
}
absl_source_set("node_hash_set") {
public = [ "node_hash_set.h" ]
deps = [
":container_memory",
":hash_container_defaults",
":node_slot_policy",
":raw_hash_set",
"//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/memory",
]
}
absl_source_set("container_memory") {
public = [ "internal/container_memory.h" ]
deps = [
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/abseil-cpp/absl/utility",
]
}
# Disabled because container_memory_test requires -frtti
# absl_test("container_memory_test") {
# sources = [ "internal/container_memory_test.cc" ]
# deps = [
# ":container_memory",
# ":test_instance_tracker",
# "//third_party/abseil-cpp/absl/base:no_destructor",
# "//third_party/abseil-cpp/absl/meta:type_traits",
# "//third_party/abseil-cpp/absl/strings",
# ]
# }
absl_source_set("hash_function_defaults") {
public = [ "internal/hash_function_defaults.h" ]
visibility = [ "//third_party/abseil-cpp/absl/container:*" ]
deps = [
":common",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/hash",
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/strings:cord",
"//third_party/abseil-cpp/absl/strings:string_view",
]
}
absl_source_set("hash_container_defaults") {
public = [ "hash_container_defaults.h" ]
visibility = [ "//third_party/abseil-cpp/absl/container:*" ]
deps = [
":hash_function_defaults",
"//third_party/abseil-cpp/absl/base:config",
]
}
absl_test("hash_function_defaults_test") {
sources = [ "internal/hash_function_defaults_test.cc" ]
deps = [
":flat_hash_map",
":flat_hash_set",
":hash_function_defaults",
"//third_party/abseil-cpp/absl/hash",
"//third_party/abseil-cpp/absl/random",
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/strings:cord",
"//third_party/abseil-cpp/absl/strings:cord_test_helpers",
]
}
absl_source_set("hash_generator_testing") {
testonly = true
sources = [ "internal/hash_generator_testing.cc" ]
public = [ "internal/hash_generator_testing.h" ]
deps = [
":hash_policy_testing",
"//third_party/abseil-cpp/absl/base:no_destructor",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/abseil-cpp/absl/strings:string_view",
]
}
absl_source_set("hash_policy_testing") {
testonly = true
public = [ "internal/hash_policy_testing.h" ]
deps = [
"//third_party/abseil-cpp/absl/hash",
"//third_party/abseil-cpp/absl/strings:string_view",
]
}
absl_source_set("hash_policy_traits") {
public = [ "internal/hash_policy_traits.h" ]
deps = [
":common_policy_traits",
"//third_party/abseil-cpp/absl/meta:type_traits",
]
}
absl_source_set("common_policy_traits") {
public = [ "internal/common_policy_traits.h" ]
visibility = [ "//third_party/abseil-cpp/absl/container:*" ]
deps = [ "//third_party/abseil-cpp/absl/meta:type_traits" ]
}
absl_test("common_policy_traits_test") {
sources = [ "internal/common_policy_traits_test.cc" ]
deps = [
":common_policy_traits",
"//third_party/abseil-cpp/absl/base:config",
]
}
absl_source_set("hashtable_debug") {
public = [ "internal/hashtable_debug.h" ]
deps = [ ":hashtable_debug_hooks" ]
}
absl_source_set("hashtable_debug_hooks") {
public = [ "internal/hashtable_debug_hooks.h" ]
deps = [ "//third_party/abseil-cpp/absl/base:config" ]
}
absl_source_set("hashtablez_sampler") {
public = [ "internal/hashtablez_sampler.h" ]
sources = [
"internal/hashtablez_sampler.cc",
"internal/hashtablez_sampler_force_weak_definition.cc",
]
deps = [
"//third_party/abseil-cpp/absl/base",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/base:no_destructor",
"//third_party/abseil-cpp/absl/base:raw_logging_internal",
"//third_party/abseil-cpp/absl/debugging:stacktrace",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/profiling:exponential_biased",
"//third_party/abseil-cpp/absl/profiling:sample_recorder",
"//third_party/abseil-cpp/absl/synchronization",
"//third_party/abseil-cpp/absl/time",
"//third_party/abseil-cpp/absl/utility",
]
}
absl_source_set("node_slot_policy") {
public = [ "internal/node_slot_policy.h" ]
deps = [ "//third_party/abseil-cpp/absl/base:config" ]
}
absl_test("node_slot_policy_test") {
sources = [ "internal/node_slot_policy_test.cc" ]
deps = [
":hash_policy_traits",
":node_slot_policy",
"//third_party/abseil-cpp/absl/base:config",
]
}
absl_source_set("raw_hash_map") {
public = [ "internal/raw_hash_map.h" ]
deps = [
":container_memory",
":raw_hash_set",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/base:throw_delegate",
]
}
absl_source_set("common") {
public = [ "internal/common.h" ]
deps = [
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/abseil-cpp/absl/types:optional",
]
}
absl_source_set("raw_hash_set") {
sources = [ "internal/raw_hash_set.cc" ]
public = [ "internal/raw_hash_set.h" ]
deps = [
":common",
":compressed_tuple",
":container_memory",
":hash_policy_traits",
":hashtable_debug_hooks",
":hashtablez_sampler",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/base:dynamic_annotations",
"//third_party/abseil-cpp/absl/base:endian",
"//third_party/abseil-cpp/absl/base:prefetch",
"//third_party/abseil-cpp/absl/base:raw_logging_internal",
"//third_party/abseil-cpp/absl/hash",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/abseil-cpp/absl/numeric:bits",
"//third_party/abseil-cpp/absl/utility",
]
}
absl_test("raw_hash_set_test") {
sources = [ "internal/raw_hash_set_test.cc" ]
deps = [
":container_memory",
":flat_hash_map",
":flat_hash_set",
":hash_function_defaults",
":hash_policy_testing",
":hashtable_debug",
":hashtablez_sampler",
":raw_hash_set",
":test_allocator",
"//third_party/abseil-cpp/absl/base",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/base:prefetch",
"//third_party/abseil-cpp/absl/functional:function_ref",
"//third_party/abseil-cpp/absl/hash",
"//third_party/abseil-cpp/absl/log",
"//third_party/abseil-cpp/absl/log:check",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/abseil-cpp/absl/strings",
]
}
absl_test("raw_hash_set_allocator_test") {
sources = [ "internal/raw_hash_set_allocator_test.cc" ]
deps = [
":container_memory",
":raw_hash_set",
":tracked",
"//third_party/abseil-cpp/absl/base:config",
]
}
absl_source_set("layout") {
public = [ "internal/layout.h" ]
deps = [
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/debugging:demangle_internal",
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:span",
"//third_party/abseil-cpp/absl/utility",
]
}
absl_test("layout_test") {
sources = [ "internal/layout_test.cc" ]
deps = [
":layout",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/log:check",
"//third_party/abseil-cpp/absl/types:span",
"//third_party/abseil-cpp/absl/utility",
]
}
absl_source_set("tracked") {
testonly = true
public = [ "internal/tracked.h" ]
deps = [ "//third_party/abseil-cpp/absl/base:config" ]
}
absl_source_set("unordered_map_constructor_test") {
testonly = true
public = [ "internal/unordered_map_constructor_test.h" ]
deps = [
":hash_generator_testing",
":hash_policy_testing",
"//third_party/googletest:gtest",
]
}
absl_source_set("unordered_map_lookup_test") {
testonly = true
public = [ "internal/unordered_map_lookup_test.h" ]
deps = [
":hash_generator_testing",
":hash_policy_testing",
"//third_party/googletest:gtest",
]
}
absl_source_set("unordered_map_modifiers_test") {
testonly = true
public = [ "internal/unordered_map_modifiers_test.h" ]
deps = [
":hash_generator_testing",
":hash_policy_testing",
"//third_party/googletest:gtest",
]
}
absl_source_set("unordered_set_constructor_test") {
testonly = true
public = [ "internal/unordered_set_constructor_test.h" ]
deps = [
":hash_generator_testing",
":hash_policy_testing",
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/googletest:gtest",
]
}
absl_source_set("unordered_set_members_test") {
testonly = true
public = [ "internal/unordered_set_members_test.h" ]
deps = [
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/googletest:gtest",
]
}
absl_source_set("unordered_map_members_test") {
testonly = true
public = [ "internal/unordered_map_members_test.h" ]
deps = [
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/googletest:gtest",
]
}
absl_source_set("unordered_set_lookup_test") {
testonly = true
public = [ "internal/unordered_set_lookup_test.h" ]
deps = [
":hash_generator_testing",
":hash_policy_testing",
"//third_party/googletest:gtest",
]
}
absl_source_set("unordered_set_modifiers_test") {
testonly = true
public = [ "internal/unordered_set_modifiers_test.h" ]
deps = [
":hash_generator_testing",
":hash_policy_testing",
"//third_party/googletest:gtest",
]
}
absl_test("sample_element_size_test") {
public = [ "sample_element_size_test.cc" ]
deps = [
":flat_hash_map",
":flat_hash_set",
":node_hash_map",
":node_hash_set",
]
}
absl_source_set("btree") {
sources = [
"internal/btree.h",
"internal/btree_container.h",
]
public = [
"btree_map.h",
"btree_set.h",
]
deps = [
":common",
":common_policy_traits",
":compressed_tuple",
":container_memory",
":layout",
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/base:raw_logging_internal",
"//third_party/abseil-cpp/absl/base:throw_delegate",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/abseil-cpp/absl/strings:cord",
"//third_party/abseil-cpp/absl/strings:string_view",
"//third_party/abseil-cpp/absl/types:compare",
]
}
absl_source_set("btree_test_common") {
testonly = true
public = [ "btree_test.h" ]
deps = [
":btree",
":flat_hash_set",
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/strings:cord",
"//third_party/abseil-cpp/absl/time",
]
}
# TODO(mbonadei): Fix issue with EXPECT_DEATH and uncomment.
# absl_test("btree_test") {
# sources = [ "btree_test.cc" ]
# deps = [
# ":btree",
# ":btree_test_common",
# ":test_allocator",
# ":test_instance_tracker",
# "//third_party/abseil-cpp/absl/algorithm:container",
# "//third_party/abseil-cpp/absl/base:core_headers",
# "//third_party/abseil-cpp/absl/base:raw_logging_internal",
# "//third_party/abseil-cpp/absl/flags:flag",
# "//third_party/abseil-cpp/absl/hash:hash_testing",
# "//third_party/abseil-cpp/absl/memory",
# "//third_party/abseil-cpp/absl/random",
# "//third_party/abseil-cpp/absl/strings",
# "//third_party/abseil-cpp/absl/types:compare",
# "//third_party/abseil-cpp/absl/types:optional",
# ]
# }

Some files were not shown because too many files have changed in this diff Show More