Skip to content

Commit

Permalink
Use 4 background threads for shader compiler on PowerVR
Browse files Browse the repository at this point in the history
Since powervr supports parallel shader compilation well, we use 
4 background threads for shader compilation.
  • Loading branch information
pixelflinger committed Aug 10, 2023
1 parent bf70443 commit d86aab2
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 12 deletions.
25 changes: 21 additions & 4 deletions filament/backend/src/opengl/ShaderCompilerService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,15 @@ ShaderCompilerService::CompilerThreadPool::~CompilerThreadPool() noexcept {
}

void ShaderCompilerService::CompilerThreadPool::init(
bool useSharedContexts, uint32_t threadCount, OpenGLPlatform& platform) noexcept {
bool useSharedContexts, uint32_t threadCount, JobSystem::Priority priority,
OpenGLPlatform& platform) noexcept {

for (size_t i = 0; i < threadCount; i++) {
mCompilerThreads.emplace_back([this, useSharedContexts, &platform]() {
mCompilerThreads.emplace_back([this, useSharedContexts, priority, &platform]() {
// give the thread a name
JobSystem::setThreadName("CompilerThreadPool");
// run at a slightly lower priority than other filament threads
JobSystem::setThreadPriority(priority);

// create a gl context current to this thread
platform.createContext(useSharedContexts);
Expand Down Expand Up @@ -256,9 +259,23 @@ void ShaderCompilerService::init() noexcept {
// a shared context, so parallel shader compilation yields no benefit.
// - on windows/linux we could use more threads, tbd.
if (mDriver.mPlatform.isExtraContextSupported()) {
mShaderCompilerThreadCount = 1;
// By default, we use one thread at the same priority as the gl thread. This is the
// safest choice that avoids priority inversions.
uint32_t poolSize = 1;
JobSystem::Priority priority = JobSystem::Priority::DISPLAY;

auto const& renderer = mDriver.getContext().state.renderer;
if (UTILS_UNLIKELY(strstr(renderer, "PowerVR"))) {
// The PowerVR driver support parallel shader compilation well, so we use 4
// threads, we can use lower priority threads here because urgent compilations
// will most likely happen on the main gl thread.
poolSize = 4;
priority = JobSystem::Priority::BACKGROUND;
}

mShaderCompilerThreadCount = poolSize;
mCompilerThreadPool.init(mUseSharedContext,
mShaderCompilerThreadCount, mDriver.mPlatform);
mShaderCompilerThreadCount, priority, mDriver.mPlatform);
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions filament/backend/src/opengl/ShaderCompilerService.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
#include <backend/Program.h>

#include <utils/CString.h>
#include <utils/Invocable.h>
#include <utils/FixedCapacityVector.h>
#include <utils/Invocable.h>
#include <utils/JobSystem.h>

#include <atomic>
#include <condition_variable>
Expand Down Expand Up @@ -97,7 +98,8 @@ class ShaderCompilerService {
CompilerThreadPool() noexcept;
~CompilerThreadPool() noexcept;
using Job = utils::Invocable<void()>;
void init(bool useSharedContexts, uint32_t threadCount, OpenGLPlatform& platform) noexcept;
void init(bool useSharedContexts, uint32_t threadCount, utils::JobSystem::Priority priority,
OpenGLPlatform& platform) noexcept;
void terminate() noexcept;
void queue(CompilerPriorityQueue priorityQueue, program_token_t const& token, Job&& job);
Job dequeue(program_token_t const& token);
Expand Down
3 changes: 2 additions & 1 deletion libs/utils/include/utils/JobSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,8 @@ class JobSystem {
enum class Priority {
NORMAL,
DISPLAY,
URGENT_DISPLAY
URGENT_DISPLAY,
BACKGROUND
};

static void setThreadPriority(Priority priority) noexcept;
Expand Down
25 changes: 20 additions & 5 deletions libs/utils/src/JobSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ static constexpr bool DEBUG_FINISH_HANGS = false;
#include <utils/JobSystem.h>

#include <utils/compiler.h>
#include <utils/Log.h>
#include <utils/memalign.h>
#include <utils/Panic.h>
#include <utils/Systrace.h>
Expand All @@ -46,16 +47,20 @@ static constexpr bool DEBUG_FINISH_HANGS = false;
#endif

#ifdef __ANDROID__
// see https://developer.android.com/topic/performance/threads#priority
# include <sys/time.h>
# include <sys/resource.h>
# ifndef ANDROID_PRIORITY_URGENT_DISPLAY
# define ANDROID_PRIORITY_URGENT_DISPLAY -8 // see include/system/thread_defs.h
# define ANDROID_PRIORITY_URGENT_DISPLAY (-8)
# endif
# ifndef ANDROID_PRIORITY_DISPLAY
# define ANDROID_PRIORITY_DISPLAY -4 // see include/system/thread_defs.h
# define ANDROID_PRIORITY_DISPLAY (-4)
# endif
# ifndef ANDROID_PRIORITY_NORMAL
# define ANDROID_PRIORITY_NORMAL 0 // see include/system/thread_defs.h
# define ANDROID_PRIORITY_NORMAL (0)
# endif
# ifndef ANDROID_PRIORITY_BACKGROUND
# define ANDROID_PRIORITY_BACKGROUND (10)
# endif
#elif defined(__linux__)
// There is no glibc wrapper for gettid on linux so we need to syscall it.
Expand Down Expand Up @@ -97,6 +102,9 @@ void JobSystem::setThreadPriority(Priority priority) noexcept {
#ifdef __ANDROID__
int androidPriority = 0;
switch (priority) {
case Priority::BACKGROUND:
androidPriority = ANDROID_PRIORITY_BACKGROUND;
break;
case Priority::NORMAL:
androidPriority = ANDROID_PRIORITY_NORMAL;
break;
Expand All @@ -107,7 +115,14 @@ void JobSystem::setThreadPriority(Priority priority) noexcept {
androidPriority = ANDROID_PRIORITY_URGENT_DISPLAY;
break;
}
setpriority(PRIO_PROCESS, 0, androidPriority);
errno = 0;
UTILS_UNUSED_IN_RELEASE int error;
error = setpriority(PRIO_PROCESS, 0, androidPriority);
#ifndef NDEBUG
if (UTILS_UNLIKELY(error)) {
slog.w << "setpriority failed: " << strerror(errno) << io::endl;
}
#endif
#endif
}

Expand Down Expand Up @@ -591,7 +606,7 @@ void JobSystem::adopt() {
"Too many calls to adopt(). No more adoptable threads!");

// all threads adopted by the JobSystem need to run at the same priority
JobSystem::setThreadPriority(JobSystem::Priority::DISPLAY);
JobSystem::setThreadPriority(Priority::DISPLAY);

// This thread's queue will be selectable immediately (i.e.: before we set its TLS)
// however, it's not a problem since mThreadState is pre-initialized and valid
Expand Down

0 comments on commit d86aab2

Please sign in to comment.