Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07144e833b | ||
|
|
c3be134e1a | ||
|
|
1536c61d2a | ||
|
|
c56db04ec7 | ||
|
|
8c445264fd | ||
|
|
caf886df6b | ||
|
|
287984dd7f | ||
|
|
3294bb64a5 | ||
|
|
f52476a323 | ||
|
|
c839915a00 | ||
|
|
2deafc6b81 | ||
|
|
fdec0f79a2 | ||
|
|
31d66002a9 | ||
|
|
f2ed382cf1 | ||
|
|
a4746eab0c | ||
|
|
0b011fae7d | ||
|
|
a6c9922d33 | ||
|
|
7fe1ee3fd5 | ||
|
|
075726db8b | ||
|
|
b22ff3bebb | ||
|
|
bc794bbf7b | ||
|
|
9c29c3d192 | ||
|
|
8e5dabfa8e | ||
|
|
e974989a95 | ||
|
|
057ce2ea4b | ||
|
|
2e920f2780 | ||
|
|
b41e6dfd5c | ||
|
|
8413c84284 | ||
|
|
10e63bf2cf | ||
|
|
73ba8fc753 |
+3
-1
@@ -65,4 +65,6 @@ SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
PackConstructorInitializers: Never
|
||||
PackConstructorInitializers: Never
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
IndentWrappedFunctionNames: true
|
||||
|
||||
+1
-1
@@ -351,7 +351,7 @@ else()
|
||||
endif()
|
||||
|
||||
if (FILAMENT_USE_EXTERNAL_GLES3)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_EXTERNAL_GLES3")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFILAMENT_USE_EXTERNAL_GLES3")
|
||||
endif()
|
||||
|
||||
if (FILAMENT_SUPPORTS_EGL_ON_LINUX)
|
||||
|
||||
+18
-6
@@ -20,7 +20,7 @@ The guiding principles of the filament code style and code formatting can be res
|
||||
- class access modifiers are not indented
|
||||
- last line of `.cpp` or `.h` file must be an empty line
|
||||
|
||||
```
|
||||
```c++
|
||||
for (int i = 0; i < max; i++) {
|
||||
}
|
||||
|
||||
@@ -73,12 +73,24 @@ src/data.inc
|
||||
- `public` class attributes *are not* prefixed
|
||||
- class attributes and methods are lower camelcase
|
||||
|
||||
```
|
||||
```c++
|
||||
extern int gGlobalWarming;
|
||||
|
||||
class FooBar {
|
||||
public:
|
||||
void methodName();
|
||||
FooBar(int attributeName, int sizeInBytes)
|
||||
: mAttributeName(attributeName),
|
||||
sizeInBytes(sizeInBytes) {}
|
||||
|
||||
void reallyLongMethodNameWithLotsOfArguments(bool argument1,
|
||||
int someSecondArgument, int bestArgument) {
|
||||
std::pair<bool, int> pair = {
|
||||
argument1,
|
||||
argument2,
|
||||
};
|
||||
// etc
|
||||
}
|
||||
|
||||
int sizeInBytes;
|
||||
private:
|
||||
int mAttributeName;
|
||||
@@ -97,7 +109,7 @@ private:
|
||||
- always include the copyright notice at the top of every file
|
||||
- make sure the date is correct
|
||||
|
||||
```
|
||||
```c++
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
@@ -139,7 +151,7 @@ conversely containers and algorithms are not allowed. There are exceptions such
|
||||
|
||||
*Sorting the headers is important to help catching missing `#include` directives.*
|
||||
|
||||
```
|
||||
```c++
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
@@ -183,7 +195,7 @@ conversely containers and algorithms are not allowed. There are exceptions such
|
||||
### Misc
|
||||
|
||||
- Use `auto` only when the type appears on the same line or with iterators and lambdas.
|
||||
```
|
||||
```c++
|
||||
auto foo = new Foo();
|
||||
for (auto& i : collection) { }
|
||||
```
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.65.4'
|
||||
implementation 'com.google.android.filament:filament-android:1.66.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.65.4'
|
||||
pod 'Filament', '~> 1.66.0'
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -7,6 +7,10 @@ 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.66.0
|
||||
|
||||
- materials: include default values of spec constants in material metadata [⚠️ **Recompile Materials**]
|
||||
|
||||
## v1.65.4
|
||||
|
||||
|
||||
|
||||
@@ -356,6 +356,7 @@ Java_com_google_android_filament_View_nSetFogOptions(JNIEnv *, jclass , jlong na
|
||||
view->setFogOptions(options);
|
||||
}
|
||||
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetBlendMode(JNIEnv *, jclass , jlong nativeView, jint blendMode) {
|
||||
View* view = (View*) nativeView;
|
||||
@@ -554,3 +555,20 @@ Java_com_google_android_filament_View_nClearFrameHistory(JNIEnv *env, jclass cla
|
||||
Engine *engine = (Engine *) nativeEngine;
|
||||
view->clearFrameHistory(*engine);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetChannelDepthClearEnabled(JNIEnv *, jclass ,
|
||||
jlong nativeView, jint channel, jboolean enabled) {
|
||||
View* view = (View*) nativeView;
|
||||
view->setChannelDepthClearEnabled((uint8_t) channel, (bool) enabled);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_View_nIsChannelDepthClearEnabled(JNIEnv *env, jclass clazz,
|
||||
jlong nativeView, jint channel) {
|
||||
// TODO: implement nIsChannelDepthClearEnabled()
|
||||
View* view = (View*) nativeView;
|
||||
return (jboolean)view->isChannelDepthClearEnabled((uint8_t) channel);
|
||||
}
|
||||
|
||||
+4
-4
@@ -332,7 +332,7 @@ public class RenderableManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the channel this renderable is associated to. There can be 4 channels.
|
||||
* Set the channel this renderable is associated to. There can be 8 channels.
|
||||
*
|
||||
* <p>All renderables in a given channel are rendered together, regardless of anything else.
|
||||
* They are sorted as usual within a channel.</p>
|
||||
@@ -342,7 +342,7 @@ public class RenderableManager {
|
||||
* <p>Channels 0 and 1 may not have render primitives using a material with `refractionType`
|
||||
* set to `screenspace`.</p>
|
||||
*
|
||||
* @param channel clamped to the range [0..3], defaults to 2.
|
||||
* @param channel clamped to the range [0..7], defaults to 2.
|
||||
*
|
||||
* @return Builder reference for chaining calls.
|
||||
*
|
||||
@@ -351,7 +351,7 @@ public class RenderableManager {
|
||||
* @see RenderableManager::setBlendOrderAt()
|
||||
*/
|
||||
@NonNull
|
||||
public Builder channel(@IntRange(from = 0, to = 3) int channel) {
|
||||
public Builder channel(@IntRange(from = 0, to = 7) int channel) {
|
||||
nBuilderChannel(mNativeBuilder, channel);
|
||||
return this;
|
||||
}
|
||||
@@ -730,7 +730,7 @@ public class RenderableManager {
|
||||
*
|
||||
* @see Builder#channel
|
||||
*/
|
||||
public void setChannel(@EntityInstance int i, @IntRange(from = 0, to = 3) int channel) {
|
||||
public void setChannel(@EntityInstance int i, @IntRange(from = 0, to = 7) int channel) {
|
||||
nSetChannel(mNativeObject, i, channel);
|
||||
}
|
||||
|
||||
|
||||
@@ -291,6 +291,25 @@ public class View {
|
||||
return mViewport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether a channel must clear the depth buffer before all primitives are rendered.
|
||||
* Channel depth clear is off by default for all channels.
|
||||
* This is orthogonal to Renderer::setClearOptions().
|
||||
* @param channel between 0 and 7
|
||||
* @param enabled true to enable clear, false to disable
|
||||
*/
|
||||
void setChannelDepthClearEnabled(@IntRange(from = 0, to = 7) int channel, boolean enabled) {
|
||||
nSetChannelDepthClearEnabled(getNativeObject(), channel, enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param channel between 0 and 7
|
||||
* @return true if this channel has depth clear enabled.
|
||||
*/
|
||||
boolean isChannelDepthClearEnabled(@IntRange(from = 0, to = 7) int channel) {
|
||||
return nIsChannelDepthClearEnabled(getNativeObject(), channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the blending mode used to draw the view into the SwapChain.
|
||||
*
|
||||
@@ -1318,6 +1337,8 @@ public class View {
|
||||
boolean lensFlare, boolean starburst, float chromaticAberration, int ghostCount, float ghostSpacing, float ghostThreshold, float haloThickness, float haloRadius, float haloThreshold);
|
||||
private static native void nSetFogOptions(long nativeView, float distance, float maximumOpacity, float height, float heightFalloff, float cutOffDistance, float v, float v1, float v2, float density, float inScatteringStart, float inScatteringSize, boolean fogColorFromIbl, long skyColorNativeObject, boolean enabled);
|
||||
private static native void nSetStereoscopicOptions(long nativeView, boolean enabled);
|
||||
private static native void nSetChannelDepthClearEnabled(long nativeView, int channel, boolean enabled);
|
||||
private static native boolean nIsChannelDepthClearEnabled(long nativeView, int channel);
|
||||
private static native void nSetBlendMode(long nativeView, int blendMode);
|
||||
private static native void nSetDepthOfFieldOptions(long nativeView, float cocScale, float maxApertureDiameter, boolean enabled, int filter,
|
||||
boolean nativeResolution, int foregroundRingCount, int backgroundRingCount, int fastGatherRingCount, int maxForegroundCOC, int maxBackgroundCOC);
|
||||
@@ -1615,7 +1636,7 @@ public class View {
|
||||
*
|
||||
* This value is used as a tint instead, when fogColorFromIbl is enabled.
|
||||
*
|
||||
* @see fogColorFromIbl
|
||||
* @see #fogColorFromIbl
|
||||
*/
|
||||
@NonNull @Size(min = 3)
|
||||
public float[] color = {1.0f, 1.0f, 1.0f};
|
||||
@@ -1656,7 +1677,7 @@ public class View {
|
||||
*
|
||||
* `fogColorFromIbl` is ignored when skyTexture is specified.
|
||||
*
|
||||
* @see skyColor
|
||||
* @see #skyColor
|
||||
*/
|
||||
public boolean fogColorFromIbl = false;
|
||||
/**
|
||||
@@ -1674,7 +1695,7 @@ public class View {
|
||||
* In `linearFog` mode mipmap level 0 is always used.
|
||||
*
|
||||
* @see Texture
|
||||
* @see fogColorFromIbl
|
||||
* @see #fogColorFromIbl
|
||||
*/
|
||||
@Nullable
|
||||
public Texture skyColor = null;
|
||||
@@ -1796,7 +1817,8 @@ public class View {
|
||||
/**
|
||||
* Structure used to set the precision of the color buffer and related quality settings.
|
||||
*
|
||||
* @see setRenderQuality, getRenderQuality
|
||||
* @see #setRenderQuality
|
||||
* @see #getRenderQuality
|
||||
*/
|
||||
public static class RenderQuality {
|
||||
/**
|
||||
@@ -1814,7 +1836,7 @@ public class View {
|
||||
|
||||
/**
|
||||
* Options for screen space Ambient Occlusion (SSAO) and Screen Space Cone Tracing (SSCT)
|
||||
* @see setAmbientOcclusionOptions()
|
||||
* @see #setAmbientOcclusionOptions
|
||||
*/
|
||||
public static class AmbientOcclusionOptions {
|
||||
public enum AmbientOcclusionType {
|
||||
@@ -1966,7 +1988,7 @@ public class View {
|
||||
|
||||
/**
|
||||
* Options for Multi-Sample Anti-aliasing (MSAA)
|
||||
* @see setMultiSampleAntiAliasingOptions()
|
||||
* @see #setMultiSampleAntiAliasingOptions
|
||||
*/
|
||||
public static class MultiSampleAntiAliasingOptions {
|
||||
/**
|
||||
@@ -1996,7 +2018,7 @@ public class View {
|
||||
* `feedback` of 0.1 effectively accumulates a maximum of 19 samples in steady state.
|
||||
* see "A Survey of Temporal Antialiasing Techniques" by Lei Yang and all for more information.
|
||||
*
|
||||
* @see setTemporalAntiAliasingOptions()
|
||||
* @see #setTemporalAntiAliasingOptions
|
||||
*/
|
||||
public static class TemporalAntiAliasingOptions {
|
||||
public enum BoxType {
|
||||
@@ -2098,7 +2120,7 @@ public class View {
|
||||
|
||||
/**
|
||||
* Options for Screen-space Reflections.
|
||||
* @see setScreenSpaceReflectionsOptions()
|
||||
* @see #setScreenSpaceReflectionsOptions
|
||||
*/
|
||||
public static class ScreenSpaceReflectionsOptions {
|
||||
/**
|
||||
@@ -2132,7 +2154,9 @@ public class View {
|
||||
|
||||
/**
|
||||
* List of available post-processing anti-aliasing techniques.
|
||||
* @see setAntiAliasing, getAntiAliasing, setSampleCount
|
||||
* @see #setAntiAliasing
|
||||
* @see #getAntiAliasing
|
||||
* @see #setSampleCount
|
||||
*/
|
||||
public enum AntiAliasing {
|
||||
/**
|
||||
@@ -2161,7 +2185,7 @@ public class View {
|
||||
|
||||
/**
|
||||
* List of available shadow mapping techniques.
|
||||
* @see setShadowType
|
||||
* @see #setShadowType
|
||||
*/
|
||||
public enum ShadowType {
|
||||
/**
|
||||
@@ -2185,7 +2209,7 @@ public class View {
|
||||
|
||||
/**
|
||||
* View-level options for VSM Shadowing.
|
||||
* @see setVsmShadowOptions()
|
||||
* @see #setVsmShadowOptions
|
||||
* @warning This API is still experimental and subject to change.
|
||||
*/
|
||||
public static class VsmShadowOptions {
|
||||
@@ -2226,7 +2250,7 @@ public class View {
|
||||
|
||||
/**
|
||||
* View-level options for DPCF and PCSS Shadowing.
|
||||
* @see setSoftShadowOptions()
|
||||
* @see #setSoftShadowOptions
|
||||
* @warning This API is still experimental and subject to change.
|
||||
*/
|
||||
public static class SoftShadowOptions {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.65.4
|
||||
VERSION_NAME=1.66.0
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ Google code style and is derived from the Java code style, but not quite.</p>
|
||||
<li>class access modifiers are not indented</li>
|
||||
<li>last line of <code>.cpp</code> or <code>.h</code> file must be an empty line</li>
|
||||
</ul>
|
||||
<pre><code>for (int i = 0; i < max; i++) {
|
||||
<pre><code class="language-c++">for (int i = 0; i < max; i++) {
|
||||
}
|
||||
|
||||
class Foo {
|
||||
@@ -227,11 +227,23 @@ src/data.inc
|
||||
<li><code>public</code> class attributes <em>are not</em> prefixed</li>
|
||||
<li>class attributes and methods are lower camelcase</li>
|
||||
</ul>
|
||||
<pre><code>extern int gGlobalWarming;
|
||||
<pre><code class="language-c++">extern int gGlobalWarming;
|
||||
|
||||
class FooBar {
|
||||
public:
|
||||
void methodName();
|
||||
FooBar(int attributeName, int sizeInBytes)
|
||||
: mAttributeName(attributeName),
|
||||
sizeInBytes(sizeInBytes) {}
|
||||
|
||||
void reallyLongMethodNameWithLotsOfArguments(bool argument1,
|
||||
int someSecondArgument, int bestArgument) {
|
||||
std::pair<bool, int> pair = {
|
||||
argument1,
|
||||
argument2,
|
||||
};
|
||||
// etc
|
||||
}
|
||||
|
||||
int sizeInBytes;
|
||||
private:
|
||||
int mAttributeName;
|
||||
@@ -248,7 +260,7 @@ private:
|
||||
<li>always include the copyright notice at the top of every file</li>
|
||||
<li>make sure the date is correct</li>
|
||||
</ul>
|
||||
<pre><code>/*
|
||||
<pre><code class="language-c++">/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -293,7 +305,7 @@ conversely containers and algorithms are not allowed. There are exceptions such
|
||||
</li>
|
||||
</ul>
|
||||
<p><em>Sorting the headers is important to help catching missing <code>#include</code> directives.</em></p>
|
||||
<pre><code>/*
|
||||
<pre><code class="language-c++">/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -336,7 +348,7 @@ from other string types.</li>
|
||||
<ul>
|
||||
<li>Use <code>auto</code> only when the type appears on the same line or with iterators and lambdas.</li>
|
||||
</ul>
|
||||
<pre><code>auto foo = new Foo();
|
||||
<pre><code class="language-c++">auto foo = new Foo();
|
||||
for (auto& i : collection) { }
|
||||
</code></pre>
|
||||
|
||||
|
||||
+2
-2
@@ -181,7 +181,7 @@ important for <code>matc</code> (material compiler).</p>
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.65.2'
|
||||
implementation 'com.google.android.filament:filament-android:1.65.3'
|
||||
}
|
||||
</code></pre>
|
||||
<p>Here are all the libraries available in the group <code>com.google.android.filament</code>:</p>
|
||||
@@ -196,7 +196,7 @@ dependencies {
|
||||
</div>
|
||||
<h3 id="ios"><a class="header" href="#ios">iOS</a></h3>
|
||||
<p>iOS projects can use CocoaPods to install the latest release:</p>
|
||||
<pre><code class="language-shell">pod 'Filament', '~> 1.65.2'
|
||||
<pre><code class="language-shell">pod 'Filament', '~> 1.65.3'
|
||||
</code></pre>
|
||||
<h2 id="documentation"><a class="header" href="#documentation">Documentation</a></h2>
|
||||
<ul>
|
||||
|
||||
@@ -276,6 +276,13 @@ For example, it could be <code>out/renderdiff/diffs/presubmit</code> for the sta
|
||||
</code></pre>
|
||||
<p>where <code>[PR #]</code> is the numeric ID of your pull request, and the <code>[github token]</code> is an acess
|
||||
token that you (as a github user) needs to generate (<a href="https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens">reference</a>).</p>
|
||||
<p>To see the results of a specific run, you would do the following</p>
|
||||
<pre><code>python3 test/renderdiff/src/viewer.py --run_number=[RUN #] --github_token=[github token]
|
||||
</code></pre>
|
||||
<p>where <code>[RUN #]</code> is the numeric ID of the run. You can find the run number in the URL of the
|
||||
GitHub Actions page. For example, in the URL
|
||||
<code>https://github.com/google/filament/actions/runs/18023632663/job/51286323708?pr=9264</code>,
|
||||
the run number is <code>18023632663</code>.</p>
|
||||
|
||||
</main>
|
||||
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -249,9 +249,10 @@ set(PRIVATE_HDRS
|
||||
set(MATERIAL_SRCS
|
||||
src/materials/antiAliasing/fxaa/fxaa.mat
|
||||
src/materials/antiAliasing/taa/taa.mat
|
||||
src/materials/blitArray.mat
|
||||
src/materials/blitDepth.mat
|
||||
src/materials/blitLow.mat
|
||||
src/materials/blitArray.mat
|
||||
src/materials/clearDepth.mat
|
||||
src/materials/bloom/bloomDownsample.mat
|
||||
src/materials/bloom/bloomDownsample2x.mat
|
||||
src/materials/bloom/bloomDownsample9.mat
|
||||
|
||||
@@ -713,6 +713,12 @@ enum class Precision : uint8_t {
|
||||
DEFAULT
|
||||
};
|
||||
|
||||
union ConstantValue {
|
||||
int32_t i;
|
||||
float f;
|
||||
bool b;
|
||||
};
|
||||
|
||||
/**
|
||||
* Shader compiler priority queue
|
||||
*
|
||||
@@ -1697,6 +1703,8 @@ enum class Workaround : uint16_t {
|
||||
// prevents these stutters by not precaching depth variants of the default material for those
|
||||
// particular browsers.
|
||||
DISABLE_DEPTH_PRECACHE_FOR_DEFAULT_MATERIAL,
|
||||
// Emulate an sRGB swapchain in shader code.
|
||||
EMULATE_SRGB_SWAPCHAIN,
|
||||
};
|
||||
|
||||
using StereoscopicType = backend::Platform::StereoscopicType;
|
||||
|
||||
@@ -236,7 +236,7 @@ public:
|
||||
* @return nullptr on failure, or a pointer to the newly created driver.
|
||||
*/
|
||||
virtual Driver* UTILS_NULLABLE createDriver(void* UTILS_NULLABLE sharedContext,
|
||||
const DriverConfig& driverConfig) noexcept = 0;
|
||||
const DriverConfig& driverConfig) = 0;
|
||||
|
||||
/**
|
||||
* Processes the platform's event queue when called from its primary event-handling thread.
|
||||
|
||||
@@ -50,11 +50,7 @@ public:
|
||||
descriptor_binding_t binding;
|
||||
};
|
||||
|
||||
struct SpecializationConstant {
|
||||
using Type = std::variant<int32_t, float, bool>;
|
||||
uint32_t id; // id set in glsl
|
||||
Type value; // value and type
|
||||
};
|
||||
using SpecializationConstant = std::variant<int32_t, float, bool>;
|
||||
|
||||
struct Uniform { // For ES2 support
|
||||
utils::CString name; // full qualified name of the uniform field
|
||||
@@ -118,7 +114,7 @@ public:
|
||||
Program& multiview(bool multiview) noexcept;
|
||||
|
||||
// For ES2 support only...
|
||||
Program& uniforms(uint32_t index, utils::CString name, UniformInfo uniforms) noexcept;
|
||||
Program& uniforms(uint32_t index, utils::CString name, UniformInfo uniforms);
|
||||
Program& attributes(AttributesInfo attributes) noexcept;
|
||||
|
||||
//
|
||||
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
*
|
||||
*/
|
||||
virtual SwapChain* UTILS_NULLABLE createSwapChain(
|
||||
void* UTILS_NULLABLE nativeWindow, uint64_t flags) noexcept = 0;
|
||||
void* UTILS_NULLABLE nativeWindow, uint64_t flags) = 0;
|
||||
|
||||
/**
|
||||
* Called by the driver create a headless SwapChain.
|
||||
@@ -126,7 +126,7 @@ public:
|
||||
* A void* might be enough.
|
||||
*/
|
||||
virtual SwapChain* UTILS_NULLABLE createSwapChain(
|
||||
uint32_t width, uint32_t height, uint64_t flags) noexcept = 0;
|
||||
uint32_t width, uint32_t height, uint64_t flags) = 0;
|
||||
|
||||
/**
|
||||
* Called by the driver to destroys the SwapChain
|
||||
|
||||
@@ -40,7 +40,7 @@ protected:
|
||||
// Platform Interface
|
||||
|
||||
Driver* createDriver(void* sharedContext,
|
||||
const DriverConfig& driverConfig) noexcept override;
|
||||
const DriverConfig& driverConfig) override;
|
||||
|
||||
// Currently returns 0
|
||||
int getOSVersion() const noexcept override;
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
// Platform Interface
|
||||
|
||||
Driver* createDriver(void* sharedGLContext,
|
||||
const DriverConfig& driverConfig) noexcept override;
|
||||
const DriverConfig& driverConfig) override;
|
||||
|
||||
int getOSVersion() const noexcept final { return 0; }
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ protected:
|
||||
* Initializes EGL, creates the OpenGL context and returns a concrete Driver implementation
|
||||
* that supports OpenGL/OpenGL ES.
|
||||
*/
|
||||
Driver* createDriver(void* sharedContext, const DriverConfig& driverConfig) noexcept override;
|
||||
Driver* createDriver(void* sharedContext, const DriverConfig& driverConfig) override;
|
||||
|
||||
/**
|
||||
* This returns zero. This method can be overridden to return something more useful.
|
||||
@@ -101,8 +101,8 @@ protected:
|
||||
bool isSRGBSwapChainSupported() const noexcept override;
|
||||
bool isMSAASwapChainSupported(uint32_t samples) const noexcept override;
|
||||
|
||||
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
|
||||
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
||||
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) override;
|
||||
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) override;
|
||||
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
||||
bool isSwapChainProtected(SwapChain* swapChain) noexcept override;
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ protected:
|
||||
int getOSVersion() const noexcept override;
|
||||
|
||||
Driver* createDriver(void* sharedContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
const Platform::DriverConfig& driverConfig) override;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// OpenGLPlatform Interface
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
PlatformEGLHeadless() noexcept;
|
||||
|
||||
Driver* createDriver(void* sharedContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
const Platform::DriverConfig& driverConfig) override;
|
||||
|
||||
protected:
|
||||
bool isOpenGL() const noexcept override;
|
||||
|
||||
@@ -39,7 +39,7 @@ protected:
|
||||
// Platform Interface
|
||||
|
||||
Driver* createDriver(void* sharedGLContext,
|
||||
const DriverConfig& driverConfig) noexcept override;
|
||||
const DriverConfig& driverConfig) override;
|
||||
|
||||
int getOSVersion() const noexcept final override { return 0; }
|
||||
|
||||
@@ -55,9 +55,9 @@ protected:
|
||||
void commit(SwapChain* swapChain) noexcept override;
|
||||
|
||||
private:
|
||||
Display *mGLXDisplay;
|
||||
GLXContext mGLXContext;
|
||||
GLXFBConfig* mGLXConfig;
|
||||
Display* mGLXDisplay;
|
||||
GLXContext mGLXContext{};
|
||||
GLXFBConfig mGLXConfig{};
|
||||
GLXPbuffer mDummySurface;
|
||||
std::vector<GLXPbuffer> mPBuffers;
|
||||
};
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
PlatformMetal();
|
||||
~PlatformMetal() noexcept override;
|
||||
|
||||
Driver* createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
Driver* createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) override;
|
||||
int getOSVersion() const noexcept override { return 0; }
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,7 +43,7 @@ protected:
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Platform Interface
|
||||
|
||||
Driver* createDriver(void* sharedGLContext, const DriverConfig& driverConfig) noexcept override;
|
||||
Driver* createDriver(void* sharedGLContext, const DriverConfig& driverConfig) override;
|
||||
|
||||
int getOSVersion() const noexcept final override { return 0; }
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ protected:
|
||||
// Platform Interface
|
||||
|
||||
Driver* createDriver(void* sharedGLContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
const Platform::DriverConfig& driverConfig) override;
|
||||
|
||||
int getOSVersion() const noexcept final override { return 0; }
|
||||
|
||||
@@ -61,8 +61,12 @@ protected:
|
||||
HWND mHWnd = NULL;
|
||||
HDC mWhdc = NULL;
|
||||
PIXELFORMATDESCRIPTOR mPfd = {};
|
||||
std::vector<HGLRC> mAdditionalContexts;
|
||||
std::vector<int> mAttribs;
|
||||
|
||||
// For shared contexts
|
||||
static constexpr int SHARED_CONTEXT_NUM = 1;
|
||||
std::vector<HGLRC> mAdditionalContexts;
|
||||
std::atomic<int> mNextFreeSharedContextIndex{0};
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -34,7 +34,7 @@ protected:
|
||||
// Platform Interface
|
||||
|
||||
Driver* createDriver(void* sharedGLContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
const Platform::DriverConfig& driverConfig) override;
|
||||
|
||||
int getOSVersion() const noexcept override;
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
~VulkanPlatform() override;
|
||||
|
||||
Driver* createDriver(void* sharedContext,
|
||||
Platform::DriverConfig const& driverConfig) noexcept override;
|
||||
Platform::DriverConfig const& driverConfig) override;
|
||||
|
||||
int getOSVersion() const noexcept override {
|
||||
return 0;
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
|
||||
protected:
|
||||
[[nodiscard]] Driver* createDriver(void* sharedContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
const Platform::DriverConfig& driverConfig) override;
|
||||
|
||||
private:
|
||||
// returns adapter request option variations applicable for the particular
|
||||
|
||||
@@ -61,7 +61,7 @@ class CommandBase {
|
||||
protected:
|
||||
using Execute = Dispatcher::Execute;
|
||||
|
||||
constexpr explicit CommandBase(Execute execute) noexcept : mExecute(execute) {}
|
||||
constexpr explicit CommandBase(Execute const execute) noexcept : mExecute(execute) {}
|
||||
|
||||
public:
|
||||
// alignment of all Commands in the CommandStream
|
||||
@@ -70,7 +70,7 @@ public:
|
||||
}
|
||||
|
||||
// executes this command and returns the next one
|
||||
inline CommandBase* execute(Driver& driver) {
|
||||
CommandBase* execute(Driver& driver) {
|
||||
// returning the next command by output parameter allows the compiler to perform the
|
||||
// tail-call optimization in the function called by mExecute, however that comes at
|
||||
// a cost here (writing and reading the stack at each iteration), in the end it's
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
return reinterpret_cast<CommandBase*>(reinterpret_cast<intptr_t>(this) + next);
|
||||
}
|
||||
|
||||
inline ~CommandBase() noexcept = default;
|
||||
~CommandBase() noexcept = default;
|
||||
|
||||
private:
|
||||
Execute mExecute;
|
||||
@@ -135,7 +135,7 @@ struct CommandType<void (Driver::*)(ARGS...)> {
|
||||
|
||||
public:
|
||||
template<typename M, typename D>
|
||||
static inline void execute(M&& method, D&& driver, CommandBase* base, intptr_t* next) {
|
||||
static void execute(M&& method, D&& driver, CommandBase* base, intptr_t* next) {
|
||||
Command* self = static_cast<Command*>(base);
|
||||
*next = align(sizeof(Command));
|
||||
#if DEBUG_COMMAND_STREAM
|
||||
@@ -147,15 +147,15 @@ struct CommandType<void (Driver::*)(ARGS...)> {
|
||||
}
|
||||
|
||||
// A command can be moved
|
||||
inline Command(Command&& rhs) noexcept = default;
|
||||
Command(Command&& rhs) noexcept = default;
|
||||
|
||||
template<typename... A>
|
||||
inline explicit constexpr Command(Execute execute, A&& ... args)
|
||||
explicit constexpr Command(Execute const execute, A&& ... args) noexcept
|
||||
: CommandBase(execute), mArgs(std::forward<A>(args)...) {
|
||||
}
|
||||
|
||||
// placement new declared as "throw" to avoid the compiler's null-check
|
||||
inline void* operator new(std::size_t, void* ptr) {
|
||||
void* operator new(std::size_t, void* ptr) noexcept {
|
||||
assert_invariant(ptr);
|
||||
return ptr;
|
||||
}
|
||||
@@ -171,8 +171,9 @@ class CustomCommand : public CommandBase {
|
||||
std::function<void()> mCommand;
|
||||
static void execute(Driver&, CommandBase* base, intptr_t* next);
|
||||
public:
|
||||
inline CustomCommand(CustomCommand&& rhs) = default;
|
||||
inline explicit CustomCommand(std::function<void()> cmd)
|
||||
CustomCommand(CustomCommand&& rhs) = default;
|
||||
|
||||
explicit CustomCommand(std::function<void()> cmd)
|
||||
: CommandBase(execute), mCommand(std::move(cmd)) { }
|
||||
};
|
||||
|
||||
@@ -184,7 +185,7 @@ class NoopCommand : public CommandBase {
|
||||
*next = static_cast<NoopCommand*>(self)->mNext;
|
||||
}
|
||||
public:
|
||||
inline constexpr explicit NoopCommand(void* next) noexcept
|
||||
constexpr explicit NoopCommand(void* next) noexcept
|
||||
: CommandBase(execute), mNext(intptr_t((char *)next - (char *)this)) { }
|
||||
};
|
||||
|
||||
@@ -207,8 +208,8 @@ class CommandStream {
|
||||
template<typename T>
|
||||
struct AutoExecute {
|
||||
T closure;
|
||||
inline explicit AutoExecute(T&& closure) : closure(std::forward<T>(closure)) {}
|
||||
inline ~AutoExecute() { closure(); }
|
||||
explicit AutoExecute(T&& closure) : closure(std::forward<T>(closure)) {}
|
||||
~AutoExecute() { closure(); }
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -221,7 +222,7 @@ public:
|
||||
|
||||
public:
|
||||
#define DECL_DRIVER_API(methodName, paramsDecl, params) \
|
||||
inline void methodName(paramsDecl) { \
|
||||
inline void methodName(paramsDecl) noexcept { \
|
||||
DEBUG_COMMAND_BEGIN(methodName, false, params); \
|
||||
using Cmd = COMMAND_TYPE(methodName); \
|
||||
void* const p = allocateCommand(CommandBase::align(sizeof(Cmd))); \
|
||||
@@ -230,7 +231,7 @@ public:
|
||||
}
|
||||
|
||||
#define DECL_DRIVER_API_SYNCHRONOUS(RetType, methodName, paramsDecl, params) \
|
||||
inline RetType methodName(paramsDecl) { \
|
||||
inline RetType methodName(paramsDecl) noexcept { \
|
||||
DEBUG_COMMAND_BEGIN(methodName, true, params); \
|
||||
AutoExecute callOnExit([=, this](){ \
|
||||
DEBUG_COMMAND_END(methodName, true); \
|
||||
@@ -239,7 +240,7 @@ public:
|
||||
}
|
||||
|
||||
#define DECL_DRIVER_API_RETURN(RetType, methodName, paramsDecl, params) \
|
||||
inline RetType methodName(paramsDecl) { \
|
||||
inline RetType methodName(paramsDecl) noexcept { \
|
||||
DEBUG_COMMAND_BEGIN(methodName, false, params); \
|
||||
RetType result = mDriver.methodName##S(); \
|
||||
using Cmd = COMMAND_TYPE(methodName##R); \
|
||||
@@ -255,7 +256,7 @@ public:
|
||||
// This is for debugging only. Currently, CircularBuffer can only be written from a
|
||||
// single thread. In debug builds we assert this condition.
|
||||
// Call this first in the render loop.
|
||||
inline void debugThreading() noexcept {
|
||||
void debugThreading() noexcept {
|
||||
#ifndef NDEBUG
|
||||
mThreadId = utils::ThreadUtils::getThreadId();
|
||||
#endif
|
||||
@@ -281,11 +282,11 @@ public:
|
||||
*/
|
||||
template<typename PodType,
|
||||
typename = typename std::enable_if<std::is_trivially_destructible<PodType>::value>::type>
|
||||
inline PodType* allocatePod(
|
||||
PodType* allocatePod(
|
||||
size_t count = 1, size_t alignment = alignof(PodType)) noexcept;
|
||||
|
||||
private:
|
||||
inline void* allocateCommand(size_t size) {
|
||||
void* allocateCommand(size_t const size) noexcept {
|
||||
assert_invariant(utils::ThreadUtils::isThisThread(mThreadId));
|
||||
return mCurrentBuffer.allocate(size);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <backend/AcquiredImage.h>
|
||||
|
||||
#include <utils/CString.h>
|
||||
#include <utils/ImmutableCString.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/compiler.h>
|
||||
|
||||
|
||||
@@ -108,15 +108,15 @@
|
||||
DECL_DRIVER_API_RETURN(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__), PAIR_ARGS_N(PARAM, ##__VA_ARGS__))
|
||||
|
||||
#define DECL_DRIVER_API_TAGGED_R_N(R, N, ...) \
|
||||
DECL_DRIVER_API_RETURN(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__, utils::CString&&, tag = {}), \
|
||||
PAIR_ARGS_N(PARAM, ##__VA_ARGS__, utils::CString&&, tag))
|
||||
DECL_DRIVER_API_RETURN(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__, utils::ImmutableCString&&, tag = {}), \
|
||||
PAIR_ARGS_N(PARAM, ##__VA_ARGS__, utils::ImmutableCString&&, tag))
|
||||
|
||||
#define DECL_DRIVER_API_SYNCHRONOUS_N(R, N, ...) \
|
||||
DECL_DRIVER_API_SYNCHRONOUS(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__), PAIR_ARGS_N(PARAM, ##__VA_ARGS__))
|
||||
|
||||
#define DECL_DRIVER_API_SYNCHRONOUS_TAGGED_N(R, N, ...) \
|
||||
DECL_DRIVER_API_SYNCHRONOUS(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__, utils::CString, tag = {}), \
|
||||
PAIR_ARGS_N(PARAM, ##__VA_ARGS__, utils::CString, tag))
|
||||
DECL_DRIVER_API_SYNCHRONOUS(R, N, PAIR_ARGS_N(ARG, ##__VA_ARGS__, utils::ImmutableCString, tag = {}), \
|
||||
PAIR_ARGS_N(PARAM, ##__VA_ARGS__, utils::ImmutableCString, tag))
|
||||
|
||||
// on some compilers the ##__VA_ARGS__ hack is not supported, so we can't handle 0-parameter APIs
|
||||
// with DECL_DRIVER_API_SYNCHRONOUS_N
|
||||
@@ -417,14 +417,6 @@ DECL_DRIVER_API_N(setExternalStream,
|
||||
backend::TextureHandle, th,
|
||||
backend::StreamHandle, sh)
|
||||
|
||||
DECL_DRIVER_API_N(beginRenderPass,
|
||||
backend::RenderTargetHandle, rth,
|
||||
const backend::RenderPassParams&, params)
|
||||
|
||||
DECL_DRIVER_API_0(endRenderPass)
|
||||
|
||||
DECL_DRIVER_API_0(nextSubpass)
|
||||
|
||||
DECL_DRIVER_API_N(beginTimerQuery,
|
||||
backend::TimerQueryHandle, tqh)
|
||||
|
||||
@@ -457,6 +449,36 @@ DECL_DRIVER_API_N(copyToMemoryMappedBuffer,
|
||||
size_t, offset,
|
||||
backend::BufferDescriptor&&, data)
|
||||
|
||||
DECL_DRIVER_API_N(setPushConstant,
|
||||
backend::ShaderStage, stage,
|
||||
uint8_t, index,
|
||||
backend::PushConstantVariant, value)
|
||||
|
||||
/*
|
||||
* Setting rendering state
|
||||
* -----------------------
|
||||
*/
|
||||
|
||||
DECL_DRIVER_API_N(beginRenderPass,
|
||||
backend::RenderTargetHandle, rth,
|
||||
const backend::RenderPassParams&, params)
|
||||
|
||||
DECL_DRIVER_API_0(endRenderPass)
|
||||
|
||||
DECL_DRIVER_API_0(nextSubpass)
|
||||
|
||||
DECL_DRIVER_API_N(bindPipeline,
|
||||
backend::PipelineState const&, state)
|
||||
|
||||
DECL_DRIVER_API_N(bindRenderPrimitive,
|
||||
backend::RenderPrimitiveHandle, rph)
|
||||
|
||||
DECL_DRIVER_API_N(bindDescriptorSet,
|
||||
backend::DescriptorSetHandle, dsh,
|
||||
backend::descriptor_set_t, set,
|
||||
backend::DescriptorSetOffsetArray&&, offsets
|
||||
)
|
||||
|
||||
/*
|
||||
* Swap chain
|
||||
*/
|
||||
@@ -474,11 +496,6 @@ DECL_DRIVER_API_N(commit,
|
||||
* -----------------------
|
||||
*/
|
||||
|
||||
DECL_DRIVER_API_N(setPushConstant,
|
||||
backend::ShaderStage, stage,
|
||||
uint8_t, index,
|
||||
backend::PushConstantVariant, value)
|
||||
|
||||
DECL_DRIVER_API_N(insertEventMarker,
|
||||
const char*, string)
|
||||
|
||||
@@ -539,18 +556,6 @@ DECL_DRIVER_API_N(blit,
|
||||
math::uint2, srcOrigin,
|
||||
math::uint2, size)
|
||||
|
||||
DECL_DRIVER_API_N(bindPipeline,
|
||||
backend::PipelineState const&, state)
|
||||
|
||||
DECL_DRIVER_API_N(bindRenderPrimitive,
|
||||
backend::RenderPrimitiveHandle, rph)
|
||||
|
||||
DECL_DRIVER_API_N(bindDescriptorSet,
|
||||
backend::DescriptorSetHandle, dsh,
|
||||
backend::descriptor_set_t, set,
|
||||
backend::DescriptorSetOffsetArray&&, offsets
|
||||
)
|
||||
|
||||
DECL_DRIVER_API_N(draw2,
|
||||
uint32_t, indexOffset,
|
||||
uint32_t, indexCount,
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <utils/Allocator.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/ImmutableCString.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/compiler.h>
|
||||
@@ -52,16 +53,16 @@ namespace filament::backend {
|
||||
class DebugTag {
|
||||
public:
|
||||
DebugTag();
|
||||
void writePoolHandleTag(HandleBase::HandleId key, utils::CString&& tag) noexcept;
|
||||
void writeHeapHandleTag(HandleBase::HandleId key, utils::CString&& tag) noexcept;
|
||||
utils::CString findHandleTag(HandleBase::HandleId key) const noexcept;
|
||||
void writePoolHandleTag(HandleBase::HandleId key, utils::ImmutableCString&& tag) noexcept;
|
||||
void writeHeapHandleTag(HandleBase::HandleId key, utils::ImmutableCString&& tag) noexcept;
|
||||
utils::ImmutableCString findHandleTag(HandleBase::HandleId key) const noexcept;
|
||||
|
||||
private:
|
||||
// This is used to associate a tag to a handle. mDebugTags is only written the in the main
|
||||
// driver thread, but it can be accessed from any thread, because it's called from handle_cast<>
|
||||
// which is used by synchronous calls.
|
||||
mutable utils::Mutex mDebugTagLock;
|
||||
tsl::robin_map<HandleBase::HandleId, utils::CString> mDebugTags;
|
||||
tsl::robin_map<HandleBase::HandleId, utils::ImmutableCString> mDebugTags;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -70,12 +71,12 @@ private:
|
||||
template<size_t P0, size_t P1, size_t P2>
|
||||
class HandleAllocator : public DebugTag {
|
||||
public:
|
||||
HandleAllocator(const char* name, size_t size) noexcept;
|
||||
HandleAllocator(const char* name, size_t size);
|
||||
HandleAllocator(const char* name, size_t size,
|
||||
bool disableUseAfterFreeCheck, bool disableHeapHandleTags) noexcept;
|
||||
bool disableUseAfterFreeCheck, bool disableHeapHandleTags);
|
||||
HandleAllocator(HandleAllocator const& rhs) = delete;
|
||||
HandleAllocator& operator=(HandleAllocator const& rhs) = delete;
|
||||
~HandleAllocator();
|
||||
~HandleAllocator() noexcept;
|
||||
|
||||
/*
|
||||
* Constructs a D object and returns a Handle<D>
|
||||
@@ -106,7 +107,7 @@ public:
|
||||
*
|
||||
*/
|
||||
template<typename D>
|
||||
Handle<D> allocate() noexcept {
|
||||
Handle<D> allocate() {
|
||||
Handle<D> h{ allocateHandle<D>() };
|
||||
return h;
|
||||
}
|
||||
@@ -222,7 +223,7 @@ public:
|
||||
return static_cast<Dp>(p);
|
||||
}
|
||||
|
||||
utils::CString getHandleTag(HandleBase::HandleId key) const noexcept;
|
||||
utils::ImmutableCString getHandleTag(HandleBase::HandleId key) const noexcept;
|
||||
|
||||
template<typename B>
|
||||
bool is_valid(Handle<B>& handle) {
|
||||
@@ -248,7 +249,7 @@ public:
|
||||
return handle_cast<Dp>(const_cast<Handle<B>&>(handle));
|
||||
}
|
||||
|
||||
void associateTagToHandle(HandleBase::HandleId id, utils::CString&& tag) noexcept {
|
||||
void associateTagToHandle(HandleBase::HandleId id, utils::ImmutableCString&& tag) noexcept {
|
||||
if (tag.empty()) {
|
||||
return;
|
||||
}
|
||||
@@ -342,7 +343,7 @@ private:
|
||||
// allocation size this is always inlined, because all these do is to call
|
||||
// allocateHandleInPool()/deallocateHandleFromPool() with the right pool size.
|
||||
template<typename D>
|
||||
HandleBase::HandleId allocateHandle() noexcept {
|
||||
HandleBase::HandleId allocateHandle() {
|
||||
constexpr size_t BUCKET_SIZE = getBucketSize<D>();
|
||||
return allocateHandleInPool<BUCKET_SIZE>();
|
||||
}
|
||||
@@ -358,7 +359,7 @@ private:
|
||||
// the code generated is not trivial (even if it's not insane either).
|
||||
template<size_t SIZE>
|
||||
UTILS_NOINLINE
|
||||
HandleBase::HandleId allocateHandleInPool() noexcept {
|
||||
HandleBase::HandleId allocateHandleInPool() {
|
||||
uint8_t age;
|
||||
void* p = mHandleArena.alloc(SIZE, alignof(std::max_align_t), 0, &age);
|
||||
if (UTILS_LIKELY(p)) {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
CallbackManager::CallbackManager(DriverBase& driver) noexcept
|
||||
CallbackManager::CallbackManager(DriverBase& driver)
|
||||
: mDriver(driver), mCallbacks(1) {
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ class CallbackManager {
|
||||
public:
|
||||
using Handle = Container::const_iterator;
|
||||
|
||||
explicit CallbackManager(DriverBase& driver) noexcept;
|
||||
explicit CallbackManager(DriverBase& driver);
|
||||
|
||||
~CallbackManager() noexcept;
|
||||
|
||||
@@ -78,7 +78,7 @@ private:
|
||||
return --mCallbacks.end();
|
||||
}
|
||||
|
||||
Container::iterator allocateNewSlot() noexcept {
|
||||
Container::iterator allocateNewSlot() {
|
||||
std::lock_guard const lock(mLock);
|
||||
auto curr = --mCallbacks.end();
|
||||
mCallbacks.emplace_back();
|
||||
|
||||
@@ -57,12 +57,15 @@ static void printParameterPack(io::ostream& out, const FIRST& first, const REMAI
|
||||
printParameterPack(out, rest...);
|
||||
}
|
||||
|
||||
static UTILS_NOINLINE UTILS_UNUSED std::string_view extractMethodName(std::string_view command) noexcept {
|
||||
constexpr const char startPattern[] = "::Command<&filament::backend::Driver::";
|
||||
static UTILS_NOINLINE UTILS_UNUSED std::string_view extractMethodName(std::string_view command) noexcept { // NOLINT(*-exception-escape)
|
||||
constexpr char startPattern[] = "::Command<&filament::backend::Driver::";
|
||||
auto pos = command.rfind(startPattern);
|
||||
auto end = command.rfind('(');
|
||||
pos += sizeof(startPattern) - 1;
|
||||
return command.substr(pos, end-pos);
|
||||
if (pos > command.size()) {
|
||||
return { command.data(), command.size() };
|
||||
}
|
||||
return command.substr(pos, end-pos); // this can't throw by construction
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -18,7 +18,14 @@
|
||||
|
||||
#include <private/utils/Tracing.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
@@ -36,7 +43,7 @@ CompilerThreadPool::~CompilerThreadPool() noexcept {
|
||||
}
|
||||
|
||||
void CompilerThreadPool::init(uint32_t threadCount,
|
||||
ThreadSetup&& threadSetup, ThreadCleanup&& threadCleanup) noexcept {
|
||||
ThreadSetup&& threadSetup, ThreadCleanup&& threadCleanup) {
|
||||
auto setup = std::make_shared<ThreadSetup>(std::move(threadSetup));
|
||||
auto cleanup = std::make_shared<ThreadCleanup>(std::move(threadCleanup));
|
||||
|
||||
|
||||
@@ -47,8 +47,7 @@ public:
|
||||
using Job = utils::Invocable<void()>;
|
||||
using ThreadSetup = utils::Invocable<void()>;
|
||||
using ThreadCleanup = utils::Invocable<void()>;
|
||||
void init(uint32_t threadCount,
|
||||
ThreadSetup&& threadSetup, ThreadCleanup&& threadCleanup) noexcept;
|
||||
void init(uint32_t threadCount, ThreadSetup&& threadSetup, ThreadCleanup&& threadCleanup);
|
||||
void terminate() noexcept;
|
||||
void queue(CompilerPriorityQueue priorityQueue, program_token_t const& token, Job&& job);
|
||||
Job dequeue(program_token_t const& token);
|
||||
|
||||
@@ -131,7 +131,7 @@ void DriverBase::purge() noexcept {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void DriverBase::scheduleDestroySlow(BufferDescriptor&& buffer) noexcept {
|
||||
void DriverBase::scheduleDestroySlow(BufferDescriptor&& buffer) {
|
||||
auto const handler = buffer.getHandler();
|
||||
scheduleCallback(handler, [buffer = std::move(buffer)]() {
|
||||
// user callback is called when BufferDescriptor gets destroyed
|
||||
@@ -140,7 +140,7 @@ void DriverBase::scheduleDestroySlow(BufferDescriptor&& buffer) noexcept {
|
||||
|
||||
// This is called from an async driver method so it's in the GL thread, but purge is called
|
||||
// on the user thread. This is typically called 0 or 1 times per frame.
|
||||
void DriverBase::scheduleRelease(AcquiredImage const& image) noexcept {
|
||||
void DriverBase::scheduleRelease(AcquiredImage const& image) {
|
||||
scheduleCallback(image.handler, [callback = image.callback, image = image.image, userData = image.userData]() {
|
||||
callback(image, userData);
|
||||
});
|
||||
|
||||
@@ -214,15 +214,15 @@ public:
|
||||
protected:
|
||||
class CallbackDataDetails;
|
||||
|
||||
void scheduleDestroy(BufferDescriptor&& buffer) noexcept {
|
||||
void scheduleDestroy(BufferDescriptor&& buffer) {
|
||||
if (buffer.hasCallback()) {
|
||||
scheduleDestroySlow(std::move(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
void scheduleDestroySlow(BufferDescriptor&& buffer) noexcept;
|
||||
void scheduleDestroySlow(BufferDescriptor&& buffer);
|
||||
|
||||
void scheduleRelease(AcquiredImage const& image) noexcept;
|
||||
void scheduleRelease(AcquiredImage const& image);
|
||||
|
||||
void debugCommandBegin(CommandStream* cmds, bool synchronous, const char* methodName) noexcept override;
|
||||
void debugCommandEnd(CommandStream* cmds, bool synchronous, const char* methodName) noexcept override;
|
||||
|
||||
@@ -81,19 +81,19 @@ HandleAllocator<P0, P1, P2>::Allocator::Allocator(AreaPolicy::HeapArea const& ar
|
||||
template <size_t P0, size_t P1, size_t P2>
|
||||
HandleAllocator<P0, P1, P2>::HandleAllocator(const char* name, size_t size,
|
||||
bool disableUseAfterFreeCheck,
|
||||
bool disableHeapHandleTags) noexcept
|
||||
bool disableHeapHandleTags)
|
||||
: mHandleArena(name, size, disableUseAfterFreeCheck),
|
||||
mUseAfterFreeCheckDisabled(disableUseAfterFreeCheck),
|
||||
mHeapHandleTagsDisabled(disableHeapHandleTags) {
|
||||
}
|
||||
|
||||
template <size_t P0, size_t P1, size_t P2>
|
||||
HandleAllocator<P0, P1, P2>::HandleAllocator(const char* name, size_t size) noexcept
|
||||
HandleAllocator<P0, P1, P2>::HandleAllocator(const char* name, size_t size)
|
||||
: HandleAllocator(name, size, false, false) {
|
||||
}
|
||||
|
||||
template <size_t P0, size_t P1, size_t P2>
|
||||
HandleAllocator<P0, P1, P2>::~HandleAllocator() {
|
||||
HandleAllocator<P0, P1, P2>::~HandleAllocator() noexcept {
|
||||
auto& overflowMap = mOverflowMap;
|
||||
if (!overflowMap.empty()) {
|
||||
PANIC_LOG("Not all handles have been freed. Probably leaking memory.");
|
||||
@@ -156,7 +156,7 @@ void HandleAllocator<P0, P1, P2>::deallocateHandleSlow(HandleBase::HandleId id,
|
||||
|
||||
template<size_t P0, size_t P1, size_t P2>
|
||||
UTILS_NOINLINE
|
||||
CString HandleAllocator<P0, P1, P2>::getHandleTag(HandleBase::HandleId id) const noexcept {
|
||||
ImmutableCString HandleAllocator<P0, P1, P2>::getHandleTag(HandleBase::HandleId id) const noexcept {
|
||||
uint32_t key = id;
|
||||
if (UTILS_LIKELY(isPoolHandle(id))) {
|
||||
// Truncate the age to get the debug tag
|
||||
@@ -172,7 +172,7 @@ DebugTag::DebugTag() {
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
CString DebugTag::findHandleTag(HandleBase::HandleId key) const noexcept {
|
||||
ImmutableCString DebugTag::findHandleTag(HandleBase::HandleId key) const noexcept {
|
||||
std::unique_lock const lock(mDebugTagLock);
|
||||
if (auto pos = mDebugTags.find(key); pos != mDebugTags.end()) {
|
||||
return pos->second;
|
||||
@@ -181,7 +181,7 @@ CString DebugTag::findHandleTag(HandleBase::HandleId key) const noexcept {
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
void DebugTag::writePoolHandleTag(HandleBase::HandleId key, CString&& tag) noexcept {
|
||||
void DebugTag::writePoolHandleTag(HandleBase::HandleId key, ImmutableCString&& tag) noexcept {
|
||||
// This line is the costly part. In the future, we could potentially use a custom
|
||||
// allocator.
|
||||
std::unique_lock const lock(mDebugTagLock);
|
||||
@@ -190,7 +190,7 @@ void DebugTag::writePoolHandleTag(HandleBase::HandleId key, CString&& tag) noexc
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
void DebugTag::writeHeapHandleTag(HandleBase::HandleId key, CString&& tag) noexcept {
|
||||
void DebugTag::writeHeapHandleTag(HandleBase::HandleId key, ImmutableCString&& tag) noexcept {
|
||||
// This line is the costly part. In the future, we could potentially use a custom
|
||||
// allocator.
|
||||
std::unique_lock const lock(mDebugTagLock);
|
||||
|
||||
@@ -41,37 +41,37 @@ Program& Program::operator=(Program&& rhs) noexcept = default;
|
||||
|
||||
Program::~Program() noexcept = default;
|
||||
|
||||
Program& Program::priorityQueue(CompilerPriorityQueue priorityQueue) noexcept {
|
||||
Program& Program::priorityQueue(CompilerPriorityQueue const priorityQueue) noexcept {
|
||||
mPriorityQueue = priorityQueue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::diagnostics(CString const& name,
|
||||
Invocable<io::ostream&(utils::CString const& name, io::ostream&)>&& logger) {
|
||||
Invocable<io::ostream&(CString const& name, io::ostream&)>&& logger) {
|
||||
mName = name;
|
||||
mLogger = std::move(logger);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::shader(ShaderStage shader, void const* data, size_t size) {
|
||||
Program& Program::shader(ShaderStage shader, void const* data, size_t const size) {
|
||||
ShaderBlob blob(size);
|
||||
std::copy_n((const uint8_t *)data, size, blob.data());
|
||||
mShadersSource[size_t(shader)] = std::move(blob);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::shaderLanguage(ShaderLanguage shaderLanguage) {
|
||||
Program& Program::shaderLanguage(ShaderLanguage const shaderLanguage) {
|
||||
mShaderLanguage = shaderLanguage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::descriptorBindings(backend::descriptor_set_t set,
|
||||
Program& Program::descriptorBindings(descriptor_set_t const set,
|
||||
DescriptorBindingsInfo descriptorBindings) noexcept {
|
||||
mDescriptorBindings[set] = std::move(descriptorBindings);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::uniforms(uint32_t index, utils::CString name, UniformInfo uniforms) noexcept {
|
||||
Program& Program::uniforms(uint32_t index, CString name, UniformInfo uniforms) {
|
||||
mBindingUniformsInfo.reserve(mBindingUniformsInfo.capacity() + 1);
|
||||
mBindingUniformsInfo.emplace_back(index, std::move(name), std::move(uniforms));
|
||||
return *this;
|
||||
@@ -88,17 +88,17 @@ Program& Program::specializationConstants(SpecializationConstantsInfo specConsta
|
||||
}
|
||||
|
||||
Program& Program::pushConstants(ShaderStage stage,
|
||||
utils::FixedCapacityVector<PushConstant> constants) noexcept {
|
||||
FixedCapacityVector<PushConstant> constants) noexcept {
|
||||
mPushConstants[static_cast<uint8_t>(stage)] = std::move(constants);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::cacheId(uint64_t cacheId) noexcept {
|
||||
Program& Program::cacheId(uint64_t const cacheId) noexcept {
|
||||
mCacheId = cacheId;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::multiview(bool multiview) noexcept {
|
||||
Program& Program::multiview(bool const multiview) noexcept {
|
||||
mMultiview = multiview;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ public:
|
||||
|
||||
void* getCpuBuffer() const noexcept { return mCpuBuffer; }
|
||||
|
||||
void setLabel(const utils::CString& label) {
|
||||
void setLabel(const utils::ImmutableCString& label) {
|
||||
#if FILAMENT_METAL_DEBUG_LABELS
|
||||
if (label.empty()) {
|
||||
return;
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <utils/Logger.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/sstream.h>
|
||||
#include <utils/ImmutableCString.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -418,14 +419,14 @@ void MetalDriver::finish(int) {
|
||||
}
|
||||
|
||||
void MetalDriver::createVertexBufferInfoR(Handle<HwVertexBufferInfo> vbih, uint8_t bufferCount,
|
||||
uint8_t attributeCount, AttributeArray attributes, utils::CString&& tag) {
|
||||
uint8_t attributeCount, AttributeArray attributes, utils::ImmutableCString&& tag) {
|
||||
construct_handle<MetalVertexBufferInfo>(vbih, *mContext,
|
||||
bufferCount, attributeCount, attributes);
|
||||
mHandleAllocator.associateTagToHandle(vbih.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createVertexBufferR(Handle<HwVertexBuffer> vbh,
|
||||
uint32_t vertexCount, Handle<HwVertexBufferInfo> vbih, utils::CString&& tag) {
|
||||
uint32_t vertexCount, Handle<HwVertexBufferInfo> vbih, utils::ImmutableCString&& tag) {
|
||||
MetalVertexBufferInfo const* const vbi = handle_cast<const MetalVertexBufferInfo>(vbih);
|
||||
construct_handle<MetalVertexBuffer>(vbh, *mContext, vertexCount, vbi->bufferCount, vbih);
|
||||
mHandleAllocator.associateTagToHandle(vbh.getId(), std::move(tag));
|
||||
@@ -433,7 +434,7 @@ void MetalDriver::createVertexBufferR(Handle<HwVertexBuffer> vbh,
|
||||
}
|
||||
|
||||
void MetalDriver::createIndexBufferR(Handle<HwIndexBuffer> ibh, ElementType elementType,
|
||||
uint32_t indexCount, BufferUsage usage, utils::CString&& tag) {
|
||||
uint32_t indexCount, BufferUsage usage, utils::ImmutableCString&& tag) {
|
||||
auto elementSize = (uint8_t)getElementTypeSize(elementType);
|
||||
auto* indexBuffer =
|
||||
construct_handle<MetalIndexBuffer>(ibh, *mContext, usage, elementSize, indexCount);
|
||||
@@ -446,7 +447,7 @@ void MetalDriver::createIndexBufferR(Handle<HwIndexBuffer> ibh, ElementType elem
|
||||
}
|
||||
|
||||
void MetalDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byteCount,
|
||||
BufferObjectBinding bindingType, BufferUsage usage, utils::CString&& tag) {
|
||||
BufferObjectBinding bindingType, BufferUsage usage, utils::ImmutableCString&& tag) {
|
||||
auto* bufferObject =
|
||||
construct_handle<MetalBufferObject>(boh, *mContext, bindingType, usage, byteCount);
|
||||
FILAMENT_CHECK_POSTCONDITION(bufferObject->getBuffer()->wasAllocationSuccessful())
|
||||
@@ -488,7 +489,7 @@ inline const char* stringify(SamplerType samplerType) {
|
||||
|
||||
void MetalDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8_t levels,
|
||||
TextureFormat format, uint8_t samples, uint32_t width, uint32_t height,
|
||||
uint32_t depth, TextureUsage usage, utils::CString&& tag) {
|
||||
uint32_t depth, TextureUsage usage, utils::ImmutableCString&& tag) {
|
||||
// Clamp sample count to what the device supports.
|
||||
auto& sc = mContext->sampleCountLookup;
|
||||
samples = sc[std::min(MAX_SAMPLE_COUNT, samples)];
|
||||
@@ -508,7 +509,7 @@ void MetalDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8
|
||||
}
|
||||
|
||||
void MetalDriver::createTextureViewR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
uint8_t baseLevel, uint8_t levelCount, utils::CString&& tag) {
|
||||
uint8_t baseLevel, uint8_t levelCount, utils::ImmutableCString&& tag) {
|
||||
MetalTexture const* src = handle_cast<MetalTexture>(srch);
|
||||
MetalTexture* texture =
|
||||
construct_handle<MetalTexture>(th, *mContext, src, baseLevel, levelCount);
|
||||
@@ -519,7 +520,7 @@ void MetalDriver::createTextureViewR(Handle<HwTexture> th, Handle<HwTexture> src
|
||||
|
||||
void MetalDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
|
||||
backend::TextureSwizzle a, utils::CString&& tag) {
|
||||
backend::TextureSwizzle a, utils::ImmutableCString&& tag) {
|
||||
MetalTexture const* src = handle_cast<MetalTexture>(srch);
|
||||
MetalTexture* texture = construct_handle<MetalTexture>(th, *mContext, src, r, g, b, a);
|
||||
mContext->textures.insert(texture);
|
||||
@@ -531,13 +532,13 @@ void MetalDriver::createTextureExternalImage2R(Handle<HwTexture> th,
|
||||
backend::SamplerType target,
|
||||
backend::TextureFormat format,
|
||||
uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef image, utils::CString&& tag) {
|
||||
Platform::ExternalImageHandleRef image, utils::ImmutableCString&& tag) {
|
||||
// FIXME: implement createTextureExternalImage2R
|
||||
}
|
||||
|
||||
void MetalDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::SamplerType target,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
void* image, utils::CString&& tag) {
|
||||
void* image, utils::ImmutableCString&& tag) {
|
||||
MetalTexture* texture = construct_handle<MetalTexture>(th, *mContext, format, width, height,
|
||||
usage, (CVPixelBufferRef) image);
|
||||
mContext->textures.insert(texture);
|
||||
@@ -550,7 +551,7 @@ void MetalDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::Sam
|
||||
|
||||
void MetalDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
void* image, uint32_t plane, utils::CString&& tag) {
|
||||
void* image, uint32_t plane, utils::ImmutableCString&& tag) {
|
||||
MetalTexture* texture = construct_handle<MetalTexture>(th, *mContext, format, width, height,
|
||||
usage, (CVPixelBufferRef) image, plane);
|
||||
mContext->textures.insert(texture);
|
||||
@@ -564,7 +565,7 @@ void MetalDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
|
||||
void MetalDriver::importTextureR(Handle<HwTexture> th, intptr_t i,
|
||||
SamplerType target, uint8_t levels,
|
||||
TextureFormat format, uint8_t samples, uint32_t width, uint32_t height,
|
||||
uint32_t depth, TextureUsage usage, utils::CString&& tag) {
|
||||
uint32_t depth, TextureUsage usage, utils::ImmutableCString&& tag) {
|
||||
id<MTLTexture> metalTexture = (id<MTLTexture>) CFBridgingRelease((void*) i);
|
||||
FILAMENT_CHECK_PRECONDITION(metalTexture.width == width)
|
||||
<< "Imported id<MTLTexture> width (" << metalTexture.width
|
||||
@@ -588,13 +589,13 @@ void MetalDriver::importTextureR(Handle<HwTexture> th, intptr_t i,
|
||||
|
||||
void MetalDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
|
||||
Handle<HwVertexBuffer> vbh, Handle<HwIndexBuffer> ibh,
|
||||
PrimitiveType pt, utils::CString&& tag) {
|
||||
PrimitiveType pt, utils::ImmutableCString&& tag) {
|
||||
construct_handle<MetalRenderPrimitive>(rph);
|
||||
MetalDriver::setRenderPrimitiveBuffer(rph, pt, vbh, ibh);
|
||||
mHandleAllocator.associateTagToHandle(rph.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createProgramR(Handle<HwProgram> rph, Program&& program, utils::CString&& tag) {
|
||||
void MetalDriver::createProgramR(Handle<HwProgram> rph, Program&& program, utils::ImmutableCString&& tag) {
|
||||
#if FILAMENT_METAL_DEBUG_LOG
|
||||
auto handleId = rph.getId();
|
||||
DEBUG_LOG("createProgramR(rph = %d, program = ", handleId);
|
||||
@@ -604,7 +605,7 @@ void MetalDriver::createProgramR(Handle<HwProgram> rph, Program&& program, utils
|
||||
mHandleAllocator.associateTagToHandle(rph.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, utils::CString&& tag) {
|
||||
void MetalDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, utils::ImmutableCString&& tag) {
|
||||
construct_handle<MetalRenderTarget>(rth, mContext);
|
||||
mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag));
|
||||
}
|
||||
@@ -612,7 +613,7 @@ void MetalDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, utils::
|
||||
void MetalDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
TargetBufferFlags targetBufferFlags, uint32_t width, uint32_t height,
|
||||
uint8_t samples, uint8_t layerCount, MRT color,
|
||||
TargetBufferInfo depth, TargetBufferInfo stencil, utils::CString&& tag) {
|
||||
TargetBufferInfo depth, TargetBufferInfo stencil, utils::ImmutableCString&& tag) {
|
||||
FILAMENT_CHECK_PRECONDITION(!isInRenderPass(mContext))
|
||||
<< "createRenderTarget must be called outside of a render pass.";
|
||||
// Clamp sample count to what the device supports.
|
||||
@@ -659,14 +660,14 @@ void MetalDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createFenceR(Handle<HwFence> fh, utils::CString&& tag) {
|
||||
void MetalDriver::createFenceR(Handle<HwFence> fh, utils::ImmutableCString&& tag) {
|
||||
auto* fence = handle_cast<MetalFence>(fh);
|
||||
fence->encode();
|
||||
mHandleAllocator.associateTagToHandle(fh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags,
|
||||
utils::CString&& tag) {
|
||||
utils::ImmutableCString&& tag) {
|
||||
// TODO: support MSAA swapchain
|
||||
|
||||
if (UTILS_UNLIKELY(flags & SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER)) {
|
||||
@@ -683,18 +684,18 @@ void MetalDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
}
|
||||
|
||||
void MetalDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch,
|
||||
uint32_t width, uint32_t height, uint64_t flags, utils::CString&& tag) {
|
||||
uint32_t width, uint32_t height, uint64_t flags, utils::ImmutableCString&& tag) {
|
||||
construct_handle<MetalSwapChain>(sch, *mContext, mPlatform, width, height, flags);
|
||||
mHandleAllocator.associateTagToHandle(sch.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createSyncR(Handle<HwSync> sh, utils::CString&& tag) {
|
||||
void MetalDriver::createSyncR(Handle<HwSync> sh, utils::ImmutableCString&& tag) {
|
||||
// TODO: Ensure sync is active, and then invoke and clear all pending
|
||||
// callbacks.
|
||||
mHandleAllocator.associateTagToHandle(sh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void MetalDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, utils::CString&& tag) {
|
||||
void MetalDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, utils::ImmutableCString&& tag) {
|
||||
// nothing to do, timer query was constructed in createTimerQueryS
|
||||
mHandleAllocator.associateTagToHandle(tqh.getId(), std::move(tag));
|
||||
}
|
||||
@@ -733,12 +734,12 @@ const char* toString(DescriptorFlags flags) {
|
||||
}
|
||||
|
||||
void MetalDriver::createDescriptorSetLayoutR(
|
||||
Handle<HwDescriptorSetLayout> dslh, DescriptorSetLayout&& info, utils::CString&& tag) {
|
||||
Handle<HwDescriptorSetLayout> dslh, DescriptorSetLayout&& info, utils::ImmutableCString&& tag) {
|
||||
#if FILAMENT_METAL_DEBUG_LOG == 1
|
||||
const char* labelStr = "";
|
||||
std::visit([&labelStr](auto&& arg) {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, utils::CString> || std::is_same_v<T, utils::StaticString>) {
|
||||
if constexpr (std::is_same_v<T, utils::ImmutableCString> || std::is_same_v<T, utils::StaticString>) {
|
||||
labelStr = arg.c_str();
|
||||
}
|
||||
}, info.label);
|
||||
@@ -758,7 +759,7 @@ void MetalDriver::createDescriptorSetLayoutR(
|
||||
}
|
||||
|
||||
void MetalDriver::createDescriptorSetR(
|
||||
Handle<HwDescriptorSet> dsh, Handle<HwDescriptorSetLayout> dslh, utils::CString&& tag) {
|
||||
Handle<HwDescriptorSet> dsh, Handle<HwDescriptorSetLayout> dslh, utils::ImmutableCString&& tag) {
|
||||
DEBUG_LOG("createDescriptorSetR(dsh = %d, dslh = %d)\n", dsh.getId(), dslh.getId());
|
||||
MetalDescriptorSetLayout* layout = handle_cast<MetalDescriptorSetLayout>(dslh);
|
||||
MetalDescriptorSet* ds = construct_handle<MetalDescriptorSet>(dsh, layout);
|
||||
@@ -1010,11 +1011,11 @@ utils::FixedCapacityVector<ShaderLanguage> MetalDriver::getShaderLanguages(
|
||||
return { backend::ShaderLanguage::METAL_LIBRARY, backend::ShaderLanguage::MSL };
|
||||
}
|
||||
|
||||
Handle<HwStream> MetalDriver::createStreamNative(void* stream, utils::CString tag) {
|
||||
Handle<HwStream> MetalDriver::createStreamNative(void* stream, utils::ImmutableCString tag) {
|
||||
return {};
|
||||
}
|
||||
|
||||
Handle<HwStream> MetalDriver::createStreamAcquired(utils::CString tag) {
|
||||
Handle<HwStream> MetalDriver::createStreamAcquired(utils::ImmutableCString tag) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -2231,7 +2232,7 @@ MemoryMappedBufferHandle MetalDriver::mapBufferS() noexcept {
|
||||
|
||||
void MetalDriver::mapBufferR(MemoryMappedBufferHandle mmbh,
|
||||
BufferObjectHandle boh, size_t offset,
|
||||
size_t size, MapBufferAccessFlags access, utils::CString&& tag) {
|
||||
size_t size, MapBufferAccessFlags access, utils::ImmutableCString&& tag) {
|
||||
construct_handle<MetalMemoryMappedBuffer>(mmbh, boh, offset, size, access);
|
||||
mHandleAllocator.associateTagToHandle(mmbh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
@@ -267,7 +267,7 @@ public:
|
||||
|
||||
static MTLPixelFormat decidePixelFormat(MetalContext* context, TextureFormat format);
|
||||
|
||||
void setLabel(const utils::CString& label) {
|
||||
void setLabel(const utils::ImmutableCString& label) {
|
||||
#if FILAMENT_METAL_DEBUG_LABELS
|
||||
if (label.empty()) {
|
||||
return;
|
||||
@@ -494,7 +494,7 @@ struct MetalDescriptorSet : public HwDescriptorSet {
|
||||
|
||||
void finalize(MetalDriver* driver);
|
||||
|
||||
void setLabel(const utils::CString& l) {
|
||||
void setLabel(const utils::ImmutableCString& l) {
|
||||
#if FILAMENT_METAL_DEBUG_LABELS
|
||||
if (l.empty()) {
|
||||
return;
|
||||
@@ -527,7 +527,7 @@ struct MetalDescriptorSet : public HwDescriptorSet {
|
||||
std::array<TrackedMetalBuffer, Program::SHADER_TYPE_COUNT> cachedBuffer = { nil };
|
||||
|
||||
#if FILAMENT_METAL_DEBUG_LABELS
|
||||
utils::CString label;
|
||||
utils::ImmutableCString label;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -153,14 +153,15 @@ bool MetalShaderCompiler::isParallelShaderCompileSupported() const noexcept {
|
||||
|
||||
MTLFunctionConstantValues* constants = [MTLFunctionConstantValues new];
|
||||
auto const& specializationConstants = program.getSpecializationConstants();
|
||||
for (auto const& sc : specializationConstants) {
|
||||
for (size_t i = 0; i < specializationConstants.size(); i++) {
|
||||
auto const& sc = specializationConstants[i];
|
||||
const std::array<MTLDataType, 3> types{
|
||||
MTLDataTypeInt, MTLDataTypeFloat, MTLDataTypeBool };
|
||||
std::visit([&sc, constants, type = types[sc.value.index()]](auto&& arg) {
|
||||
std::visit([i, constants, type = types[sc.index()]](auto&& arg) {
|
||||
[constants setConstantValue:&arg
|
||||
type:type
|
||||
atIndex:sc.id];
|
||||
}, sc.value);
|
||||
atIndex:i];
|
||||
}, sc);
|
||||
}
|
||||
|
||||
id<MTLFunction> function = [library newFunctionWithName:@"main0"
|
||||
|
||||
@@ -52,7 +52,7 @@ PlatformMetal::~PlatformMetal() noexcept {
|
||||
delete pImpl;
|
||||
}
|
||||
|
||||
Driver* PlatformMetal::createDriver(void* /*sharedContext*/, const Platform::DriverConfig& driverConfig) noexcept {
|
||||
Driver* PlatformMetal::createDriver(void* /*sharedContext*/, const Platform::DriverConfig& driverConfig) {
|
||||
pImpl->mDrawableFailureBehavior = driverConfig.metalDisablePanicOnDrawableFailure
|
||||
? DrawableFailureBehavior::ABORT_FRAME
|
||||
: DrawableFailureBehavior::PANIC;
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "noop/NoopDriver.h"
|
||||
#include "CommandStreamDispatcher.h"
|
||||
|
||||
#include <utils/ImmutableCString.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
@@ -135,11 +137,11 @@ void NoopDriver::destroyDescriptorSetLayout(Handle<HwDescriptorSetLayout> tqh) {
|
||||
void NoopDriver::destroyDescriptorSet(Handle<HwDescriptorSet> tqh) {
|
||||
}
|
||||
|
||||
Handle<HwStream> NoopDriver::createStreamNative(void* nativeStream, utils::CString tag) {
|
||||
Handle<HwStream> NoopDriver::createStreamNative(void* nativeStream, utils::ImmutableCString tag) {
|
||||
return {};
|
||||
}
|
||||
|
||||
Handle<HwStream> NoopDriver::createStreamAcquired(utils::CString tag) {
|
||||
Handle<HwStream> NoopDriver::createStreamAcquired(utils::ImmutableCString tag) {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
Driver* PlatformNoop::createDriver(void* sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept {
|
||||
Driver* PlatformNoop::createDriver(void* sharedGLContext, const Platform::DriverConfig& driverConfig) {
|
||||
return NoopDriver::create();
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
Driver* createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept override;
|
||||
Driver* createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) override;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <utils/BitmaskEnum.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Logger.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/bitset.h>
|
||||
#include <utils/compiler.h>
|
||||
@@ -49,7 +50,7 @@
|
||||
namespace filament::backend {
|
||||
|
||||
GLDescriptorSet::GLDescriptorSet(OpenGLContext& gl, DescriptorSetLayoutHandle dslh,
|
||||
GLDescriptorSetLayout const* layout) noexcept
|
||||
GLDescriptorSetLayout const* layout)
|
||||
: descriptors(layout->maxDescriptorBinding + 1),
|
||||
dslh(std::move(dslh)) {
|
||||
|
||||
@@ -156,8 +157,9 @@ void GLDescriptorSet::update(OpenGLContext&,
|
||||
arg.bo = bo;
|
||||
arg.offset = uint32_t(offset);
|
||||
} else {
|
||||
// API usage error. User asked to update the wrong type of descriptor.
|
||||
PANIC_PRECONDITION("descriptor %d is not a buffer", +binding);
|
||||
// User asked to update the wrong type of descriptor. This should never happen
|
||||
// because we're checking that on the filament side
|
||||
LOG(ERROR) << "descriptor " << +binding << " is not a buffer";
|
||||
}
|
||||
}, descriptors[binding].desc);
|
||||
}
|
||||
@@ -214,8 +216,9 @@ void GLDescriptorSet::update(OpenGLContext& gl, HandleAllocatorGL& handleAllocat
|
||||
arg.params = params;
|
||||
}
|
||||
} else {
|
||||
// API usage error. User asked to update the wrong type of descriptor.
|
||||
PANIC_PRECONDITION("descriptor %d is not a texture", +binding);
|
||||
// User asked to update the wrong type of descriptor. This should never happen
|
||||
// because we're checking that on the filament side
|
||||
LOG(ERROR) << "descriptor " << +binding << " is not a texture";
|
||||
}
|
||||
}, descriptors[binding].desc);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ struct GLDescriptorSet : public HwDescriptorSet {
|
||||
using HwDescriptorSet::HwDescriptorSet;
|
||||
|
||||
GLDescriptorSet(OpenGLContext& gl, DescriptorSetLayoutHandle dslh,
|
||||
GLDescriptorSetLayout const* layout) noexcept;
|
||||
GLDescriptorSetLayout const* layout);
|
||||
|
||||
// update a buffer descriptor in the set
|
||||
void update(OpenGLContext& gl,
|
||||
|
||||
@@ -277,7 +277,7 @@ void OpenGLContext::terminate() noexcept {
|
||||
}
|
||||
|
||||
void OpenGLContext::destroyWithContext(
|
||||
size_t index, std::function<void(OpenGLContext&)> const& closure) noexcept {
|
||||
size_t index, std::function<void(OpenGLContext&)> const& closure) {
|
||||
if (index == 0) {
|
||||
// Note: we only need to delay the destruction of objects on the unprotected context
|
||||
// (index 0) because the protected context is always immediately destroyed and all its
|
||||
@@ -296,7 +296,7 @@ void OpenGLContext::unbindEverything() noexcept {
|
||||
// worry about.
|
||||
}
|
||||
|
||||
void OpenGLContext::synchronizeStateAndCache(size_t index) noexcept {
|
||||
void OpenGLContext::synchronizeStateAndCache(size_t index) {
|
||||
|
||||
// if we're just switching back to context 0, run all the pending destructors
|
||||
if (index == 0) {
|
||||
@@ -865,10 +865,12 @@ GLuint OpenGLContext::bindFramebuffer(GLenum target, GLuint buffer) noexcept {
|
||||
if (UTILS_UNLIKELY(buffer == 0)) {
|
||||
// we're binding the default frame buffer, resolve its actual name
|
||||
auto& defaultFboForThisContext = mDefaultFbo[contextIndex];
|
||||
|
||||
if (UTILS_UNLIKELY(!defaultFboForThisContext.has_value())) {
|
||||
defaultFboForThisContext = GLuint(mPlatform.getDefaultFramebufferObject());
|
||||
}
|
||||
buffer = defaultFboForThisContext.value();
|
||||
// by construction, defaultFboForThisContext has a value. value_or() avoids a throwing call.
|
||||
buffer = defaultFboForThisContext.value_or(0);
|
||||
}
|
||||
bindFramebufferResolved(target, buffer);
|
||||
return buffer;
|
||||
|
||||
@@ -193,7 +193,7 @@ public:
|
||||
void deleteBuffer(GLuint buffer, GLenum target) noexcept;
|
||||
void deleteVertexArray(GLuint vao) noexcept;
|
||||
|
||||
void destroyWithContext(size_t index, std::function<void(OpenGLContext&)> const& closure) noexcept;
|
||||
void destroyWithContext(size_t index, std::function<void(OpenGLContext&)> const& closure);
|
||||
|
||||
// glGet*() values
|
||||
struct Gets {
|
||||
@@ -498,7 +498,7 @@ public:
|
||||
} procs{};
|
||||
|
||||
void unbindEverything() noexcept;
|
||||
void synchronizeStateAndCache(size_t index) noexcept;
|
||||
void synchronizeStateAndCache(size_t index);
|
||||
|
||||
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
|
||||
GLuint getSamplerSlow(SamplerParams sp) const noexcept;
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include <type_traits>
|
||||
#include <utils/BitmaskEnum.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/ImmutableCString.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Invocable.h>
|
||||
#include <utils/Logger.h>
|
||||
@@ -394,7 +395,7 @@ void OpenGLDriver::setPushConstant(ShaderStage const stage, uint8_t const index,
|
||||
}
|
||||
#endif
|
||||
|
||||
Slice<std::pair<GLint, ConstantType>> constants;
|
||||
Slice<const std::pair<GLint, ConstantType>> constants;
|
||||
if (stage == ShaderStage::VERTEX) {
|
||||
constants = mCurrentPushConstants->vertexConstants;
|
||||
} else if (stage == ShaderStage::FRAGMENT) {
|
||||
@@ -661,7 +662,7 @@ void OpenGLDriver::createVertexBufferInfoR(
|
||||
uint8_t bufferCount,
|
||||
uint8_t attributeCount,
|
||||
AttributeArray attributes,
|
||||
CString&& tag) {
|
||||
ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
construct<GLVertexBufferInfo>(vbih, bufferCount, attributeCount, attributes);
|
||||
mHandleAllocator.associateTagToHandle(vbih.getId(), std::move(tag));
|
||||
@@ -671,7 +672,7 @@ void OpenGLDriver::createVertexBufferR(
|
||||
Handle<HwVertexBuffer> vbh,
|
||||
uint32_t vertexCount,
|
||||
Handle<HwVertexBufferInfo> vbih,
|
||||
CString&& tag) {
|
||||
ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
construct<GLVertexBuffer>(vbh, vertexCount, vbih);
|
||||
mHandleAllocator.associateTagToHandle(vbh.getId(), std::move(tag));
|
||||
@@ -682,7 +683,7 @@ void OpenGLDriver::createIndexBufferR(
|
||||
ElementType const elementType,
|
||||
uint32_t indexCount,
|
||||
BufferUsage const usage,
|
||||
CString&& tag) {
|
||||
ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
auto& gl = mContext;
|
||||
@@ -698,7 +699,7 @@ void OpenGLDriver::createIndexBufferR(
|
||||
}
|
||||
|
||||
void OpenGLDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byteCount,
|
||||
BufferObjectBinding bindingType, BufferUsage usage, CString&& tag) {
|
||||
BufferObjectBinding bindingType, BufferUsage usage, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
assert_invariant(byteCount > 0);
|
||||
|
||||
@@ -725,7 +726,7 @@ void OpenGLDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byte
|
||||
|
||||
void OpenGLDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
|
||||
Handle<HwVertexBuffer> vbh, Handle<HwIndexBuffer> ibh,
|
||||
PrimitiveType const pt, CString&& tag) {
|
||||
PrimitiveType const pt, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
auto& gl = mContext;
|
||||
@@ -761,32 +762,9 @@ void OpenGLDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
|
||||
mHandleAllocator.associateTagToHandle(rph.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program, CString&& tag) {
|
||||
void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
|
||||
if (UTILS_UNLIKELY(mContext.isES2())) {
|
||||
// Here we patch the specialization constants to enable or not the rec709 output
|
||||
// color space emulation in this program. Obviously, the backend shouldn't know about
|
||||
// specific spec-constants, so we need to handle failures gracefully. This cannot be
|
||||
// done at Material creation time because only the backend has access to
|
||||
// Platform.isSRGBSwapChainSupported().
|
||||
if (!mPlatform.isSRGBSwapChainSupported()) {
|
||||
auto& specializationConstants = program.getSpecializationConstants();
|
||||
auto const pos = std::find_if(specializationConstants.begin(), specializationConstants.end(),
|
||||
[](auto&& sc) {
|
||||
// This constant must match
|
||||
// ReservedSpecializationConstants::CONFIG_SRGB_SWAPCHAIN_EMULATION
|
||||
// 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).
|
||||
return sc.id == 3;
|
||||
});
|
||||
if (pos != specializationConstants.end()) {
|
||||
pos->value = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
construct<OpenGLProgram>(ph, *this, std::move(program));
|
||||
CHECK_GL_ERROR()
|
||||
mHandleAllocator.associateTagToHandle(ph.getId(), std::move(tag));
|
||||
@@ -894,7 +872,7 @@ void OpenGLDriver::textureStorage(GLTexture* t,
|
||||
|
||||
void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8_t levels,
|
||||
TextureFormat format, uint8_t samples, uint32_t width, uint32_t height, uint32_t depth,
|
||||
TextureUsage usage, CString&& tag) {
|
||||
TextureUsage usage, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
GLenum internalFormat = getInternalFormat(format);
|
||||
@@ -987,7 +965,7 @@ void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
|
||||
Handle<HwTexture> srch, uint8_t const baseLevel, uint8_t const levelCount, CString&& tag) {
|
||||
Handle<HwTexture> srch, uint8_t const baseLevel, uint8_t const levelCount, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
GLTexture const* const src = handle_cast<GLTexture const*>(srch);
|
||||
|
||||
@@ -1035,7 +1013,7 @@ void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
|
||||
|
||||
void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
TextureSwizzle const r, TextureSwizzle const g, TextureSwizzle const b, TextureSwizzle const a,
|
||||
CString&& tag) {
|
||||
ImmutableCString&& tag) {
|
||||
|
||||
DEBUG_MARKER()
|
||||
GLTexture const* const src = handle_cast<GLTexture const*>(srch);
|
||||
@@ -1101,7 +1079,7 @@ void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
|
||||
|
||||
void OpenGLDriver::createTextureExternalImage2R(Handle<HwTexture> th, SamplerType target,
|
||||
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef image, CString&& tag) {
|
||||
Platform::ExternalImageHandleRef image, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
usage |= TextureUsage::SAMPLEABLE;
|
||||
@@ -1153,7 +1131,7 @@ void OpenGLDriver::createTextureExternalImage2R(Handle<HwTexture> th, SamplerTyp
|
||||
|
||||
void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType target,
|
||||
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage, void* image,
|
||||
CString&& tag) {
|
||||
ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
usage |= TextureUsage::SAMPLEABLE;
|
||||
@@ -1204,13 +1182,13 @@ void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType
|
||||
|
||||
void OpenGLDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
|
||||
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage,
|
||||
void* image, uint32_t plane, CString&&) {
|
||||
void* image, uint32_t plane, ImmutableCString&&) {
|
||||
// not relevant for the OpenGL backend
|
||||
}
|
||||
|
||||
void OpenGLDriver::importTextureR(Handle<HwTexture> th, intptr_t const id,
|
||||
SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples,
|
||||
uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage, CString&& tag) {
|
||||
uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
auto const& gl = mContext;
|
||||
@@ -1665,7 +1643,7 @@ void OpenGLDriver::renderBufferStorage(GLuint const rbo, GLenum internalformat,
|
||||
}
|
||||
|
||||
void OpenGLDriver::createDefaultRenderTargetR(
|
||||
Handle<HwRenderTarget> rth, CString&& tag) {
|
||||
Handle<HwRenderTarget> rth, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
construct<GLRenderTarget>(rth, 0, 0); // FIXME: we don't know the width/height
|
||||
@@ -1688,7 +1666,7 @@ void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
MRT color,
|
||||
TargetBufferInfo depth,
|
||||
TargetBufferInfo stencil,
|
||||
CString&& tag) {
|
||||
ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
GLRenderTarget* rt = construct<GLRenderTarget>(rth, width, height);
|
||||
@@ -1804,7 +1782,7 @@ void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
mHandleAllocator.associateTagToHandle(rth.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createFenceR(Handle<HwFence> fh, CString&& tag) {
|
||||
void OpenGLDriver::createFenceR(Handle<HwFence> fh, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
mHandleAllocator.associateTagToHandle(fh.getId(), std::move(tag));
|
||||
@@ -1838,7 +1816,7 @@ void OpenGLDriver::createFenceR(Handle<HwFence> fh, CString&& tag) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLDriver::createSyncR(Handle<HwSync> sh, CString&& tag) {
|
||||
void OpenGLDriver::createSyncR(Handle<HwSync> sh, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
GLSyncFence* s = handle_cast<GLSyncFence*>(sh);
|
||||
@@ -1857,7 +1835,7 @@ void OpenGLDriver::createSyncR(Handle<HwSync> sh, CString&& tag) {
|
||||
}
|
||||
|
||||
void OpenGLDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t const flags,
|
||||
CString&& tag) {
|
||||
ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
GLSwapChain* sc = handle_cast<GLSwapChain*>(sch);
|
||||
@@ -1879,7 +1857,7 @@ void OpenGLDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
}
|
||||
|
||||
void OpenGLDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch,
|
||||
uint32_t const width, uint32_t const height, uint64_t const flags, CString&& tag) {
|
||||
uint32_t const width, uint32_t const height, uint64_t const flags, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
|
||||
GLSwapChain* sc = handle_cast<GLSwapChain*>(sch);
|
||||
@@ -1901,7 +1879,7 @@ void OpenGLDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch,
|
||||
mHandleAllocator.associateTagToHandle(sch.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, CString&& tag) {
|
||||
void OpenGLDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
GLTimerQuery* tq = handle_cast<GLTimerQuery*>(tqh);
|
||||
mContext.createTimerQuery(tq);
|
||||
@@ -1909,14 +1887,14 @@ void OpenGLDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, CString&& tag) {
|
||||
}
|
||||
|
||||
void OpenGLDriver::createDescriptorSetLayoutR(Handle<HwDescriptorSetLayout> dslh,
|
||||
DescriptorSetLayout&& info, CString&& tag) {
|
||||
DescriptorSetLayout&& info, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
construct<GLDescriptorSetLayout>(dslh, std::move(info));
|
||||
mHandleAllocator.associateTagToHandle(dslh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void OpenGLDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
|
||||
Handle<HwDescriptorSetLayout> dslh, CString&& tag) {
|
||||
Handle<HwDescriptorSetLayout> dslh, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
GLDescriptorSetLayout const* dsl = handle_cast<GLDescriptorSetLayout*>(dslh);
|
||||
construct<GLDescriptorSet>(dsh, mContext, dslh, dsl);
|
||||
@@ -1925,7 +1903,7 @@ void OpenGLDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
|
||||
|
||||
void OpenGLDriver::mapBufferR(MemoryMappedBufferHandle mmbh,
|
||||
BufferObjectHandle boh, size_t offset,
|
||||
size_t size, MapBufferAccessFlags access, CString&& tag) {
|
||||
size_t size, MapBufferAccessFlags access, ImmutableCString&& tag) {
|
||||
DEBUG_MARKER()
|
||||
construct<GLMemoryMappedBuffer>(mmbh, mContext, mHandleAllocator, boh, offset, size, access);
|
||||
mHandleAllocator.associateTagToHandle(mmbh.getId(), std::move(tag));
|
||||
@@ -2195,14 +2173,14 @@ void OpenGLDriver::unmapBuffer(MemoryMappedBufferHandle mmbh) {
|
||||
// These are called on the application's thread
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
Handle<HwStream> OpenGLDriver::createStreamNative(void* nativeStream, CString tag) {
|
||||
Handle<HwStream> OpenGLDriver::createStreamNative(void* nativeStream, ImmutableCString tag) {
|
||||
Platform::Stream* stream = mPlatform.createStream(nativeStream);
|
||||
auto handle = initHandle<GLStream>(stream);
|
||||
mHandleAllocator.associateTagToHandle(handle.getId(), std::move(tag));
|
||||
return handle;
|
||||
}
|
||||
|
||||
Handle<HwStream> OpenGLDriver::createStreamAcquired(CString tag) {
|
||||
Handle<HwStream> OpenGLDriver::createStreamAcquired(ImmutableCString tag) {
|
||||
auto handle = initHandle<GLStream>();
|
||||
mHandleAllocator.associateTagToHandle(handle.getId(), std::move(tag));
|
||||
return handle;
|
||||
@@ -2640,6 +2618,8 @@ bool OpenGLDriver::isWorkaroundNeeded(Workaround const workaround) {
|
||||
return mContext.bugs.powervr_shader_workarounds;
|
||||
case Workaround::DISABLE_DEPTH_PRECACHE_FOR_DEFAULT_MATERIAL:
|
||||
return mContext.bugs.disable_depth_precache_for_default_material;
|
||||
case Workaround::EMULATE_SRGB_SWAPCHAIN:
|
||||
return mContext.isES2() && !mPlatform.isSRGBSwapChainSupported();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -3213,7 +3193,7 @@ void OpenGLDriver::setExternalStream(Handle<HwTexture> th, Handle<HwStream> sh)
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
void OpenGLDriver::attachStream(GLTexture* t, GLStream* hwStream) noexcept {
|
||||
void OpenGLDriver::attachStream(GLTexture* t, GLStream* hwStream) {
|
||||
mTexturesWithStreamsAttached.push_back(t);
|
||||
|
||||
switch (hwStream->streamType) {
|
||||
@@ -3799,16 +3779,16 @@ void OpenGLDriver::readBufferSubData(BufferObjectHandle boh,
|
||||
}
|
||||
|
||||
|
||||
void OpenGLDriver::runEveryNowAndThen(std::function<bool()> fn) noexcept {
|
||||
void OpenGLDriver::runEveryNowAndThen(std::function<bool()> fn) {
|
||||
mEveryNowAndThenOps.push_back(std::move(fn));
|
||||
}
|
||||
|
||||
void OpenGLDriver::executeEveryNowAndThenOps() noexcept {
|
||||
void OpenGLDriver::executeEveryNowAndThenOps() noexcept { // NOLINT(*-exception-escape)
|
||||
auto& v = mEveryNowAndThenOps;
|
||||
auto it = v.begin();
|
||||
while (it != v.end()) {
|
||||
if ((*it)()) {
|
||||
it = v.erase(it);
|
||||
it = v.erase(it); // cannot throw by construction
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
@@ -3816,17 +3796,17 @@ void OpenGLDriver::executeEveryNowAndThenOps() noexcept {
|
||||
}
|
||||
|
||||
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
|
||||
void OpenGLDriver::whenFrameComplete(const std::function<void()>& fn) noexcept {
|
||||
void OpenGLDriver::whenFrameComplete(const std::function<void()>& fn) {
|
||||
mFrameCompleteOps.push_back(fn);
|
||||
}
|
||||
|
||||
void OpenGLDriver::whenGpuCommandsComplete(const std::function<void()>& fn) noexcept {
|
||||
void OpenGLDriver::whenGpuCommandsComplete(const std::function<void()>& fn) {
|
||||
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
mGpuCommandCompleteOps.emplace_back(sync, fn);
|
||||
CHECK_GL_ERROR()
|
||||
}
|
||||
|
||||
void OpenGLDriver::executeGpuCommandsCompleteOps() noexcept {
|
||||
void OpenGLDriver::executeGpuCommandsCompleteOps() noexcept { // NOLINT(*-exception-escape)
|
||||
auto& v = mGpuCommandCompleteOps;
|
||||
auto it = v.begin();
|
||||
while (it != v.end()) {
|
||||
@@ -3842,13 +3822,13 @@ void OpenGLDriver::executeGpuCommandsCompleteOps() noexcept {
|
||||
// ready
|
||||
it->second();
|
||||
glDeleteSync(sync);
|
||||
it = v.erase(it);
|
||||
it = v.erase(it); // cannot throw by construction
|
||||
break;
|
||||
default:
|
||||
// This should never happen, but is very problematic if it does, as we might leak
|
||||
// some data depending on what the callback does. However, we clean up our own state.
|
||||
glDeleteSync(sync);
|
||||
it = v.erase(it);
|
||||
it = v.erase(it); // cannot throw by construction
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/ImmutableCString.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <math/vec4.h>
|
||||
@@ -395,23 +396,23 @@ private:
|
||||
|
||||
std::unordered_map<GLuint, BufferObjectStreamDescriptor> mStreamUniformDescriptors;
|
||||
|
||||
void attachStream(GLTexture* t, GLStream* stream) noexcept;
|
||||
void attachStream(GLTexture* t, GLStream* stream);
|
||||
void detachStream(GLTexture* t) noexcept;
|
||||
void replaceStream(GLTexture* t, GLStream* stream) noexcept;
|
||||
math::mat3f getStreamTransformMatrix(Handle<HwStream> sh);
|
||||
|
||||
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
|
||||
// tasks executed on the main thread after the fence signaled
|
||||
void whenGpuCommandsComplete(const std::function<void()>& fn) noexcept;
|
||||
void whenGpuCommandsComplete(const std::function<void()>& fn);
|
||||
void executeGpuCommandsCompleteOps() noexcept;
|
||||
std::vector<std::pair<GLsync, std::function<void()>>> mGpuCommandCompleteOps;
|
||||
|
||||
void whenFrameComplete(const std::function<void()>& fn) noexcept;
|
||||
void whenFrameComplete(const std::function<void()>& fn);
|
||||
std::vector<std::function<void()>> mFrameCompleteOps;
|
||||
#endif
|
||||
|
||||
// tasks regularly executed on the main thread at until they return true
|
||||
void runEveryNowAndThen(std::function<bool()> fn) noexcept;
|
||||
void runEveryNowAndThen(std::function<bool()> fn);
|
||||
void executeEveryNowAndThenOps() noexcept;
|
||||
std::vector<std::function<bool()>> mEveryNowAndThenOps;
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ void OpenGLProgram::initialize(OpenGLDriver& gld) {
|
||||
* checkProgramStatus() has been successfully called.
|
||||
*/
|
||||
void OpenGLProgram::initializeProgramState(OpenGLContext& context, GLuint program,
|
||||
LazyInitializationData& lazyInitializationData) noexcept {
|
||||
LazyInitializationData& lazyInitializationData) {
|
||||
FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
||||
|
||||
// from the pipeline layout we compute a mapping from {set, binding} to {binding}
|
||||
|
||||
@@ -43,8 +43,8 @@ namespace filament::backend {
|
||||
class OpenGLDriver;
|
||||
|
||||
struct PushConstantBundle {
|
||||
utils::Slice<std::pair<GLint, ConstantType>> vertexConstants;
|
||||
utils::Slice<std::pair<GLint, ConstantType>> fragmentConstants;
|
||||
utils::Slice<const std::pair<GLint, ConstantType>> vertexConstants;
|
||||
utils::Slice<const std::pair<GLint, ConstantType>> fragmentConstants;
|
||||
};
|
||||
|
||||
class OpenGLProgram : public HwProgram {
|
||||
@@ -94,8 +94,8 @@ public:
|
||||
PushConstantBundle getPushConstants() {
|
||||
auto fragBegin = mPushConstants.begin() + mPushConstantFragmentStageOffset;
|
||||
return {
|
||||
.vertexConstants = utils::Slice(mPushConstants.begin(), fragBegin),
|
||||
.fragmentConstants = utils::Slice(fragBegin, mPushConstants.end()),
|
||||
.vertexConstants = { mPushConstants.begin(), fragBegin },
|
||||
.fragmentConstants = { fragBegin, mPushConstants.end() },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ private:
|
||||
void initialize(OpenGLDriver& gld);
|
||||
|
||||
void initializeProgramState(OpenGLContext& context, GLuint program,
|
||||
LazyInitializationData& lazyInitializationData) noexcept;
|
||||
LazyInitializationData& lazyInitializationData);
|
||||
|
||||
BindingMap mBindingMap; // 8 bytes + out-of-line 256 bytes
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ class OpenGLDriver;
|
||||
bool TimerQueryFactory::mGpuTimeSupported = false;
|
||||
|
||||
TimerQueryFactoryInterface* TimerQueryFactory::init(
|
||||
OpenGLPlatform& platform, OpenGLContext& context) noexcept {
|
||||
OpenGLPlatform& platform, OpenGLContext& context) {
|
||||
(void)context;
|
||||
|
||||
TimerQueryFactoryInterface* impl = nullptr;
|
||||
@@ -172,46 +172,12 @@ void TimerQueryNativeFactory::endTimeElapsedQuery(OpenGLDriver& driver, GLTimerQ
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
TimerQueryFenceFactory::TimerQueryFenceFactory(OpenGLPlatform& platform)
|
||||
: mPlatform(platform) {
|
||||
mQueue.reserve(2);
|
||||
mThread = std::thread([this]() {
|
||||
utils::JobSystem::setThreadName("OpenGLTimerQueryFence");
|
||||
utils::JobSystem::setThreadPriority(utils::JobSystem::Priority::URGENT_DISPLAY);
|
||||
auto& queue = mQueue;
|
||||
bool exitRequested;
|
||||
do {
|
||||
std::unique_lock<utils::Mutex> lock(mLock);
|
||||
mCondition.wait(lock, [this, &queue]() -> bool {
|
||||
return mExitRequested || !queue.empty();
|
||||
});
|
||||
exitRequested = mExitRequested;
|
||||
if (!queue.empty()) {
|
||||
Job const job(queue.front());
|
||||
queue.erase(queue.begin());
|
||||
lock.unlock();
|
||||
job();
|
||||
}
|
||||
} while (!exitRequested);
|
||||
});
|
||||
: mPlatform(platform),
|
||||
mJobQueue("OpenGLTimerQueryFence", utils::AsyncJobQueue::Priority::URGENT_DISPLAY) {
|
||||
}
|
||||
|
||||
TimerQueryFenceFactory::~TimerQueryFenceFactory() {
|
||||
assert_invariant(mQueue.empty());
|
||||
if (mThread.joinable()) {
|
||||
std::unique_lock<utils::Mutex> lock(mLock);
|
||||
mExitRequested = true;
|
||||
mCondition.notify_one();
|
||||
lock.unlock();
|
||||
if (mThread.joinable()) {
|
||||
mThread.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimerQueryFenceFactory::push(TimerQueryFenceFactory::Job&& job) {
|
||||
std::unique_lock<utils::Mutex> const lock(mLock);
|
||||
mQueue.push_back(std::move(job));
|
||||
mCondition.notify_one();
|
||||
mJobQueue.drainAndExit();
|
||||
}
|
||||
|
||||
void TimerQueryFenceFactory::createTimerQuery(GLTimerQuery* tq) {
|
||||
@@ -236,7 +202,7 @@ void TimerQueryFenceFactory::beginTimeElapsedQuery(GLTimerQuery* tq) {
|
||||
// on a dummy target for instance, or somehow latch the begin time at the next renderpass
|
||||
// start.
|
||||
|
||||
push([&platform = mPlatform, fence = mPlatform.createFence(), weak]() {
|
||||
mJobQueue.push([&platform = mPlatform, fence = mPlatform.createFence(), weak]() {
|
||||
auto state = weak.lock();
|
||||
if (state) {
|
||||
platform.waitFence(fence, FENCE_WAIT_FOR_EVER);
|
||||
@@ -252,7 +218,7 @@ void TimerQueryFenceFactory::endTimeElapsedQuery(OpenGLDriver&, GLTimerQuery* tq
|
||||
assert_invariant(tq->state);
|
||||
std::weak_ptr<GLTimerQuery::State> const weak = tq->state;
|
||||
|
||||
push([&platform = mPlatform, fence = mPlatform.createFence(), weak]() {
|
||||
mJobQueue.push([&platform = mPlatform, fence = mPlatform.createFence(), weak]() {
|
||||
auto state = weak.lock();
|
||||
if (state) {
|
||||
platform.waitFence(fence, FENCE_WAIT_FOR_EVER);
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
|
||||
#include "DriverBase.h"
|
||||
|
||||
#include <utils/Condition.h>
|
||||
#include <utils/Mutex.h>
|
||||
#include <utils/AsyncJobQueue.h>
|
||||
|
||||
#include "gl_headers.h"
|
||||
|
||||
@@ -65,7 +64,7 @@ class TimerQueryFactory {
|
||||
static bool mGpuTimeSupported;
|
||||
public:
|
||||
static TimerQueryFactoryInterface* init(
|
||||
OpenGLPlatform& platform, OpenGLContext& context) noexcept;
|
||||
OpenGLPlatform& platform, OpenGLContext& context);
|
||||
|
||||
static bool isGpuTimeSupported() noexcept {
|
||||
return mGpuTimeSupported;
|
||||
@@ -108,22 +107,13 @@ public:
|
||||
explicit TimerQueryFenceFactory(OpenGLPlatform& platform);
|
||||
~TimerQueryFenceFactory() override;
|
||||
private:
|
||||
using Job = std::function<void()>;
|
||||
using Container = std::vector<Job>;
|
||||
|
||||
void createTimerQuery(GLTimerQuery* query) override;
|
||||
void destroyTimerQuery(GLTimerQuery* query) override;
|
||||
void beginTimeElapsedQuery(GLTimerQuery* tq) override;
|
||||
void endTimeElapsedQuery(OpenGLDriver& driver, GLTimerQuery* tq) override;
|
||||
|
||||
void push(Job&& job);
|
||||
|
||||
OpenGLPlatform& mPlatform;
|
||||
std::thread mThread;
|
||||
mutable utils::Mutex mLock;
|
||||
mutable utils::Condition mCondition;
|
||||
Container mQueue;
|
||||
bool mExitRequested = false;
|
||||
utils::AsyncJobQueue mJobQueue;
|
||||
};
|
||||
|
||||
class TimerQueryFallbackFactory final : public TimerQueryFactoryInterface {
|
||||
|
||||
@@ -71,7 +71,7 @@ static CString to_string(int const i) { return utils::to_string(i); }
|
||||
static CString to_string(float const f) { return "float(" + utils::to_string(f) + ")"; }
|
||||
|
||||
static void logCompilationError(ShaderStage shaderType, const char* name, GLuint shaderId,
|
||||
Program::ShaderBlob const& sourceCode) noexcept;
|
||||
Program::ShaderBlob const& sourceCode);
|
||||
static void logProgramLinkError(char const* name, GLuint program) noexcept;
|
||||
|
||||
static void process_GOOGLE_cpp_style_line_directive(OpenGLContext const& context, char* source,
|
||||
@@ -79,7 +79,7 @@ static void process_GOOGLE_cpp_style_line_directive(OpenGLContext const& context
|
||||
static void process_OVR_multiview2(OpenGLContext const& context, int32_t eyeCount, char* source,
|
||||
size_t len) noexcept;
|
||||
static std::string_view process_ARB_shading_language_packing(OpenGLContext& context) noexcept;
|
||||
static std::array<std::string_view, 3> splitShaderSource(std::string_view source) noexcept;
|
||||
static std::array<std::string_view, 3> splitShaderSource(std::string_view source);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -312,7 +312,7 @@ ShaderCompilerService::program_token_t ShaderCompilerService::createProgram(
|
||||
}
|
||||
|
||||
void ShaderCompilerService::compileProgram(
|
||||
program_token_t const& token, Program&& program) noexcept {
|
||||
program_token_t const& token, Program&& program) {
|
||||
auto& gl = mDriver.getContext();
|
||||
CompilerPriorityQueue const priorityQueue = program.getPriorityQueue();
|
||||
switch (mMode) {
|
||||
@@ -343,6 +343,12 @@ void ShaderCompilerService::compileProgram(
|
||||
program.getSpecializationConstants(), program.isMultiview(),
|
||||
token);
|
||||
linkProgram(gl, token);
|
||||
// Check status of program linking. If it failed, errors will be logged.
|
||||
bool const linked = checkLinkStatusAndCleanupShaders(token);
|
||||
// We panic if it failed to create the program.
|
||||
FILAMENT_CHECK_POSTCONDITION(linked)
|
||||
<< "OpenGL program " << token->name.c_str_safe()
|
||||
<< " failed to link or compile";
|
||||
}
|
||||
// Now `token->gl.program` must be populated, so we signal the completion
|
||||
// of the linking. We don't need to check the result of the program here
|
||||
@@ -475,16 +481,14 @@ GLuint ShaderCompilerService::initialize(program_token_t& token) {
|
||||
ensureTokenIsReady(token);
|
||||
assert_invariant(token->gl.program);
|
||||
|
||||
// Check status of program linking. If it failed, errors will be logged.
|
||||
bool const linked = checkLinkStatusAndCleanupShaders(token);
|
||||
|
||||
// We panic if it failed to create the program.
|
||||
FILAMENT_CHECK_POSTCONDITION(linked)
|
||||
<< "OpenGL program " << token->name.c_str_safe() << " failed to link or compile";
|
||||
|
||||
GLuint const program = token->gl.program;
|
||||
|
||||
if (mMode != Mode::THREAD_POOL) {
|
||||
// Check status of program linking. If it failed, errors will be logged.
|
||||
bool const linked = checkLinkStatusAndCleanupShaders(token);
|
||||
// We panic if it failed to create the program.
|
||||
FILAMENT_CHECK_POSTCONDITION(linked)
|
||||
<< "OpenGL program " << token->name.c_str_safe() << " failed to link or compile";
|
||||
// The program has been successfully created. Try caching the program blob for
|
||||
// non-THREAD_POOL modes. In the THREAD_POOL mode, caching is performed in the pool.
|
||||
tryCachingProgram(mBlobCache, mDriver.mPlatform, token);
|
||||
@@ -586,7 +590,7 @@ void ShaderCompilerService::handleCanceledTokensForThreadPool() {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void ShaderCompilerService::runAtNextTick(CompilerPriorityQueue priority,
|
||||
program_token_t const& token, Job job) noexcept {
|
||||
program_token_t const& token, Job job) {
|
||||
// insert items in order of priority and at the end of the range
|
||||
auto& ops = mRunAtNextTickOps;
|
||||
auto const pos = std::lower_bound(ops.begin(), ops.end(), priority,
|
||||
@@ -614,7 +618,7 @@ bool ShaderCompilerService::cancelTickOp(program_token_t const& token) noexcept
|
||||
return false;
|
||||
}
|
||||
|
||||
void ShaderCompilerService::executeTickOps() noexcept {
|
||||
void ShaderCompilerService::executeTickOps() {
|
||||
auto& ops = mRunAtNextTickOps;
|
||||
auto it = ops.begin();
|
||||
while (it != ops.end()) {
|
||||
@@ -636,7 +640,7 @@ bool ShaderCompilerService::shouldCompileSynchronousProgramThisTick() const noex
|
||||
mNumTicksUntilNextSynchronousProgram == 0);
|
||||
}
|
||||
|
||||
void ShaderCompilerService::compilePendingSynchronousPrograms() noexcept {
|
||||
void ShaderCompilerService::compilePendingSynchronousPrograms() {
|
||||
if (mDriver.getDriverConfig().disableAmortizedShaderCompile) {
|
||||
return;
|
||||
}
|
||||
@@ -655,7 +659,7 @@ void ShaderCompilerService::compilePendingSynchronousPrograms() noexcept {
|
||||
}
|
||||
|
||||
void ShaderCompilerService::compilePendingSynchronousProgramNow(
|
||||
program_token_t const& token) noexcept {
|
||||
program_token_t const& token) {
|
||||
if (mDriver.getDriverConfig().disableAmortizedShaderCompile) {
|
||||
return;
|
||||
}
|
||||
@@ -692,27 +696,28 @@ void ShaderCompilerService::cancelPendingSynchronousProgram(program_token_t cons
|
||||
/* static */ void ShaderCompilerService::compileShaders(OpenGLContext& context,
|
||||
Program::ShaderSource shadersSource,
|
||||
FixedCapacityVector<Program::SpecializationConstant> const& specializationConstants,
|
||||
bool multiview, program_token_t const& token) noexcept {
|
||||
bool multiview, program_token_t const& token) {
|
||||
FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
||||
|
||||
auto const appendSpecConstantString = +[](CString& s, Program::SpecializationConstant const& sc) {
|
||||
s += "#define SPIRV_CROSS_CONSTANT_ID_" + utils::to_string(sc.id) + ' ';
|
||||
s += std::visit([](auto&& arg) { return to_string(arg); }, sc.value);
|
||||
s += '\n';
|
||||
return s;
|
||||
};
|
||||
auto const appendSpecConstantString =
|
||||
+[](CString& s, size_t id, Program::SpecializationConstant const& sc) {
|
||||
s += "#define SPIRV_CROSS_CONSTANT_ID_" + utils::to_string(id) + ' ';
|
||||
s += std::visit([](auto&& arg) { return to_string(arg); }, sc);
|
||||
s += '\n';
|
||||
return s;
|
||||
};
|
||||
|
||||
CString 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);
|
||||
}
|
||||
// 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).
|
||||
constexpr size_t CONFIG_STEREO_EYE_COUNT = 8;
|
||||
int32_t numViews = specializationConstants.size() >= CONFIG_STEREO_EYE_COUNT
|
||||
? std::get<int32_t>(specializationConstants[CONFIG_STEREO_EYE_COUNT])
|
||||
: 2;
|
||||
for (size_t id = 0; id < specializationConstants.size(); id++) {
|
||||
appendSpecConstantString(specializationConstantString, id, specializationConstants[id]);
|
||||
}
|
||||
if (!specializationConstantString.empty()) {
|
||||
specializationConstantString += '\n';
|
||||
@@ -817,7 +822,7 @@ void ShaderCompilerService::cancelPendingSynchronousProgram(program_token_t cons
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ void ShaderCompilerService::checkCompileStatus(program_token_t const& token) noexcept {
|
||||
/* static */ void ShaderCompilerService::checkCompileStatus(program_token_t const& token) {
|
||||
FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
||||
|
||||
UTILS_NOUNROLL
|
||||
@@ -839,7 +844,7 @@ void ShaderCompilerService::cancelPendingSynchronousProgram(program_token_t cons
|
||||
}
|
||||
|
||||
/* static */ void ShaderCompilerService::linkProgram(OpenGLContext const& context,
|
||||
program_token_t const& token) noexcept {
|
||||
program_token_t const& token) {
|
||||
FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
||||
|
||||
// Shader compilation should be completed by now. Check the status and log errors on failure.
|
||||
@@ -933,7 +938,7 @@ void ShaderCompilerService::cancelPendingSynchronousProgram(program_token_t cons
|
||||
UTILS_NOINLINE
|
||||
/* static */ void logCompilationError(ShaderStage shaderType, const char* name,
|
||||
GLuint const shaderId,
|
||||
UTILS_UNUSED_IN_RELEASE Program::ShaderBlob const& sourceCode) noexcept {
|
||||
UTILS_UNUSED_IN_RELEASE Program::ShaderBlob const& sourceCode) {
|
||||
|
||||
// Collects the current GL error for additional context. While often redundant,
|
||||
// errors like `GL_CONTEXT_LOST` can occur asynchronously after `glCompileShader`.
|
||||
@@ -1179,7 +1184,7 @@ mediump vec4 unpackSnorm4x8(highp uint v) {
|
||||
// - the version line
|
||||
// - extensions
|
||||
// - everything else
|
||||
/* static */ std::array<std::string_view, 3> splitShaderSource(std::string_view source) noexcept {
|
||||
/* static */ std::array<std::string_view, 3> splitShaderSource(std::string_view source) {
|
||||
auto const version_start = source.find("#version");
|
||||
assert_invariant(version_start != std::string_view::npos);
|
||||
|
||||
|
||||
@@ -148,16 +148,16 @@ private:
|
||||
|
||||
// Methods for SYNCHRONOUS and ASYNCHRONOUS modes.
|
||||
void runAtNextTick(CompilerPriorityQueue priority, program_token_t const& token,
|
||||
Job job) noexcept;
|
||||
void executeTickOps() noexcept;
|
||||
Job job);
|
||||
void executeTickOps();
|
||||
bool cancelTickOp(program_token_t const& token) noexcept;
|
||||
|
||||
bool shouldCompileSynchronousProgramThisTick() const noexcept;
|
||||
void compilePendingSynchronousPrograms() noexcept;
|
||||
void compilePendingSynchronousProgramNow(program_token_t const& token) noexcept;
|
||||
void compilePendingSynchronousPrograms();
|
||||
void compilePendingSynchronousProgramNow(program_token_t const& token);
|
||||
void cancelPendingSynchronousProgram(program_token_t const& token) noexcept;
|
||||
|
||||
void compileProgram(program_token_t const& token, Program&& program) noexcept;
|
||||
void compileProgram(program_token_t const& token, Program&& program);
|
||||
|
||||
// Compile shaders with the given `shaderSource`. `gl.shaders` is always populated with valid
|
||||
// shader IDs after this method. But this doesn't necessarily mean the shaders are successfully
|
||||
@@ -165,20 +165,20 @@ private:
|
||||
static void compileShaders(OpenGLContext& context, Program::ShaderSource shadersSource,
|
||||
utils::FixedCapacityVector<Program::SpecializationConstant> const&
|
||||
specializationConstants,
|
||||
bool multiview, program_token_t const& token) noexcept;
|
||||
bool multiview, program_token_t const& token);
|
||||
|
||||
// Check if the shader compilation is completed. You may want to call this when the extension
|
||||
// `KHR_parallel_shader_compile` is enabled.
|
||||
static bool isCompileCompleted(program_token_t const& token) noexcept;
|
||||
|
||||
// Check compilation status of the shaders and log errors on failure.
|
||||
static void checkCompileStatus(program_token_t const& token) noexcept;
|
||||
static void checkCompileStatus(program_token_t const& token);
|
||||
|
||||
// Create a program by linking the compiled shaders. `gl.program` is always populated with a
|
||||
// valid program ID after this method. But this doesn't necessarily mean the program is
|
||||
// successfully linked. Errors can be checked by calling `checkLinkStatusAndCleanupShaders`
|
||||
// later.
|
||||
static void linkProgram(OpenGLContext const& context, program_token_t const& token) noexcept;
|
||||
static void linkProgram(OpenGLContext const& context, program_token_t const& token);
|
||||
|
||||
// Check if the program link is completed. You may want to call this when the extension
|
||||
// `KHR_parallel_shader_compile` is enabled.
|
||||
|
||||
@@ -148,7 +148,7 @@ PlatformCocoaGL::~PlatformCocoaGL() noexcept {
|
||||
delete pImpl;
|
||||
}
|
||||
|
||||
Driver* PlatformCocoaGL::createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept {
|
||||
Driver* PlatformCocoaGL::createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) {
|
||||
// NSOpenGLPFAColorSize: when unspecified, a format that matches the screen is preferred
|
||||
NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = {
|
||||
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
||||
|
||||
@@ -64,7 +64,7 @@ PlatformCocoaTouchGL::~PlatformCocoaTouchGL() noexcept {
|
||||
delete pImpl;
|
||||
}
|
||||
|
||||
Driver* PlatformCocoaTouchGL::createDriver(void* sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept {
|
||||
Driver* PlatformCocoaTouchGL::createDriver(void* sharedGLContext, const Platform::DriverConfig& driverConfig) {
|
||||
EAGLSharegroup* sharegroup = (__bridge EAGLSharegroup*) sharedGLContext;
|
||||
|
||||
EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3 sharegroup:sharegroup];
|
||||
|
||||
@@ -119,7 +119,7 @@ bool PlatformEGL::isOpenGL() const noexcept {
|
||||
|
||||
PlatformEGL::ExternalImageEGL::~ExternalImageEGL() = default;
|
||||
|
||||
Driver* PlatformEGL::createDriver(void* sharedContext, const DriverConfig& driverConfig) noexcept {
|
||||
Driver* PlatformEGL::createDriver(void* sharedContext, const DriverConfig& driverConfig) {
|
||||
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
assert_invariant(mEGLDisplay != EGL_NO_DISPLAY);
|
||||
|
||||
@@ -500,7 +500,7 @@ bool PlatformEGL::isMSAASwapChainSupported(uint32_t samples) const noexcept {
|
||||
}
|
||||
|
||||
Platform::SwapChain* PlatformEGL::createSwapChain(
|
||||
void* nativeWindow, uint64_t flags) noexcept {
|
||||
void* nativeWindow, uint64_t flags) {
|
||||
|
||||
Config attribs;
|
||||
|
||||
@@ -561,7 +561,7 @@ Platform::SwapChain* PlatformEGL::createSwapChain(
|
||||
}
|
||||
|
||||
Platform::SwapChain* PlatformEGL::createSwapChain(
|
||||
uint32_t width, uint32_t height, uint64_t flags) noexcept {
|
||||
uint32_t width, uint32_t height, uint64_t flags) {
|
||||
|
||||
Config attribs = {
|
||||
{ EGL_WIDTH, EGLint(width) },
|
||||
|
||||
@@ -198,7 +198,7 @@ void backend::PlatformEGLAndroid::preCommit() noexcept {
|
||||
}
|
||||
|
||||
Driver* PlatformEGLAndroid::createDriver(void* sharedContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept {
|
||||
const Platform::DriverConfig& driverConfig) {
|
||||
|
||||
// the refresh rate default value doesn't matter, we change it later
|
||||
int32_t const tid = gettid();
|
||||
|
||||
@@ -39,7 +39,7 @@ bool PlatformEGLHeadless::isOpenGL() const noexcept {
|
||||
}
|
||||
|
||||
backend::Driver* PlatformEGLHeadless::createDriver(void* sharedContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept {
|
||||
const Platform::DriverConfig& driverConfig) {
|
||||
EGLBoolean bindAPI = eglBindAPI(EGL_OPENGL_API);
|
||||
if (UTILS_UNLIKELY(!bindAPI)) {
|
||||
LOG(ERROR) << "eglBindAPI EGL_OPENGL_API failed";
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
// Function pointer types for X11 functions
|
||||
typedef Display* (* X11_OPEN_DISPLAY)(const char*);
|
||||
typedef Display* (* X11_CLOSE_DISPLAY)(Display*);
|
||||
typedef int (* X11_FREE)(void*);
|
||||
|
||||
// Function pointer types for GLX functions
|
||||
typedef void (* GLX_DESTROY_CONTEXT)(Display*, GLXContext);
|
||||
@@ -43,7 +44,7 @@ struct GLXFunctions {
|
||||
PFNGLXDESTROYPBUFFERPROC destroyPbuffer;
|
||||
PFNGLXMAKECONTEXTCURRENTPROC setCurrentContext;
|
||||
|
||||
/*
|
||||
/*
|
||||
When creating a shared GL context, we query the used
|
||||
GLX_FBCONFIG_ID to make sure our display framebuffer
|
||||
attributes match; otherwise making our context current
|
||||
@@ -52,7 +53,7 @@ struct GLXFunctions {
|
||||
*/
|
||||
PFNGLXQUERYCONTEXTPROC queryContext;
|
||||
|
||||
/*
|
||||
/*
|
||||
When creating a shared GL context, we select the matching
|
||||
GLXFBConfig that is used by the shared GL context. `getFBConfigs`
|
||||
will return all the available GLXFBConfigs.
|
||||
@@ -76,6 +77,7 @@ struct GLXFunctions {
|
||||
struct X11Functions {
|
||||
X11_OPEN_DISPLAY openDisplay;
|
||||
X11_CLOSE_DISPLAY closeDisplay;
|
||||
X11_FREE free;
|
||||
void* library;
|
||||
} g_x11;
|
||||
|
||||
@@ -121,6 +123,7 @@ static bool loadLibraries() {
|
||||
|
||||
g_x11.openDisplay = (X11_OPEN_DISPLAY)dlsym(g_x11.library, "XOpenDisplay");
|
||||
g_x11.closeDisplay = (X11_CLOSE_DISPLAY)dlsym(g_x11.library, "XCloseDisplay");
|
||||
g_x11.free = (X11_FREE)dlsym(g_x11.library, "XFree");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -129,7 +132,7 @@ namespace filament::backend {
|
||||
using namespace backend;
|
||||
|
||||
Driver* PlatformGLX::createDriver(void* sharedGLContext,
|
||||
const DriverConfig& driverConfig) noexcept {
|
||||
const DriverConfig& driverConfig) {
|
||||
loadLibraries();
|
||||
// Get the display device
|
||||
mGLXDisplay = g_x11.openDisplay(NULL);
|
||||
@@ -151,16 +154,13 @@ Driver* PlatformGLX::createDriver(void* sharedGLContext,
|
||||
|
||||
int numConfigs = 0;
|
||||
GLXFBConfig* fbConfigs = g_glx.getFbConfigs(mGLXDisplay, 0, &numConfigs);
|
||||
|
||||
if (fbConfigs == nullptr) {
|
||||
LOG(ERROR) << "Failed to get the available GLXFBConfigs.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int fbId = 0;
|
||||
int fbIndex = -1;
|
||||
|
||||
for (int i = 0; i < numConfigs; ++i) {
|
||||
int fbId = 0;
|
||||
r = g_glx.getFbConfigAttrib(mGLXDisplay, fbConfigs[i], GLX_FBCONFIG_ID, &fbId);
|
||||
if (r != 0) {
|
||||
LOG(ERROR) << "Failed to get GLX_FBCONFIG_ID for entry " << i << ".";
|
||||
@@ -168,17 +168,17 @@ Driver* PlatformGLX::createDriver(void* sharedGLContext,
|
||||
}
|
||||
|
||||
if (fbId == usedFbId) {
|
||||
fbIndex = i;
|
||||
mGLXConfig = fbConfigs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fbIndex < 0) {
|
||||
g_x11.free(fbConfigs);
|
||||
|
||||
if (!mGLXConfig) {
|
||||
LOG(ERROR) << "Failed to find an `GLXFBConfig` with the requested ID.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mGLXConfig = fbConfigs + fbIndex;
|
||||
} else {
|
||||
// Create a context
|
||||
static int attribs[] = {
|
||||
@@ -188,17 +188,17 @@ Driver* PlatformGLX::createDriver(void* sharedGLContext,
|
||||
};
|
||||
|
||||
int configCount = 0;
|
||||
mGLXConfig = g_glx.chooseFbConfig(mGLXDisplay, DefaultScreen(mGLXDisplay),
|
||||
GLXFBConfig* fbConfigs = g_glx.chooseFbConfig(mGLXDisplay, DefaultScreen(mGLXDisplay),
|
||||
attribs, &configCount);
|
||||
if (mGLXConfig == nullptr || configCount == 0) {
|
||||
if (fbConfigs == nullptr || configCount == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mGLXConfig = fbConfigs[0];
|
||||
g_x11.free(fbConfigs);
|
||||
}
|
||||
|
||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
|
||||
getProcAddress((GLubyte*)"glXCreateContextAttribsARB");
|
||||
|
||||
if (glXCreateContextAttribs == nullptr) {
|
||||
if (g_glx.createContext == nullptr) {
|
||||
LOG(INFO) << "Unable to retrieve function pointer for `glXCreateContextAttribs()`.";
|
||||
return nullptr;
|
||||
}
|
||||
@@ -209,7 +209,7 @@ Driver* PlatformGLX::createDriver(void* sharedGLContext,
|
||||
GL_NONE
|
||||
};
|
||||
|
||||
mGLXContext = g_glx.createContext(mGLXDisplay, mGLXConfig[0],
|
||||
mGLXContext = g_glx.createContext(mGLXDisplay, mGLXConfig,
|
||||
(GLXContext)sharedGLContext, True, contextAttribs);
|
||||
|
||||
int pbufferAttribs[] = {
|
||||
@@ -218,7 +218,7 @@ Driver* PlatformGLX::createDriver(void* sharedGLContext,
|
||||
GL_NONE
|
||||
};
|
||||
|
||||
mDummySurface = g_glx.createPbuffer(mGLXDisplay, mGLXConfig[0], pbufferAttribs);
|
||||
mDummySurface = g_glx.createPbuffer(mGLXDisplay, mGLXConfig, pbufferAttribs);
|
||||
g_glx.setCurrentContext(mGLXDisplay, mDummySurface, mDummySurface, mGLXContext);
|
||||
|
||||
int result = bluegl::bind();
|
||||
@@ -246,7 +246,7 @@ Platform::SwapChain* PlatformGLX::createSwapChain(
|
||||
GLX_PBUFFER_HEIGHT, int(height),
|
||||
GL_NONE
|
||||
};
|
||||
GLXPbuffer sur = g_glx.createPbuffer(mGLXDisplay, mGLXConfig[0], pbufferAttribs);
|
||||
GLXPbuffer sur = g_glx.createPbuffer(mGLXDisplay, mGLXConfig, pbufferAttribs);
|
||||
if (sur) {
|
||||
mPBuffers.push_back(sur);
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ private:
|
||||
}// anonymous namespace
|
||||
|
||||
Driver* PlatformOSMesa::createDriver(void* sharedGLContext,
|
||||
const DriverConfig& driverConfig) noexcept {
|
||||
const DriverConfig& driverConfig) {
|
||||
|
||||
OSMesaAPI* api = new OSMesaAPI();
|
||||
mOsMesaApi = api;
|
||||
|
||||
@@ -75,7 +75,7 @@ struct WGLSwapChain {
|
||||
static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs = nullptr;
|
||||
|
||||
Driver* PlatformWGL::createDriver(void* sharedGLContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept {
|
||||
const Platform::DriverConfig& driverConfig) {
|
||||
int result = 0;
|
||||
int pixelFormat = 0;
|
||||
DWORD dwError = 0;
|
||||
@@ -124,8 +124,6 @@ Driver* PlatformWGL::createDriver(void* sharedGLContext,
|
||||
(PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");
|
||||
|
||||
// try all versions down, from GL 4.5 to 4.1
|
||||
|
||||
|
||||
for (int minor = 5; minor >= 1; minor--) {
|
||||
mAttribs = {
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
|
||||
@@ -144,6 +142,18 @@ Driver* PlatformWGL::createDriver(void* sharedGLContext,
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Create shared contexts here for use by other threads. This is a Windows specific workaround
|
||||
// necessitated by the requirement that shared contexts must be initialized on the same thread
|
||||
// as the primary context. If more shared contexts are necessary, the constant
|
||||
// SHARED_CONTEXT_NUM must be updated.
|
||||
for (int i = 0; i < SHARED_CONTEXT_NUM; ++i) {
|
||||
HGLRC context = wglCreateContextAttribs(mWhdc, mContext, mAttribs.data());
|
||||
if (context) {
|
||||
mAdditionalContexts.push_back(context);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the temporary context
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(tempContext);
|
||||
tempContext = NULL;
|
||||
@@ -169,13 +179,17 @@ error:
|
||||
}
|
||||
|
||||
bool PlatformWGL::isExtraContextSupported() const noexcept {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlatformWGL::createContext(bool shared) {
|
||||
HGLRC context = wglCreateContextAttribs(mWhdc, shared ? mContext : nullptr, mAttribs.data());
|
||||
wglMakeCurrent(mWhdc, context);
|
||||
mAdditionalContexts.push_back(context);
|
||||
int nextIndex = mNextFreeSharedContextIndex.fetch_add(1, std::memory_order_relaxed);
|
||||
FILAMENT_CHECK_PRECONDITION(nextIndex < SHARED_CONTEXT_NUM)
|
||||
<< "Shared context index out of range. Increase SHARED_CONTEXT_NUM.";
|
||||
|
||||
HGLRC context = mAdditionalContexts[nextIndex];
|
||||
BOOL result = wglMakeCurrent(mWhdc, context);
|
||||
FILAMENT_CHECK_POSTCONDITION(result) << "Failed to make current.";
|
||||
}
|
||||
|
||||
void PlatformWGL::terminate() noexcept {
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace filament::backend {
|
||||
using namespace backend;
|
||||
|
||||
Driver* PlatformWebGL::createDriver(void* sharedGLContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept {
|
||||
const Platform::DriverConfig& driverConfig) {
|
||||
return OpenGLPlatform::createDefaultDriver(this, sharedGLContext, driverConfig);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/ImmutableCString.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#ifndef NDEBUG
|
||||
@@ -524,7 +525,7 @@ void VulkanDriver::finish(int dummy) {
|
||||
|
||||
void VulkanDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
|
||||
Handle<HwVertexBuffer> vbh, Handle<HwIndexBuffer> ibh,
|
||||
PrimitiveType pt, utils::CString&& tag) {
|
||||
PrimitiveType pt, utils::ImmutableCString&& tag) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto vb = resource_ptr<VulkanVertexBuffer>::cast(&mResourceManager, vbh);
|
||||
auto ib = resource_ptr<VulkanIndexBuffer>::cast(&mResourceManager, ibh);
|
||||
@@ -543,7 +544,7 @@ void VulkanDriver::destroyRenderPrimitive(Handle<HwRenderPrimitive> rph) {
|
||||
}
|
||||
|
||||
void VulkanDriver::createVertexBufferInfoR(Handle<HwVertexBufferInfo> vbih, uint8_t bufferCount,
|
||||
uint8_t attributeCount, AttributeArray attributes, utils::CString&& tag) {
|
||||
uint8_t attributeCount, AttributeArray attributes, utils::ImmutableCString&& tag) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto vbi = resource_ptr<VulkanVertexBufferInfo>::make(&mResourceManager, vbih, bufferCount,
|
||||
attributeCount, attributes);
|
||||
@@ -561,7 +562,7 @@ void VulkanDriver::destroyVertexBufferInfo(Handle<HwVertexBufferInfo> vbih) {
|
||||
}
|
||||
|
||||
void VulkanDriver::createVertexBufferR(Handle<HwVertexBuffer> vbh, uint32_t vertexCount,
|
||||
Handle<HwVertexBufferInfo> vbih, utils::CString&& tag) {
|
||||
Handle<HwVertexBufferInfo> vbih, utils::ImmutableCString&& tag) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto vbi = resource_ptr<VulkanVertexBufferInfo>::cast(&mResourceManager, vbih);
|
||||
auto vb = resource_ptr<VulkanVertexBuffer>::make(&mResourceManager, vbh, mContext, mStagePool,
|
||||
@@ -580,7 +581,7 @@ void VulkanDriver::destroyVertexBuffer(Handle<HwVertexBuffer> vbh) {
|
||||
}
|
||||
|
||||
void VulkanDriver::createIndexBufferR(Handle<HwIndexBuffer> ibh, ElementType elementType,
|
||||
uint32_t indexCount, BufferUsage usage, utils::CString&& tag) {
|
||||
uint32_t indexCount, BufferUsage usage, utils::ImmutableCString&& tag) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto elementSize = (uint8_t) getElementTypeSize(elementType);
|
||||
auto ib = resource_ptr<VulkanIndexBuffer>::make(&mResourceManager, ibh, mContext, mAllocator,
|
||||
@@ -599,7 +600,7 @@ void VulkanDriver::destroyIndexBuffer(Handle<HwIndexBuffer> ibh) {
|
||||
}
|
||||
|
||||
void VulkanDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byteCount,
|
||||
BufferObjectBinding bindingType, BufferUsage usage, utils::CString&& tag) {
|
||||
BufferObjectBinding bindingType, BufferUsage usage, utils::ImmutableCString&& tag) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto bo = resource_ptr<VulkanBufferObject>::make(&mResourceManager, boh, mContext, mAllocator,
|
||||
mStagePool, mBufferCache, byteCount, bindingType, usage);
|
||||
@@ -618,7 +619,7 @@ void VulkanDriver::destroyBufferObject(Handle<HwBufferObject> boh) {
|
||||
|
||||
void VulkanDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8_t levels,
|
||||
TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
|
||||
TextureUsage usage, utils::CString&& tag) {
|
||||
TextureUsage usage, utils::ImmutableCString&& tag) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
|
||||
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mResourceManager, &mCommands,
|
||||
@@ -635,7 +636,7 @@ void VulkanDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
|
||||
}
|
||||
|
||||
void VulkanDriver::createTextureViewR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
uint8_t baseLevel, uint8_t levelCount, utils::CString&& tag) {
|
||||
uint8_t baseLevel, uint8_t levelCount, utils::ImmutableCString&& tag) {
|
||||
auto src = resource_ptr<VulkanTexture>::cast(&mResourceManager, srch);
|
||||
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
|
||||
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, src, baseLevel,
|
||||
@@ -646,7 +647,7 @@ void VulkanDriver::createTextureViewR(Handle<HwTexture> th, Handle<HwTexture> sr
|
||||
|
||||
void VulkanDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
|
||||
backend::TextureSwizzle a, utils::CString&& tag) {
|
||||
backend::TextureSwizzle a, utils::ImmutableCString&& tag) {
|
||||
TextureSwizzle const swizzleArray[] = { r, g, b, a };
|
||||
VkComponentMapping const swizzle = fvkutils::getSwizzleMap(swizzleArray);
|
||||
auto src = resource_ptr<VulkanTexture>::cast(&mResourceManager, srch);
|
||||
@@ -658,7 +659,7 @@ void VulkanDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
|
||||
|
||||
void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th, backend::SamplerType target,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef externalImage, utils::CString&& tag) {
|
||||
Platform::ExternalImageHandleRef externalImage, utils::ImmutableCString&& tag) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto metadata = mPlatform->extractExternalImageMetadata(externalImage);
|
||||
|
||||
@@ -709,7 +710,7 @@ void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th, backend::S
|
||||
|
||||
void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::SamplerType target,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
void* externalImage, utils::CString&& tag) {
|
||||
void* externalImage, utils::ImmutableCString&& tag) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
assert_invariant(false && "Not supported in Vulkan backend");
|
||||
// not supported in this backend
|
||||
@@ -717,14 +718,14 @@ void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::Sa
|
||||
|
||||
void VulkanDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
|
||||
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
|
||||
void* image, uint32_t plane, utils::CString&& tag) {
|
||||
void* image, uint32_t plane, utils::ImmutableCString&& tag) {
|
||||
assert_invariant(false && "Not supported in Vulkan backend");
|
||||
}
|
||||
|
||||
void VulkanDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
|
||||
SamplerType target, uint8_t levels,
|
||||
TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,
|
||||
TextureUsage usage, utils::CString&& tag) {
|
||||
TextureUsage usage, utils::ImmutableCString&& tag) {
|
||||
// not supported in this backend
|
||||
assert_invariant(false && "Not supported in Vulkan backend");
|
||||
mResourceManager.associateHandle(th.getId(), std::move(tag));
|
||||
@@ -740,7 +741,7 @@ void VulkanDriver::destroyTexture(Handle<HwTexture> th) {
|
||||
mExternalImageManager.removeExternallySampledTexture(texture);
|
||||
}
|
||||
|
||||
void VulkanDriver::createProgramR(Handle<HwProgram> ph, Program&& program, utils::CString&& tag) {
|
||||
void VulkanDriver::createProgramR(Handle<HwProgram> ph, Program&& program, utils::ImmutableCString&& tag) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto vprogram = resource_ptr<VulkanProgram>::make(&mResourceManager, ph, mPlatform->getDevice(),
|
||||
program);
|
||||
@@ -756,7 +757,7 @@ void VulkanDriver::destroyProgram(Handle<HwProgram> ph) {
|
||||
vprogram.dec();
|
||||
}
|
||||
|
||||
void VulkanDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, utils::CString&& tag) {
|
||||
void VulkanDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, utils::ImmutableCString&& tag) {
|
||||
assert_invariant(mDefaultRenderTarget); // Default render target should already exist.
|
||||
|
||||
auto renderTarget = resource_ptr<VulkanRenderTarget>::make(&mResourceManager, rth,
|
||||
@@ -769,7 +770,7 @@ void VulkanDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, utils:
|
||||
void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
||||
TargetBufferFlags targets, uint32_t width, uint32_t height, uint8_t samples,
|
||||
uint8_t layerCount, MRT color, TargetBufferInfo depth, TargetBufferInfo stencil,
|
||||
utils::CString&& tag) {
|
||||
utils::ImmutableCString&& tag) {
|
||||
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
|
||||
@@ -846,7 +847,7 @@ void VulkanDriver::destroyRenderTarget(Handle<HwRenderTarget> rth) {
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanDriver::createFenceR(Handle<HwFence> fh, utils::CString&& tag) {
|
||||
void VulkanDriver::createFenceR(Handle<HwFence> fh, utils::ImmutableCString&& tag) {
|
||||
VulkanCommandBuffer* cmdbuf;
|
||||
if (mCurrentRenderPass.commandBuffer) {
|
||||
cmdbuf = mCurrentRenderPass.commandBuffer;
|
||||
@@ -861,7 +862,7 @@ void VulkanDriver::createFenceR(Handle<HwFence> fh, utils::CString&& tag) {
|
||||
mResourceManager.associateHandle(fh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::createSyncR(Handle<HwSync> sh, utils::CString&& tag) {
|
||||
void VulkanDriver::createSyncR(Handle<HwSync> sh, utils::ImmutableCString&& tag) {
|
||||
auto sync = resource_ptr<VulkanSync>::cast(&mResourceManager, sh);
|
||||
VkFence fence = VK_NULL_HANDLE;
|
||||
std::shared_ptr<VulkanCmdFence> fenceStatus;
|
||||
@@ -892,7 +893,7 @@ void VulkanDriver::createSyncR(Handle<HwSync> sh, utils::CString&& tag) {
|
||||
}
|
||||
|
||||
void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags,
|
||||
utils::CString&& tag) {
|
||||
utils::ImmutableCString&& tag) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
// Running gc() to guard against an edge case where the old swapchains need to have been
|
||||
// destroyed before the new swapchain can be created. Otherwise, we would fail
|
||||
@@ -921,7 +922,7 @@ void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
}
|
||||
|
||||
void VulkanDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t width,
|
||||
uint32_t height, uint64_t flags, utils::CString&& tag) {
|
||||
uint32_t height, uint64_t flags, utils::ImmutableCString&& tag) {
|
||||
if ((flags & backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0 && !isSRGBSwapChainSupported()) {
|
||||
FVK_LOGW << "sRGB swapchain requested, but Platform does not support it";
|
||||
flags = flags | ~(backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE);
|
||||
@@ -934,13 +935,13 @@ void VulkanDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t wi
|
||||
mResourceManager.associateHandle(sch.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, utils::CString&& tag) {
|
||||
void VulkanDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, utils::ImmutableCString&& tag) {
|
||||
// nothing to do, timer query was constructed in createTimerQueryS
|
||||
mResourceManager.associateHandle(tqh.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void VulkanDriver::createDescriptorSetLayoutR(Handle<HwDescriptorSetLayout> dslh,
|
||||
backend::DescriptorSetLayout&& info, utils::CString&& tag) {
|
||||
backend::DescriptorSetLayout&& info, utils::ImmutableCString&& tag) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto layout = mDescriptorSetLayoutCache.createLayout(dslh, std::move(info));
|
||||
layout.inc();
|
||||
@@ -948,7 +949,7 @@ void VulkanDriver::createDescriptorSetLayoutR(Handle<HwDescriptorSetLayout> dslh
|
||||
}
|
||||
|
||||
void VulkanDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
|
||||
Handle<HwDescriptorSetLayout> dslh, utils::CString&& tag) {
|
||||
Handle<HwDescriptorSetLayout> dslh, utils::ImmutableCString&& tag) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
fvkmemory::resource_ptr<VulkanDescriptorSetLayout> layout =
|
||||
fvkmemory::resource_ptr<VulkanDescriptorSetLayout>::cast(&mResourceManager, dslh);
|
||||
@@ -964,7 +965,7 @@ void VulkanDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
|
||||
|
||||
void VulkanDriver::mapBufferR(MemoryMappedBufferHandle mmbh,
|
||||
BufferObjectHandle boh, size_t offset,
|
||||
size_t size, MapBufferAccessFlags access, utils::CString&& tag) {
|
||||
size_t size, MapBufferAccessFlags access, utils::ImmutableCString&& tag) {
|
||||
FVK_SYSTRACE_SCOPE();
|
||||
auto mmb = resource_ptr<VulkanMemoryMappedBuffer>::make(&mResourceManager, mmbh,
|
||||
boh, offset, size, access);
|
||||
@@ -1131,11 +1132,11 @@ void VulkanDriver::destroyDescriptorSet(Handle<HwDescriptorSet> dsh) {
|
||||
}
|
||||
}
|
||||
|
||||
Handle<HwStream> VulkanDriver::createStreamNative(void* nativeStream, utils::CString tag) {
|
||||
Handle<HwStream> VulkanDriver::createStreamNative(void* nativeStream, utils::ImmutableCString tag) {
|
||||
return {};
|
||||
}
|
||||
|
||||
Handle<HwStream> VulkanDriver::createStreamAcquired(utils::CString tag) {
|
||||
Handle<HwStream> VulkanDriver::createStreamAcquired(utils::ImmutableCString tag) {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <private/backend/HandleAllocator.h>
|
||||
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/ImmutableCString.h>
|
||||
|
||||
namespace filament::backend::fvkmemory {
|
||||
|
||||
@@ -36,7 +37,7 @@ public:
|
||||
return mHandleAllocatorImpl.allocate<D>();
|
||||
}
|
||||
|
||||
inline void associateHandle(HandleBase::HandleId id, utils::CString&& tag) noexcept {
|
||||
inline void associateHandle(HandleBase::HandleId id, utils::ImmutableCString&& tag) noexcept {
|
||||
mHandleAllocatorImpl.associateTagToHandle(id, std::move(tag));
|
||||
}
|
||||
|
||||
|
||||
@@ -713,7 +713,7 @@ void VulkanPlatform::terminate() {
|
||||
|
||||
// This is the main entry point for context creation.
|
||||
Driver* VulkanPlatform::createDriver(void* sharedContext,
|
||||
Platform::DriverConfig const& driverConfig) noexcept {
|
||||
Platform::DriverConfig const& driverConfig) {
|
||||
// Load Vulkan entry points.
|
||||
FILAMENT_CHECK_POSTCONDITION(bluevk::initialize()) << "BlueVK is unable to load entry points.";
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace {
|
||||
|
||||
// This function transforms an OpSpecConstant instruction into just a OpConstant instruction.
|
||||
// Additionally, it will adjust the value of the constant as given by the program.
|
||||
void getTransformedConstantInst(SpecConstantValue* value, uint32_t* inst) {
|
||||
void getTransformedConstantInst(Program::SpecializationConstant const& value, uint32_t* inst) {
|
||||
|
||||
// The first word is the size of the instruction and the instruction type.
|
||||
// The second word is the type of the instruction.
|
||||
@@ -42,25 +42,15 @@ void getTransformedConstantInst(SpecConstantValue* value, uint32_t* inst) {
|
||||
constexpr size_t const OP = 0;
|
||||
constexpr size_t const VALUE = 3;
|
||||
|
||||
if (!value) {
|
||||
// If a specialization wasn't provided, just switch the opcode.
|
||||
uint32_t const op = inst[OP] & 0x0000FFFF;
|
||||
if (op == spv::Op::OpSpecConstantFalse) {
|
||||
inst[OP] = (3 << 16) | spv::Op::OpConstantFalse;
|
||||
} else if (op == spv::Op::OpSpecConstantTrue) {
|
||||
inst[OP] = (3 << 16) | spv::Op::OpConstantTrue;
|
||||
} else if (op == spv::Op::OpSpecConstant) {
|
||||
inst[OP] = (4 << 16) | spv::Op::OpConstant;
|
||||
}
|
||||
} else if (std::holds_alternative<bool>(*value)) {
|
||||
if (std::holds_alternative<bool>(value)) {
|
||||
inst[OP] = (3 << 16)
|
||||
| (std::get<bool>(*value) ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse);
|
||||
} else if (std::holds_alternative<float>(*value)) {
|
||||
float const fval = std::get<float>(*value);
|
||||
| (std::get<bool>(value) ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse);
|
||||
} else if (std::holds_alternative<float>(value)) {
|
||||
float const fval = std::get<float>(value);
|
||||
inst[OP] = (4 << 16) | spv::Op::OpConstant;
|
||||
inst[VALUE] = *reinterpret_cast<uint32_t const*>(&fval);
|
||||
} else {
|
||||
int const ival = std::get<int>(*value);
|
||||
int const ival = std::get<int>(value);
|
||||
inst[OP] = (4 << 16) | spv::Op::OpConstant;
|
||||
inst[VALUE] = *reinterpret_cast<uint32_t const*>(&ival);
|
||||
}
|
||||
@@ -72,15 +62,9 @@ void workaroundSpecConstant(Program::ShaderBlob const& blob,
|
||||
utils::FixedCapacityVector<Program::SpecializationConstant> const& specConstants,
|
||||
std::vector<uint32_t>& output) {
|
||||
using WordMap = std::unordered_map<uint32_t, uint32_t>;
|
||||
using SpecValueMap = std::unordered_map<uint32_t, SpecConstantValue>;
|
||||
constexpr size_t HEADER_SIZE = 5;
|
||||
|
||||
WordMap varToIdMap;
|
||||
SpecValueMap idToValue;
|
||||
|
||||
for (auto spec: specConstants) {
|
||||
idToValue[spec.id] = spec.value;
|
||||
}
|
||||
|
||||
// The follow loop will iterate through all the instructions and look for instructions of the
|
||||
// form:
|
||||
@@ -116,9 +100,7 @@ void workaroundSpecConstant(Program::ShaderBlob const& blob,
|
||||
assert_invariant(idItr != varToIdMap.end() &&
|
||||
"Cannot find variable previously decorated with SpecId");
|
||||
|
||||
auto valItr = idToValue.find(idItr->second);
|
||||
|
||||
SpecConstantValue* val = (valItr != idToValue.end()) ? &valItr->second : nullptr;
|
||||
auto const& val = specConstants[idItr->second];
|
||||
std::memcpy(&outputData[outputCursor], &data[cursor], wordCount * 4);
|
||||
getTransformedConstantInst(val, &outputData[outputCursor]);
|
||||
outputCursor += wordCount;
|
||||
|
||||
@@ -21,13 +21,10 @@
|
||||
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
namespace filament::backend::fvkutils {
|
||||
|
||||
using SpecConstantValue = Program::SpecializationConstant::Type;
|
||||
|
||||
// For certain drivers, using spec constant can lead to compile errors [1] or undesirable behaviors
|
||||
// [2]. In those instances, we simply change the spirv and set them to constants.
|
||||
//
|
||||
@@ -44,7 +41,7 @@ void workaroundSpecConstant(Program::ShaderBlob const& blob,
|
||||
std::vector<uint32_t>& output);
|
||||
|
||||
// bindings for UBO, samplers, input attachment
|
||||
// This is no longer needed after the descriptor set refactor, but the code is good for reference.
|
||||
// This is no longer needed after the descriptor set refactor, but the code is good for reference.
|
||||
// std::tuple<uint32_t, uint32_t, uint32_t> getProgramBindings(Program::ShaderBlob const& blob);
|
||||
|
||||
} // namespace filament::backend::fvkutils
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include <math/mat3.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/ImmutableCString.h>
|
||||
#include <utils/Hash.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/compiler.h>
|
||||
@@ -451,7 +452,7 @@ Handle<HwTexture> WebGPUDriver::createTextureExternalImagePlaneS() noexcept {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
const uint64_t flags, utils::CString&& tag) {
|
||||
const uint64_t flags, utils::ImmutableCString&& tag) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
|
||||
// TODO: support MSAA swapchain
|
||||
@@ -481,7 +482,7 @@ void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
}
|
||||
|
||||
void WebGPUDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t width,
|
||||
uint32_t height, uint64_t flags, utils::CString&& tag) {
|
||||
uint32_t height, uint64_t flags, utils::ImmutableCString&& tag) {
|
||||
wgpu::Extent2D extent = { .width = width, .height = height };
|
||||
mSwapChain = constructHandle<WebGPUSwapChain>(sch, extent, mAdapter,
|
||||
mDevice, flags);
|
||||
@@ -494,7 +495,7 @@ void WebGPUDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t wi
|
||||
|
||||
void WebGPUDriver::createVertexBufferInfoR(Handle<HwVertexBufferInfo> vertexBufferInfoHandle,
|
||||
const uint8_t bufferCount, const uint8_t attributeCount, const AttributeArray attributes,
|
||||
utils::CString&& tag) {
|
||||
utils::ImmutableCString&& tag) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
constructHandle<WebGPUVertexBufferInfo>(vertexBufferInfoHandle, bufferCount, attributeCount,
|
||||
attributes, mDeviceLimits);
|
||||
@@ -503,7 +504,7 @@ void WebGPUDriver::createVertexBufferInfoR(Handle<HwVertexBufferInfo> vertexBuff
|
||||
|
||||
void WebGPUDriver::createVertexBufferR(Handle<HwVertexBuffer> vertexBufferHandle,
|
||||
const uint32_t vertexCount, Handle<HwVertexBufferInfo> vertexBufferInfoHandle,
|
||||
utils::CString&& tag) {
|
||||
utils::ImmutableCString&& tag) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
const auto vertexBufferInfo = handleCast<WebGPUVertexBufferInfo>(vertexBufferInfoHandle);
|
||||
constructHandle<WebGPUVertexBuffer>(vertexBufferHandle, vertexCount,
|
||||
@@ -513,7 +514,7 @@ void WebGPUDriver::createVertexBufferR(Handle<HwVertexBuffer> vertexBufferHandle
|
||||
|
||||
void WebGPUDriver::createIndexBufferR(Handle<HwIndexBuffer> indexBufferHandle,
|
||||
const ElementType elementType, const uint32_t indexCount, const BufferUsage usage,
|
||||
utils::CString&& tag) {
|
||||
utils::ImmutableCString&& tag) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
const auto elementSize = static_cast<uint8_t>(getElementTypeSize(elementType));
|
||||
constructHandle<WebGPUIndexBuffer>(indexBufferHandle, mDevice, elementSize, indexCount);
|
||||
@@ -522,7 +523,7 @@ void WebGPUDriver::createIndexBufferR(Handle<HwIndexBuffer> indexBufferHandle,
|
||||
|
||||
void WebGPUDriver::createBufferObjectR(Handle<HwBufferObject> bufferObjectHandle,
|
||||
const uint32_t byteCount, const BufferObjectBinding bindingType, const BufferUsage usage,
|
||||
utils::CString&& tag) {
|
||||
utils::ImmutableCString&& tag) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
constructHandle<WebGPUBufferObject>(bufferObjectHandle, mDevice, bindingType, byteCount);
|
||||
setDebugTag(bufferObjectHandle.getId(), std::move(tag));
|
||||
@@ -531,7 +532,7 @@ void WebGPUDriver::createBufferObjectR(Handle<HwBufferObject> bufferObjectHandle
|
||||
void WebGPUDriver::createTextureR(Handle<HwTexture> textureHandle, const SamplerType target,
|
||||
const uint8_t levels, const TextureFormat format, const uint8_t samples,
|
||||
const uint32_t width, const uint32_t height, const uint32_t depth,
|
||||
const TextureUsage usage, utils::CString&& tag) {
|
||||
const TextureUsage usage, utils::ImmutableCString&& tag) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
constructHandle<WebGPUTexture>(textureHandle, target, levels, format, samples, width, height,
|
||||
depth, usage, mDevice);
|
||||
@@ -540,7 +541,7 @@ void WebGPUDriver::createTextureR(Handle<HwTexture> textureHandle, const Sampler
|
||||
|
||||
void WebGPUDriver::createTextureViewR(Handle<HwTexture> textureHandle,
|
||||
Handle<HwTexture> sourceTextureHandle, const uint8_t baseLevel, const uint8_t levelCount,
|
||||
utils::CString&& tag) {
|
||||
utils::ImmutableCString&& tag) {
|
||||
auto source = handleCast<WebGPUTexture>(sourceTextureHandle);
|
||||
|
||||
constructHandle<WebGPUTexture>(textureHandle, source, baseLevel, levelCount);
|
||||
@@ -551,7 +552,7 @@ void WebGPUDriver::createTextureViewR(Handle<HwTexture> textureHandle,
|
||||
void WebGPUDriver::createTextureViewSwizzleR(Handle<HwTexture> textureHandle,
|
||||
Handle<HwTexture> sourceTextureHandle, const backend::TextureSwizzle r,
|
||||
const backend::TextureSwizzle g, const backend::TextureSwizzle b,
|
||||
const backend::TextureSwizzle a, utils::CString&& tag) {
|
||||
const backend::TextureSwizzle a, utils::ImmutableCString&& tag) {
|
||||
|
||||
if (!isTextureSwizzleSupported()) {
|
||||
FWGPU_LOGW << "WebGPUDriver::createTextureViewSwizzleR called while texture swizzling is "
|
||||
@@ -578,7 +579,7 @@ void WebGPUDriver::createTextureViewSwizzleR(Handle<HwTexture> textureHandle,
|
||||
void WebGPUDriver::createTextureExternalImage2R(Handle<HwTexture> textureHandle,
|
||||
const backend::SamplerType target, const backend::TextureFormat format,
|
||||
const uint32_t width, const uint32_t height, const backend::TextureUsage usage,
|
||||
Platform::ExternalImageHandleRef externalImage, utils::CString&& tag) {
|
||||
Platform::ExternalImageHandleRef externalImage, utils::ImmutableCString&& tag) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
PANIC_POSTCONDITION("External WebGPU Texture is not supported");
|
||||
}
|
||||
@@ -586,27 +587,27 @@ void WebGPUDriver::createTextureExternalImage2R(Handle<HwTexture> textureHandle,
|
||||
void WebGPUDriver::createTextureExternalImageR(Handle<HwTexture> textureHandle,
|
||||
const backend::SamplerType target, const backend::TextureFormat format,
|
||||
const uint32_t width, const uint32_t height, const backend::TextureUsage usage,
|
||||
void* externalImage, utils::CString&& tag) {
|
||||
void* externalImage, utils::ImmutableCString&& tag) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
PANIC_POSTCONDITION("External WebGPU Texture is not supported");
|
||||
}
|
||||
|
||||
void WebGPUDriver::createTextureExternalImagePlaneR(Handle<HwTexture> textureHandle,
|
||||
const backend::TextureFormat format, const uint32_t width, const uint32_t height,
|
||||
const backend::TextureUsage usage, void* image, const uint32_t plane, utils::CString&& tag) {
|
||||
const backend::TextureUsage usage, void* image, const uint32_t plane, utils::ImmutableCString&& tag) {
|
||||
PANIC_POSTCONDITION("External WebGPU Texture is not supported");
|
||||
}
|
||||
|
||||
void WebGPUDriver::importTextureR(Handle<HwTexture> textureHandle, const intptr_t id,
|
||||
const SamplerType target, const uint8_t levels, const TextureFormat format,
|
||||
const uint8_t samples, const uint32_t width, const uint32_t height, const uint32_t depth,
|
||||
const TextureUsage usage, utils::CString&& tag) {
|
||||
const TextureUsage usage, utils::ImmutableCString&& tag) {
|
||||
PANIC_POSTCONDITION("Import WebGPU Texture is not supported");
|
||||
}
|
||||
|
||||
void WebGPUDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> renderPrimitiveHandle,
|
||||
Handle<HwVertexBuffer> vertexBufferHandle, Handle<HwIndexBuffer> indexBufferHandle,
|
||||
const PrimitiveType primitiveType, utils::CString&& tag) {
|
||||
const PrimitiveType primitiveType, utils::ImmutableCString&& tag) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
assert_invariant(mDevice);
|
||||
const auto renderPrimitive = constructHandle<WebGPURenderPrimitive>(renderPrimitiveHandle);
|
||||
@@ -619,14 +620,14 @@ void WebGPUDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> renderPrimit
|
||||
}
|
||||
|
||||
void WebGPUDriver::createProgramR(Handle<HwProgram> programHandle, Program&& program,
|
||||
utils::CString&& tag) {
|
||||
utils::ImmutableCString&& tag) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
constructHandle<WebGPUProgram>(programHandle, mDevice, program);
|
||||
setDebugTag(programHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> renderTargetHandle,
|
||||
utils::CString&& tag) {
|
||||
utils::ImmutableCString&& tag) {
|
||||
assert_invariant(!mDefaultRenderTarget);
|
||||
mDefaultRenderTarget = constructHandle<WebGPURenderTarget>(renderTargetHandle);
|
||||
assert_invariant(mDefaultRenderTarget);
|
||||
@@ -639,7 +640,7 @@ void WebGPUDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> renderTarge
|
||||
void WebGPUDriver::createRenderTargetR(Handle<HwRenderTarget> renderTargetHandle,
|
||||
const TargetBufferFlags targetFlags, const uint32_t width, const uint32_t height,
|
||||
const uint8_t samples, const uint8_t layerCount, const MRT color,
|
||||
const TargetBufferInfo depth, const TargetBufferInfo stencil, utils::CString&& tag) {
|
||||
const TargetBufferInfo depth, const TargetBufferInfo stencil, utils::ImmutableCString&& tag) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
constructHandle<WebGPURenderTarget>(
|
||||
renderTargetHandle, width, height, samples, layerCount, color, depth, stencil,
|
||||
@@ -651,7 +652,7 @@ void WebGPUDriver::createRenderTargetR(Handle<HwRenderTarget> renderTargetHandle
|
||||
setDebugTag(renderTargetHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createFenceR(Handle<HwFence> fenceHandle, utils::CString&& tag) {
|
||||
void WebGPUDriver::createFenceR(Handle<HwFence> fenceHandle, utils::ImmutableCString&& tag) {
|
||||
// The handle is constructed synchronously in createFenceS.
|
||||
const auto fence = handleCast<WebGPUFence>(fenceHandle);
|
||||
assert_invariant(mQueue);
|
||||
@@ -659,24 +660,24 @@ void WebGPUDriver::createFenceR(Handle<HwFence> fenceHandle, utils::CString&& ta
|
||||
setDebugTag(fenceHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createSyncR(Handle<HwSync> syncHandle, utils::CString&& tag) {
|
||||
void WebGPUDriver::createSyncR(Handle<HwSync> syncHandle, utils::ImmutableCString&& tag) {
|
||||
// TODO: Ensure sync is active, and then invoke and clear all pending
|
||||
// callbacks.
|
||||
setDebugTag(syncHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, utils::CString&& tag) {}
|
||||
void WebGPUDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, utils::ImmutableCString&& tag) {}
|
||||
|
||||
void WebGPUDriver::createDescriptorSetLayoutR(
|
||||
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle,
|
||||
backend::DescriptorSetLayout&& info, utils::CString&& tag) {
|
||||
backend::DescriptorSetLayout&& info, utils::ImmutableCString&& tag) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
constructHandle<WebGPUDescriptorSetLayout>(descriptorSetLayoutHandle, std::move(info), mDevice);
|
||||
setDebugTag(descriptorSetLayoutHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
void WebGPUDriver::createDescriptorSetR(Handle<HwDescriptorSet> descriptorSetHandle,
|
||||
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle, utils::CString&& tag) {
|
||||
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle, utils::ImmutableCString&& tag) {
|
||||
FWGPU_SYSTRACE_SCOPE();
|
||||
auto layout = handleCast<WebGPUDescriptorSetLayout>(descriptorSetLayoutHandle);
|
||||
constructHandle<WebGPUDescriptorSet>(descriptorSetHandle, layout->getLayout(),
|
||||
@@ -684,13 +685,13 @@ void WebGPUDriver::createDescriptorSetR(Handle<HwDescriptorSet> descriptorSetHan
|
||||
setDebugTag(descriptorSetHandle.getId(), std::move(tag));
|
||||
}
|
||||
|
||||
Handle<HwStream> WebGPUDriver::createStreamNative(void* nativeStream, utils::CString tag) {
|
||||
Handle<HwStream> WebGPUDriver::createStreamNative(void* nativeStream, utils::ImmutableCString tag) {
|
||||
return {
|
||||
//todo
|
||||
};
|
||||
}
|
||||
|
||||
Handle<HwStream> WebGPUDriver::createStreamAcquired(utils::CString tag) {
|
||||
Handle<HwStream> WebGPUDriver::createStreamAcquired(utils::ImmutableCString tag) {
|
||||
return {
|
||||
//todo
|
||||
};
|
||||
@@ -2100,7 +2101,7 @@ void WebGPUDriver::bindDescriptorSet(Handle<HwDescriptorSet> descriptorSetHandle
|
||||
.offsets = std::move(offsets) };
|
||||
}
|
||||
|
||||
void WebGPUDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString&& tag) {
|
||||
void WebGPUDriver::setDebugTag(HandleBase::HandleId handleId, utils::ImmutableCString&& tag) {
|
||||
//todo
|
||||
}
|
||||
|
||||
@@ -2223,7 +2224,7 @@ MemoryMappedBufferHandle WebGPUDriver::mapBufferS() noexcept {
|
||||
|
||||
void WebGPUDriver::mapBufferR(MemoryMappedBufferHandle mmbh,
|
||||
BufferObjectHandle boh, size_t offset,
|
||||
size_t size, MapBufferAccessFlags access, utils::CString&& tag) {
|
||||
size_t size, MapBufferAccessFlags access, utils::ImmutableCString&& tag) {
|
||||
// TODO: MetalDriver::mapBufferR
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ private:
|
||||
ShaderLanguage preferredLanguage) const noexcept final;
|
||||
[[nodiscard]] wgpu::Sampler makeSampler(SamplerParams const& params);
|
||||
[[nodiscard]] static wgpu::AddressMode fWrapModeToWAddressMode(const filament::backend::SamplerWrapMode& fUsage);
|
||||
void setDebugTag(HandleBase::HandleId handleId, utils::CString&& tag);
|
||||
void setDebugTag(HandleBase::HandleId handleId, utils::ImmutableCString&& tag);
|
||||
|
||||
// The platform (e.g. OS) specific aspects of the WebGPU backend are strictly only
|
||||
// handled in the WebGPUPlatform.
|
||||
|
||||
@@ -57,8 +57,7 @@ namespace {
|
||||
*/
|
||||
[[nodiscard]] std::string replaceSpecConstants(std::string_view shaderLabel,
|
||||
std::string_view shaderSource,
|
||||
std::unordered_map<uint32_t, std::variant<int32_t, float, bool>> const&
|
||||
specConstants) {
|
||||
utils::FixedCapacityVector<Program::SpecializationConstant> const& specConstants) {
|
||||
// this function is not expected to be called at all if no spec constants are to be replaced
|
||||
assert_invariant(!specConstants.empty());
|
||||
static constexpr std::string_view specConstantPrefix = "FILAMENT_SPEC_CONST_";
|
||||
@@ -120,16 +119,7 @@ namespace {
|
||||
constantId = static_cast<int>(tempConstantId);
|
||||
}
|
||||
}
|
||||
const auto newValueItr = specConstants.find(static_cast<uint32_t>(constantId));
|
||||
if (newValueItr == specConstants.end()) {
|
||||
// The constant is not being overridden, so keep the default value.
|
||||
processedShaderSource << std::string_view(sourceData + pos,
|
||||
posEndOfStatement + 1 - pos);
|
||||
pos = posEndOfStatement + 1;
|
||||
continue;
|
||||
}
|
||||
// need to override the constant...
|
||||
const std::variant<int32_t, float, bool> newValue = newValueItr->second;
|
||||
const std::variant<int32_t, float, bool> newValue = specConstants[constantId];
|
||||
// stream up to the equal sign...
|
||||
processedShaderSource << std::string_view(sourceData + pos, posOfEqual + 1 - pos);
|
||||
// stream the new value...
|
||||
@@ -156,15 +146,13 @@ namespace {
|
||||
* @param program The "program" to compile/create the shader, which includes the shader source
|
||||
* @param stage The stage (e.g. vertex, fragment, etc.) to create the shader module
|
||||
* @param specConstants Override constants to apply when creating/compiling the shader module.
|
||||
* The expectation is that this is consistent with the program's spec constants, just in a map
|
||||
* format for quick access
|
||||
* @return the proper WebGPU shader module compiled/created from the input parameters. This might
|
||||
* wrap a null handle if the shader is not present (if the shader source is empty), such as
|
||||
* a missing fragment or compute shader.
|
||||
*/
|
||||
[[nodiscard]] wgpu::ShaderModule createShaderModule(wgpu::Device const& device,
|
||||
Program const& program, const ShaderStage stage,
|
||||
std::unordered_map<uint32_t, std::variant<int32_t, float, bool>> const& specConstants) {
|
||||
utils::FixedCapacityVector<Program::SpecializationConstant> const& specConstants) {
|
||||
const char* const programName = program.getName().c_str_safe();
|
||||
std::array<utils::FixedCapacityVector<uint8_t>, Program::SHADER_TYPE_COUNT> const&
|
||||
shaderSource = program.getShadersSource();
|
||||
@@ -260,26 +248,12 @@ namespace {
|
||||
return shaderModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to convert the array structure of constants to a map indexed by constant
|
||||
* id.
|
||||
* @param specConstants Original spec constant structure (immutable)
|
||||
* @param outConstantById Output map of spec constants indexed by constant id
|
||||
*/
|
||||
void toMap(utils::FixedCapacityVector<Program::SpecializationConstant> const& specConstants,
|
||||
std::unordered_map<uint32_t, std::variant<int32_t, float, bool>>& outConstantById) {
|
||||
outConstantById.reserve(specConstants.size());
|
||||
for (auto const& specConstant: specConstants) {
|
||||
outConstantById.emplace(specConstant.id, specConstant.value);
|
||||
}
|
||||
}
|
||||
|
||||
}// namespace
|
||||
|
||||
WebGPUProgram::WebGPUProgram(wgpu::Device const& device, Program const& program)
|
||||
: HwProgram{ program.getName() } {
|
||||
std::unordered_map<uint32_t, std::variant<int32_t, float, bool>> specConstants;
|
||||
toMap(program.getSpecializationConstants(), specConstants);
|
||||
utils::FixedCapacityVector<Program::SpecializationConstant> const& specConstants =
|
||||
program.getSpecializationConstants();
|
||||
// TODO: Consider creating/compiling these shaders in parallel.
|
||||
vertexShaderModule = createShaderModule(device, program, ShaderStage::VERTEX, specConstants);
|
||||
fragmentShaderModule =
|
||||
|
||||
@@ -694,7 +694,7 @@ wgpu::Device WebGPUPlatform::requestDevice(wgpu::Adapter const& adapter) {
|
||||
}
|
||||
|
||||
Driver* WebGPUPlatform::createDriver(void* sharedContext,
|
||||
const Platform::DriverConfig& driverConfig) noexcept {
|
||||
const Platform::DriverConfig& driverConfig) {
|
||||
if (sharedContext) {
|
||||
FWGPU_LOGW << "sharedContext is ignored/unused in the WebGPU backend. A non-null "
|
||||
"sharedContext was provided, but it will be ignored.";
|
||||
|
||||
@@ -176,7 +176,7 @@ protected:
|
||||
// Map the buffer with a specific offset.
|
||||
MemoryMappedBufferHandle const memoryMappedBuffer =
|
||||
api.mapBuffer(bufferObject, mapOffset, vertexDataSize + copyOffset,
|
||||
MapBufferAccessFlags::WRITE_BIT, utils::CString{ screenshotName });
|
||||
MapBufferAccessFlags::WRITE_BIT, utils::ImmutableCString{ screenshotName });
|
||||
|
||||
copyData(vertices.data(), vertexDataSize, copyOffset, memoryMappedBuffer, callbackExecuted);
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/PrivateImplementation.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/ImmutableCString.h>
|
||||
#include <utils/StaticString.h>
|
||||
|
||||
#include <stddef.h>
|
||||
@@ -57,7 +57,7 @@ template<typename T>
|
||||
using BuilderBase = utils::PrivateImplementation<T>;
|
||||
|
||||
// This needs to be public because it is used in the following template.
|
||||
UTILS_PUBLIC void builderMakeName(utils::CString& outName, const char* name, size_t len) noexcept;
|
||||
UTILS_PUBLIC void builderMakeName(utils::ImmutableCString& outName, const char* name, size_t len) noexcept;
|
||||
|
||||
template <typename Builder>
|
||||
class UTILS_PUBLIC BuilderNameMixin {
|
||||
@@ -73,18 +73,18 @@ public:
|
||||
return static_cast<Builder&>(*this);
|
||||
}
|
||||
|
||||
utils::CString const& getName() const noexcept { return mName; }
|
||||
utils::ImmutableCString const& getName() const noexcept { return mName; }
|
||||
|
||||
utils::CString const& getNameOrDefault() const noexcept {
|
||||
utils::ImmutableCString const& getNameOrDefault() const noexcept {
|
||||
if (const auto& name = getName(); !name.empty()) {
|
||||
return name;
|
||||
}
|
||||
static const utils::CString sDefaultName = "(none)";
|
||||
static const utils::ImmutableCString sDefaultName = "(none)";
|
||||
return sDefaultName;
|
||||
}
|
||||
|
||||
private:
|
||||
utils::CString mName;
|
||||
utils::ImmutableCString mName;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -297,7 +297,7 @@ public:
|
||||
Builder& priority(uint8_t priority) noexcept;
|
||||
|
||||
/**
|
||||
* Set the channel this renderable is associated to. There can be 4 channels.
|
||||
* Set the channel this renderable is associated to. There can be 8 channels.
|
||||
* All renderables in a given channel are rendered together, regardless of anything else.
|
||||
* They are sorted as usual within a channel.
|
||||
* Channels work similarly to priorities, except that they enforce the strongest ordering.
|
||||
@@ -305,7 +305,7 @@ public:
|
||||
* Channels 0 and 1 may not have render primitives using a material with `refractionType`
|
||||
* set to `screenspace`.
|
||||
*
|
||||
* @param channel clamped to the range [0..3], defaults to 2.
|
||||
* @param channel clamped to the range [0..7], defaults to 2.
|
||||
*
|
||||
* @return Builder reference for chaining calls.
|
||||
*
|
||||
|
||||
@@ -218,6 +218,22 @@ public:
|
||||
return const_cast<View*>(this)->getCamera();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets whether a channel must clear the depth buffer before all primitives are rendered.
|
||||
* Channel depth clear is off by default for all channels.
|
||||
* This is orthogonal to Renderer::setClearOptions().
|
||||
* @param channel between 0 and 7
|
||||
* @param enabled true to enable clear, false to disable
|
||||
*/
|
||||
void setChannelDepthClearEnabled(uint8_t channel, bool enabled) noexcept;
|
||||
|
||||
/**
|
||||
* @param channel between 0 and 7
|
||||
* @return true if this channel has depth clear enabled.
|
||||
*/
|
||||
bool isChannelDepthClearEnabled(uint8_t channel) const noexcept;
|
||||
|
||||
/**
|
||||
* Sets the blending mode used to draw the view into the SwapChain.
|
||||
*
|
||||
|
||||
@@ -16,16 +16,18 @@
|
||||
|
||||
#include <filament/FilamentAPI.h>
|
||||
|
||||
#include <utils/ImmutableCString.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace filament {
|
||||
|
||||
void builderMakeName(utils::CString& outName, const char* name, size_t const len) noexcept {
|
||||
void builderMakeName(utils::ImmutableCString& outName, const char* name, size_t const len) noexcept {
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
size_t const length = std::min(len, size_t { 128u });
|
||||
outName = utils::CString(name, length);
|
||||
outName = utils::ImmutableCString(name, length);
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
+13
-11
@@ -107,18 +107,19 @@ void FrameInfoManager::beginFrame(DriverApi& driver, Config const& config, uint3
|
||||
// read the pending timer queries until we find one that's not ready
|
||||
}
|
||||
|
||||
#if 0
|
||||
// keep this just for debugging
|
||||
if constexpr (false) {
|
||||
using namespace utils;
|
||||
auto h = getFrameInfoHistory(1);
|
||||
if (!h.empty()) {
|
||||
DLOG(INFO) << frameId << ": " << h[0].frameId << " (" << frameId - h[0].frameId << ")"
|
||||
<< ", Dm=" << h[0].endFrame - h[0].beginFrame
|
||||
<< ", L =" << h[0].backendBeginFrame - h[0].beginFrame
|
||||
<< ", Db=" << h[0].backendEndFrame - h[0].backendBeginFrame
|
||||
<< ", T =" << h[0].frameTime;
|
||||
}
|
||||
using namespace utils;
|
||||
auto h = getFrameInfoHistory(1); // this can throw
|
||||
if (!h.empty()) {
|
||||
DLOG(INFO) << frameId << ": " << h[0].frameId << " (" << frameId - h[0].frameId <<
|
||||
")"
|
||||
<< ", Dm=" << h[0].endFrame - h[0].beginFrame
|
||||
<< ", L =" << h[0].backendBeginFrame - h[0].beginFrame
|
||||
<< ", Db=" << h[0].backendEndFrame - h[0].backendBeginFrame
|
||||
<< ", T =" << h[0].frameTime;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FrameInfoManager::endFrame(DriverApi& driver) noexcept {
|
||||
@@ -172,7 +173,7 @@ void FrameInfoManager::denoiseFrameTime(FrameHistoryQueue& history, Config const
|
||||
}
|
||||
|
||||
FixedCapacityVector<Renderer::FrameInfo> FrameInfoManager::getFrameInfoHistory(
|
||||
size_t historySize) const noexcept {
|
||||
size_t historySize) const {
|
||||
auto result = FixedCapacityVector<Renderer::FrameInfo>::with_capacity(MAX_FRAMETIME_HISTORY);
|
||||
auto const& history = mFrameTimeHistory;
|
||||
size_t i = 0;
|
||||
@@ -188,6 +189,7 @@ FixedCapacityVector<Renderer::FrameInfo> FrameInfoManager::getFrameInfoHistory(
|
||||
for (; i < c && historySize; ++i, --historySize) {
|
||||
auto const& entry = history[i];
|
||||
using namespace std::chrono;
|
||||
// can't throw by construction
|
||||
result.push_back({
|
||||
entry.frameId,
|
||||
duration_cast<nanoseconds>(entry.frameTime).count(),
|
||||
|
||||
+66
-11
@@ -51,14 +51,36 @@ struct FrameInfo {
|
||||
struct FrameInfoImpl : public details::FrameInfo {
|
||||
using clock = std::chrono::steady_clock;
|
||||
using time_point = clock::time_point;
|
||||
uint32_t const frameId;
|
||||
uint32_t frameId;
|
||||
time_point beginFrame; // main thread beginFrame time
|
||||
time_point endFrame; // main thread endFrame time
|
||||
time_point backendBeginFrame; // backend thread beginFrame time (makeCurrent time)
|
||||
time_point backendEndFrame; // backend thread endFrame time (present time)
|
||||
std::atomic_bool ready{}; // true once backend thread has populated its data
|
||||
explicit FrameInfoImpl(uint32_t const frameId) noexcept
|
||||
: frameId(frameId) {
|
||||
explicit FrameInfoImpl(uint32_t const id) noexcept
|
||||
: frameId(id) {
|
||||
}
|
||||
|
||||
FrameInfoImpl(FrameInfoImpl&& rhs) noexcept :
|
||||
details::FrameInfo(rhs),
|
||||
frameId(rhs.frameId),
|
||||
beginFrame(rhs.beginFrame),
|
||||
endFrame(rhs.endFrame),
|
||||
backendBeginFrame(rhs.backendBeginFrame),
|
||||
backendEndFrame(rhs.backendEndFrame),
|
||||
ready(rhs.ready.load())
|
||||
{
|
||||
}
|
||||
|
||||
FrameInfoImpl& operator=(FrameInfoImpl&& rhs) noexcept {
|
||||
details::FrameInfo::operator=(rhs);
|
||||
frameId = rhs.frameId;
|
||||
beginFrame = rhs.beginFrame;
|
||||
endFrame = rhs.endFrame;
|
||||
backendBeginFrame = rhs.backendBeginFrame;
|
||||
backendEndFrame = rhs.backendEndFrame;
|
||||
ready.store(rhs.ready.load());
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -69,11 +91,43 @@ public:
|
||||
using reference = value_type&;
|
||||
using const_reference = value_type const&;
|
||||
|
||||
size_t capacity() const {
|
||||
CircularQueue() = default;
|
||||
|
||||
~CircularQueue() {
|
||||
if constexpr (!std::is_trivially_destructible_v<T>) {
|
||||
for (size_t i = 0, c = mSize; i < c; ++i) {
|
||||
size_t const index = (mFront + CAPACITY - i) % CAPACITY;
|
||||
std::destroy_at(std::launder(reinterpret_cast<T*>(&mStorage[index])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CircularQueue(const CircularQueue&) = delete;
|
||||
CircularQueue& operator=(const CircularQueue&) = delete;
|
||||
|
||||
CircularQueue(CircularQueue&& other) noexcept {
|
||||
for (size_t i = 0; i < other.mSize; i++) {
|
||||
size_t const index = (other.mFront + CAPACITY - i) % CAPACITY;
|
||||
new(&mStorage[index]) T(std::move(*std::launder(reinterpret_cast<T*>(&other.mStorage[index]))));
|
||||
}
|
||||
mFront = other.mFront;
|
||||
mSize = other.mSize;
|
||||
other.mSize = 0;
|
||||
}
|
||||
|
||||
CircularQueue& operator=(CircularQueue&& other) noexcept {
|
||||
if (this != &other) {
|
||||
this->~CircularQueue();
|
||||
new(this) CircularQueue(std::move(other));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t capacity() const noexcept {
|
||||
return CAPACITY;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
size_t size() const noexcept {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
@@ -84,7 +138,8 @@ public:
|
||||
void pop_back() noexcept {
|
||||
assert_invariant(!empty());
|
||||
--mSize;
|
||||
std::destroy_at(&mStorage[(mFront - mSize) % CAPACITY]);
|
||||
size_t const index = (mFront + CAPACITY - mSize) % CAPACITY;
|
||||
std::destroy_at(std::launder(reinterpret_cast<T*>(&mStorage[index])));
|
||||
}
|
||||
|
||||
void push_front(T const& v) noexcept {
|
||||
@@ -133,9 +188,9 @@ public:
|
||||
private:
|
||||
using Storage = std::aligned_storage_t<sizeof(T), alignof(T)>;
|
||||
Storage mStorage[CAPACITY];
|
||||
uint32_t mFront = 0; // always index 0
|
||||
uint32_t mFront = 0;
|
||||
uint32_t mSize = 0;
|
||||
[[nodiscard]] inline uint32_t advance(uint32_t const v) noexcept {
|
||||
[[nodiscard]] uint32_t advance(uint32_t const v) noexcept {
|
||||
return (v + 1) % CAPACITY;
|
||||
}
|
||||
};
|
||||
@@ -168,7 +223,7 @@ public:
|
||||
return pFront ? *pFront : details::FrameInfo{};
|
||||
}
|
||||
|
||||
utils::FixedCapacityVector<Renderer::FrameInfo> getFrameInfoHistory(size_t historySize) const noexcept;
|
||||
utils::FixedCapacityVector<Renderer::FrameInfo> getFrameInfoHistory(size_t historySize) const;
|
||||
|
||||
private:
|
||||
using FrameHistoryQueue = CircularQueue<FrameInfoImpl, MAX_FRAMETIME_HISTORY>;
|
||||
@@ -177,11 +232,11 @@ private:
|
||||
backend::Handle<backend::HwTimerQuery> handle{};
|
||||
FrameInfoImpl* pInfo = nullptr;
|
||||
};
|
||||
std::array<Query, POOL_COUNT> mQueries;
|
||||
std::array<Query, POOL_COUNT> mQueries{};
|
||||
uint32_t mIndex = 0; // index of current query
|
||||
uint32_t mLast = 0; // index of oldest query still active
|
||||
FrameInfoImpl* pFront = nullptr; // the most recent slot with a valid frame time
|
||||
FrameHistoryQueue mFrameTimeHistory;
|
||||
FrameHistoryQueue mFrameTimeHistory{};
|
||||
};
|
||||
|
||||
|
||||
|
||||
+10
-11
@@ -243,29 +243,28 @@ bool Froxelizer::prepare(
|
||||
*/
|
||||
|
||||
// froxel buffer (16 KiB with 4096 froxels)
|
||||
mFroxelBufferUser = {
|
||||
mFroxelBufferUser.set(
|
||||
driverApi.allocatePod<FroxelEntry>(mFroxelBufferEntryCount),
|
||||
mFroxelBufferEntryCount };
|
||||
mFroxelBufferEntryCount);
|
||||
|
||||
// record buffer (64 KiB max)
|
||||
mRecordBufferUser = {
|
||||
mRecordBufferUser.set(
|
||||
driverApi.allocatePod<RecordBufferType>(mFroxelRecordBufferEntryCount),
|
||||
mFroxelRecordBufferEntryCount };
|
||||
mFroxelRecordBufferEntryCount);
|
||||
|
||||
/*
|
||||
* Temporary allocations for processing all froxel data
|
||||
*/
|
||||
|
||||
// light records per froxel (~256 KiB with 4096 froxels)
|
||||
mLightRecords = {
|
||||
mLightRecords.set(
|
||||
rootArenaScope.allocate<LightRecord>(getFroxelBufferEntryCount(), CACHELINE_SIZE),
|
||||
getFroxelBufferEntryCount() };
|
||||
getFroxelBufferEntryCount());
|
||||
|
||||
// froxel thread data (~256KiB with 8192 max froxels and 256 lights)
|
||||
mFroxelShardedData = {
|
||||
mFroxelShardedData.set(
|
||||
rootArenaScope.allocate<FroxelThreadData>(GROUP_COUNT, CACHELINE_SIZE),
|
||||
uint32_t(GROUP_COUNT)
|
||||
};
|
||||
uint32_t(GROUP_COUNT));
|
||||
|
||||
assert_invariant(mFroxelBufferUser.begin());
|
||||
assert_invariant(mRecordBufferUser.begin());
|
||||
@@ -703,7 +702,7 @@ void Froxelizer::froxelizeLoop(FEngine& engine,
|
||||
void Froxelizer::froxelizeAssignRecordsCompress() noexcept {
|
||||
FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
||||
|
||||
Slice<FroxelThreadData> const froxelThreadData = mFroxelShardedData;
|
||||
Slice<const FroxelThreadData> froxelThreadData = mFroxelShardedData;
|
||||
|
||||
// Convert froxel data from N groups of M bits to LightRecord::bitset, so we can
|
||||
// easily compare adjacent froxels, for compaction. The conversion loops below get
|
||||
@@ -986,7 +985,7 @@ void Froxelizer::froxelizePointAndSpotLight(
|
||||
*/
|
||||
void Froxelizer::computeLightTree(
|
||||
LightTreeNode* lightTree,
|
||||
Slice<RecordBufferType> const& lightList,
|
||||
Slice<const RecordBufferType> lightList,
|
||||
const FScene::LightSoa& lightData,
|
||||
size_t lightRecordsOffset) noexcept {
|
||||
|
||||
|
||||
@@ -162,8 +162,8 @@ public:
|
||||
// We can't change this easily because the shader expects 16 indices per uint4
|
||||
using RecordBufferType = uint8_t;
|
||||
|
||||
const utils::Slice<FroxelEntry>& getFroxelBufferUser() const { return mFroxelBufferUser; }
|
||||
const utils::Slice<RecordBufferType>& getRecordBufferUser() const { return mRecordBufferUser; }
|
||||
utils::Slice<const FroxelEntry> getFroxelBufferUser() const { return mFroxelBufferUser; }
|
||||
utils::Slice<const RecordBufferType> getRecordBufferUser() const { return mRecordBufferUser; }
|
||||
|
||||
// This is chosen so froxelizePointAndSpotLight() vectorizes 4 froxel tests / spotlight
|
||||
// with 256 lights this implies 8 jobs (256 / 32) for froxelization.
|
||||
@@ -224,7 +224,7 @@ private:
|
||||
math::mat4f const& projection, const LightParams& light) const noexcept;
|
||||
|
||||
static void computeLightTree(LightTreeNode* lightTree,
|
||||
utils::Slice<RecordBufferType> const& lightList,
|
||||
utils::Slice<const RecordBufferType> lightList,
|
||||
const FScene::LightSoa& lightData, size_t lightRecordsOffset) noexcept;
|
||||
|
||||
static void updateBoundingSpheres(
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
#include <details/Engine.h>
|
||||
|
||||
#include <private/filament/PushConstantInfo.h>
|
||||
|
||||
#include <utils/Logger.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
@@ -150,7 +152,8 @@ MaterialDefinition::MaterialDefinition(FEngine& engine,
|
||||
|
||||
processMain();
|
||||
processBlendingMode();
|
||||
processSpecializationConstants();
|
||||
processSpecializationConstants(engine);
|
||||
processPushConstants();
|
||||
processDescriptorSets(engine);
|
||||
}
|
||||
|
||||
@@ -338,17 +341,122 @@ void MaterialDefinition::processBlendingMode() {
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialDefinition::processSpecializationConstants() {
|
||||
void MaterialDefinition::processSpecializationConstants(FEngine& engine) {
|
||||
// Older materials won't have a constants chunk, but that's okay.
|
||||
mMaterialParser->getConstants(&materialConstants);
|
||||
|
||||
// Initialize the default specialization constant values.
|
||||
const int size = materialConstants.size() + CONFIG_MAX_RESERVED_SPEC_CONSTANTS;
|
||||
specializationConstants.reserve(size);
|
||||
specializationConstants.resize(size);
|
||||
|
||||
specializationConstants[+ReservedSpecializationConstants::BACKEND_FEATURE_LEVEL] =
|
||||
int(engine.getSupportedFeatureLevel());
|
||||
|
||||
// Feature level 0 doesn't support instancing.
|
||||
specializationConstants[+ReservedSpecializationConstants::CONFIG_MAX_INSTANCES] =
|
||||
int((engine.getActiveFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0)
|
||||
? 1 : CONFIG_MAX_INSTANCES);
|
||||
|
||||
specializationConstants
|
||||
[+ReservedSpecializationConstants::CONFIG_STATIC_TEXTURE_TARGET_WORKAROUND] =
|
||||
engine.getDriverApi().isWorkaroundNeeded(
|
||||
Workaround::METAL_STATIC_TEXTURE_TARGET_ERROR);
|
||||
|
||||
specializationConstants[+ReservedSpecializationConstants::CONFIG_SRGB_SWAPCHAIN_EMULATION] =
|
||||
engine.getDriverApi().isWorkaroundNeeded(Workaround::EMULATE_SRGB_SWAPCHAIN);
|
||||
|
||||
// The 16u below denotes the 16 bytes in a uvec4, which is how the froxel buffer is stored.
|
||||
specializationConstants[+ReservedSpecializationConstants::CONFIG_FROXEL_BUFFER_HEIGHT] =
|
||||
int(Froxelizer::getFroxelBufferByteCount(engine.getDriverApi()) / 16u);
|
||||
|
||||
specializationConstants[+ReservedSpecializationConstants::CONFIG_POWER_VR_SHADER_WORKAROUNDS] =
|
||||
engine.getDriverApi().isWorkaroundNeeded(Workaround::POWER_VR_SHADER_WORKAROUNDS);
|
||||
|
||||
specializationConstants[+ReservedSpecializationConstants::CONFIG_DEBUG_DIRECTIONAL_SHADOWMAP] =
|
||||
engine.debug.shadowmap.debug_directional_shadowmap;
|
||||
|
||||
specializationConstants[+ReservedSpecializationConstants::CONFIG_DEBUG_FROXEL_VISUALIZATION] =
|
||||
engine.debug.lighting.debug_froxel_visualization;
|
||||
|
||||
specializationConstants[+ReservedSpecializationConstants::CONFIG_STEREO_EYE_COUNT] =
|
||||
int(engine.getConfig().stereoscopicEyeCount);
|
||||
|
||||
// Actual value set in FMaterial::processSpecializationConstants.
|
||||
specializationConstants[+ReservedSpecializationConstants::CONFIG_SH_BANDS_COUNT] = 0;
|
||||
|
||||
// Actual value set in FMaterial::processSpecializationConstants.
|
||||
specializationConstants[+ReservedSpecializationConstants::CONFIG_SHADOW_SAMPLING_METHOD] = 0;
|
||||
|
||||
specializationConstants[+ReservedSpecializationConstants::CONFIG_FROXEL_RECORD_BUFFER_HEIGHT] =
|
||||
int(Froxelizer::getFroxelRecordBufferByteCount(engine.getDriverApi()) / 16u);
|
||||
|
||||
// Initialize the rest of the reserved constants with a dummy value.
|
||||
for (size_t i = CONFIG_NEXT_RESERVED_SPEC_CONSTANT; i < CONFIG_MAX_RESERVED_SPEC_CONSTANTS;
|
||||
i++) {
|
||||
specializationConstants[i] = 0;
|
||||
}
|
||||
|
||||
// Initialize the remaining constants and specializationConstantsNameToIndex.
|
||||
for (size_t i = 0, c = materialConstants.size(); i < c; i++) {
|
||||
auto& item = materialConstants[i];
|
||||
|
||||
// the key can be a string_view because mMaterialConstant owns the CString
|
||||
std::string_view const key{ item.name.data(), item.name.size() };
|
||||
specializationConstantsNameToIndex[key] = i;
|
||||
|
||||
// Copy the default value to the corresponding specializationConstants entry.
|
||||
const size_t id = CONFIG_MAX_RESERVED_SPEC_CONSTANTS + i;
|
||||
switch (item.type) {
|
||||
case ConstantType::INT:
|
||||
specializationConstants[id] = item.defaultValue.i;
|
||||
break;
|
||||
case ConstantType::FLOAT:
|
||||
specializationConstants[id] = item.defaultValue.f;
|
||||
break;
|
||||
case ConstantType::BOOL:
|
||||
specializationConstants[id] = item.defaultValue.b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialDefinition::processPushConstants() {
|
||||
FixedCapacityVector<Program::PushConstant>& vertexConstants =
|
||||
pushConstants[uint8_t(ShaderStage::VERTEX)];
|
||||
FixedCapacityVector<Program::PushConstant>& fragmentConstants =
|
||||
pushConstants[uint8_t(ShaderStage::FRAGMENT)];
|
||||
|
||||
CString structVarName;
|
||||
FixedCapacityVector<MaterialPushConstant> pushConstants;
|
||||
mMaterialParser->getPushConstants(&structVarName, &pushConstants);
|
||||
|
||||
vertexConstants.reserve(pushConstants.size());
|
||||
fragmentConstants.reserve(pushConstants.size());
|
||||
|
||||
constexpr size_t MAX_NAME_LEN = 60;
|
||||
char buf[MAX_NAME_LEN];
|
||||
uint8_t vertexCount = 0, fragmentCount = 0;
|
||||
|
||||
std::for_each(pushConstants.cbegin(), pushConstants.cend(),
|
||||
[&](MaterialPushConstant const& constant) {
|
||||
snprintf(buf, sizeof(buf), "%s.%s", structVarName.c_str(), constant.name.c_str());
|
||||
|
||||
switch (constant.stage) {
|
||||
case ShaderStage::VERTEX:
|
||||
vertexConstants.push_back({CString(buf), constant.type});
|
||||
vertexCount++;
|
||||
break;
|
||||
case ShaderStage::FRAGMENT:
|
||||
fragmentConstants.push_back({CString(buf), constant.type});
|
||||
fragmentCount++;
|
||||
break;
|
||||
case ShaderStage::COMPUTE:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MaterialDefinition::processDescriptorSets(FEngine& engine) {
|
||||
UTILS_UNUSED_IN_RELEASE bool success;
|
||||
|
||||
|
||||
@@ -99,10 +99,17 @@ struct MaterialDefinition {
|
||||
BindingUniformInfoContainer bindingUniformInfo;
|
||||
AttributeInfoContainer attributeInfo;
|
||||
|
||||
// Constants defined by this Material
|
||||
// Constants defined by this material. Does not include reserved constants.
|
||||
utils::FixedCapacityVector<MaterialConstant> materialConstants;
|
||||
// A map from the Constant name to the materialConstants index
|
||||
// A map from the Constant name to the materialConstants index.
|
||||
std::unordered_map<std::string_view, uint32_t> specializationConstantsNameToIndex;
|
||||
// A list of default values for spec constants. Includes reserved constants.
|
||||
utils::FixedCapacityVector<backend::Program::SpecializationConstant> specializationConstants;
|
||||
|
||||
// current push constants for the HwProgram
|
||||
std::array<utils::FixedCapacityVector<backend::Program::PushConstant>,
|
||||
backend::Program::SHADER_TYPE_COUNT>
|
||||
pushConstants;
|
||||
|
||||
utils::CString name;
|
||||
uint64_t cacheId = 0;
|
||||
@@ -120,7 +127,8 @@ private:
|
||||
|
||||
void processMain();
|
||||
void processBlendingMode();
|
||||
void processSpecializationConstants();
|
||||
void processSpecializationConstants(FEngine& engine);
|
||||
void processPushConstants();
|
||||
void processDescriptorSets(FEngine& engine);
|
||||
|
||||
std::unique_ptr<MaterialParser> mMaterialParser;
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
|
||||
using Record = MaterialInstanceManager::Record;
|
||||
@@ -39,15 +44,15 @@ std::pair<FMaterialInstance*, int32_t> Record::getInstance() {
|
||||
return { inst, mAvailable++ };
|
||||
}
|
||||
|
||||
FMaterialInstance* Record::getInstance(int32_t fixedInstanceindex) {
|
||||
assert_invariant(fixedInstanceindex >= 0 && fixedInstanceindex < (int32_t) mInstances.size());
|
||||
FMaterialInstance* Record::getInstance(int32_t const fixedInstanceindex) const {
|
||||
assert_invariant(fixedInstanceindex >= 0 && fixedInstanceindex < int32_t(mInstances.size()));
|
||||
return mInstances[fixedInstanceindex];
|
||||
}
|
||||
|
||||
// Defined in cpp to avoid inlining
|
||||
Record::Record(Record const& rhs) noexcept = default;
|
||||
Record& Record::operator=(Record const& rhs) noexcept = default;
|
||||
Record::Record(MaterialInstanceManager::Record&& rhs) noexcept = default;
|
||||
Record::Record(Record&& rhs) noexcept = default;
|
||||
Record& Record::operator=(Record&& rhs) noexcept = default;
|
||||
|
||||
void Record::terminate(FEngine& engine) {
|
||||
@@ -73,7 +78,7 @@ void MaterialInstanceManager::terminate(FEngine& engine) {
|
||||
});
|
||||
}
|
||||
|
||||
Record& MaterialInstanceManager::getRecord(FMaterial const* ma) {
|
||||
Record& MaterialInstanceManager::getRecord(FMaterial const* const ma) const {
|
||||
auto itr = std::find_if(mMaterials.begin(), mMaterials.end(), [ma](auto& record) {
|
||||
return ma == record.mMaterial;
|
||||
});
|
||||
@@ -84,13 +89,13 @@ Record& MaterialInstanceManager::getRecord(FMaterial const* ma) {
|
||||
return *itr;
|
||||
}
|
||||
|
||||
FMaterialInstance* MaterialInstanceManager::getMaterialInstance(FMaterial const* ma) {
|
||||
FMaterialInstance* MaterialInstanceManager::getMaterialInstance(FMaterial const* ma) const {
|
||||
auto [inst, index] = getRecord(ma).getInstance();
|
||||
return inst;
|
||||
}
|
||||
|
||||
FMaterialInstance* MaterialInstanceManager::getMaterialInstance(FMaterial const* ma,
|
||||
int32_t const fixedIndex) {
|
||||
int32_t const fixedIndex) const {
|
||||
return getRecord(ma).getInstance(fixedIndex);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
void terminate(FEngine& engine);
|
||||
void reset() { mAvailable = 0; }
|
||||
std::pair<FMaterialInstance*, int32_t> getInstance();
|
||||
FMaterialInstance* getInstance(int32_t fixedInstanceindex);
|
||||
FMaterialInstance* getInstance(int32_t fixedInstanceindex) const;
|
||||
|
||||
private:
|
||||
FMaterial const* mMaterial = nullptr;
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
~MaterialInstanceManager();
|
||||
|
||||
/*
|
||||
* Destroy all of the cached material instances. This needs to be done before the destruction of
|
||||
* Destroy all the cached material instances. This needs to be done before the destruction of
|
||||
* the corresponding Material.
|
||||
*/
|
||||
void terminate(FEngine& engine);
|
||||
@@ -76,13 +76,13 @@ public:
|
||||
* available instance in the cache. If one is not found, then a new instance will be created and
|
||||
* added to the cache.
|
||||
*/
|
||||
FMaterialInstance* getMaterialInstance(FMaterial const* ma);
|
||||
FMaterialInstance* getMaterialInstance(FMaterial const* ma) const;
|
||||
|
||||
/*
|
||||
* This returns a material instance given a material and an index. The `fixedIndex` should be
|
||||
* a value returned by getiFixedMaterialInstance.
|
||||
*/
|
||||
FMaterialInstance* getMaterialInstance(FMaterial const* ma, int32_t const fixedIndex);
|
||||
FMaterialInstance* getMaterialInstance(FMaterial const* ma, int32_t const fixedIndex) const;
|
||||
|
||||
/*
|
||||
* This returns a material instance and an index given a material. This is needed for the
|
||||
@@ -102,9 +102,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
Record& getRecord(FMaterial const* material);
|
||||
Record& getRecord(FMaterial const* material) const;
|
||||
|
||||
std::vector<Record> mMaterials;
|
||||
mutable std::vector<Record> mMaterials;
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -800,6 +800,7 @@ bool ChunkMaterialConstants::unflatten(Unflattener& unflattener,
|
||||
for (uint64_t i = 0; i < numConstants; i++) {
|
||||
CString constantName;
|
||||
uint8_t constantType = 0;
|
||||
ConstantValue defaultValue;
|
||||
|
||||
if (!unflattener.read(&constantName)) {
|
||||
return false;
|
||||
@@ -809,8 +810,13 @@ bool ChunkMaterialConstants::unflatten(Unflattener& unflattener,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!unflattener.read(&defaultValue.i)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
(*materialConstants)[i].name = constantName;
|
||||
(*materialConstants)[i].type = static_cast<ConstantType>(constantType);
|
||||
(*materialConstants)[i].defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -253,7 +253,7 @@ void PostProcessManager::bindPostProcessDescriptorSet(DriverApi& driver) const n
|
||||
mPostProcessDescriptorSet.bind(driver);
|
||||
}
|
||||
|
||||
void PostProcessManager::bindPerRenderableDescriptorSet(DriverApi& driver) noexcept {
|
||||
void PostProcessManager::bindPerRenderableDescriptorSet(DriverApi& driver) const noexcept {
|
||||
driver.bindDescriptorSet(mDummyPerRenderableDsh, +DescriptorSetBindingPoints::PER_RENDERABLE,
|
||||
{ { 0, 0 }, driver });
|
||||
}
|
||||
@@ -265,14 +265,15 @@ void PostProcessManager::registerPostProcessMaterial(std::string_view const name
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
PostProcessManager::PostProcessMaterial& PostProcessManager::getPostProcessMaterial(
|
||||
std::string_view const name) noexcept {
|
||||
|
||||
PostProcessManager::PostProcessMaterial const& PostProcessManager::getPostProcessMaterial(
|
||||
std::string_view const name) const noexcept {
|
||||
auto pos = mMaterialRegistry.find(name);
|
||||
assert_invariant(pos != mMaterialRegistry.end());
|
||||
return pos.value();
|
||||
}
|
||||
|
||||
// StaticMaterialInfo::ConstantInfo destructor is called during shut-down, to avoid side-effect
|
||||
// StaticMaterialInfo::ConstantInfo destructor is called during shut-down, to avoid side effect
|
||||
// we ensure it's trivially destructible
|
||||
static_assert(std::is_trivially_destructible_v<PostProcessManager::StaticMaterialInfo::ConstantInfo>);
|
||||
|
||||
@@ -285,6 +286,7 @@ static const PostProcessManager::StaticMaterialInfo sMaterialListFeatureLevel0[]
|
||||
static const PostProcessManager::StaticMaterialInfo sMaterialList[] = {
|
||||
{ "blitArray", MATERIAL(MATERIALS, BLITARRAY) },
|
||||
{ "blitDepth", MATERIAL(MATERIALS, BLITDEPTH) },
|
||||
{ "clearDepth", MATERIAL(MATERIALS, CLEARDEPTH) },
|
||||
{ "separableGaussianBlur1", MATERIAL(MATERIALS, SEPARABLEGAUSSIANBLUR),
|
||||
{ {"arraySampler", false}, {"componentCount", 1} } },
|
||||
{ "separableGaussianBlur1L", MATERIAL(MATERIALS, SEPARABLEGAUSSIANBLUR),
|
||||
@@ -2561,8 +2563,6 @@ void PostProcessManager::customResolveSubpass(DriverApi& driver) noexcept {
|
||||
bindPostProcessDescriptorSet(driver);
|
||||
bindPerRenderableDescriptorSet(driver);
|
||||
|
||||
FEngine const& engine = mEngine;
|
||||
Handle<HwRenderPrimitive> const& fullScreenRenderPrimitive = engine.getFullScreenRenderPrimitive();
|
||||
auto const& material = getPostProcessMaterial("customResolveAsSubpass");
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
// the UBO has been set and committed in customResolvePrepareSubpass()
|
||||
@@ -2573,7 +2573,7 @@ void PostProcessManager::customResolveSubpass(DriverApi& driver) noexcept {
|
||||
auto const pipeline = getPipelineState(ma);
|
||||
driver.nextSubpass();
|
||||
driver.scissor(mi->getScissor());
|
||||
driver.draw(pipeline, fullScreenRenderPrimitive, 0, 3, 1);
|
||||
driver.draw(pipeline, mFullScreenQuadRph, 0, 3, 1);
|
||||
}
|
||||
|
||||
FrameGraphId<FrameGraphTexture> PostProcessManager::customResolveUncompressPass(FrameGraph& fg,
|
||||
@@ -2602,6 +2602,43 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::customResolveUncompressPass(
|
||||
return detonemapPass->inout;
|
||||
}
|
||||
|
||||
|
||||
void PostProcessManager::clearAncillaryBuffersPrepare(DriverApi& driver) noexcept {
|
||||
auto const& material = getPostProcessMaterial("clearDepth");
|
||||
auto ma = material.getMaterial(mEngine, PostProcessVariant::OPAQUE);
|
||||
auto [mi, fixedIndex] = mMaterialInstanceManager.getFixedMaterialInstance(ma);
|
||||
mFixedMaterialInstanceIndex.clearDepth = fixedIndex;
|
||||
mi->commit(driver);
|
||||
material.getMaterial(mEngine);
|
||||
}
|
||||
|
||||
void PostProcessManager::clearAncillaryBuffers(DriverApi& driver,
|
||||
TargetBufferFlags attachments) const noexcept {
|
||||
// in the future we might allow STENCIL as well
|
||||
attachments &= TargetBufferFlags::DEPTH;
|
||||
if (none(attachments & TargetBufferFlags::DEPTH)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bindPostProcessDescriptorSet(driver);
|
||||
bindPerRenderableDescriptorSet(driver);
|
||||
|
||||
auto const& material = getPostProcessMaterial("clearDepth");
|
||||
FMaterial const* const ma = material.getMaterial(mEngine);
|
||||
|
||||
// the UBO has been set and committed in clearAncillaryBuffersPrepare()
|
||||
FMaterialInstance const* const mi = mMaterialInstanceManager.getMaterialInstance(ma,
|
||||
mFixedMaterialInstanceIndex.clearDepth);
|
||||
|
||||
mi->use(driver);
|
||||
|
||||
auto pipeline = getPipelineState(ma);
|
||||
pipeline.rasterState.depthFunc = RasterState::DepthFunc::A;
|
||||
|
||||
driver.scissor(mi->getScissor());
|
||||
driver.draw(pipeline, mFullScreenQuadRph, 0, 3, 1);
|
||||
}
|
||||
|
||||
FrameGraphId<FrameGraphTexture> PostProcessManager::colorGrading(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> const input, filament::Viewport const& vp,
|
||||
FrameGraphId<FrameGraphTexture> const bloom,
|
||||
@@ -2874,7 +2911,7 @@ void PostProcessManager::configureTemporalAntiAliasingMaterial(
|
||||
}
|
||||
|
||||
FMaterialInstance* PostProcessManager::configureColorGradingMaterial(
|
||||
PostProcessMaterial& material, FColorGrading const* colorGrading,
|
||||
PostProcessMaterial const& material, FColorGrading const* colorGrading,
|
||||
ColorGradingConfig const& colorGradingConfig, VignetteOptions const& vignetteOptions,
|
||||
uint32_t const width, uint32_t const height) noexcept {
|
||||
FMaterial* ma = material.getMaterial(mEngine);
|
||||
@@ -3407,8 +3444,8 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::upscaleFSR1(FrameGraph& fg,
|
||||
// --------------------------------------------------------------------------------
|
||||
// set uniforms
|
||||
|
||||
PostProcessMaterial* splitEasuMaterial = nullptr;
|
||||
PostProcessMaterial* easuMaterial = nullptr;
|
||||
PostProcessMaterial const* splitEasuMaterial = nullptr;
|
||||
PostProcessMaterial const* easuMaterial = nullptr;
|
||||
|
||||
if (twoPassesEASU) {
|
||||
splitEasuMaterial = &getPostProcessMaterial("fsr_easu_mobileF");
|
||||
@@ -3637,7 +3674,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::blitDepth(FrameGraph& fg,
|
||||
}
|
||||
|
||||
FrameGraphId<FrameGraphTexture> PostProcessManager::resolve(FrameGraph& fg,
|
||||
const char* outputBufferName, FrameGraphId<FrameGraphTexture> const input,
|
||||
utils::StaticString outputBufferName, FrameGraphId<FrameGraphTexture> const input,
|
||||
FrameGraphTexture::Descriptor outDesc) noexcept {
|
||||
|
||||
// Don't do anything if we're not a MSAA buffer
|
||||
@@ -3691,7 +3728,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::resolve(FrameGraph& fg,
|
||||
}
|
||||
|
||||
FrameGraphId<FrameGraphTexture> PostProcessManager::resolveDepth(FrameGraph& fg,
|
||||
const char* outputBufferName, FrameGraphId<FrameGraphTexture> const input,
|
||||
utils::StaticString outputBufferName, FrameGraphId<FrameGraphTexture> const input,
|
||||
FrameGraphTexture::Descriptor outDesc) noexcept {
|
||||
|
||||
// Don't do anything if we're not a MSAA buffer
|
||||
@@ -3752,7 +3789,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::vsmMipmapPass(FrameGraph& fg
|
||||
|
||||
auto const& depthMipmapPass = fg.addPass<VsmMipData>("VSM Generate Mipmap Pass",
|
||||
[&](FrameGraph::Builder& builder, auto& data) {
|
||||
const char* name = builder.getName(input);
|
||||
utils::StaticString name = builder.getName(input);
|
||||
data.in = builder.sample(input);
|
||||
|
||||
auto out = builder.createSubresource(data.in, "Mip level", {
|
||||
|
||||
@@ -213,6 +213,11 @@ public:
|
||||
FrameGraphId<FrameGraphTexture> customResolveUncompressPass(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> inout) noexcept;
|
||||
|
||||
// clear depth buffer pass
|
||||
void clearAncillaryBuffersPrepare(backend::DriverApi& driver) noexcept;
|
||||
void clearAncillaryBuffers(backend::DriverApi& driver,
|
||||
backend::TargetBufferFlags attachments) const noexcept;
|
||||
|
||||
// Anti-aliasing
|
||||
FrameGraphId<FrameGraphTexture> fxaa(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> input, Viewport const& vp,
|
||||
@@ -286,13 +291,13 @@ public:
|
||||
// Resolves base level of input and outputs a texture from outDesc.
|
||||
// outDesc with, height, format and samples will be overridden.
|
||||
FrameGraphId<FrameGraphTexture> resolve(FrameGraph& fg,
|
||||
const char* outputBufferName, FrameGraphId<FrameGraphTexture> input,
|
||||
utils::StaticString outputBufferName, FrameGraphId<FrameGraphTexture> input,
|
||||
FrameGraphTexture::Descriptor outDesc) noexcept;
|
||||
|
||||
// Resolves base level of input and outputs a texture from outDesc.
|
||||
// outDesc with, height, format and samples will be overridden.
|
||||
FrameGraphId<FrameGraphTexture> resolveDepth(FrameGraph& fg,
|
||||
const char* outputBufferName, FrameGraphId<FrameGraphTexture> input,
|
||||
utils::StaticString outputBufferName, FrameGraphId<FrameGraphTexture> input,
|
||||
FrameGraphTexture::Descriptor outDesc) noexcept;
|
||||
|
||||
// VSM shadow mipmap pass
|
||||
@@ -355,12 +360,13 @@ public:
|
||||
// mSize == 0 if mMaterial is valid, otherwise mSize > 0
|
||||
mutable uint32_t mSize{};
|
||||
// the objects' must outlive the Slice<>
|
||||
utils::Slice<StaticMaterialInfo::ConstantInfo> mConstants{};
|
||||
utils::Slice<const StaticMaterialInfo::ConstantInfo> mConstants{};
|
||||
};
|
||||
|
||||
void registerPostProcessMaterial(std::string_view name, StaticMaterialInfo const& info);
|
||||
|
||||
PostProcessMaterial& getPostProcessMaterial(std::string_view name) noexcept;
|
||||
PostProcessManager::PostProcessMaterial const& getPostProcessMaterial(
|
||||
std::string_view name) const noexcept;
|
||||
|
||||
void setFrameUniforms(backend::DriverApi& driver,
|
||||
TypedUniformBuffer<PerViewUib>& uniforms) noexcept;
|
||||
@@ -390,7 +396,7 @@ public:
|
||||
// Sets the necessary spec constants and uniforms common to both colorGrading.mat and
|
||||
// colorGradingAsSubpass.mat.
|
||||
FMaterialInstance* configureColorGradingMaterial(
|
||||
PostProcessMaterial& material, FColorGrading const* colorGrading,
|
||||
PostProcessMaterial const& material, FColorGrading const* colorGrading,
|
||||
ColorGradingConfig const& colorGradingConfig, VignetteOptions const& vignetteOptions,
|
||||
uint32_t width, uint32_t height) noexcept;
|
||||
|
||||
@@ -401,7 +407,7 @@ public:
|
||||
private:
|
||||
static void unbindAllDescriptorSets(backend::DriverApi& driver) noexcept;
|
||||
|
||||
void bindPerRenderableDescriptorSet(backend::DriverApi& driver) noexcept;
|
||||
void bindPerRenderableDescriptorSet(backend::DriverApi& driver) const noexcept;
|
||||
|
||||
// Helper to get a MaterialInstance from a FMaterial
|
||||
// This currently just call FMaterial::getDefaultInstance().
|
||||
@@ -461,6 +467,7 @@ private:
|
||||
int32_t colorGradingTranslucent = MaterialInstanceManager::INVALID_FIXED_INDEX;
|
||||
int32_t colorGradingOpaque = MaterialInstanceManager::INVALID_FIXED_INDEX;
|
||||
int32_t customResolve = MaterialInstanceManager::INVALID_FIXED_INDEX;
|
||||
int32_t clearDepth = MaterialInstanceManager::INVALID_FIXED_INDEX;
|
||||
} mFixedMaterialInstanceIndex;
|
||||
|
||||
backend::Handle<backend::HwTexture> mStarburstTexture;
|
||||
|
||||
@@ -254,7 +254,7 @@ void RenderPass::appendCustomCommand(Command* commands,
|
||||
|
||||
assert_invariant((uint64_t(order) << CUSTOM_ORDER_SHIFT) <= CUSTOM_ORDER_MASK);
|
||||
|
||||
channel = std::min(channel, uint8_t(0x3));
|
||||
channel = std::min(channel, uint8_t(CHANNEL_COUNT - 1));
|
||||
|
||||
uint32_t const index = mCustomCommands.size();
|
||||
mCustomCommands.push_back(std::move(command));
|
||||
@@ -693,7 +693,7 @@ RenderPass::Command* RenderPass::generateCommandsImpl(CommandTypeFlags extraFlag
|
||||
const bool shadowCaster = soaVisibility[i].castShadows & hasShadowing;
|
||||
const bool writeDepthForShadowCasters = depthContainsShadowCasters & shadowCaster;
|
||||
|
||||
const Slice<FRenderPrimitive>& primitives = soaPrimitives[i];
|
||||
Slice<const FRenderPrimitive> primitives = soaPrimitives[i];
|
||||
/*
|
||||
* This is our hot loop. It's written to avoid branches.
|
||||
* When modifying this code, always ensure it stays efficient.
|
||||
|
||||
+35
-31
@@ -25,6 +25,7 @@
|
||||
#include "details/Scene.h"
|
||||
|
||||
#include "private/filament/Variant.h"
|
||||
#include "private/filament/EngineEnums.h"
|
||||
|
||||
#include <backend/DriverApiForward.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
@@ -67,7 +68,7 @@ public:
|
||||
* Command key encoding
|
||||
* --------------------
|
||||
*
|
||||
* CC = Channel
|
||||
* CCC = Channel
|
||||
* PP = Pass
|
||||
* a = alpha masking
|
||||
* ppp = priority
|
||||
@@ -79,43 +80,43 @@ public:
|
||||
* auto-instancing can work better
|
||||
*
|
||||
* DEPTH command (b00)
|
||||
* | | | 2| 2| 2|1| 3 | 2| 6 | 10 | 32 |
|
||||
* +--+--+--+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* |CC|00|00|01|00|0|ppp|00|000000| Z-bucket | material-id |
|
||||
* +--+--+--+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* | 3|1| 2| 2| 2|1| 3 | 2| 6 | 10 | 32 |
|
||||
* +---+-+--+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* |CCC|0|00|01|00|0|ppp|00|000000| Z-bucket | material-id |
|
||||
* +---+-+--+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* | correctness | optimizations (truncation allowed) |
|
||||
*
|
||||
*
|
||||
* COLOR (b01) and REFRACT (b10) commands
|
||||
* | | 2| 2| 2| 2|1| 3 | 2| 6 | 10 | 32 |
|
||||
* +--+--+--+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* |CC|00|01|01|00|a|ppp|00|000000| Z-bucket | material-id |
|
||||
* |CC|00|10|01|00|a|ppp|00|000000| Z-bucket | material-id | refraction
|
||||
* +--+--+--+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* | 3|1| 2| 2| 2|1| 3 | 2| 6 | 10 | 32 |
|
||||
* +---+-+--+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* |CCC|0|01|01|00|a|ppp|00|000000| Z-bucket | material-id |
|
||||
* |CCC|0|10|01|00|a|ppp|00|000000| Z-bucket | material-id | refraction
|
||||
* +---+-+--+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* | correctness | optimizations (truncation allowed) |
|
||||
*
|
||||
*
|
||||
* BLENDED command (b11)
|
||||
* | 2| 2| 2| 2| 2|1| 3 | 2| 32 | 15 |1|
|
||||
* +--+--+--+--+--+-+---+--+--------------------------------+---------------+-+
|
||||
* |CC|00|11|01|00|0|ppp|00| ~distanceBits | blendOrder |t|
|
||||
* +--+--+--+--+--+-+---+--+--------------------------------+---------------+-+
|
||||
* | 3|1| 2| 2| 2|1| 3 | 2| 32 | 15 |1|
|
||||
* +---+-+--+--+--+-+---+--+--------------------------------+---------------+-+
|
||||
* |CCC|0|11|01|00|0|ppp|00| ~distanceBits | blendOrder |t|
|
||||
* +---+-+--+--+--+-+---+--+--------------------------------+---------------+-+
|
||||
* | correctness |
|
||||
*
|
||||
*
|
||||
* pre-CUSTOM command
|
||||
* | 2| 2| 2| 2| 2| 22 | 32 |
|
||||
* +--+--+--+--+--+----------------------+--------------------------------+
|
||||
* |CC|00|PP|00|00| order | custom command index |
|
||||
* +--+--+--+--+--+----------------------+--------------------------------+
|
||||
* CUSTOM command (prologue)
|
||||
* | 3|1| 2| 2| 2| 22 | 32 |
|
||||
* +---+-+--+--+--+----------------------+--------------------------------+
|
||||
* |CCC|0|PP|00|00| order | custom command index |
|
||||
* +---+-+--+--+--+----------------------+--------------------------------+
|
||||
* | correctness |
|
||||
*
|
||||
*
|
||||
* post-CUSTOM command
|
||||
* | 2| 2| 2| 2| 2| 22 | 32 |
|
||||
* +--+--+--+--+--+----------------------+--------------------------------+
|
||||
* |CC|00|PP|11|00| order | custom command index |
|
||||
* +--+--+--+--+--+----------------------+--------------------------------+
|
||||
* CUSTOM command (epilogue)
|
||||
* | 3|1| 2| 2| 2| 22 | 32 |
|
||||
* +---+-+--+--+--+----------------------+--------------------------------+
|
||||
* |CCC|0|PP|10|00| order | custom command index |
|
||||
* +---+-+--+--+--+----------------------+--------------------------------+
|
||||
* | correctness |
|
||||
*
|
||||
*
|
||||
@@ -127,6 +128,8 @@ public:
|
||||
*/
|
||||
using CommandKey = uint64_t;
|
||||
|
||||
static constexpr uint64_t CHANNEL_COUNT = CONFIG_RENDERPASS_CHANNEL_COUNT;
|
||||
|
||||
static constexpr uint64_t BLEND_ORDER_MASK = 0xFFFEllu;
|
||||
static constexpr unsigned BLEND_ORDER_SHIFT = 1;
|
||||
|
||||
@@ -163,8 +166,9 @@ public:
|
||||
static constexpr uint64_t PASS_MASK = 0x0C00000000000000llu;
|
||||
static constexpr unsigned PASS_SHIFT = 58;
|
||||
|
||||
static constexpr uint64_t CHANNEL_MASK = 0xC000000000000000llu;
|
||||
static constexpr unsigned CHANNEL_SHIFT = 62;
|
||||
static constexpr unsigned CHANNEL_SHIFT = 61;
|
||||
static constexpr uint64_t CHANNEL_MASK = (CHANNEL_COUNT - 1) << CHANNEL_SHIFT;
|
||||
|
||||
|
||||
static constexpr uint64_t CUSTOM_ORDER_MASK = 0x003FFFFF00000000llu;
|
||||
static constexpr unsigned CUSTOM_ORDER_SHIFT = 32;
|
||||
@@ -184,9 +188,9 @@ public:
|
||||
};
|
||||
|
||||
enum class CustomCommand : uint64_t { // 2-bits max
|
||||
PROLOG = uint64_t(0x0) << CUSTOM_SHIFT,
|
||||
PASS = uint64_t(0x1) << CUSTOM_SHIFT,
|
||||
EPILOG = uint64_t(0x2) << CUSTOM_SHIFT
|
||||
PROLOGUE = uint64_t(0x0) << CUSTOM_SHIFT,
|
||||
PASS = uint64_t(0x1) << CUSTOM_SHIFT,
|
||||
EPILOGUE = uint64_t(0x2) << CUSTOM_SHIFT
|
||||
};
|
||||
|
||||
enum class CommandTypeFlags : uint32_t {
|
||||
@@ -345,8 +349,8 @@ public:
|
||||
friend class RenderPassBuilder;
|
||||
|
||||
// these fields are constant after creation
|
||||
utils::Slice<Command> mCommands;
|
||||
utils::Slice<CustomCommandFn> mCustomCommands;
|
||||
utils::Slice<const Command> mCommands;
|
||||
utils::Slice<const CustomCommandFn> mCustomCommands;
|
||||
BufferObjectSharedHandle mInstancedUboHandle;
|
||||
DescriptorSetSharedHandle mInstancedDescriptorSetHandle;
|
||||
ColorPassDescriptorSet const* mColorPassDescriptorSet = nullptr;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user