Skip to content

Commit

Permalink
[opengl] Fix GLES support (#6121)
Browse files Browse the repository at this point in the history
Issue: #5769 

### Brief Summary
GLES support was broken since the migration to spirv-based codegen and
this PR is the first step to bring it back. Also added a bunch of
`check_opengl_error` calls to make debugging easier.
Note thorough testing for GLES backend is currently missing and should
be added in followup PRs.
  • Loading branch information
ailzhang authored Sep 21, 2022
1 parent 9eae78d commit a4b24d1
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 8 deletions.
9 changes: 7 additions & 2 deletions taichi/rhi/opengl/opengl_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ bool initialize_opengl(bool use_gles, bool error_tolerance) {
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
}
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
#if defined(__APPLE__)
glfwWindowHint(GLFW_COCOA_MENUBAR, GLFW_FALSE);
#endif
// GL context needs a window (when using GLFW)
GLFWwindow *window =
glfwCreateWindow(1, 1, "Make OpenGL Context", nullptr, nullptr);
Expand Down Expand Up @@ -206,8 +208,11 @@ bool is_gles() {

std::shared_ptr<Device> make_opengl_device() {
std::shared_ptr<Device> dev = std::make_shared<GLDevice>();
dev->set_cap(DeviceCapability::spirv_has_int64, true);
dev->set_cap(DeviceCapability::spirv_has_float64, true);
if (!is_gles()) {
// 64bit isn't supported in ES profile
dev->set_cap(DeviceCapability::spirv_has_int64, true);
dev->set_cap(DeviceCapability::spirv_has_float64, true);
}
dev->set_cap(DeviceCapability::spirv_version, 0x10300);
return dev;
}
Expand Down
42 changes: 37 additions & 5 deletions taichi/rhi/opengl/opengl_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ GLPipeline::GLPipeline(const PipelineSourceDesc &desc,
const std::string &name) {
GLuint shader_id;
shader_id = glCreateShader(GL_COMPUTE_SHADER);
check_opengl_error("glCreateShader");

if (desc.type == PipelineSourceType::glsl_src) {
const GLchar *source_cstr = (const GLchar *)desc.data;
Expand All @@ -261,9 +262,13 @@ GLPipeline::GLPipeline(const PipelineSourceDesc &desc,
spirv_cross::CompilerGLSL glsl((uint32_t *)desc.data,
desc.size / sizeof(uint32_t));
spirv_cross::CompilerGLSL::Options options;
options.es = is_gles();
if (is_gles()) {
options.es = true;
options.version = 310;
} else {
options.enable_420pack_extension = true;
}
options.vulkan_semantics = false;
options.enable_420pack_extension = true;
glsl.set_common_options(options);
std::string source = glsl.compile();
TI_TRACE("GLSL source: \n{}", source);
Expand All @@ -277,37 +282,50 @@ GLPipeline::GLPipeline(const PipelineSourceDesc &desc,
}

glCompileShader(shader_id);
check_opengl_error("glCompileShader");
int status = GL_TRUE;
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &status);
check_opengl_error("glGetShaderiv");
if (status != GL_TRUE) {
GLsizei logLength;
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &logLength);
check_opengl_error("glGetShaderiv");

auto log = std::vector<GLchar>(logLength + 1);
glGetShaderInfoLog(shader_id, logLength, &logLength, log.data());
check_opengl_error("glGetShaderInfoLog");

log[logLength] = 0;
TI_ERROR("[glsl] error while compiling shader:\n{}", log.data());
}
check_opengl_error();

program_id_ = glCreateProgram();
check_opengl_error("glCreateProgram");
glAttachShader(program_id_, shader_id);
check_opengl_error("glAttachShader");
glLinkProgram(program_id_);
check_opengl_error("glLinkProgram");
glGetProgramiv(program_id_, GL_LINK_STATUS, &status);
check_opengl_error("glGetProgramiv");
if (status != GL_TRUE) {
GLsizei logLength;
glGetProgramiv(program_id_, GL_INFO_LOG_LENGTH, &logLength);
check_opengl_error("glGetProgramiv");
auto log = std::vector<GLchar>(logLength + 1);
glGetProgramInfoLog(program_id_, logLength, &logLength, log.data());
check_opengl_error("glGetProgramInfoLog");
log[logLength] = 0;
TI_ERROR("[glsl] error while linking program:\n{}", log.data());
}
check_opengl_error();

glDeleteShader(shader_id);
check_opengl_error("glDeleteShader");
}

GLPipeline::~GLPipeline() {
glDeleteProgram(program_id_);
check_opengl_error("glDeleteShader");
}

ResourceBinder *GLPipeline::resource_binder() {
Expand Down Expand Up @@ -489,12 +507,14 @@ StreamSemaphore GLStream::submit_synced(
const std::vector<StreamSemaphore> &wait_semaphores) {
submit(cmdlist);
glFinish();
check_opengl_error("glFinish");

// OpenGL is fully serial
return nullptr;
}
void GLStream::command_sync() {
glFinish();
check_opengl_error("glFinish");
}

GLDevice::GLDevice() : stream_(this) {
Expand Down Expand Up @@ -553,6 +573,7 @@ GLint GLDevice::get_devalloc_size(DeviceAllocation handle) {
check_opengl_error("glGetBufferParameteriv");
return size;
glBindBuffer(GL_ARRAY_BUFFER, 0);
check_opengl_error("glBindBuffer");
}

std::unique_ptr<Pipeline> GLDevice::create_pipeline(
Expand All @@ -576,7 +597,11 @@ void *GLDevice::map_range(DevicePtr ptr, uint64_t size) {
void *GLDevice::map(DeviceAllocation alloc) {
int size = 0;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, alloc.alloc_id);
check_opengl_error("glBindBuffer");

glGetBufferParameteriv(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size);
check_opengl_error("glGetBufferParameteriv");

return map_range(alloc.get_ptr(0), size);
}

Expand Down Expand Up @@ -604,6 +629,7 @@ void GLDevice::memcpy_internal(DevicePtr dst, DevicePtr src, uint64_t size) {
dst.offset, size);
check_opengl_error("glCopyBufferSubData");
glFinish();
check_opengl_error("glFinish");
}

Stream *GLDevice::get_compute_stream() {
Expand All @@ -629,6 +655,7 @@ Stream *GLDevice::get_graphics_stream() {

void GLDevice::wait_idle() {
glFinish();
check_opengl_error("glFinish");
}

std::unique_ptr<Surface> GLDevice::create_surface(const SurfaceConfig &config) {
Expand Down Expand Up @@ -686,6 +713,7 @@ void GLDevice::image_transition(DeviceAllocation img,
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT |
GL_SHADER_IMAGE_ACCESS_BARRIER_BIT |
GL_FRAMEBUFFER_BARRIER_BIT);
check_opengl_error("glMemoryBarrier");
}

void GLDevice::buffer_to_image(DeviceAllocation dst_img,
Expand Down Expand Up @@ -779,8 +807,8 @@ void GLCommandList::CmdBufferFill::execute() {
glGetBufferParameteriv(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &buf_size);
check_opengl_error("glGetBufferParameteriv");
if (is_gles()) {
TI_ASSERT(offset == 0 && data == 0 && size == buf_size &&
"GLES only supports full clear");
TI_ASSERT_INFO(offset == 0 && data == 0 && size >= buf_size,
"GLES only supports full clear");
glBufferData(GL_SHADER_STORAGE_BUFFER, buf_size, nullptr, GL_DYNAMIC_READ);
check_opengl_error("glBufferData");
} else {
Expand All @@ -793,12 +821,14 @@ void GLCommandList::CmdBufferFill::execute() {

void GLCommandList::CmdDispatch::execute() {
glDispatchCompute(x, y, z);
check_opengl_error("glDispatchCompute");
}

void GLCommandList::CmdImageTransition::execute() {
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT |
GL_SHADER_IMAGE_ACCESS_BARRIER_BIT |
GL_FRAMEBUFFER_BARRIER_BIT);
check_opengl_error("glMemoryBarrier");
}

void GLCommandList::CmdBufferToImage::execute() {
Expand Down Expand Up @@ -830,7 +860,9 @@ void GLCommandList::CmdBufferToImage::execute() {
}
check_opengl_error("glTexSubImage");
glBindTexture(image_dims, /*target=*/0);
check_opengl_error("glBindTexture");
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, /*target=*/0);
check_opengl_error("glBindBuffer");
}

void GLCommandList::CmdImageToBuffer::execute() {
Expand Down
4 changes: 3 additions & 1 deletion tests/python/test_aot.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,10 @@ def test_non_dense_snode():
m.add_field('y', y)


@pytest.mark.parametrize('use_gles', [True, False])
@test_utils.test(arch=[ti.opengl, ti.vulkan])
def test_mpm88_aot():
def test_mpm88_aot(use_gles):
ti.init(ti.lang.impl.current_cfg().arch, use_gles=use_gles)
n_particles = 8192
n_grid = 128
dx = 1 / n_grid
Expand Down

0 comments on commit a4b24d1

Please sign in to comment.