Compare commits
34
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3041a7ccc0 | ||
|
|
06f8d073da | ||
|
|
e5b8f91859 | ||
|
|
70f2cda9b6 | ||
|
|
c3e4894d49 | ||
|
|
a128d9143a | ||
|
|
2cf10999f4 | ||
|
|
e0e44da185 | ||
|
|
ce62e0ef06 | ||
|
|
826b885d0e | ||
|
|
5b9a24edf0 | ||
|
|
b651f63e02 | ||
|
|
c48273df3c | ||
|
|
8397a15914 | ||
|
|
d76567b4a8 | ||
|
|
ce62b169cb | ||
|
|
9244f8ee21 | ||
|
|
3c7a871e7e | ||
|
|
31d698e9ca | ||
|
|
769b0db858 | ||
|
|
b40064b1ab | ||
|
|
889a62d617 | ||
|
|
784b3ce565 | ||
|
|
4f77547ab3 | ||
|
|
46c89499d0 | ||
|
|
57c782685b | ||
|
|
bc799c78f6 | ||
|
|
86e688a2a3 | ||
|
|
3dead231d4 | ||
|
|
fd382ce219 | ||
|
|
46358572b7 | ||
|
|
546b986107 | ||
|
|
5245141c46 | ||
|
|
62b182fe04 |
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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.
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#ifndef TNT_UTILS_STATICSTRING_H
|
||||
#define TNT_UTILS_STATICSTRING_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <type_traits>
|
||||
#include <string_view>
|
||||
|
||||
|
||||
@@ -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__/
|
||||
Vendored
-374
@@ -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
@@ -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
@@ -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
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(googletest-external NONE)
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -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
@@ -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}" ..
|
||||
|
||||
Vendored
+44
-54
@@ -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
|
||||
|
||||
Vendored
-6
@@ -1,6 +0,0 @@
|
||||
monorail: {
|
||||
component: "Internals>Core"
|
||||
}
|
||||
buganizer_public: {
|
||||
component_id: 1456128
|
||||
}
|
||||
Vendored
+18
-14
@@ -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",
|
||||
)
|
||||
|
||||
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
danilchap@chromium.org
|
||||
mbonadei@chromium.org
|
||||
|
||||
# For .def files updates:
|
||||
hans@chromium.org
|
||||
Vendored
-43
@@ -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
|
||||
Vendored
+37
-20
@@ -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",
|
||||
)
|
||||
|
||||
Vendored
-128
@@ -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",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+3
-92
@@ -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
@@ -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
@@ -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
@@ -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",
|
||||
]
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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_
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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_
|
||||
|
||||
@@ -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_
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user