Compare commits

..

1 Commits

Author SHA1 Message Date
Powei Feng
69fc1f302c vk: testing a robin_map key hash failure
Executable on device with:

./build.sh -p android -q arm64-v8a release test_compiler && adb push out/cmake-android-release-aarch64/filament/test/test_compiler /data/local/tmp/ && adb shell chmod 777 /data/local/tmp/test_compiler && adb shell /data/local/tmp/test_compiler
2024-07-26 12:23:28 +08:00
32 changed files with 216 additions and 324 deletions

View File

@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.53.5'
implementation 'com.google.android.filament:filament-android:1.53.2'
}
```
@@ -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.53.5'
pod 'Filament', '~> 1.53.2'
```
### Snapshots

View File

@@ -7,14 +7,6 @@ A new header is inserted each time a *tag* is created.
Instead, if you are authoring a PR for the main branch, add your release note to
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
## v1.53.5
- engine: Fix bug causing certain sampler parameters to not be applied correctly in GLES 2.0 and on
certain GLES 3.0 drivers.
## v1.53.4
## v1.53.3
- Add drag and drop support for IBL files for desktop gltf_viewer.

View File

@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.53.5
VERSION_NAME=1.53.2
POM_DESCRIPTION=Real-time physically based rendering engine for Android.

View File

@@ -39,7 +39,7 @@
#define HandleAllocatorGL HandleAllocator<32, 64, 136> // ~4520 / pool / MiB
#define HandleAllocatorVK HandleAllocator<64, 160, 312> // ~1820 / pool / MiB
#define HandleAllocatorMTL HandleAllocator<32, 64, 552> // ~1660 / pool / MiB
#define HandleAllocatorMTL HandleAllocator<32, 48, 552> // ~1660 / pool / MiB
namespace filament::backend {

View File

@@ -101,8 +101,9 @@ void CommandBufferQueue::flush() noexcept {
size_t const used = std::distance(
static_cast<char const*>(begin), static_cast<char const*>(end));
std::unique_lock<utils::Mutex> lock(mLock);
mCommandBuffersToExecute.push_back({ begin, end });
mCondition.notify_one();
// circular buffer is too small, we corrupted the stream
FILAMENT_CHECK_POSTCONDITION(used <= mFreeSpace) <<
@@ -111,13 +112,11 @@ void CommandBufferQueue::flush() noexcept {
"Space used at this time: " << used <<
" bytes, overflow: " << used - mFreeSpace << " bytes";
mFreeSpace -= used;
mCommandBuffersToExecute.push_back({ begin, end });
mCondition.notify_one();
// wait until there is enough space in the buffer
mFreeSpace -= used;
if (UTILS_UNLIKELY(mFreeSpace < requiredSize)) {
#ifndef NDEBUG
size_t const totalUsed = circularBuffer.size() - mFreeSpace;
slog.d << "CommandStream used too much space (will block): "
@@ -154,10 +153,8 @@ std::vector<CommandBufferQueue::Range> CommandBufferQueue::waitForCommands() con
}
void CommandBufferQueue::releaseBuffer(CommandBufferQueue::Range const& buffer) {
size_t const used = std::distance(
static_cast<char const*>(buffer.begin), static_cast<char const*>(buffer.end));
std::lock_guard<utils::Mutex> const lock(mLock);
mFreeSpace += used;
mFreeSpace += uintptr_t(buffer.end) - uintptr_t(buffer.begin);
mCondition.notify_one();
}

View File

@@ -53,14 +53,14 @@ Driver* MetalDriverFactory::create(MetalPlatform* const platform, const Platform
// MetalRenderPrimitive : 24 many
// MetalVertexBuffer : 32 moderate
// -- less than or equal 32 bytes
// MetalIndexBuffer : 40 moderate
// MetalFence : 48 few
// MetalIndexBuffer : 56 moderate
// MetalBufferObject : 64 many
// -- less than or equal 64 bytes
// MetalBufferObject : 48 many
// -- less than or equal 48 bytes
// MetalSamplerGroup : 112 few
// MetalProgram : 152 moderate
// MetalTexture : 152 moderate
// MetalSwapChain : 208 few
// MetalSwapChain : 184 few
// MetalRenderTarget : 272 few
// MetalVertexBufferInfo : 552 moderate
// -- less than or equal to 552 bytes

View File

@@ -2341,15 +2341,6 @@ void OpenGLDriver::updateSamplerGroup(Handle<HwSamplerGroup> sbh,
GLTexture const* const t = handle_cast<const GLTexture*>(th);
assert_invariant(t);
if (UTILS_UNLIKELY(es2)
#if defined(GL_EXT_texture_filter_anisotropic)
|| UTILS_UNLIKELY(anisotropyWorkaround)
#endif
) {
// We must set texture parameters on the texture itself.
bindTexture(OpenGLContext::DUMMY_TEXTURE_BINDING, t);
}
SamplerParams params = pSamplers[i].s;
if (UTILS_UNLIKELY(t->target == SamplerType::SAMPLER_EXTERNAL)) {
// From OES_EGL_image_external spec:
@@ -3890,7 +3881,6 @@ void OpenGLDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
}
void OpenGLDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t instanceCount) {
DEBUG_MARKER()
GLRenderPrimitive const* const rp = mBoundRenderPrimitive;
if (UTILS_UNLIKELY(!rp || !mValidProgram)) {
return;
@@ -3912,7 +3902,6 @@ void OpenGLDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t ins
}
void OpenGLDriver::draw2GLES2(uint32_t indexOffset, uint32_t indexCount, uint32_t instanceCount) {
DEBUG_MARKER()
GLRenderPrimitive const* const rp = mBoundRenderPrimitive;
if (UTILS_UNLIKELY(!rp || !mValidProgram)) {
return;
@@ -3933,7 +3922,6 @@ void OpenGLDriver::draw2GLES2(uint32_t indexOffset, uint32_t indexCount, uint32_
}
void OpenGLDriver::scissor(Viewport scissor) {
DEBUG_MARKER()
setScissor(scissor);
}
@@ -3953,7 +3941,6 @@ void OpenGLDriver::draw(PipelineState state, Handle<HwRenderPrimitive> rph,
}
void OpenGLDriver::dispatchCompute(Handle<HwProgram> program, math::uint3 workGroupCount) {
DEBUG_MARKER()
getShaderCompilerService().tick();
OpenGLProgram* const p = handle_cast<OpenGLProgram*>(program);

View File

@@ -143,25 +143,21 @@ void TimerQueryNativeFactory::endTimeElapsedQuery(OpenGLDriver& driver, GLTimerQ
driver.runEveryNowAndThen([&context = mContext, weak]() -> bool {
auto state = weak.lock();
if (!state) {
// The timer query state has been destroyed on the way, very likely due to the IBL
// prefilter context destruction. We still return true to get this element removed from
// the query list.
return true;
if (state) {
GLuint available = 0;
context.procs.getQueryObjectuiv(state->gl.query, GL_QUERY_RESULT_AVAILABLE, &available);
CHECK_GL_ERROR(utils::slog.e)
if (!available) {
// we need to try this one again later
return false;
}
GLuint64 elapsedTime = 0;
// we won't end-up here if we're on ES and don't have GL_EXT_disjoint_timer_query
context.procs.getQueryObjectui64v(state->gl.query, GL_QUERY_RESULT, &elapsedTime);
state->elapsed.store((int64_t)elapsedTime, std::memory_order_relaxed);
} else {
state->elapsed.store(int64_t(TimerQueryResult::ERROR), std::memory_order_relaxed);
}
GLuint available = 0;
context.procs.getQueryObjectuiv(state->gl.query, GL_QUERY_RESULT_AVAILABLE, &available);
CHECK_GL_ERROR(utils::slog.e)
if (!available) {
// we need to try this one again later
return false;
}
GLuint64 elapsedTime = 0;
// we won't end-up here if we're on ES and don't have GL_EXT_disjoint_timer_query
context.procs.getQueryObjectui64v(state->gl.query, GL_QUERY_RESULT, &elapsedTime);
state->elapsed.store((int64_t)elapsedTime, std::memory_order_relaxed);
return true;
});
}

View File

@@ -572,16 +572,23 @@ void ShaderCompilerService::compileShaders(OpenGLContext& context,
// split shader source, so we can insert the specialization constants and the packing
// functions
auto const [prolog, body] = splitShaderSource({ shader_src, shader_len });
auto [version, prolog, body] = splitShaderSource({ shader_src, shader_len });
const std::array<const char*, 4> sources = {
// enable ESSL 3.10 if available
if (context.isAtLeastGLES<3, 1>()) {
version = "#version 310 es\n";
}
const std::array<const char*, 5> sources = {
version.data(),
prolog.data(),
specializationConstantString.c_str(),
packingFunctions.data(),
body.data()
};
const std::array<GLint, 4> lengths = {
const std::array<GLint, 5> lengths = {
(GLint)version.length(),
(GLint)prolog.length(),
(GLint)specializationConstantString.length(),
(GLint)packingFunctions.length(),
@@ -661,6 +668,7 @@ void ShaderCompilerService::process_OVR_multiview2(OpenGLContext& context,
// Tragically, OpenGL 4.1 doesn't support unpackHalf2x16 (appeared in 4.2) and
// macOS doesn't support GL_ARB_shading_language_packing
// Also GLES3.0 didn't have the full set of packing/unpacking functions
std::string_view ShaderCompilerService::process_ARB_shading_language_packing(OpenGLContext& context) noexcept {
using namespace std::literals;
#ifdef BACKEND_OPENGL_VERSION_GL
@@ -700,31 +708,102 @@ highp uint packHalf2x16(vec2 v) {
highp uint y = fp32tou16(v.y);
return (y << 16u) | x;
}
highp uint packUnorm4x8(mediump vec4 v) {
v = round(clamp(v, 0.0, 1.0) * 255.0);
highp uint a = uint(v.x);
highp uint b = uint(v.y) << 8;
highp uint c = uint(v.z) << 16;
highp uint d = uint(v.w) << 24;
return (a|b|c|d);
}
highp uint packSnorm4x8(mediump vec4 v) {
v = round(clamp(v, -1.0, 1.0) * 127.0);
highp uint a = uint((int(v.x) & 0xff));
highp uint b = uint((int(v.y) & 0xff)) << 8;
highp uint c = uint((int(v.z) & 0xff)) << 16;
highp uint d = uint((int(v.w) & 0xff)) << 24;
return (a|b|c|d);
}
mediump vec4 unpackUnorm4x8(highp uint v) {
return vec4(float((v & 0x000000ffu) ),
float((v & 0x0000ff00u) >> 8),
float((v & 0x00ff0000u) >> 16),
float((v & 0xff000000u) >> 24)) / 255.0;
}
mediump vec4 unpackSnorm4x8(highp uint v) {
int a = int(((v ) & 0xffu) << 24u) >> 24 ;
int b = int(((v >> 8u) & 0xffu) << 24u) >> 24 ;
int c = int(((v >> 16u) & 0xffu) << 24u) >> 24 ;
int d = int(((v >> 24u) & 0xffu) << 24u) >> 24 ;
return clamp(vec4(float(a), float(b), float(c), float(d)) / 127.0, -1.0, 1.0);
}
)"sv;
}
#endif // BACKEND_OPENGL_VERSION_GL
#ifdef BACKEND_OPENGL_VERSION_GLES
if (!context.isES2() && !context.isAtLeastGLES<3, 1>()) {
return R"(
highp uint packUnorm4x8(mediump vec4 v) {
v = round(clamp(v, 0.0, 1.0) * 255.0);
highp uint a = uint(v.x);
highp uint b = uint(v.y) << 8;
highp uint c = uint(v.z) << 16;
highp uint d = uint(v.w) << 24;
return (a|b|c|d);
}
highp uint packSnorm4x8(mediump vec4 v) {
v = round(clamp(v, -1.0, 1.0) * 127.0);
highp uint a = uint((int(v.x) & 0xff));
highp uint b = uint((int(v.y) & 0xff)) << 8;
highp uint c = uint((int(v.z) & 0xff)) << 16;
highp uint d = uint((int(v.w) & 0xff)) << 24;
return (a|b|c|d);
}
mediump vec4 unpackUnorm4x8(highp uint v) {
return vec4(float((v & 0x000000ffu) ),
float((v & 0x0000ff00u) >> 8),
float((v & 0x00ff0000u) >> 16),
float((v & 0xff000000u) >> 24)) / 255.0;
}
mediump vec4 unpackSnorm4x8(highp uint v) {
int a = int(((v ) & 0xffu) << 24u) >> 24 ;
int b = int(((v >> 8u) & 0xffu) << 24u) >> 24 ;
int c = int(((v >> 16u) & 0xffu) << 24u) >> 24 ;
int d = int(((v >> 24u) & 0xffu) << 24u) >> 24 ;
return clamp(vec4(float(a), float(b), float(c), float(d)) / 127.0, -1.0, 1.0);
}
)"sv;
}
#endif // BACKEND_OPENGL_VERSION_GLES
return ""sv;
}
// split shader source code in two, the first section goes from the start to the line after the
// last #extension, and the 2nd part goes from there to the end.
std::array<std::string_view, 2> ShaderCompilerService::splitShaderSource(std::string_view source) noexcept {
auto start = source.find("#version");
assert_invariant(start != std::string_view::npos);
// split shader source code in three:
// - the version line
// - extensions
// - everything else
std::array<std::string_view, 3> ShaderCompilerService::splitShaderSource(std::string_view source) noexcept {
auto version_start = source.find("#version");
assert_invariant(version_start != std::string_view::npos);
auto pos = source.rfind("\n#extension");
if (pos == std::string_view::npos) {
pos = start;
auto version_eol = source.find('\n', version_start) + 1;
assert_invariant(version_eol != std::string_view::npos);
auto prolog_start = version_eol;
auto prolog_eol = source.rfind("\n#extension"); // last #extension line
if (prolog_eol == std::string_view::npos) {
prolog_eol = prolog_start;
} else {
++pos;
prolog_eol = source.find('\n', prolog_eol + 1) + 1;
}
auto body_start = prolog_eol;
auto eol = source.find('\n', pos) + 1;
assert_invariant(eol != std::string_view::npos);
std::string_view const version = source.substr(start, eol - start);
std::string_view const body = source.substr(version.length(), source.length() - version.length());
return { version, body };
std::string_view const version = source.substr(version_start, version_eol - version_start);
std::string_view const prolog = source.substr(prolog_start, prolog_eol - prolog_start);
std::string_view const body = source.substr(body_start, source.length() - body_start);
return { version, prolog, body };
}
/*

View File

@@ -146,7 +146,7 @@ private:
static std::string_view process_ARB_shading_language_packing(OpenGLContext& context) noexcept;
static std::array<std::string_view, 2> splitShaderSource(std::string_view source) noexcept;
static std::array<std::string_view, 3> splitShaderSource(std::string_view source) noexcept;
static GLuint linkProgram(OpenGLContext& context,
std::array<GLuint, Program::SHADER_TYPE_COUNT> shaders,

View File

@@ -59,11 +59,7 @@ VkExtent2D VulkanAttachment::getExtent2D() const {
VkImageView VulkanAttachment::getImageView() {
assert_invariant(texture);
VkImageSubresourceRange range = getSubresourceRange();
if (range.layerCount > 1) {
return texture->getMultiviewAttachmentView(range);
}
return texture->getAttachmentView(range);
return texture->getAttachmentView(getSubresourceRange());
}
bool VulkanAttachment::isDepth() const {
@@ -77,7 +73,7 @@ VkImageSubresourceRange VulkanAttachment::getSubresourceRange() const {
.baseMipLevel = uint32_t(level),
.levelCount = 1,
.baseArrayLayer = uint32_t(layer),
.layerCount = layerCount,
.layerCount = 1,
};
}

View File

@@ -43,8 +43,6 @@ struct VulkanCommandBuffer;
struct VulkanAttachment {
VulkanTexture* texture = nullptr;
uint8_t level = 0;
uint8_t baseViewIndex = 0;
uint8_t layerCount = 1;
uint16_t layer = 0;
bool isDepth() const;

View File

@@ -595,8 +595,6 @@ void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
colorTargets[i] = {
.texture = mResourceAllocator.handle_cast<VulkanTexture*>(color[i].handle),
.level = color[i].level,
.baseViewIndex = color[i].baseViewIndex,
.layerCount = layerCount,
.layer = color[i].layer,
};
UTILS_UNUSED_IN_RELEASE VkExtent2D extent = colorTargets[i].getExtent2D();
@@ -611,8 +609,6 @@ void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
depthStencil[0] = {
.texture = mResourceAllocator.handle_cast<VulkanTexture*>(depth.handle),
.level = depth.level,
.baseViewIndex = depth.baseViewIndex,
.layerCount = layerCount,
.layer = depth.layer,
};
UTILS_UNUSED_IN_RELEASE VkExtent2D extent = depthStencil[0].getExtent2D();
@@ -625,8 +621,6 @@ void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
depthStencil[1] = {
.texture = mResourceAllocator.handle_cast<VulkanTexture*>(stencil.handle),
.level = stencil.level,
.baseViewIndex = stencil.baseViewIndex,
.layerCount = layerCount,
.layer = stencil.layer,
};
UTILS_UNUSED_IN_RELEASE VkExtent2D extent = depthStencil[1].getExtent2D();
@@ -643,7 +637,7 @@ void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
auto renderTarget = mResourceAllocator.construct<VulkanRenderTarget>(rth, mPlatform->getDevice(),
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, width, height,
samples, colorTargets, depthStencil, mStagePool, layerCount);
samples, colorTargets, depthStencil, mStagePool);
mResourceManager.acquire(renderTarget);
}
@@ -1273,8 +1267,6 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
}
}
uint8_t const renderTargetLayerCount = rt->getLayerCount();
// Create the VkRenderPass or fetch it from cache.
VulkanFboCache::RenderPassKey rpkey = {
.initialColorLayoutMask = 0,
@@ -1285,12 +1277,10 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
.discardEnd = discardEndVal,
.samples = rt->getSamples(),
.subpassMask = uint8_t(params.subpassMask),
.viewCount = renderTargetLayerCount,
};
for (int i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; i++) {
const VulkanAttachment& info = rt->getColor(i);
if (info.texture) {
assert_invariant(info.layerCount == renderTargetLayerCount);
rpkey.initialColorLayoutMask |= 1 << i;
rpkey.colorFormat[i] = info.getFormat();
if (rpkey.samples > 1 && info.texture->samples == 1) {

View File

@@ -43,7 +43,6 @@ bool VulkanFboCache::RenderPassEq::operator()(const RenderPassKey& k1,
if (k1.samples != k2.samples) return false;
if (k1.needsResolveMask != k2.needsResolveMask) return false;
if (k1.subpassMask != k2.subpassMask) return false;
if (k1.viewCount != k2.viewCount) return false;
return true;
}
@@ -187,25 +186,6 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey config) noexcept {
.pDependencies = dependencies
};
VkRenderPassMultiviewCreateInfo multiviewCreateInfo = {};
uint32_t const subpassViewMask = (1 << config.viewCount) - 1;
// Prepare a view mask array for the maximum number of subpasses. All subpasses have all views
// activated.
uint32_t const viewMasks[2] = {subpassViewMask, subpassViewMask};
if (config.viewCount > 1) {
// Fill the multiview create info.
multiviewCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
multiviewCreateInfo.pNext = nullptr;
multiviewCreateInfo.subpassCount = hasSubpasses ? 2u : 1u;
multiviewCreateInfo.pViewMasks = viewMasks;
multiviewCreateInfo.dependencyCount = 0;
multiviewCreateInfo.pViewOffsets = nullptr;
multiviewCreateInfo.correlationMaskCount = 1;
multiviewCreateInfo.pCorrelationMasks = &subpassViewMask;
renderPassInfo.pNext = &multiviewCreateInfo;
}
int attachmentIndex = 0;
// Populate the Color Attachments.

View File

@@ -64,7 +64,7 @@ public:
uint8_t samples; // 1 byte
uint8_t needsResolveMask; // 1 byte
uint8_t subpassMask; // 1 byte
uint8_t viewCount; // 1 byte
uint8_t padding2; // 1 byte
};
struct RenderPassVal {
VkRenderPass handle;

View File

@@ -323,12 +323,11 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
VulkanContext const& context, VmaAllocator allocator, VulkanCommands* commands,
uint32_t width, uint32_t height, uint8_t samples,
VulkanAttachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT],
VulkanAttachment depthStencil[2], VulkanStagePool& stagePool, uint8_t layerCount)
VulkanAttachment depthStencil[2], VulkanStagePool& stagePool)
: HwRenderTarget(width, height),
VulkanResource(VulkanResourceType::RENDER_TARGET),
mOffscreen(true),
mSamples(samples),
mLayerCount(layerCount) {
mSamples(samples) {
for (int index = 0; index < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; index++) {
mColor[index] = color[index];
}

View File

@@ -304,7 +304,7 @@ struct VulkanRenderTarget : private HwRenderTarget, VulkanResource {
VulkanContext const& context, VmaAllocator allocator,
VulkanCommands* commands, uint32_t width, uint32_t height,
uint8_t samples, VulkanAttachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT],
VulkanAttachment depthStencil[2], VulkanStagePool& stagePool, uint8_t layerCount);
VulkanAttachment depthStencil[2], VulkanStagePool& stagePool);
// Creates a special "default" render target (i.e. associated with the swap chain)
explicit VulkanRenderTarget();
@@ -319,7 +319,6 @@ struct VulkanRenderTarget : private HwRenderTarget, VulkanResource {
VulkanAttachment& getMsaaDepth();
uint8_t getColorTargetCount(const VulkanRenderPass& pass) const;
uint8_t getSamples() const { return mSamples; }
uint8_t getLayerCount() const { return mLayerCount; }
bool hasDepth() const { return mDepth.texture; }
bool isSwapChain() const { return !mOffscreen; }
void bindToSwapChain(VulkanSwapChain& surf);
@@ -331,7 +330,6 @@ private:
VulkanAttachment mMsaaDepthAttachment = {};
const bool mOffscreen : 1;
uint8_t mSamples : 7;
uint8_t mLayerCount = 1;
};
struct VulkanBufferObject;

View File

@@ -387,15 +387,12 @@ void VulkanTexture::setPrimaryRange(uint32_t minMiplevel, uint32_t maxMiplevel)
}
VkImageView VulkanTexture::getAttachmentView(VkImageSubresourceRange range) {
// Attachments should only have one mipmap level and one layer.
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);
}

View File

@@ -73,10 +73,6 @@ struct VulkanTexture : public HwTexture, VulkanResource {
// and the identity swizzle.
VkImageView getAttachmentView(VkImageSubresourceRange range);
// 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 File

@@ -16,8 +16,6 @@
#include "details/Engine.h"
#include "ResourceAllocator.h"
#include "details/BufferObject.h"
#include "details/Camera.h"
#include "details/Fence.h"

View File

@@ -163,9 +163,9 @@ public:
// call this immediately before "swap buffers"
void endFrame(backend::DriverApi& driver) noexcept;
details::FrameInfo getLastFrameInfo() const noexcept {
// if pFront is not set yet, return FrameInfo(). But the `valid` field will be false in this case.
return pFront ? *pFront : details::FrameInfo{};
details::FrameInfo const& getLastFrameInfo() const noexcept {
// if pFront is not set yet, return front() but in this case front().valid will be false
return pFront ? *pFront : mFrameTimeHistory.front();
}
utils::FixedCapacityVector<Renderer::FrameInfo> getFrameInfoHistory(size_t historySize) const noexcept;

View File

@@ -16,10 +16,9 @@
#include <filament/Renderer.h>
#include "ResourceAllocator.h"
#include "details/Renderer.h"
#include "details/Engine.h"
#include "details/Renderer.h"
#include "details/View.h"
#include <utils/FixedCapacityVector.h>

View File

@@ -75,7 +75,7 @@ FrameGraphId<FrameGraphTexture> RendererUtils::colorPass(
TargetBufferFlags const clearColorFlags = config.clearFlags & TargetBufferFlags::COLOR;
TargetBufferFlags clearDepthFlags = config.clearFlags & TargetBufferFlags::DEPTH;
TargetBufferFlags clearStencilFlags = config.clearFlags & TargetBufferFlags::STENCIL;
uint8_t layerCount = 1;
uint8_t layerCount = 0;
data.shadows = blackboard.get<FrameGraphTexture>("shadows");
data.ssao = blackboard.get<FrameGraphTexture>("ssao");

View File

@@ -48,7 +48,7 @@ struct FrameGraphRenderPass {
Viewport viewport{};
math::float4 clearColor{};
uint8_t samples = 0; // # of samples (0 = unset, default)
uint8_t layerCount = 1; // # of layer (# > 1 = multiview)
uint8_t layerCount = 0; // # of layer (# > 1 = multiview)
backend::TargetBufferFlags clearFlags{};
backend::TargetBufferFlags discardStart{};
};

View File

@@ -62,6 +62,7 @@ if (ANDROID)
target_link_libraries(test_compiler PRIVATE utils)
target_link_libraries(test_compiler PRIVATE EGL)
target_link_libraries(test_compiler PRIVATE GLESv3)
target_link_libraries(test_compiler PRIVATE bluevk)
endif()
add_executable(test_material_parser

View File

@@ -1,181 +1,82 @@
/*
* Copyright (C) 2023 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 <iostream>
#include <utils/Hash.h>
#include <tsl/robin_map.h>
#include <bluevk/BlueVK.h>
#include <utils/Log.h>
namespace {
#include <GLES3/gl3.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <gtest/gtest.h>
using namespace utils;
using namespace std::literals;
class CompilerTest : public testing::Test {
protected:
void SetUp() override {
EGLBoolean success;
EGLint major, minor;
dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
ASSERT_NE(dpy, EGL_NO_DISPLAY);
EGLBoolean const initialized = eglInitialize(dpy, &major, &minor);
ASSERT_TRUE(initialized);
EGLint const contextAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
EGLint configsCount;
EGLint configAttribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, // 0
EGL_RED_SIZE, 8, // 2
EGL_GREEN_SIZE, 8, // 4
EGL_BLUE_SIZE, 8, // 6
EGL_NONE // 14
};
success = eglChooseConfig(dpy, configAttribs, &config, 1, &configsCount);
ASSERT_TRUE(success);
context = eglCreateContext(dpy, config, EGL_NO_CONTEXT, contextAttribs);
ASSERT_NE(context, EGL_NO_CONTEXT);
success = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, context);
ASSERT_TRUE(success);
ASSERT_EQ(eglGetError(), EGL_SUCCESS);
}
void TearDown() override {
eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(dpy, context);
eglTerminate(dpy);
}
private:
EGLDisplay dpy;
EGLContext context;
EGLConfig config;
struct T {
};
TEST_F(CompilerTest, Simple) {
auto shader = R"(
#version 300 es
void main()
{
})"sv;
constexpr uint8_t const UNIQUE_DESCRIPTOR_SET_COUNT = 3;
constexpr uint8_t const SHADER_TYPE_COUNT = 3;
using Timestamp = uint64_t;
using VulkanResourceAllocator = T;
const char* const src = shader.data();
GLint const len = (GLint)shader.size();
struct PushConstantKey {
uint8_t stage;// We have one set of push constant per shader stage (fragment, vertex, etc).
uint8_t size;
};
GLuint const id = glCreateShader(GL_VERTEX_SHADER);
EXPECT_EQ(glGetError(), GL_NO_ERROR);
struct PipelineLayoutKey {
using DescriptorSetLayoutArray = std::array<VkDescriptorSetLayout, UNIQUE_DESCRIPTOR_SET_COUNT>;
DescriptorSetLayoutArray descSetLayouts = {}; // 8 * 3
PushConstantKey pushConstant[SHADER_TYPE_COUNT] = {};// 2 * 3
uint16_t padding = 0;
};
static_assert(sizeof(PipelineLayoutKey) == 32);
glShaderSource(id, 1, &src, &len);
EXPECT_EQ(glGetError(), GL_NO_ERROR);
using PipelineLayoutKeyHashFn = utils::hash::MurmurHashFn<PipelineLayoutKey>;
struct PipelineLayoutKeyEqual {
bool operator()(PipelineLayoutKey const& k1, PipelineLayoutKey const& k2) const {
return 0 == memcmp((const void*) &k1, (const void*) &k2, sizeof(PipelineLayoutKey));
}
};
glCompileShader(id);
EXPECT_EQ(glGetError(), GL_NO_ERROR);
struct PipelineLayoutCacheEntry {
VkPipelineLayout handle;
Timestamp lastUsed;
};
GLint result = 0;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
EXPECT_EQ(result, GL_TRUE);
using PipelineLayoutMap = tsl::robin_map<PipelineLayoutKey, PipelineLayoutCacheEntry,
PipelineLayoutKeyHashFn, PipelineLayoutKeyEqual>;
glDeleteShader(id);
EXPECT_EQ(glGetError(), GL_NO_ERROR);
class TestClass {
public:
VkDevice mDevice;
VulkanResourceAllocator* mAllocator;
Timestamp mTimestamp;
PipelineLayoutMap layout;
};
void insert(PipelineLayoutMap& layout, uint64_t val) {
PipelineLayoutKey key{};
key.descSetLayouts[0] = (VkDescriptorSetLayout) val;
layout[key] = {(VkPipelineLayout) val, val};
}
TEST_F(CompilerTest, CrashPVRUniFlexCompileToHw) {
// Some PowerVR driver crash with this shader
auto shader = R"(
#version 300 es
layout(location = 0) in vec4 mesh_position;
layout(std140) uniform FrameUniforms {
vec2 i;
} frameUniforms;
void main() {
gl_Position = mesh_position;
gl_Position.z = dot(gl_Position.zw, frameUniforms.i);
})"sv;
const char* const src = shader.data();
GLint const len = (GLint)shader.size();
GLuint const id = glCreateShader(GL_VERTEX_SHADER);
EXPECT_EQ(glGetError(), GL_NO_ERROR);
glShaderSource(id, 1, &src, &len);
EXPECT_EQ(glGetError(), GL_NO_ERROR);
glCompileShader(id);
EXPECT_EQ(glGetError(), GL_NO_ERROR);
GLint result = 0;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
EXPECT_EQ(result, GL_TRUE);
glDeleteShader(id);
EXPECT_EQ(glGetError(), GL_NO_ERROR);
}
TEST_F(CompilerTest, ConstParameters) {
// Some PowerVR driver fail to compile this shader
auto shader = R"(
#version 300 es
highp mat3 m;
void buggy(const mediump vec3 n) {
m*n;
}
void main() {
})"sv;
const char* const src = shader.data();
GLint const len = (GLint)shader.size();
GLuint const id = glCreateShader(GL_FRAGMENT_SHADER);
EXPECT_EQ(glGetError(), GL_NO_ERROR);
glShaderSource(id, 1, &src, &len);
EXPECT_EQ(glGetError(), GL_NO_ERROR);
glCompileShader(id);
EXPECT_EQ(glGetError(), GL_NO_ERROR);
GLint result = 0;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
EXPECT_EQ(result, GL_TRUE);
EXPECT_EQ(glGetError(), GL_NO_ERROR);
glDeleteShader(id);
EXPECT_EQ(glGetError(), GL_NO_ERROR);
}
}// namespace
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
constexpr uint32_t START = 1000;
TestClass c;
auto& layout = c.layout;
uint64_t count = 0;
for (; count < 20; count++) {
insert(layout, count + START);
}
for (uint64_t t = 0; t < count; ++t) {
PipelineLayoutKey key = {};
key.descSetLayouts[0] = (VkDescriptorSetLayout)(START + t);
if (layout.find(key) != layout.end()) {
std::cout << "found " << t << std::endl;
} else {
std::cout << "not found" << t << std::endl;
}
}
return 0;
}

View File

@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
spec.version = "1.53.5"
spec.version = "1.53.2"
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.53.5/filament-v1.53.5-ios.tgz" }
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.53.2/filament-v1.53.2-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = {

View File

@@ -96,8 +96,7 @@ static std::string getNodeName(cgltf_node const* node, char const* defaultNodeNa
if (node->mesh && node->mesh->name) return node->mesh->name;
if (node->light && node->light->name) return node->light->name;
if (node->camera && node->camera->name) return node->camera->name;
if (defaultNodeName) return defaultNodeName;
return "<unknown>";
return defaultNodeName;
};
std::string strOrig(getNameImpl());

View File

@@ -70,8 +70,7 @@ struct AssetLoaderExtended {
: mEngine(engine),
mGltfPath(config.gltfPath),
mMaterials(materials),
mUriDataCache(std::make_shared<UriDataCache>()),
mCgltfBuffersLoaded(false) {}
mUriDataCache(std::make_shared<UriDataCache>()) {}
~AssetLoaderExtended() = default;

View File

@@ -18,7 +18,6 @@
#define TNT_UTILS_WORKSTEALINGDEQUEUE_H
#include <atomic>
#include <type_traits>
#include <assert.h>
#include <stddef.h>
@@ -93,11 +92,9 @@ void WorkStealingDequeue<TYPE, COUNT>::push(TYPE item) noexcept {
index_t bottom = mBottom.load(std::memory_order_relaxed);
setItemAt(bottom, item);
// Here we need std::memory_order_release because we release, the item we just pushed, to other
// std::memory_order_release is used because we release the item we just pushed to other
// threads which are calling steal().
// However, generally seq_cst cannot be mixed with other memory orders. So we must use seq_cst.
// see: https://plv.mpi-sws.org/scfix/paper.pdf
mBottom.store(bottom + 1, std::memory_order_seq_cst);
mBottom.store(bottom + 1, std::memory_order_release);
}
/*
@@ -157,11 +154,9 @@ TYPE WorkStealingDequeue<TYPE, COUNT>::pop() noexcept {
assert(top - bottom == 1);
}
// Here, we only need std::memory_order_relaxed because we're not publishing any data.
// std::memory_order_relaxed used because we're not publishing any data.
// No concurrent writes to mBottom possible, it's always safe to write mBottom.
// However, generally seq_cst cannot be mixed with other memory orders. So we must use seq_cst.
// see: https://plv.mpi-sws.org/scfix/paper.pdf
mBottom.store(top, std::memory_order_seq_cst);
mBottom.store(top, std::memory_order_relaxed);
return item;
}

View File

@@ -7,11 +7,6 @@ vec4 fog(vec4 color, highp vec3 view) {
// note: d can be +inf with the skybox
highp float d = length(view);
// early exit for object "in front" of the fog
if (d < frameUniforms.fogStart) {
return color;
}
// fogCutOffDistance is set to +inf to disable the cutoff distance
if (d > frameUniforms.fogCutOffDistance) {
return color;

View File

@@ -1,6 +1,6 @@
{
"name": "filament",
"version": "1.53.5",
"version": "1.53.2",
"description": "Real-time physically based rendering engine",
"main": "filament.js",
"module": "filament.js",