Merge pull request #16864 from hrydgard/gl-refactor-breakout

GL refactor: Breakout a couple of commits
This commit is contained in:
Henrik Rydgård 2023-01-30 11:49:08 +01:00 committed by GitHub
commit a410ea5535
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 90 deletions

View File

@ -1166,17 +1166,20 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
glBindBuffer(GL_ARRAY_BUFFER, buf);
curArrayBuffer = buf;
}
int enable = layout->semanticsMask_ & ~attrMask;
int disable = (~layout->semanticsMask_) & attrMask;
for (int i = 0; i < 7; i++) { // SEM_MAX
if (enable & (1 << i)) {
glEnableVertexAttribArray(i);
}
if (disable & (1 << i)) {
glDisableVertexAttribArray(i);
if (attrMask != layout->semanticsMask_) {
int enable = layout->semanticsMask_ & ~attrMask;
int disable = (~layout->semanticsMask_) & attrMask;
for (int i = 0; i < 7; i++) { // SEM_MAX
if (enable & (1 << i)) {
glEnableVertexAttribArray(i);
}
if (disable & (1 << i)) {
glDisableVertexAttribArray(i);
}
}
attrMask = layout->semanticsMask_;
}
attrMask = layout->semanticsMask_;
for (size_t i = 0; i < layout->entries.size(); i++) {
auto &entry = layout->entries[i];
glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, entry.stride, (const void *)(c.bindVertexBuffer.offset + entry.offset));

View File

@ -512,59 +512,12 @@ void GLRenderManager::Finish() {
insideFrame_ = false;
}
void GLRenderManager::BeginSubmitFrame(int frame) {
// Render thread
void GLRenderManager::Run(int frame) {
FrameData &frameData = frameData_[frame];
if (!frameData.hasBegun) {
frameData.hasBegun = true;
}
}
// Render thread
void GLRenderManager::Submit(int frame, bool triggerFence) {
FrameData &frameData = frameData_[frame];
// In GL, submission happens automatically in Run().
// When !triggerFence, we notify after syncing with Vulkan.
if (triggerFence) {
VLOG("PULL: Frame %d.readyForFence = true", frame);
std::unique_lock<std::mutex> lock(frameData.push_mutex);
_assert_(frameData.readyForSubmit);
frameData.readyForFence = true;
frameData.readyForSubmit = false;
frameData.push_condVar.notify_all();
}
}
// Render thread
void GLRenderManager::EndSubmitFrame(int frame) {
FrameData &frameData = frameData_[frame];
frameData.hasBegun = false;
Submit(frame, true);
if (!frameData.skipSwap) {
if (swapIntervalChanged_) {
swapIntervalChanged_ = false;
if (swapIntervalFunction_) {
swapIntervalFunction_(swapInterval_);
}
}
if (swapFunction_) {
swapFunction_();
}
} else {
frameData.skipSwap = false;
}
}
// Render thread
void GLRenderManager::Run(int frame) {
BeginSubmitFrame(frame);
FrameData &frameData = frameData_[frame];
auto &stepsOnThread = frameData_[frame].steps;
auto &initStepsOnThread = frameData_[frame].initSteps;
@ -600,11 +553,42 @@ void GLRenderManager::Run(int frame) {
switch (frameData.type) {
case GLRRunType::END:
EndSubmitFrame(frame);
frameData.hasBegun = false;
VLOG("PULL: Frame %d.readyForFence = true", frame);
{
std::unique_lock<std::mutex> lock(frameData.push_mutex);
_assert_(frameData.readyForSubmit);
frameData.readyForFence = true;
frameData.readyForSubmit = false;
frameData.push_condVar.notify_all();
}
if (!frameData.skipSwap) {
if (swapIntervalChanged_) {
swapIntervalChanged_ = false;
if (swapIntervalFunction_) {
swapIntervalFunction_(swapInterval_);
}
}
if (swapFunction_) {
swapFunction_();
}
} else {
frameData.skipSwap = false;
}
break;
case GLRRunType::SYNC:
EndSyncFrame(frame);
// glFinish is not actually necessary here, and won't be unless we start using
// glBufferStorage. Then we need to use fences.
{
std::unique_lock<std::mutex> lock(frameData.push_mutex);
frameData.readyForFence = true;
frameData.readyForSubmit = true;
frameData.push_condVar.notify_all();
}
break;
default:
@ -641,27 +625,6 @@ void GLRenderManager::FlushSync() {
}
}
// Render thread
void GLRenderManager::EndSyncFrame(int frame) {
FrameData &frameData = frameData_[frame];
Submit(frame, false);
// glFinish is not actually necessary here, and won't be until we start using
// glBufferStorage. Then we need to use fences.
// glFinish();
// At this point we can resume filling the command buffers for the current frame since
// we know the device is idle - and thus all previously enqueued command buffers have been processed.
// No need to switch to the next frame number.
{
std::unique_lock<std::mutex> lock(frameData.push_mutex);
frameData.readyForFence = true;
frameData.readyForSubmit = true;
frameData.push_condVar.notify_all();
}
}
void GLRenderManager::Wipe() {
initSteps_.clear();
for (auto step : steps_) {

View File

@ -395,9 +395,15 @@ public:
GLRenderManager() {}
~GLRenderManager();
void SetInvalidationCallback(InvalidationCallback callback) {
invalidationCallback_ = callback;
}
void ThreadStart(Draw::DrawContext *draw);
void ThreadEnd();
bool ThreadFrame(); // Returns false to request exiting the loop.
void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {
queueRunner_.SetErrorCallback(callback, userdata);
}
@ -406,10 +412,6 @@ public:
caps_ = caps;
}
void ThreadStart(Draw::DrawContext *draw);
void ThreadEnd();
bool ThreadFrame(); // Returns false to request exiting the loop.
// Makes sure that the GPU has caught up enough that we can start writing buffers of this frame again.
void BeginFrame();
// Can run on a different thread!
@ -1014,13 +1016,8 @@ public:
}
private:
void BeginSubmitFrame(int frame);
void EndSubmitFrame(int frame);
void Submit(int frame, bool triggerFence);
// Bad for performance but sometimes necessary for synchronous CPU readbacks (screenshots and whatnot).
void FlushSync();
void EndSyncFrame(int frame);
// When using legacy functionality for push buffers (glBufferData), we need to flush them
// before actually making the glDraw* calls. It's best if the render manager handles that.