diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index d05a80ccf2..89cf8cf4e5 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -318,12 +318,15 @@ void GLGSRender::end() } else { - glBindTexture(target, GL_NONE); + glBindTexture(target, m_null_textures[target]->id()); } } else { - glBindTexture(GL_TEXTURE_2D, GL_NONE); + glBindTexture(GL_TEXTURE_1D, m_null_textures[GL_TEXTURE_1D]->id()); + glBindTexture(GL_TEXTURE_2D, m_null_textures[GL_TEXTURE_2D]->id()); + glBindTexture(GL_TEXTURE_3D, m_null_textures[GL_TEXTURE_3D]->id()); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_null_textures[GL_TEXTURE_CUBE_MAP]->id()); } } } @@ -672,6 +675,40 @@ void GLGSRender::on_init_thread() tex.bind(); } + //Fallback null texture instead of relying on texture0 + { + std::vector pixeldata = {0, 0, 0, 0}; + + //1D + auto tex1D = std::make_unique(); + tex1D->create(); + tex1D->set_target(gl::texture::target::texture1D); + tex1D->config().width(1).min_lod(0.f).max_lod(0.f).pixels(pixeldata.data()).apply(); + + //2D + auto tex2D = std::make_unique(); + tex2D->create(); + tex2D->set_target(gl::texture::target::texture2D); + tex2D->config().width(1).height(1).min_lod(0.f).max_lod(0.f).pixels(pixeldata.data()).apply(); + + //3D + auto tex3D = std::make_unique(); + tex3D->create(); + tex3D->set_target(gl::texture::target::texture3D); + tex3D->config().width(1).height(1).depth(1).min_lod(0.f).max_lod(0.f).pixels(pixeldata.data()).apply(); + + //CUBE + auto texCUBE = std::make_unique(); + texCUBE->create(); + texCUBE->set_target(gl::texture::target::textureCUBE); + texCUBE->config().width(1).height(1).depth(1).min_lod(0.f).max_lod(0.f).pixels(pixeldata.data()).apply(); + + m_null_textures[GL_TEXTURE_1D] = std::move(tex1D); + m_null_textures[GL_TEXTURE_2D] = std::move(tex2D); + m_null_textures[GL_TEXTURE_3D] = std::move(tex3D); + m_null_textures[GL_TEXTURE_CUBE_MAP] = std::move(texCUBE); + } + if (!gl_caps.ARB_buffer_storage_supported) { LOG_WARNING(RSX, "Forcing use of legacy OpenGL buffers because ARB_buffer_storage is not supported"); @@ -844,6 +881,11 @@ void GLGSRender::on_exit() sampler.remove(); } + for (auto &tex : m_null_textures) + { + tex.second->remove(); + } + if (m_attrib_ring_buffer) { m_attrib_ring_buffer->remove(); diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 5ba2ae0005..002c96ccd2 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -330,6 +330,7 @@ private: std::atomic_bool m_samplers_dirty = {true}; std::array, rsx::limits::fragment_textures_count> fs_sampler_state = {}; std::array, rsx::limits::vertex_textures_count> vs_sampler_state = {}; + std::unordered_map> m_null_textures; public: GLGSRender(); diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.cpp b/rpcs3/Emu/RSX/GL/GLHelpers.cpp index 9a0322d6dd..bf06769279 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.cpp +++ b/rpcs3/Emu/RSX/GL/GLHelpers.cpp @@ -74,7 +74,7 @@ namespace gl { bind_as(target::read_frame_buffer); dst.bind_as(target::draw_frame_buffer); - __glcheck glBlitFramebuffer( + glBlitFramebuffer( src_area.x1, src_area.y1, src_area.x2, src_area.y2, dst_area.x1, dst_area.y1, dst_area.x2, dst_area.y2, (GLbitfield)buffers_, (GLenum)filter_); @@ -122,7 +122,7 @@ namespace gl { save_binding_state save(*this); GLenum buf = buffer.id(); - __glcheck glDrawBuffers(1, &buf); + glDrawBuffers(1, &buf); } void fbo::draw_buffers(const std::initializer_list& indexes) const @@ -134,7 +134,7 @@ namespace gl for (auto &index : indexes) ids.push_back(index.id()); - __glcheck glDrawBuffers((GLsizei)ids.size(), ids.data()); + glDrawBuffers((GLsizei)ids.size(), ids.data()); } void fbo::read_buffer(const attachment& buffer) const @@ -142,13 +142,13 @@ namespace gl save_binding_state save(*this); GLenum buf = buffer.id(); - __glcheck glReadBuffer(buf); + glReadBuffer(buf); } void fbo::draw_arrays(rsx::primitive_type mode, GLsizei count, GLint first) const { save_binding_state save(*this); - __glcheck glDrawArrays(draw_mode(mode), first, count); + glDrawArrays(draw_mode(mode), first, count); } void fbo::draw_arrays(const buffer& buffer, rsx::primitive_type mode, GLsizei count, GLint first) const @@ -166,19 +166,19 @@ namespace gl void fbo::draw_elements(rsx::primitive_type mode, GLsizei count, indices_type type, const GLvoid *indices) const { save_binding_state save(*this); - __glcheck glDrawElements(draw_mode(mode), count, (GLenum)type, indices); + glDrawElements(draw_mode(mode), count, (GLenum)type, indices); } void fbo::draw_elements(const buffer& buffer, rsx::primitive_type mode, GLsizei count, indices_type type, const GLvoid *indices) const { buffer.bind(buffer::target::array); - __glcheck glDrawElements(draw_mode(mode), count, (GLenum)type, indices); + glDrawElements(draw_mode(mode), count, (GLenum)type, indices); } void fbo::draw_elements(rsx::primitive_type mode, GLsizei count, indices_type type, const buffer& indices, size_t indices_buffer_offset) const { indices.bind(buffer::target::element_array); - __glcheck glDrawElements(draw_mode(mode), count, (GLenum)type, (GLvoid*)indices_buffer_offset); + glDrawElements(draw_mode(mode), count, (GLenum)type, (GLvoid*)indices_buffer_offset); } void fbo::draw_elements(const buffer& buffer_, rsx::primitive_type mode, GLsizei count, indices_type type, const buffer& indices, size_t indices_buffer_offset) const @@ -337,42 +337,68 @@ namespace gl } } - __glcheck glCompressedTexImage2D((GLenum)m_parent->get_target(), m_level, (GLint)m_internal_format, m_width, m_height, 0, compressed_image_size, m_pixels); + if (m_parent->get_target() != gl::texture::target::texture2D) + fmt::throw_exception("Mutable compressed texture of non-2D type is unimplemented" HERE); + + glCompressedTexImage2D((GLenum)m_parent->get_target(), m_level, (GLint)m_internal_format, m_width, m_height, 0, compressed_image_size, m_pixels); } else { - __glcheck glTexImage2D((GLenum)m_parent->get_target(), m_level, (GLint)m_internal_format, m_width, m_height, 0, (GLint)m_format, (GLint)m_type, m_pixels); + switch ((GLenum)m_parent->get_target()) + { + case GL_TEXTURE_1D: + { + glTexImage1D(GL_TEXTURE_1D, m_level, (GLint)m_internal_format, m_width, 0, (GLint)m_format, (GLint)m_type, m_pixels); + break; + } + case GL_TEXTURE_2D: + { + glTexImage2D(GL_TEXTURE_2D, m_level, (GLint)m_internal_format, m_width, m_height, 0, (GLint)m_format, (GLint)m_type, m_pixels); + break; + } + case GL_TEXTURE_3D: + { + glTexImage3D(GL_TEXTURE_3D, m_level, (GLint)m_internal_format, m_width, m_height, m_depth, 0, (GLint)m_format, (GLint)m_type, m_pixels); + break; + } + case GL_TEXTURE_CUBE_MAP: + { + for (int face = 0; face < 6; ++face) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, m_level, (GLint)m_internal_format, m_width, m_height, 0, (GLint)m_format, (GLint)m_type, m_pixels); + break; + } + } } - __glcheck glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_MAX_LEVEL, m_max_level); + glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_MAX_LEVEL, m_max_level); if (m_pixels) { - __glcheck glTexParameteri((GLenum)m_parent->get_target(), GL_GENERATE_MIPMAP, m_generate_mipmap ? GL_TRUE : GL_FALSE); + glTexParameteri((GLenum)m_parent->get_target(), GL_GENERATE_MIPMAP, m_generate_mipmap ? GL_TRUE : GL_FALSE); } - __glcheck glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_WRAP_S, (GLint)m_wrap_s); - __glcheck glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_WRAP_T, (GLint)m_wrap_t); - __glcheck glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_WRAP_R, (GLint)m_wrap_r); + glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_WRAP_S, (GLint)m_wrap_s); + glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_WRAP_T, (GLint)m_wrap_t); + glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_WRAP_R, (GLint)m_wrap_r); - __glcheck glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_COMPARE_MODE, (GLint)m_compare_mode); - __glcheck glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_COMPARE_FUNC, (GLint)m_compare_func); + glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_COMPARE_MODE, (GLint)m_compare_mode); + glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_COMPARE_FUNC, (GLint)m_compare_func); - __glcheck glTexParameterf((GLenum)m_parent->get_target(), GL_TEXTURE_MIN_LOD, m_max_lod); - __glcheck glTexParameterf((GLenum)m_parent->get_target(), GL_TEXTURE_MAX_LOD, m_min_lod); - __glcheck glTexParameterf((GLenum)m_parent->get_target(), GL_TEXTURE_LOD_BIAS, m_lod); + glTexParameterf((GLenum)m_parent->get_target(), GL_TEXTURE_MIN_LOD, m_max_lod); + glTexParameterf((GLenum)m_parent->get_target(), GL_TEXTURE_MAX_LOD, m_min_lod); + glTexParameterf((GLenum)m_parent->get_target(), GL_TEXTURE_LOD_BIAS, m_lod); - __glcheck glTexParameterfv((GLenum)m_parent->get_target(), GL_TEXTURE_BORDER_COLOR, m_border_color.rgba); + glTexParameterfv((GLenum)m_parent->get_target(), GL_TEXTURE_BORDER_COLOR, m_border_color.rgba); - __glcheck glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_MIN_FILTER, (GLint)m_min_filter); - __glcheck glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_MAG_FILTER, (GLint)m_mag_filter); + glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_MIN_FILTER, (GLint)m_min_filter); + glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_MAG_FILTER, (GLint)m_mag_filter); - __glcheck glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_SWIZZLE_R, (GLint)m_swizzle_r); - __glcheck glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_SWIZZLE_G, (GLint)m_swizzle_g); - __glcheck glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_SWIZZLE_B, (GLint)m_swizzle_b); - __glcheck glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_SWIZZLE_A, (GLint)m_swizzle_a); + glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_SWIZZLE_R, (GLint)m_swizzle_r); + glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_SWIZZLE_G, (GLint)m_swizzle_g); + glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_SWIZZLE_B, (GLint)m_swizzle_b); + glTexParameteri((GLenum)m_parent->get_target(), GL_TEXTURE_SWIZZLE_A, (GLint)m_swizzle_a); - __glcheck glTexParameterf((GLenum)m_parent->get_target(), GL_TEXTURE_MAX_ANISOTROPY_EXT, m_aniso); + glTexParameterf((GLenum)m_parent->get_target(), GL_TEXTURE_MAX_ANISOTROPY_EXT, m_aniso); } void texture::settings::apply() @@ -432,6 +458,12 @@ namespace gl return *this; } + texture::settings& texture::settings::depth(uint depth) + { + m_depth = depth; + return *this; + } + texture::settings& texture::settings::size(sizei size) { return width(size.width).height(size.height); diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.h b/rpcs3/Emu/RSX/GL/GLHelpers.h index 4d8d21aedf..30e5faa53f 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.h +++ b/rpcs3/Emu/RSX/GL/GLHelpers.h @@ -1342,6 +1342,7 @@ namespace gl texture1D = GL_TEXTURE_1D, texture2D = GL_TEXTURE_2D, texture3D = GL_TEXTURE_3D, + textureCUBE = GL_TEXTURE_CUBE_MAP, textureBuffer = GL_TEXTURE_BUFFER }; @@ -1841,6 +1842,7 @@ namespace gl uint m_width = 0; uint m_height = 0; + uint m_depth = 1; int m_level = 0; int m_compressed_image_size = 0; @@ -1887,6 +1889,7 @@ namespace gl settings& filter(min_filter min_filter, filter mag_filter); settings& width(uint width); settings& height(uint height); + settings& depth(uint depth); settings& size(sizei size); settings& level(int value); settings& compressed_image_size(int size); diff --git a/rpcs3/Emu/RSX/GL/GLProcTable.h b/rpcs3/Emu/RSX/GL/GLProcTable.h index 9866f07bac..2104dbefc7 100644 --- a/rpcs3/Emu/RSX/GL/GLProcTable.h +++ b/rpcs3/Emu/RSX/GL/GLProcTable.h @@ -36,6 +36,7 @@ OPENGL_PROC(PFNGLGENVERTEXARRAYSPROC, GenVertexArrays); OPENGL_PROC(PFNGLBINDVERTEXARRAYPROC, BindVertexArray); OPENGL_PROC(PFNGLDELETEVERTEXARRAYSPROC, DeleteVertexArrays); OPENGL_PROC(PFNGLDEPTHRANGEFPROC, DepthRangef); +OPENGL_PROC(PFNGLTEXIMAGE3DPROC, TexImage3D); OPENGL_PROC(PFNGLVERTEXATTRIB1FPROC, VertexAttrib1f); OPENGL_PROC(PFNGLVERTEXATTRIB1DPROC, VertexAttrib1d);