[Fix] (Shader): Finally fix atomicCounter emulation.

This commit is contained in:
BZLZHH 2025-07-28 17:18:49 +08:00
parent 2d10487fc4
commit a61dd20947
4 changed files with 81 additions and 29 deletions

View File

@ -73,7 +73,10 @@ void temporarilyBindBuffer(GLuint bufferID, GLenum target = GL_ARRAY_BUFFER) {
GLenum bindingQuery = GetBindingQuery(target);
GLint prev = 0;
glGetIntegerv(bindingQuery, &prev);
if (prev == bufferID) {
bufferBindingStack[target].push_back(-1);
return;
}
bufferBindingStack[target].push_back(static_cast<GLuint>(prev));
LOG_D("[DSA] [TempBind] target=0x%X, prev=%u -> bind=%u", target, prev, bufferID);
@ -91,6 +94,11 @@ void restoreTemporaryBufferBinding(GLenum target = GL_ARRAY_BUFFER) {
GLuint toRestore = it->second.back();
it->second.pop_back();
if (toRestore == static_cast<GLuint>(-1)) {
LOG_D("[DSA] [Restore] target=0x%X, no binding to restore", target);
return;
}
LOG_D("[DSA] [Restore] target=0x%X, bind back to %u", target, toRestore);
CHECK_GL_ERROR;
glBindBuffer(target, toRestore);
@ -374,6 +382,10 @@ void temporarilyBindFramebuffer(GLuint framebufferID, GLenum target = GL_DRAW_FR
GLenum bindingQuery = GetBindingQuery(target);
GLint prev = 0;
glGetIntegerv(bindingQuery, &prev);
if (prev == framebufferID) {
framebufferBindingStack[target].push_back(-1);
return;
}
framebufferBindingStack[target].push_back(static_cast<GLuint>(prev));
LOG_D("[DSA] [TempBind] target=0x%X, prev=%u -> bind=%u", target, prev, framebufferID);
CHECK_GL_ERROR;
@ -388,6 +400,10 @@ void restoreTemporaryFramebufferBinding(GLenum target = GL_DRAW_FRAMEBUFFER) {
}
GLuint toRestore = it->second.back();
it->second.pop_back();
if (toRestore == static_cast<GLuint>(-1)) {
LOG_D("[DSA] [Restore] target=0x%X, no binding to restore", target);
return;
}
LOG_D("[DSA] [Restore] target=0x%X, bind back to %u", target, toRestore);
CHECK_GL_ERROR;
glBindFramebuffer(target, toRestore);
@ -674,6 +690,10 @@ void temporarilyBindRenderbuffer(GLuint renderbufferID) {
GLenum bindingQuery = GetBindingQuery(GL_RENDERBUFFER);
GLint prev = 0;
glGetIntegerv(bindingQuery, &prev);
if (prev == renderbufferID) {
renderbufferBindingStack[GL_RENDERBUFFER].push_back(-1);
return;
}
renderbufferBindingStack[GL_RENDERBUFFER].push_back(static_cast<GLuint>(prev));
LOG_D("[DSA] [TempBind] prev=%u -> bind=%u", prev, renderbufferID);
CHECK_GL_ERROR;
@ -688,6 +708,10 @@ void restoreTemporaryRenderbufferBinding() {
}
GLuint toRestore = it->second.back();
it->second.pop_back();
if (toRestore == static_cast<GLuint>(-1)) {
LOG_D("[DSA] [Restore] no binding to restore for GL_RENDERBUFFER");
return;
}
LOG_D("[DSA] [Restore] bind back to %u", toRestore);
CHECK_GL_ERROR;
glBindRenderbuffer(GL_RENDERBUFFER, toRestore);
@ -776,6 +800,10 @@ void temporarilyBindTexture(GLuint textureID, GLenum possibleTarget = 0) {
GLenum bindingQuery = GetBindingQuery(target, true);
GLint prev = 0;
glGetIntegerv(bindingQuery, &prev);
if (prev == static_cast<GLint>(textureID)) {
textureBindingStack[target].push_back(-1);
return;
}
textureBindingStack[target].push_back(static_cast<GLuint>(prev));
LOG_D("[DSA] [TempBind] target=0x%X, prev=%u -> bind=%u", target, prev, textureID);
CHECK_GL_ERROR;
@ -793,6 +821,10 @@ void restoreTemporaryTextureBinding(GLuint textureID, GLenum possibleTarget = 0)
GLuint toRestore = stackIt->second.back();
stackIt->second.pop_back();
if (toRestore == static_cast<GLuint>(-1)) {
LOG_D("[DSA] [Restore] target=0x%X, no binding to restore", target);
return;
}
LOG_D("[DSA] [Restore] target=0x%X, bind back to %u", target, toRestore);
CHECK_GL_ERROR;
glBindTexture(target, toRestore);
@ -1108,9 +1140,10 @@ void glGetTextureParameteriv(GLuint texture, GLenum pname, GLint* params) {
}
// vertex array
static thread_local GLint prevVAO = 0;
static thread_local GLint prevVAO = -1;
void temporarilyBindVertexArray(GLint vaoID) {
if (prevVAO == vaoID) {
prevVAO = -1;
return;
}
LOG_D("[DSA] [TempBind] VAO: %u -> bind=%u", prevVAO, vaoID);
@ -1120,14 +1153,14 @@ void temporarilyBindVertexArray(GLint vaoID) {
CHECK_GL_ERROR_NO_INIT;
}
void restoreTemporaryVertexArrayBinding() {
if (prevVAO == 0) {
if (prevVAO == -1) {
return;
}
LOG_D("[DSA] [Restore] VAO: bind back to %u", prevVAO);
CHECK_GL_ERROR;
glBindVertexArray(prevVAO);
CHECK_GL_ERROR_NO_INIT;
prevVAO = 0;
prevVAO = -1;
}
void glCreateVertexArrays(GLsizei n, GLuint* arrays) {
@ -1503,6 +1536,10 @@ static void pushXFB(GLuint xfb) {
LOG_D("[DSA] pushXFB, xfb: %u", xfb);
GLint prev = 0;
glGetIntegerv(GL_TRANSFORM_FEEDBACK_BINDING, &prev);
if (xfb == prev) {
g_xfbBindingStack.push_back(-1);
return;
}
g_xfbBindingStack.push_back(prev);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
CHECK_GL_ERROR;
@ -1513,6 +1550,10 @@ static void popXFB() {
assert(!g_xfbBindingStack.empty());
GLint prev = g_xfbBindingStack.back();
g_xfbBindingStack.pop_back();
if (prev == -1) {
LOG_D("[DSA] No previous XFB binding to restore");
return;
}
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, (GLuint)prev);
CHECK_GL_ERROR;
}

View File

@ -233,6 +233,28 @@ void glBindBuffer(GLenum target, GLuint buffer) {
CHECK_GL_ERROR
}
struct atomic_buffer {
GLuint id;
GLsizeiptr size;
GLintptr offset;
};
static std::vector<atomic_buffer> g_buffer_map_atomic_buffer_info;
static std::vector<GLuint> g_buffer_map_ssbo_id; // shall we use this in the future?
void bindAllAtomicCounterAsSSBO() {
const size_t count = g_buffer_map_atomic_buffer_info.size();
for (size_t i = 0; i < count; ++i) {
atomic_buffer buf = g_buffer_map_atomic_buffer_info[i];
if (buf.id != 0) {
GLuint realID = find_real_buffer(buf.id);
GLES.glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, realID, buf.offset, buf.size);
LOG_D("Bound atomic counter buffer %u(real: %u) as SSBO at index %zu", buf, realID, i);
}
}
}
void glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
LOG()
LOG_D("glBindBufferRange, target = %s, index = %d, buffer = %d, offset = %p, size = %zi", glEnumToString(target), index, buffer, (void*) offset, size)
@ -254,6 +276,12 @@ void glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offs
CHECK_GL_ERROR
}
GLES.glBindBufferRange(target, index, real_buffer, offset, size);
if (target == GL_ATOMIC_COUNTER_BUFFER) {
if (g_buffer_map_atomic_buffer_info.empty()) {
g_buffer_map_atomic_buffer_info.resize(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, {});
}
g_buffer_map_atomic_buffer_info[index] = { buffer, size, offset };
}
CHECK_GL_ERROR
}
@ -278,6 +306,12 @@ void glBindBufferBase(GLenum target, GLuint index, GLuint buffer) {
CHECK_GL_ERROR
}
GLES.glBindBufferBase(target, index, real_buffer);
if (target == GL_SHADER_STORAGE_BUFFER) {
if (g_buffer_map_ssbo_id.empty()) {
g_buffer_map_ssbo_id.resize(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, 0);
}
g_buffer_map_ssbo_id[index] = buffer;
}
CHECK_GL_ERROR
}

View File

@ -132,30 +132,7 @@ void glUniform1i(GLint location, GLint v0) {
CHECK_GL_ERROR
}
void bindAllAtomicCounterAsSSBO() {
GLint maxBindings = 0;
GLES.glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &maxBindings);
if (maxBindings <= 0) {
LOG_W("No atomic counter buffer bindings available, maxBindings: %d", maxBindings);
return;
}
std::vector<GLuint> buffers(maxBindings, 0);
for (GLint i = 0; i < maxBindings; ++i) {
GLES.glGetIntegeri_v(GL_ATOMIC_COUNTER_BUFFER_BINDING, i, reinterpret_cast<GLint*>(&buffers[i]));
}
for (GLint i = 0; i < maxBindings; ++i) {
GLuint buf = buffers[i];
if (buf != 0) {
GLES.glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, buf);
}
}
LOG_D("Bound %d atomic counter buffers as SSBOs", maxBindings);
}
void bindAllAtomicCounterAsSSBO();
void glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) {
LOG()
LOG_D("glDispatchCompute, num_groups_x: %d, num_groups_y: %d, num_groups_z: %d",

View File

@ -563,7 +563,7 @@ bool process_non_opaque_atomic_to_ssbo(std::string& source) {
std::string matched_stmt = it->str();
result += matched_stmt;
result += "\n memoryBarrierBuffer();";
result += "\n memoryBarrierBuffer();barrier();";
processed_positions.insert(start_pos);
last_pos = end_pos;