Compare commits
27
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3da96d424 | ||
|
|
a068143953 | ||
|
|
90d90094dc | ||
|
|
54df4524eb | ||
|
|
d70f2e1b81 | ||
|
|
2f359b73a4 | ||
|
|
abb0cbc98e | ||
|
|
2763931b47 | ||
|
|
0ead96b606 | ||
|
|
317c1bb7ea | ||
|
|
9aaaad9271 | ||
|
|
d2ce714e73 | ||
|
|
8398175d9c | ||
|
|
26258a4718 | ||
|
|
3644e7f808 | ||
|
|
4d774820d9 | ||
|
|
aad45d9119 | ||
|
|
5389b37002 | ||
|
|
d5fe9e236f | ||
|
|
59890ac85a | ||
|
|
435969f565 | ||
|
|
e3db39105f | ||
|
|
dfa821d351 | ||
|
|
1ab223c965 | ||
|
|
29bb60cd94 | ||
|
|
93b15dac87 | ||
|
|
a8fda9b4d0 |
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.51.1'
|
||||
implementation 'com.google.android.filament:filament-android:1.51.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.51.1'
|
||||
pod 'Filament', '~> 1.51.0'
|
||||
```
|
||||
|
||||
### Snapshots
|
||||
|
||||
@@ -104,6 +104,14 @@ Java_com_google_android_filament_RenderableManager_nBuilderGeometry__JIIJJIIII(J
|
||||
(size_t) count);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nBuilderGeometryType(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, int type) {
|
||||
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
|
||||
builder->geometryType((RenderableManager::Builder::GeometryType)type);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nBuilderMaterial(JNIEnv*, jclass,
|
||||
|
||||
@@ -243,9 +243,11 @@ public class Engine {
|
||||
/**
|
||||
* Sets the initial paused state of the rendering thread.
|
||||
*
|
||||
* <p>Warning: This is an experimental API. See {@link Engine#setPaused(boolean)} for
|
||||
* caveats.
|
||||
*
|
||||
* @param paused Whether to start the rendering thread paused.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
* @warning Experimental.
|
||||
*/
|
||||
public Builder paused(boolean paused) {
|
||||
nSetBuilderPaused(mNativeBuilder, paused);
|
||||
@@ -1209,7 +1211,16 @@ public class Engine {
|
||||
|
||||
/**
|
||||
* Pause or resume the rendering thread.
|
||||
* @warning Experimental.
|
||||
*
|
||||
* <p>Warning: This is an experimental API. In particular, note the following caveats.
|
||||
*
|
||||
* <ul><li>
|
||||
* Buffer callbacks will never be called as long as the rendering thread is paused.
|
||||
* Do not rely on a buffer callback to unpause the thread.
|
||||
* </li><li>
|
||||
* While the rendering thread is paused, rendering commands will continue to be queued until the
|
||||
* buffer limit is reached. When the limit is reached, the program will abort.
|
||||
* </li></ul>
|
||||
*/
|
||||
public void setPaused(boolean paused) {
|
||||
nSetPaused(getNativeObject(), paused);
|
||||
|
||||
+27
@@ -175,6 +175,32 @@ public class RenderableManager {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of geometry for a Renderable
|
||||
*/
|
||||
public enum GeometryType {
|
||||
/** dynamic gemoetry has no restriction */
|
||||
DYNAMIC,
|
||||
/** bounds and world space transform are immutable */
|
||||
STATIC_BOUNDS,
|
||||
/** skinning/morphing not allowed and Vertex/IndexBuffer immutables */
|
||||
STATIC
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether this renderable has static bounds. In this context his means that
|
||||
* the renderable's bounding box cannot change and that the renderable's transform is
|
||||
* assumed immutable. Changing the renderable's transform via the TransformManager
|
||||
* can lead to corrupted graphics. Note that skinning and morphing are not forbidden.
|
||||
* Disabled by default.
|
||||
* @param enable whether this renderable has static bounds. false by default.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder geometryType(GeometryType type) {
|
||||
nBuilderGeometryType(mNativeBuilder, type.ordinal());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a material instance to the specified primitive.
|
||||
*
|
||||
@@ -964,6 +990,7 @@ public class RenderableManager {
|
||||
private static native void nBuilderGeometry(long nativeBuilder, int index, int value, long nativeVertexBuffer, long nativeIndexBuffer);
|
||||
private static native void nBuilderGeometry(long nativeBuilder, int index, int value, long nativeVertexBuffer, long nativeIndexBuffer, int offset, int count);
|
||||
private static native void nBuilderGeometry(long nativeBuilder, int index, int value, long nativeVertexBuffer, long nativeIndexBuffer, int offset, int minIndex, int maxIndex, int count);
|
||||
private static native void nBuilderGeometryType(long nativeBuilder, int type);
|
||||
private static native void nBuilderMaterial(long nativeBuilder, int index, long nativeMaterialInstance);
|
||||
private static native void nBuilderBlendOrder(long nativeBuilder, int index, int blendOrder);
|
||||
private static native void nBuilderGlobalBlendOrderEnabled(long nativeBuilder, int index, boolean enabled);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.51.1
|
||||
VERSION_NAME=1.51.0
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -516,7 +516,7 @@ function build_android {
|
||||
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
|
||||
for sample in ${ANDROID_SAMPLES}; do
|
||||
echo "Installing out/${sample}-debug.apk"
|
||||
cp samples/${sample}/build/outputs/apk/debug/${sample}-debug-unsigned.apk \
|
||||
cp samples/${sample}/build/outputs/apk/debug/${sample}-debug.apk \
|
||||
../out/${sample}-debug.apk
|
||||
done
|
||||
fi
|
||||
|
||||
@@ -116,6 +116,8 @@ public:
|
||||
|
||||
Program& cacheId(uint64_t cacheId) noexcept;
|
||||
|
||||
Program& multiview(bool multiview) noexcept;
|
||||
|
||||
ShaderSource const& getShadersSource() const noexcept { return mShadersSource; }
|
||||
ShaderSource& getShadersSource() noexcept { return mShadersSource; }
|
||||
|
||||
@@ -143,6 +145,8 @@ public:
|
||||
|
||||
uint64_t getCacheId() const noexcept { return mCacheId; }
|
||||
|
||||
bool isMultiview() const noexcept { return mMultiview; }
|
||||
|
||||
CompilerPriorityQueue getPriorityQueue() const noexcept { return mPriorityQueue; }
|
||||
|
||||
private:
|
||||
@@ -158,6 +162,11 @@ private:
|
||||
utils::FixedCapacityVector<std::pair<utils::CString, uint8_t>> mAttributes;
|
||||
std::array<UniformInfo, Program::UNIFORM_BINDING_COUNT> mBindingUniformInfo;
|
||||
CompilerPriorityQueue mPriorityQueue = CompilerPriorityQueue::HIGH;
|
||||
// Indicates the current engine was initialized with multiview stereo, and the variant for this
|
||||
// program contains STE flag. This will be referred later for the OpenGL shader compiler to
|
||||
// determine whether shader code replacement for the num_views should be performed.
|
||||
// This variable could be promoted as a more generic variable later if other similar needs occur.
|
||||
bool mMultiview = false;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -58,6 +58,7 @@ void CommandBufferQueue::requestExit() {
|
||||
}
|
||||
|
||||
void CommandBufferQueue::setPaused(bool paused) {
|
||||
std::lock_guard<utils::Mutex> const lock(mLock);
|
||||
if (paused) {
|
||||
mPaused = true;
|
||||
} else {
|
||||
@@ -125,6 +126,9 @@ void CommandBufferQueue::flush() noexcept {
|
||||
#endif
|
||||
|
||||
SYSTRACE_NAME("waiting: CircularBuffer::flush()");
|
||||
ASSERT_POSTCONDITION(!mPaused,
|
||||
"CommandStream is full, but since the rendering thread is paused, "
|
||||
"the buffer cannot flush and we will deadlock. Instead, abort.");
|
||||
mCondition.wait(lock, [this, requiredSize]() -> bool {
|
||||
// TODO: on macOS, we need to call pumpEvents from time to time
|
||||
return mFreeSpace >= requiredSize;
|
||||
|
||||
@@ -91,6 +91,11 @@ Program& Program::cacheId(uint64_t cacheId) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::multiview(bool multiview) noexcept {
|
||||
mMultiview = multiview;
|
||||
return *this;
|
||||
}
|
||||
|
||||
io::ostream& operator<<(io::ostream& out, const Program& builder) {
|
||||
out << "Program{";
|
||||
builder.mLogger(out);
|
||||
|
||||
@@ -2472,7 +2472,9 @@ void OpenGLDriver::setTextureData(GLTexture* t, uint32_t level,
|
||||
size_t const stride = p.stride ? p.stride : width;
|
||||
size_t const bpp = PBD::computeDataSize(p.format, p.type, 1, 1, 1);
|
||||
size_t const bpr = PBD::computeDataSize(p.format, p.type, stride, 1, p.alignment);
|
||||
void const* const buffer = static_cast<char const*>(p.buffer) + p.left * bpp + bpr * p.top;
|
||||
size_t const bpl = bpr * height; // TODO: PBD should have a "layer stride"
|
||||
void const* const buffer = static_cast<char const*>(p.buffer)
|
||||
+ bpp* p.left + bpr * p.top + bpl * 0; // TODO: PBD should have a p.depth
|
||||
|
||||
switch (t->target) {
|
||||
case SamplerType::SAMPLER_EXTERNAL:
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Systrace.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
@@ -264,6 +265,7 @@ ShaderCompilerService::program_token_t ShaderCompilerService::createProgram(
|
||||
compileShaders(gl,
|
||||
std::move(program.getShadersSource()),
|
||||
program.getSpecializationConstants(),
|
||||
program.isMultiview(),
|
||||
shaders,
|
||||
token->shaderSourceCode);
|
||||
|
||||
@@ -299,6 +301,7 @@ ShaderCompilerService::program_token_t ShaderCompilerService::createProgram(
|
||||
compileShaders(gl,
|
||||
std::move(program.getShadersSource()),
|
||||
program.getSpecializationConstants(),
|
||||
program.isMultiview(),
|
||||
token->gl.shaders,
|
||||
token->shaderSourceCode);
|
||||
|
||||
@@ -501,6 +504,7 @@ GLuint ShaderCompilerService::initialize(program_token_t& token) noexcept {
|
||||
void ShaderCompilerService::compileShaders(OpenGLContext& context,
|
||||
Program::ShaderSource shadersSource,
|
||||
utils::FixedCapacityVector<Program::SpecializationConstant> const& specializationConstants,
|
||||
bool multiview,
|
||||
std::array<GLuint, Program::SHADER_TYPE_COUNT>& outShaders,
|
||||
UTILS_UNUSED_IN_RELEASE std::array<CString, Program::SHADER_TYPE_COUNT>& outShaderSourceCode) noexcept {
|
||||
|
||||
@@ -514,8 +518,16 @@ void ShaderCompilerService::compileShaders(OpenGLContext& context,
|
||||
};
|
||||
|
||||
std::string specializationConstantString;
|
||||
int32_t numViews = 2;
|
||||
for (auto const& sc : specializationConstants) {
|
||||
appendSpecConstantString(specializationConstantString, sc);
|
||||
if (sc.id == 8) {
|
||||
// This constant must match
|
||||
// ReservedSpecializationConstants::CONFIG_STEREO_EYE_COUNT
|
||||
// which we can't use here because it's defined in EngineEnums.h.
|
||||
// (we're breaking layering here, but it's for the good cause).
|
||||
numViews = std::get<int32_t>(sc.value);
|
||||
}
|
||||
}
|
||||
if (!specializationConstantString.empty()) {
|
||||
specializationConstantString += '\n';
|
||||
@@ -544,17 +556,23 @@ void ShaderCompilerService::compileShaders(OpenGLContext& context,
|
||||
|
||||
if (UTILS_LIKELY(!shadersSource[i].empty())) {
|
||||
Program::ShaderBlob& shader = shadersSource[i];
|
||||
char* shader_src = reinterpret_cast<char*>(shader.data());
|
||||
size_t shader_len = shader.size();
|
||||
|
||||
// remove GOOGLE_cpp_style_line_directive
|
||||
std::string_view const source = process_GOOGLE_cpp_style_line_directive(context,
|
||||
reinterpret_cast<char*>(shader.data()), shader.size());
|
||||
process_GOOGLE_cpp_style_line_directive(context, shader_src, shader_len);
|
||||
|
||||
// replace the value of layout(num_views = X) for multiview extension
|
||||
if (multiview && stage == ShaderStage::VERTEX) {
|
||||
process_OVR_multiview2(context, numViews, shader_src, shader_len);
|
||||
}
|
||||
|
||||
// add support for ARB_shading_language_packing if needed
|
||||
auto const packingFunctions = process_ARB_shading_language_packing(context);
|
||||
|
||||
// split shader source, so we can insert the specialization constants and the packing
|
||||
// functions
|
||||
auto const [prolog, body] = splitShaderSource(source);
|
||||
auto const [prolog, body] = splitShaderSource({ shader_src, shader_len });
|
||||
|
||||
const std::array<const char*, 4> sources = {
|
||||
prolog.data(),
|
||||
@@ -577,7 +595,7 @@ void ShaderCompilerService::compileShaders(OpenGLContext& context,
|
||||
#ifndef NDEBUG
|
||||
// for debugging we return the original shader source (without the modifications we
|
||||
// made here), otherwise the line numbers wouldn't match.
|
||||
outShaderSourceCode[i] = { source.data(), source.length() };
|
||||
outShaderSourceCode[i] = { shader_src, shader_len };
|
||||
#endif
|
||||
|
||||
outShaders[i] = shaderId;
|
||||
@@ -586,15 +604,59 @@ void ShaderCompilerService::compileShaders(OpenGLContext& context,
|
||||
}
|
||||
|
||||
// If usages of the Google-style line directive are present, remove them, as some
|
||||
// drivers don't allow the quotation marks. This happens in-place.
|
||||
std::string_view ShaderCompilerService::process_GOOGLE_cpp_style_line_directive(OpenGLContext& context,
|
||||
// drivers don't allow the quotation marks. This source modification happens in-place.
|
||||
void ShaderCompilerService::process_GOOGLE_cpp_style_line_directive(OpenGLContext& context,
|
||||
char* source, size_t len) noexcept {
|
||||
if (!context.ext.GOOGLE_cpp_style_line_directive) {
|
||||
if (UTILS_UNLIKELY(requestsGoogleLineDirectivesExtension({ source, len }))) {
|
||||
removeGoogleLineDirectives(source, len); // length is unaffected
|
||||
}
|
||||
}
|
||||
return { source, len };
|
||||
}
|
||||
|
||||
// Look up the `source` to replace the number of eyes for multiview with the given number. This is
|
||||
// necessary for OpenGL because OpenGL relies on the number specified in shader files to determine
|
||||
// the number of views, which is assumed as a single digit, for multiview.
|
||||
// This source modification happens in-place.
|
||||
void ShaderCompilerService::process_OVR_multiview2(OpenGLContext& context,
|
||||
int32_t eyeCount, char* source, size_t len) noexcept {
|
||||
// We don't use regular expression in favor of performance.
|
||||
if (context.ext.OVR_multiview2) {
|
||||
const std::string_view shader{ source, len };
|
||||
const std::string_view layout = "layout";
|
||||
const std::string_view num_views = "num_views";
|
||||
size_t found = 0;
|
||||
while (true) {
|
||||
found = shader.find(layout, found);
|
||||
if (found == std::string_view::npos) {
|
||||
break;
|
||||
}
|
||||
found = shader.find_first_not_of(' ', found + layout.size());
|
||||
if (found == std::string_view::npos || shader[found] != '(') {
|
||||
continue;
|
||||
}
|
||||
found = shader.find_first_not_of(' ', found + 1);
|
||||
if (found == std::string_view::npos) {
|
||||
continue;
|
||||
}
|
||||
if (shader.compare(found, num_views.size(), num_views) != 0) {
|
||||
continue;
|
||||
}
|
||||
found = shader.find_first_not_of(' ', found + num_views.size());
|
||||
if (found == std::string_view::npos || shader[found] != '=') {
|
||||
continue;
|
||||
}
|
||||
found = shader.find_first_not_of(' ', found + 1);
|
||||
if (found == std::string_view::npos) {
|
||||
continue;
|
||||
}
|
||||
// We assume the value should be one-digit number.
|
||||
assert_invariant(eyeCount < 10);
|
||||
assert_invariant(!::isdigit(source[found + 1]));
|
||||
source[found] = '0' + eyeCount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tragically, OpenGL 4.1 doesn't support unpackHalf2x16 (appeared in 4.2) and
|
||||
|
||||
@@ -134,10 +134,14 @@ private:
|
||||
OpenGLContext& context,
|
||||
Program::ShaderSource shadersSource,
|
||||
utils::FixedCapacityVector<Program::SpecializationConstant> const& specializationConstants,
|
||||
bool multiview,
|
||||
std::array<GLuint, Program::SHADER_TYPE_COUNT>& outShaders,
|
||||
std::array<utils::CString, Program::SHADER_TYPE_COUNT>& outShaderSourceCode) noexcept;
|
||||
|
||||
static std::string_view process_GOOGLE_cpp_style_line_directive(OpenGLContext& context,
|
||||
static void process_GOOGLE_cpp_style_line_directive(OpenGLContext& context,
|
||||
char* source, size_t len) noexcept;
|
||||
|
||||
static void process_OVR_multiview2(OpenGLContext& context, int32_t eyeCount,
|
||||
char* source, size_t len) noexcept;
|
||||
|
||||
static std::string_view process_ARB_shading_language_packing(OpenGLContext& context) noexcept;
|
||||
|
||||
@@ -43,9 +43,12 @@
|
||||
// Enables Android systrace
|
||||
#define FVK_DEBUG_SYSTRACE 0x00000001
|
||||
|
||||
// Group markers are used to denote collection of GPU commands. It is typically at the granualarity
|
||||
// of a renderpass.
|
||||
#define FVK_DEBUG_GROUP_MARKERS 0x00000002
|
||||
// Group markers are used to denote collections of GPU commands. It is typically at the
|
||||
// granualarity of a renderpass. You can enable this along with FVK_DEBUG_DEBUG_UTILS to take
|
||||
// advantage of vkCmdBegin/EndDebugUtilsLabelEXT. You can also just enable this with
|
||||
// FVK_DEBUG_PRINT_GROUP_MARKERS to print the current marker to stdout.
|
||||
#define FVK_DEBUG_GROUP_MARKERS 0x00000002
|
||||
|
||||
#define FVK_DEBUG_TEXTURE 0x00000004
|
||||
#define FVK_DEBUG_LAYOUT_TRANSITION 0x00000008
|
||||
#define FVK_DEBUG_COMMAND_BUFFER 0x00000010
|
||||
@@ -63,9 +66,11 @@
|
||||
// Enable the debug utils extension if it is available.
|
||||
#define FVK_DEBUG_DEBUG_UTILS 0x00008000
|
||||
|
||||
// Use this to debug potential Handle/Resource leakage. It will print out reference counts for all
|
||||
// the currently active resources.
|
||||
#define FVK_DEBUG_RESOURCE_LEAK 0x00010000
|
||||
|
||||
// Usefaul default combinations
|
||||
// Useful default combinations
|
||||
#define FVK_DEBUG_EVERYTHING 0xFFFFFFFF
|
||||
#define FVK_DEBUG_PERFORMANCE \
|
||||
FVK_DEBUG_SYSTRACE
|
||||
|
||||
@@ -239,7 +239,7 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey config) noexcept {
|
||||
.format = config.colorFormat[i],
|
||||
.samples = (VkSampleCountFlagBits) config.samples,
|
||||
.loadOp = clear ? kClear : (discard ? kDontCare : kKeep),
|
||||
.storeOp = config.samples == 1 ? kEnableStore : kDisableStore,
|
||||
.storeOp = kEnableStore,
|
||||
.stencilLoadOp = kDontCare,
|
||||
.stencilStoreOp = kDisableStore,
|
||||
.initialLayout = ((!discard && config.initialColorLayoutMask & (1 << i)) || clear)
|
||||
|
||||
@@ -77,7 +77,11 @@ private:
|
||||
|
||||
struct PipelineInfo {
|
||||
PipelineInfo()
|
||||
: bindingToSamplerIndex(MAX_SAMPLER_COUNT, 0xffff) {}
|
||||
: bindingToSamplerIndex(MAX_SAMPLER_COUNT, 0xffff)
|
||||
#if FVK_ENABLED_DEBUG_SAMPLER_NAME
|
||||
, bindingToName(MAX_SAMPLER_COUNT, "")
|
||||
#endif
|
||||
{}
|
||||
|
||||
// This bitset maps to each of the sampler in the sampler groups associated with this
|
||||
// program, and whether each sampler is used in which shader (i.e. vert, frag, compute).
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
#include "VulkanTexture.h"
|
||||
#include "VulkanUtility.h"
|
||||
|
||||
#include <DataReshaper.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <private/backend/BackendUtils.h>
|
||||
|
||||
#include "DataReshaper.h"
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
using namespace bluevk;
|
||||
@@ -100,9 +100,13 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
|
||||
|
||||
// Filament expects blit() to work with any texture, so we almost always set these usage flags.
|
||||
// TODO: investigate performance implications of setting these flags.
|
||||
const VkImageUsageFlags blittable = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||
constexpr VkImageUsageFlags blittable = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
|
||||
if (any(usage & (TextureUsage::BLIT_DST | TextureUsage::BLIT_SRC))) {
|
||||
imageInfo.usage |= blittable;
|
||||
}
|
||||
|
||||
if (any(usage & TextureUsage::SAMPLEABLE)) {
|
||||
|
||||
#if FVK_ENABLED(FVK_DEBUG_TEXTURE)
|
||||
|
||||
@@ -408,9 +408,10 @@ public:
|
||||
Builder& featureLevel(FeatureLevel featureLevel) noexcept;
|
||||
|
||||
/**
|
||||
* Warning: This is an experimental API. See Engine::setPaused(bool) for caveats.
|
||||
*
|
||||
* @param paused Whether to start the rendering thread paused.
|
||||
* @return A reference to this Builder for chaining calls.
|
||||
* @warning Experimental.
|
||||
*/
|
||||
Builder& paused(bool paused) noexcept;
|
||||
|
||||
@@ -841,7 +842,16 @@ public:
|
||||
|
||||
/**
|
||||
* Pause or resume rendering thread.
|
||||
* @warning Experimental.
|
||||
*
|
||||
* <p>Warning: This is an experimental API. In particular, note the following caveats.
|
||||
*
|
||||
* <ul><li>
|
||||
* Buffer callbacks will never be called as long as the rendering thread is paused.
|
||||
* Do not rely on a buffer callback to unpause the thread.
|
||||
* </li><li>
|
||||
* While the rendering thread is paused, rendering commands will continue to be queued until the
|
||||
* buffer limit is reached. When the limit is reached, the program will abort.
|
||||
* </li></ul>
|
||||
*/
|
||||
void setPaused(bool paused);
|
||||
|
||||
|
||||
@@ -156,6 +156,15 @@ public:
|
||||
*/
|
||||
static constexpr uint8_t DEFAULT_CHANNEL = 2u;
|
||||
|
||||
/**
|
||||
* Type of geometry for a Renderable
|
||||
*/
|
||||
enum class GeometryType : uint8_t {
|
||||
DYNAMIC, //!< dynamic gemoetry has no restriction
|
||||
STATIC_BOUNDS, //!< bounds and world space transform are immutable
|
||||
STATIC //!< skinning/morphing not allowed and Vertex/IndexBuffer immutables
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a builder for renderable components.
|
||||
*
|
||||
@@ -204,6 +213,17 @@ public:
|
||||
VertexBuffer* UTILS_NONNULL vertices,
|
||||
IndexBuffer* UTILS_NONNULL indices) noexcept; //!< \overload
|
||||
|
||||
|
||||
/**
|
||||
* Specify the type of geometry for this renderable. DYNAMIC geometry has no restriction,
|
||||
* STATIC_BOUNDS geometry means that both the bounds and the world-space transform of the
|
||||
* the renderable are immutable.
|
||||
* STATIC geometry has the same restrictions as STATIC_BOUNDS, but in addition disallows
|
||||
* skinning, morphing and changing the VertexBuffer or IndexBuffer in any way.
|
||||
* @param enable whether this renderable has static bounds. false by default.
|
||||
*/
|
||||
Builder& geometryType(GeometryType type) noexcept;
|
||||
|
||||
/**
|
||||
* Binds a material instance to the specified primitive.
|
||||
*
|
||||
@@ -603,11 +623,12 @@ public:
|
||||
|
||||
/**
|
||||
* Changes the bounding box used for frustum culling.
|
||||
* The renderable must not have staticGeometry enabled.
|
||||
*
|
||||
* \see Builder::boundingBox()
|
||||
* \see RenderableManager::getAxisAlignedBoundingBox()
|
||||
*/
|
||||
void setAxisAlignedBoundingBox(Instance instance, const Box& aabb) noexcept;
|
||||
void setAxisAlignedBoundingBox(Instance instance, const Box& aabb);
|
||||
|
||||
/**
|
||||
* Changes the visibility bits.
|
||||
|
||||
@@ -3292,8 +3292,9 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::debugCombineArrayTexture(Fra
|
||||
SamplerMagFilter filterMag,
|
||||
SamplerMinFilter filterMin) noexcept {
|
||||
|
||||
assert_invariant(fg.getDescriptor(input).depth > 1);
|
||||
assert_invariant(fg.getDescriptor(input).type == SamplerType::SAMPLER_2D_ARRAY);
|
||||
auto& inputTextureDesc = fg.getDescriptor(input);
|
||||
assert_invariant(inputTextureDesc.depth > 1);
|
||||
assert_invariant(inputTextureDesc.type == SamplerType::SAMPLER_2D_ARRAY);
|
||||
|
||||
// TODO: add support for sub-resources
|
||||
assert_invariant(fg.getSubResourceDescriptor(input).layer == 0);
|
||||
@@ -3329,14 +3330,12 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::debugCombineArrayTexture(Fra
|
||||
.filterMag = filterMag,
|
||||
.filterMin = filterMin
|
||||
});
|
||||
mi->setParameter("layerIndex", 0);
|
||||
mi->setParameter("viewport", float4{
|
||||
float(vp.left) / inputDesc.width,
|
||||
float(vp.bottom) / inputDesc.height,
|
||||
float(vp.width) / inputDesc.width,
|
||||
float(vp.height) / inputDesc.height
|
||||
});
|
||||
mi->commit(driver);
|
||||
mi->use(driver);
|
||||
|
||||
auto pipeline = material.getPipelineState(mEngine);
|
||||
@@ -3347,18 +3346,19 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::debugCombineArrayTexture(Fra
|
||||
pipeline.first.rasterState.blendFunctionDstAlpha = BlendFunction::ONE_MINUS_SRC_ALPHA;
|
||||
}
|
||||
|
||||
// Blit the scene rendered to the first layer to the left half of the screen.
|
||||
out.params.viewport.width /= 2;
|
||||
render(out, pipeline, driver);
|
||||
// The width of each view takes up 1/depth of the screen width.
|
||||
out.params.viewport.width /= inputTextureDesc.depth;
|
||||
|
||||
// Blit the scene rendered to the second layer to the right half of the screen.
|
||||
// Don't clear or discard the target to keep the previously rendered left half image.
|
||||
mi->setParameter("layerIndex", 1);
|
||||
mi->commit(driver);
|
||||
out.params.flags.clear = filament::backend::TargetBufferFlags::NONE;
|
||||
out.params.flags.discardStart = filament::backend::TargetBufferFlags::NONE;
|
||||
out.params.viewport.left += out.params.viewport.width;
|
||||
render(out, pipeline, driver);
|
||||
// Render all layers of the texture to the screen side-by-side.
|
||||
for (uint32_t i = 0; i < inputTextureDesc.depth; ++i) {
|
||||
mi->setParameter("layerIndex", i);
|
||||
mi->commit(driver);
|
||||
render(out, pipeline, driver);
|
||||
// From the second draw, don't clear the targetbuffer.
|
||||
out.params.flags.clear = filament::backend::TargetBufferFlags::NONE;
|
||||
out.params.flags.discardStart = filament::backend::TargetBufferFlags::NONE;
|
||||
out.params.viewport.left += out.params.viewport.width;
|
||||
}
|
||||
});
|
||||
|
||||
return ppQuadBlit->output;
|
||||
|
||||
@@ -56,7 +56,7 @@ void RenderableManager::destroy(utils::Entity e) noexcept {
|
||||
return downcast(this)->destroy(e);
|
||||
}
|
||||
|
||||
void RenderableManager::setAxisAlignedBoundingBox(Instance instance, const Box& aabb) noexcept {
|
||||
void RenderableManager::setAxisAlignedBoundingBox(Instance instance, const Box& aabb) {
|
||||
downcast(this)->setAxisAlignedBoundingBox(instance, aabb);
|
||||
}
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@ float3 PBRNeutralToneMapper::operator()(math::float3 color) const noexcept {
|
||||
color *= newPeak / peak;
|
||||
|
||||
float g = 1.0f - 1.0f / (desaturation * (peak - newPeak) + 1.0f);
|
||||
return mix(color, float3(1.0f), g);
|
||||
return mix(color, float3(newPeak), g);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -58,6 +58,7 @@ struct RenderableManager::BuilderDetails {
|
||||
bool mScreenSpaceContactShadows : 1;
|
||||
bool mSkinningBufferMode : 1;
|
||||
bool mFogEnabled : 1;
|
||||
RenderableManager::Builder::GeometryType mGeometryType : 2;
|
||||
size_t mSkinningBoneCount = 0;
|
||||
size_t mMorphTargetCount = 0;
|
||||
Bone const* mUserBones = nullptr;
|
||||
@@ -75,7 +76,9 @@ struct RenderableManager::BuilderDetails {
|
||||
explicit BuilderDetails(size_t count)
|
||||
: mEntries(count), mCulling(true), mCastShadows(false),
|
||||
mReceiveShadows(true), mScreenSpaceContactShadows(false),
|
||||
mSkinningBufferMode(false), mFogEnabled(true), mBonePairs() {
|
||||
mSkinningBufferMode(false), mFogEnabled(true),
|
||||
mGeometryType(RenderableManager::Builder::GeometryType::DYNAMIC),
|
||||
mBonePairs() {
|
||||
}
|
||||
// this is only needed for the explicit instantiation below
|
||||
BuilderDetails() = default;
|
||||
@@ -121,6 +124,11 @@ RenderableManager::Builder& RenderableManager::Builder::geometry(size_t index,
|
||||
return *this;
|
||||
}
|
||||
|
||||
RenderableManager::Builder& RenderableManager::Builder::geometryType(GeometryType type) noexcept {
|
||||
mImpl->mGeometryType = type;
|
||||
return *this;
|
||||
}
|
||||
|
||||
RenderableManager::Builder& RenderableManager::Builder::material(size_t index,
|
||||
MaterialInstance const* materialInstance) noexcept {
|
||||
if (index < mImpl->mEntries.size()) {
|
||||
@@ -388,11 +396,21 @@ RenderableManager::Builder::Result RenderableManager::Builder::build(Engine& eng
|
||||
|
||||
ASSERT_PRECONDITION(mImpl->mSkinningBoneCount <= CONFIG_MAX_BONE_COUNT,
|
||||
"bone count > %u", CONFIG_MAX_BONE_COUNT);
|
||||
|
||||
ASSERT_PRECONDITION(mImpl->mInstanceCount <= CONFIG_MAX_INSTANCES || !mImpl->mInstanceBuffer,
|
||||
"instance count is %zu, but instance count is limited to CONFIG_MAX_INSTANCES (%zu) "
|
||||
"instances when supplying transforms via an InstanceBuffer.",
|
||||
mImpl->mInstanceCount,
|
||||
CONFIG_MAX_INSTANCES);
|
||||
|
||||
if (mImpl->mGeometryType == GeometryType::STATIC) {
|
||||
ASSERT_PRECONDITION(mImpl->mSkinningBoneCount > 0,
|
||||
"Skinning can't be used with STATIC geometry");
|
||||
|
||||
ASSERT_PRECONDITION(mImpl->mMorphTargetCount > 0,
|
||||
"Morphing can't be used with STATIC geometry");
|
||||
}
|
||||
|
||||
if (mImpl->mInstanceBuffer) {
|
||||
size_t const bufferInstanceCount = mImpl->mInstanceBuffer->mInstanceCount;
|
||||
ASSERT_PRECONDITION(mImpl->mInstanceCount <= bufferInstanceCount,
|
||||
@@ -519,6 +537,8 @@ void FRenderableManager::create(
|
||||
setSkinning(ci, false);
|
||||
setMorphing(ci, builder->mMorphTargetCount);
|
||||
setFogEnabled(ci, builder->mFogEnabled);
|
||||
// do this after calling setAxisAlignedBoundingBox
|
||||
static_cast<Visibility&>(mManager[ci].visibility).geometryType = builder->mGeometryType;
|
||||
mManager[ci].channels = builder->mLightChannels;
|
||||
|
||||
InstancesInfo& instances = manager[ci].instances;
|
||||
|
||||
@@ -22,22 +22,30 @@
|
||||
#include "HwRenderPrimitiveFactory.h"
|
||||
#include "UniformBuffer.h"
|
||||
|
||||
#include "backend/DriverApiForward.h"
|
||||
|
||||
#include <backend/Handle.h>
|
||||
#include <details/InstanceBuffer.h>
|
||||
|
||||
#include <filament/Box.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
|
||||
#include <details/InstanceBuffer.h>
|
||||
|
||||
#include <private/filament/UibStructs.h>
|
||||
|
||||
#include <backend/DriverApiForward.h>
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Entity.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/SingleInstanceComponentManager.h>
|
||||
#include <utils/Slice.h>
|
||||
#include <utils/Range.h>
|
||||
|
||||
#include <math/mat4.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
class FBufferObject;
|
||||
@@ -49,9 +57,12 @@ class FSkinningBuffer;
|
||||
class FVertexBuffer;
|
||||
class FTexture;
|
||||
|
||||
class MorphTargetBuffer;
|
||||
|
||||
class FRenderableManager : public RenderableManager {
|
||||
public:
|
||||
using Instance = RenderableManager::Instance;
|
||||
using GeometryType = RenderableManager::Builder::GeometryType;
|
||||
|
||||
// TODO: consider renaming, this pertains to material variants, not strictly visibility.
|
||||
struct Visibility {
|
||||
@@ -60,11 +71,13 @@ public:
|
||||
bool castShadows : 1;
|
||||
bool receiveShadows : 1;
|
||||
bool culling : 1;
|
||||
|
||||
bool skinning : 1;
|
||||
bool morphing : 1;
|
||||
bool screenSpaceContactShadows : 1;
|
||||
bool reversedWindingOrder : 1;
|
||||
bool fog : 1;
|
||||
GeometryType geometryType : 2;
|
||||
};
|
||||
|
||||
static_assert(sizeof(Visibility) == sizeof(uint16_t), "Visibility should be 16 bits");
|
||||
@@ -115,7 +128,7 @@ public:
|
||||
|
||||
void destroy(utils::Entity e) noexcept;
|
||||
|
||||
inline void setAxisAlignedBoundingBox(Instance instance, const Box& aabb) noexcept;
|
||||
inline void setAxisAlignedBoundingBox(Instance instance, const Box& aabb);
|
||||
|
||||
inline void setLayerMask(Instance instance, uint8_t select, uint8_t values) noexcept;
|
||||
|
||||
@@ -136,13 +149,13 @@ public:
|
||||
|
||||
inline void setPrimitives(Instance instance, utils::Slice<FRenderPrimitive> const& primitives) noexcept;
|
||||
|
||||
inline void setSkinning(Instance instance, bool enable) noexcept;
|
||||
inline void setSkinning(Instance instance, bool enable);
|
||||
void setBones(Instance instance, Bone const* transforms, size_t boneCount, size_t offset = 0);
|
||||
void setBones(Instance instance, math::mat4f const* transforms, size_t boneCount, size_t offset = 0);
|
||||
void setSkinningBuffer(Instance instance, FSkinningBuffer* skinningBuffer,
|
||||
size_t count, size_t offset);
|
||||
|
||||
inline void setMorphing(Instance instance, bool enable) noexcept;
|
||||
inline void setMorphing(Instance instance, bool enable);
|
||||
void setMorphWeights(Instance instance, float const* weights, size_t count, size_t offset);
|
||||
void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
|
||||
FMorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count);
|
||||
@@ -295,8 +308,12 @@ private:
|
||||
|
||||
FILAMENT_DOWNCAST(RenderableManager)
|
||||
|
||||
void FRenderableManager::setAxisAlignedBoundingBox(Instance instance, const Box& aabb) noexcept {
|
||||
void FRenderableManager::setAxisAlignedBoundingBox(Instance instance, const Box& aabb) {
|
||||
if (instance) {
|
||||
ASSERT_PRECONDITION(
|
||||
static_cast<Visibility const&>(
|
||||
mManager[instance].visibility).geometryType == GeometryType::DYNAMIC,
|
||||
"This renderable has staticBounds enabled; its AABB cannot change.");
|
||||
mManager[instance].aabb = aabb;
|
||||
}
|
||||
}
|
||||
@@ -368,16 +385,26 @@ bool FRenderableManager::getFogEnabled(RenderableManager::Instance instance) con
|
||||
return getVisibility(instance).fog;
|
||||
}
|
||||
|
||||
void FRenderableManager::setSkinning(Instance instance, bool enable) noexcept {
|
||||
void FRenderableManager::setSkinning(Instance instance, bool enable) {
|
||||
if (instance) {
|
||||
Visibility& visibility = mManager[instance].visibility;
|
||||
|
||||
ASSERT_PRECONDITION(
|
||||
visibility.geometryType != GeometryType::STATIC || !enable,
|
||||
"Skinning can't be used with STATIC geometry");
|
||||
|
||||
visibility.skinning = enable;
|
||||
}
|
||||
}
|
||||
|
||||
void FRenderableManager::setMorphing(Instance instance, bool enable) noexcept {
|
||||
void FRenderableManager::setMorphing(Instance instance, bool enable) {
|
||||
if (instance) {
|
||||
Visibility& visibility = mManager[instance].visibility;
|
||||
|
||||
ASSERT_PRECONDITION(
|
||||
visibility.geometryType != GeometryType::STATIC || !enable,
|
||||
"Morphing can't be used with STATIC geometry");
|
||||
|
||||
visibility.morphing = enable;
|
||||
}
|
||||
}
|
||||
@@ -446,22 +473,22 @@ FRenderableManager::getInstancesInfo(Instance instance) const noexcept {
|
||||
}
|
||||
|
||||
utils::Slice<FRenderPrimitive> const& FRenderableManager::getRenderPrimitives(
|
||||
Instance instance, uint8_t level) const noexcept {
|
||||
Instance instance, UTILS_UNUSED uint8_t level) const noexcept {
|
||||
return mManager[instance].primitives;
|
||||
}
|
||||
|
||||
utils::Slice<FRenderPrimitive>& FRenderableManager::getRenderPrimitives(
|
||||
Instance instance, uint8_t level) noexcept {
|
||||
Instance instance, UTILS_UNUSED uint8_t level) noexcept {
|
||||
return mManager[instance].primitives;
|
||||
}
|
||||
|
||||
utils::Slice<FRenderableManager::MorphTargets> const& FRenderableManager::getMorphTargets(
|
||||
Instance instance, uint8_t level) const noexcept {
|
||||
Instance instance, UTILS_UNUSED uint8_t level) const noexcept {
|
||||
return mManager[instance].morphTargets;
|
||||
}
|
||||
|
||||
utils::Slice<FRenderableManager::MorphTargets>& FRenderableManager::getMorphTargets(
|
||||
Instance instance, uint8_t level) noexcept {
|
||||
Instance instance, UTILS_UNUSED uint8_t level) noexcept {
|
||||
return mManager[instance].morphTargets;
|
||||
}
|
||||
|
||||
|
||||
@@ -641,6 +641,9 @@ void FMaterial::getSurfaceProgramSlow(Variant variant,
|
||||
|
||||
Program pb{ getProgramWithVariants(variant, vertexVariant, fragmentVariant) };
|
||||
pb.priorityQueue(priorityQueue);
|
||||
pb.multiview(
|
||||
mEngine.getConfig().stereoscopicType == StereoscopicType::MULTIVIEW &&
|
||||
Variant::isStereoVariant(variant));
|
||||
createAndCacheProgram(std::move(pb), variant);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,14 +25,33 @@
|
||||
|
||||
#include <filament/Texture.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <ibl/Cubemap.h>
|
||||
#include <ibl/CubemapIBL.h>
|
||||
#include <ibl/CubemapUtils.h>
|
||||
#include <ibl/Image.h>
|
||||
|
||||
#include <math/half.h>
|
||||
#include <math/scalar.h>
|
||||
#include <math/vec3.h>
|
||||
|
||||
#include <utils/Allocator.h>
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
using namespace utils;
|
||||
|
||||
namespace filament {
|
||||
@@ -246,20 +265,20 @@ size_t FTexture::getDepth(size_t level) const noexcept {
|
||||
void FTexture::setImage(FEngine& engine, size_t level,
|
||||
uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
|
||||
uint32_t width, uint32_t height, uint32_t depth,
|
||||
FTexture::PixelBufferDescriptor&& buffer) const {
|
||||
FTexture::PixelBufferDescriptor&& p) const {
|
||||
|
||||
if (UTILS_UNLIKELY(!engine.hasFeatureLevel(FeatureLevel::FEATURE_LEVEL_1))) {
|
||||
ASSERT_PRECONDITION(buffer.stride == 0 || buffer.stride == width,
|
||||
ASSERT_PRECONDITION(p.stride == 0 || p.stride == width,
|
||||
"PixelBufferDescriptor stride must be 0 (or width) at FEATURE_LEVEL_0");
|
||||
}
|
||||
|
||||
// this should have been validated already
|
||||
assert_invariant(isTextureFormatSupported(engine, mFormat));
|
||||
|
||||
ASSERT_PRECONDITION(buffer.type == PixelDataType::COMPRESSED ||
|
||||
validatePixelFormatAndType(mFormat, buffer.format, buffer.type),
|
||||
ASSERT_PRECONDITION(p.type == PixelDataType::COMPRESSED ||
|
||||
validatePixelFormatAndType(mFormat, p.format, p.type),
|
||||
"The combination of internal format=%u and {format=%u, type=%u} is not supported.",
|
||||
unsigned(mFormat), unsigned(buffer.format), unsigned(buffer.type));
|
||||
unsigned(mFormat), unsigned(p.format), unsigned(p.type));
|
||||
|
||||
ASSERT_PRECONDITION(!mStream, "setImage() called on a Stream texture.");
|
||||
|
||||
@@ -283,7 +302,7 @@ void FTexture::setImage(FEngine& engine, size_t level,
|
||||
unsigned(yoffset), unsigned(height), unsigned(valueForLevel(level, mHeight)),
|
||||
unsigned(level));
|
||||
|
||||
ASSERT_PRECONDITION(buffer.buffer, "Data buffer is nullptr.");
|
||||
ASSERT_PRECONDITION(p.buffer, "Data buffer is nullptr.");
|
||||
|
||||
uint32_t effectiveTextureDepthOrLayers;
|
||||
switch (mTarget) {
|
||||
@@ -311,8 +330,21 @@ void FTexture::setImage(FEngine& engine, size_t level,
|
||||
"zoffset (%u) + depth (%u) > texture depth (%u) at level (%u)",
|
||||
unsigned(zoffset), unsigned(depth), effectiveTextureDepthOrLayers, unsigned(level));
|
||||
|
||||
using PBD = PixelBufferDescriptor;
|
||||
size_t const stride = p.stride ? p.stride : width;
|
||||
size_t const bpp = PBD::computeDataSize(p.format, p.type, 1, 1, 1);
|
||||
size_t const bpr = PBD::computeDataSize(p.format, p.type, stride, 1, p.alignment);
|
||||
size_t const bpl = bpr * height; // TODO: PBD should have a "layer stride"
|
||||
// TODO: PBD should have a p.depth (# layers to skip)
|
||||
ASSERT_PRECONDITION(bpp * p.left + bpr * p.top + bpl * (0 + depth) <= p.size,
|
||||
"buffer overflow: (size=%lu, stride=%lu, left=%u, top=%u) smaller than specified region "
|
||||
"{{%u,%u,%u},{%u,%u,%u)}}",
|
||||
size_t(p.size), size_t(p.stride), unsigned(p.left), unsigned(p.top),
|
||||
unsigned(xoffset), unsigned(yoffset), unsigned(zoffset),
|
||||
unsigned(width), unsigned(height), unsigned(depth));
|
||||
|
||||
engine.getDriverApi().update3DImage(mHandle,
|
||||
uint8_t(level), xoffset, yoffset, zoffset, width, height, depth, std::move(buffer));
|
||||
uint8_t(level), xoffset, yoffset, zoffset, width, height, depth, std::move(p));
|
||||
}
|
||||
|
||||
// deprecated
|
||||
|
||||
@@ -58,6 +58,15 @@ fragment {
|
||||
|
||||
vertex {
|
||||
void materialVertex(inout MaterialVertexInputs material) {
|
||||
material.eyeDirection.xyz = material.worldPosition.xyz;
|
||||
// This code is taken from computeWorldPosition and assumes the vertex domain is 'device'.
|
||||
vec4 p = getPosition();
|
||||
// GL convention to inverted DX convention
|
||||
p.z = p.z * -0.5 + 0.5;
|
||||
vec4 worldPosition = getWorldFromClipMatrix() * p;
|
||||
// Getting the true world position would require dividing by w, but since this is a skybox
|
||||
// at inifinity, this results in very large numbers for material.eyeDirection.
|
||||
// Since the eyeDirection is only used as a direction vector in the fragment shader, we can
|
||||
// skip that step to improve precision.
|
||||
material.eyeDirection.xyz = worldPosition.xyz;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.51.1"
|
||||
spec.version = "1.51.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.51.1/filament-v1.51.1-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.51.0/filament-v1.51.0-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -275,10 +275,6 @@ const float kSensitivity = 100.0f;
|
||||
- (void)dealloc {
|
||||
[self destroyModel];
|
||||
|
||||
delete _manipulator;
|
||||
delete _stbDecoder;
|
||||
delete _ktxDecoder;
|
||||
|
||||
_materialProvider->destroyMaterials();
|
||||
delete _materialProvider;
|
||||
auto* ncm = _assetLoader->getNames();
|
||||
@@ -286,6 +282,10 @@ const float kSensitivity = 100.0f;
|
||||
AssetLoader::destroy(&_assetLoader);
|
||||
delete _resourceLoader;
|
||||
|
||||
delete _manipulator;
|
||||
delete _stbDecoder;
|
||||
delete _ktxDecoder;
|
||||
|
||||
_engine->destroy(_swapChain);
|
||||
_engine->destroy(_view);
|
||||
EntityManager::get().destroy(_entities.camera);
|
||||
|
||||
@@ -68,7 +68,7 @@ enum class ReservedSpecializationConstants : uint8_t {
|
||||
CONFIG_POWER_VR_SHADER_WORKAROUNDS = 5,
|
||||
CONFIG_DEBUG_DIRECTIONAL_SHADOWMAP = 6,
|
||||
CONFIG_DEBUG_FROXEL_VISUALIZATION = 7,
|
||||
CONFIG_STEREO_EYE_COUNT = 8,
|
||||
CONFIG_STEREO_EYE_COUNT = 8, // don't change (hardcoded in ShaderCompilerService.cpp)
|
||||
};
|
||||
|
||||
// This value is limited by UBO size, ES3.0 only guarantees 16 KiB.
|
||||
|
||||
@@ -97,8 +97,8 @@ struct AssetConfiguration {
|
||||
*
|
||||
* // Load buffers and textures from disk.
|
||||
* ResourceLoader resourceLoader({engine, ".", true});
|
||||
* resourceLoader.addTextureProvider("image/png", decoder)
|
||||
* resourceLoader.addTextureProvider("image/jpeg", decoder)
|
||||
* resourceLoader.addTextureProvider("image/png", decoder);
|
||||
* resourceLoader.addTextureProvider("image/jpeg", decoder);
|
||||
* resourceLoader.loadResources(asset);
|
||||
*
|
||||
* // Free the glTF hierarchy as it is no longer needed.
|
||||
|
||||
@@ -93,7 +93,8 @@ public:
|
||||
/**
|
||||
* Register a plugin that can consume PNG / JPEG content and produce filament::Texture objects.
|
||||
*
|
||||
* Destruction of the given provider is the client's responsibility.
|
||||
* Destruction of the given provider is the client's responsibility and must be done after the
|
||||
* destruction of this ResourceLoader.
|
||||
*/
|
||||
void addTextureProvider(const char* mimeType, TextureProvider* provider);
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ highp vec2 toEquirect(const highp vec3 s) {
|
||||
highp float xf = atan(s.x, s.z) * (1.0 / PI); // range [-1.0, 1.0]
|
||||
highp float yf = asin(s.y) * (2.0 / PI); // range [-1.0, 1.0]
|
||||
xf = (xf + 1.0) * 0.5; // range [0, 1.0]
|
||||
yf = (yf + 1.0) * 0.5; // range [0, 1.0]
|
||||
yf = (1.0 - yf) * 0.5; // range [0, 1.0]
|
||||
return vec2(xf, yf);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,9 @@ mediump vec3 sampleEquirect(mediump sampler2D equirect, const highp vec3 r) {
|
||||
|
||||
void postProcess(inout PostProcessInputs postProcess) {
|
||||
highp vec2 uv = variable_vertex.xy; // interpolated at pixel's center
|
||||
highp vec2 p = uv * 2.0 - 1.0;
|
||||
highp vec2 p = vec2(
|
||||
uv.x * 2.0 - 1.0,
|
||||
1.0 - uv.y * 2.0);
|
||||
|
||||
float side = materialParams.side;
|
||||
float mirror = materialParams.mirror;
|
||||
|
||||
@@ -87,6 +87,7 @@ if (LINUX OR ANDROID)
|
||||
list(APPEND SRCS src/linux/Path.cpp)
|
||||
endif()
|
||||
if (APPLE)
|
||||
list(APPEND SRCS src/darwin/Exception.mm)
|
||||
list(APPEND SRCS src/darwin/Path.mm)
|
||||
list(APPEND SRCS src/darwin/Systrace.cpp)
|
||||
endif()
|
||||
@@ -122,6 +123,10 @@ if (LINUX)
|
||||
target_link_libraries(${TARGET} PRIVATE dl)
|
||||
endif()
|
||||
|
||||
if (APPLE AND NOT IOS)
|
||||
target_link_libraries(${TARGET} PRIVATE "-framework Cocoa")
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# Installation
|
||||
# ==================================================================================================
|
||||
|
||||
@@ -258,6 +258,18 @@ public:
|
||||
*/
|
||||
virtual const char* what() const noexcept = 0;
|
||||
|
||||
/**
|
||||
* Get the reason for the panic.
|
||||
* @return a C string containing the reason for the panic.
|
||||
*/
|
||||
virtual const char* getReason() const noexcept = 0;
|
||||
|
||||
/**
|
||||
* Get the type of the panic. When compiled without RTTI, this returns a generic type name.
|
||||
* @return a C string containing the type of the panic.
|
||||
*/
|
||||
virtual const char* getType() const noexcept = 0;
|
||||
|
||||
/**
|
||||
* Get the function name where the panic was detected
|
||||
* @return a C string containing the function name where the panic was detected
|
||||
@@ -305,6 +317,8 @@ public:
|
||||
const char* what() const noexcept override;
|
||||
|
||||
// Panic interface
|
||||
const char* getReason() const noexcept override;
|
||||
const char* getType() const noexcept override;
|
||||
const char* getFunction() const noexcept override;
|
||||
const char* getFile() const noexcept override;
|
||||
int getLine() const noexcept override;
|
||||
@@ -369,7 +383,8 @@ private:
|
||||
char const* const m_function = nullptr;
|
||||
char const* const m_file = nullptr;
|
||||
const int m_line = -1;
|
||||
mutable std::string m_msg;
|
||||
std::string m_msg;
|
||||
std::string m_type;
|
||||
};
|
||||
|
||||
namespace details {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TNT_UTILS_DARWIN_EXCEPTION_H
|
||||
#define TNT_UTILS_DARWIN_EXCEPTION_H
|
||||
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace utils::details {
|
||||
|
||||
void throwDarwinException(const Panic& exception) UTILS_NORETURN;
|
||||
|
||||
}
|
||||
|
||||
#endif // TNT_UTILS_DARWIN_EXCEPTION_H
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <utils/darwin/Exception.h>
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdarg>
|
||||
#include <cstdlib>
|
||||
@@ -88,6 +92,16 @@ const char* TPanic<T>::what() const noexcept {
|
||||
return m_msg.c_str();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const char* TPanic<T>::getReason() const noexcept {
|
||||
return m_reason.c_str();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const char* TPanic<T>::getType() const noexcept {
|
||||
return m_type.c_str();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const char* TPanic<T>::getFunction() const noexcept {
|
||||
return m_function;
|
||||
@@ -116,13 +130,12 @@ void TPanic<T>::log() const noexcept {
|
||||
|
||||
template<typename T>
|
||||
void TPanic<T>::buildMessage() {
|
||||
std::string type;
|
||||
#if UTILS_HAS_RTTI
|
||||
type = CallStack::demangleTypeName(typeid(T).name()).c_str();
|
||||
m_type = CallStack::demangleTypeName(typeid(T).name()).c_str();
|
||||
#else
|
||||
type = "Panic";
|
||||
m_type = "Panic";
|
||||
#endif
|
||||
m_msg = panicString(type, m_function, m_line, m_file, m_reason.c_str());
|
||||
m_msg = panicString(m_type, m_function, m_line, m_file, m_reason.c_str());
|
||||
}
|
||||
|
||||
UTILS_ALWAYS_INLINE
|
||||
@@ -139,6 +152,11 @@ void TPanic<T>::panic(char const* function, char const* file, int line, const ch
|
||||
va_end(args);
|
||||
T e(function, formatFile(file), line, reason);
|
||||
e.log();
|
||||
|
||||
#if defined(__APPLE__)
|
||||
details::throwDarwinException(e);
|
||||
#endif
|
||||
|
||||
#ifdef __EXCEPTIONS
|
||||
throw e;
|
||||
#endif
|
||||
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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 <utils/Panic.h>
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
namespace utils::details {
|
||||
|
||||
void throwDarwinException(const Panic& exception) {
|
||||
// Turn this exception into an NSException and raise it.
|
||||
// This is allowed even if we're built without Objective-C exceptions (-fno-objc-exceptions).
|
||||
[[NSException exceptionWithName:@(exception.getType())
|
||||
reason:@(exception.getReason())
|
||||
userInfo:@{
|
||||
@"file" : @(exception.getFile()),
|
||||
@"line" : @(exception.getLine()),
|
||||
@"function" : @(exception.getFunction())
|
||||
}] raise];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -938,6 +938,10 @@ class_<RenderableBuilder>("RenderableManager$Builder")
|
||||
size_t count), {
|
||||
return &builder->geometry(index, type, vertices, indices, offset, minIndex, maxIndex, count); })
|
||||
|
||||
.BUILDER_FUNCTION("geometryType", RenderableBuilder, (RenderableBuilder* builder,
|
||||
RenderableManager::Builder::GeometryType type), {
|
||||
return &builder->geometryType(type); })
|
||||
|
||||
.BUILDER_FUNCTION("material", RenderableBuilder, (RenderableBuilder* builder,
|
||||
size_t index, MaterialInstance* mi), {
|
||||
return &builder->material(index, mi); })
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "filament",
|
||||
"version": "1.51.1",
|
||||
"version": "1.51.0",
|
||||
"description": "Real-time physically based rendering engine",
|
||||
"main": "filament.js",
|
||||
"module": "filament.js",
|
||||
|
||||
Reference in New Issue
Block a user