rework shader pre-compilation

This commit is contained in:
SamGondelman 2018-11-27 14:38:02 -08:00
parent 372f4390e8
commit 1f354f813c
13 changed files with 75 additions and 45 deletions

View file

@ -2862,6 +2862,13 @@ void Application::initializeGL() {
_glWidget->makeCurrent();
_gpuContext = std::make_shared<gpu::Context>();
static std::once_flag once;
std::call_once(once, [&] {
_gpuContext->pushProgramsToSync(shader::allPrograms(), [this] {
_programsCompiled.store(true);
}, 1);
});
DependencyManager::get<TextureCache>()->setGPUContext(_gpuContext);
}

View file

@ -795,5 +795,7 @@ private:
bool _prevShowTrackedObjects { false };
std::shared_ptr<ProceduralSkybox> _splashScreen { std::make_shared<ProceduralSkybox>() };
std::atomic<bool> _programsCompiled { false };
};
#endif // hifi_Application_h

View file

@ -115,7 +115,7 @@ void Application::paintGL() {
finalFramebuffer = framebufferCache->getFramebuffer();
}
if (!displayPlugin->areAllProgramsLoaded()) {
if (!_programsCompiled.load()) {
gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) {
batch.setFramebuffer(finalFramebuffer);
batch.enableSkybox(true);

View file

@ -525,6 +525,9 @@ void OpenGLDisplayPlugin::updateFrameData() {
if (_newFrameQueue.size() > 1) {
_droppedFrameRate.increment(_newFrameQueue.size() - 1);
}
_gpuContext->processProgramsToSync();
while (!_newFrameQueue.empty()) {
_currentFrame = _newFrameQueue.front();
_newFrameQueue.pop();
@ -633,29 +636,11 @@ void OpenGLDisplayPlugin::internalPresent() {
_presentRate.increment();
}
std::atomic<bool> OpenGLDisplayPlugin::_allProgramsLoaded { false };
unsigned int OpenGLDisplayPlugin::_currentLoadingProgramIndex { 0 };
bool OpenGLDisplayPlugin::areAllProgramsLoaded() const {
return OpenGLDisplayPlugin::_allProgramsLoaded.load();
}
void OpenGLDisplayPlugin::present() {
auto frameId = (uint64_t)presentCount();
PROFILE_RANGE_EX(render, __FUNCTION__, 0xffffff00, frameId)
uint64_t startPresent = usecTimestampNow();
if (!OpenGLDisplayPlugin::_allProgramsLoaded.load()) {
const auto& programIDs = shader::allPrograms();
if (OpenGLDisplayPlugin::_currentLoadingProgramIndex < programIDs.size()) {
gpu::doInBatch("createAndSyncProgram", _gpuContext, [&programIDs](gpu::Batch& batch) {
batch.createAndSyncProgram(programIDs.at(OpenGLDisplayPlugin::_currentLoadingProgramIndex++));
});
} else {
OpenGLDisplayPlugin::_allProgramsLoaded.store(true);
}
}
{
PROFILE_RANGE_EX(render, "updateFrameData", 0xff00ff00, frameId)
updateFrameData();

View file

@ -83,8 +83,6 @@ public:
void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override;
bool areAllProgramsLoaded() const override;
protected:
friend class PresentThread;
@ -182,8 +180,5 @@ protected:
// be serialized through this mutex
mutable Mutex _presentMutex;
float _hudAlpha{ 1.0f };
static std::atomic<bool> _allProgramsLoaded;
static unsigned int _currentLoadingProgramIndex;
};

View file

@ -102,8 +102,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::gl::GLBackend::do_pushProfileRange),
(&::gpu::gl::GLBackend::do_popProfileRange),
(&::gpu::gl::GLBackend::do_createAndSyncProgram),
};
#define GL_GET_INTEGER(NAME) glGetIntegerv(GL_##NAME, &const_cast<GLint&>(NAME));
@ -708,11 +706,6 @@ void GLBackend::do_glColor4f(const Batch& batch, size_t paramOffset) {
(void)CHECK_GL_ERROR();
}
void GLBackend::do_createAndSyncProgram(const Batch& batch, size_t paramOffset) {
auto shader = gpu::Shader::createProgram(batch._params[paramOffset + 0]._uint);
gpu::gl::GLShader::sync(*this, *shader);
}
void GLBackend::releaseBuffer(GLuint id, Size size) const {
Lock lock(_trashMutex);
_currentFrameTrash.buffersTrash.push_back({ id, size });
@ -866,3 +859,7 @@ void GLBackend::setCameraCorrection(const Mat4& correction, const Mat4& prevRend
_pipeline._cameraCorrectionBuffer._buffer->setSubData(0, _transform._correction);
_pipeline._cameraCorrectionBuffer._buffer->flush();
}
void GLBackend::syncProgram(const gpu::ShaderPointer& program) {
gpu::gl::GLShader::sync(*this, *program);
}

View file

@ -249,6 +249,8 @@ public:
// Let's try to avoid to do that as much as possible!
void syncCache() final override;
void syncProgram(const gpu::ShaderPointer& program) override;
// This is the ugly "download the pixels to sysmem for taking a snapshot"
// Just avoid using it, it's ugly and will break performances
virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer,
@ -380,8 +382,6 @@ public:
virtual void do_setStateBlendFactor(const Batch& batch, size_t paramOffset) final;
virtual void do_setStateScissorRect(const Batch& batch, size_t paramOffset) final;
virtual void do_createAndSyncProgram(const Batch& batch, size_t paramOffset) final;
virtual GLuint getFramebufferID(const FramebufferPointer& framebuffer) = 0;
virtual GLuint getTextureID(const TexturePointer& texture) final;
virtual GLuint getBufferID(const Buffer& buffer) = 0;

View file

@ -759,10 +759,4 @@ void Batch::flush() {
}
buffer->flush();
}
}
void Batch::createAndSyncProgram(unsigned int programID) {
ADD_COMMAND(createAndSyncProgram);
_params.emplace_back(programID);
}

View file

@ -289,8 +289,6 @@ public:
void _glColor4f(float red, float green, float blue, float alpha);
void createAndSyncProgram(unsigned int programID);
// Maybe useful but shoudln't be public. Please convince me otherwise
// Well porting to gles i need it...
void runLambda(std::function<void()> f);
@ -370,8 +368,6 @@ public:
COMMAND_pushProfileRange,
COMMAND_popProfileRange,
COMMAND_createAndSyncProgram,
NUM_COMMANDS,
};
typedef std::vector<Command> Commands;

View file

@ -335,6 +335,39 @@ Size Context::getTextureResourceIdealGPUMemSize() {
return Backend::textureResourceIdealGPUMemSize.getValue();
}
void Context::pushProgramsToSync(const std::vector<uint32_t>& programIDs, std::function<void()> callback, size_t rate) {
std::vector<gpu::ShaderPointer> programs;
for (auto programID : programIDs) {
programs.push_back(gpu::Shader::createProgram(programID));
}
pushProgramsToSync(programs, callback, rate);
}
void Context::pushProgramsToSync(const std::vector<gpu::ShaderPointer>& programs, std::function<void()> callback, size_t rate) {
Lock lock(_programsToSyncMutex);
_programsToSyncQueue.emplace(programs, callback, rate == 0 ? programs.size() : rate);
}
void Context::processProgramsToSync() {
Lock lock(_programsToSyncMutex);
if (!_programsToSyncQueue.empty()) {
ProgramsToSync programsToSync = _programsToSyncQueue.front();
int numSynced = 0;
while (_nextProgramToSyncIndex < programsToSync.programs.size() && numSynced < programsToSync.rate) {
auto nextProgram = programsToSync.programs.at(_nextProgramToSyncIndex);
_backend->syncProgram(nextProgram);
_syncedPrograms.push_back(nextProgram);
_nextProgramToSyncIndex++;
numSynced++;
}
if (_nextProgramToSyncIndex == programsToSync.programs.size()) {
programsToSync.callback();
_nextProgramToSyncIndex = 0;
_programsToSyncQueue.pop();
}
}
}
BatchPointer Context::acquireBatch(const char* name) {
Batch* rawBatch = nullptr;

View file

@ -13,6 +13,7 @@
#include <assert.h>
#include <mutex>
#include <queue>
#include <GLMHelpers.h>
@ -61,6 +62,7 @@ public:
virtual void render(const Batch& batch) = 0;
virtual void syncCache() = 0;
virtual void syncProgram(const gpu::ShaderPointer& program) = 0;
virtual void recycle() const = 0;
virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0;
@ -245,6 +247,20 @@ public:
static Size getTextureResourcePopulatedGPUMemSize();
static Size getTextureResourceIdealGPUMemSize();
struct ProgramsToSync {
ProgramsToSync(const std::vector<gpu::ShaderPointer>& programs, std::function<void()> callback, size_t rate) :
programs(programs), callback(callback), rate(rate) {}
std::vector<gpu::ShaderPointer> programs;
std::function<void()> callback;
size_t rate;
};
void pushProgramsToSync(const std::vector<uint32_t>& programIDs, std::function<void()> callback, size_t rate = 0);
void pushProgramsToSync(const std::vector<gpu::ShaderPointer>& programs, std::function<void()> callback, size_t rate = 0);
void processProgramsToSync();
protected:
Context(const Context& context);
@ -256,6 +272,11 @@ protected:
RangeTimerPointer _frameRangeTimer;
StereoState _stereo;
std::mutex _programsToSyncMutex;
std::queue<ProgramsToSync> _programsToSyncQueue;
gpu::Shaders _syncedPrograms;
size_t _nextProgramToSyncIndex { 0 };
// Sampled at the end of every frame, the stats of all the counters
mutable ContextStats _frameStats;

View file

@ -43,6 +43,8 @@ public:
// Let's try to avoid to do that as much as possible!
void syncCache() final { }
void syncProgram(const gpu::ShaderPointer& program) final {}
// This is the ugly "download the pixels to sysmem for taking a snapshot"
// Just avoid using it, it's ugly and will break performances
virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) final { }

View file

@ -217,8 +217,6 @@ public:
static const QString& MENU_PATH();
virtual bool areAllProgramsLoaded() const { return true; }
signals:
void recommendedFramebufferSizeChanged(const QSize& size);
void resetSensorsRequested();