/* by korenkonder GitHub/GitLab: korenkonder */ #include "gl_wrap.hpp" #include "../../KKdLib/hash.hpp" #include "../gl_state.hpp" #include "../static_var.hpp" #include "../texture.hpp" #include "CommandBuffer.hpp" #include "Manager.hpp" #include #include namespace Vulkan { struct gl_texture_data { struct tex_data { std::vector data; tex_data(); ~tex_data(); void set_data(GLint internal_format, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data); static bool convert(GLenum internal_format, GLsizei width, GLsizei height, GLenum format, GLenum src_type, GLenum dst_type, const void* src_data, void* dst_data, ssize_t alignment, bool unpack); tex_data& operator=(const tex_data& other); }; GLenum target; GLenum internal_format; GLsizei width; GLsizei height; uint32_t level_count; std::vector data[6]; gl_texture_data(); ~gl_texture_data(); tex_data* get_tex_data(uint32_t level, uint32_t layer, bool get = false); bool valid(); gl_texture_data& operator=(const gl_texture_data& other); static gl_texture_data* get(GLuint texture); }; struct gl_wrap_manager { GLuint buffer_counter; GLuint framebuffer_counter; GLuint program_counter; GLuint query_counter; GLuint sampler_counter; GLuint texture_counter; GLuint vertex_array_counter; Vulkan::VertexBuffer dummy_vertex_buffer; std::unordered_map gl_buffers; std::vector gl_errors; std::unordered_map gl_framebuffers; std::unordered_map gl_index_buffers; std::unordered_map gl_programs; std::unordered_map gl_queries; std::unordered_map gl_samplers; std::unordered_map gl_storage_buffers; std::unordered_map gl_textures; std::unordered_map gl_texture_datas; std::unordered_map gl_uniform_buffers; std::unordered_map gl_vertex_arrays; std::unordered_map gl_vertex_buffers; vec4 clear_color; float_t clear_depth; int32_t clear_stencil; int32_t pack_alignment; int32_t unpack_alignment; GLuint query_samples_passed; gl_wrap_manager(); ~gl_wrap_manager(); GLuint create_buffer(); GLuint create_framebuffer(); GLuint create_program(); GLuint create_query(); GLuint create_sampler(); GLuint create_texture(); GLuint create_vertex_array(); GLenum get_error(); void push_error(GLenum error); void release_buffer(GLuint buffer); void release_framebuffer(GLuint framebuffer); void release_program(GLuint sampler); void release_query(GLuint query); void release_sampler(GLuint sampler); void release_texture(GLuint texture); void release_vertex_array(GLuint array); void update_buffers(); }; gl_wrap_manager* gl_wrap_manager_ptr; static void gl_wrap_manager_begin_query(GLenum target, GLuint id); static void gl_wrap_manager_bind_buffer(GLenum target, GLuint buffer); static void gl_wrap_manager_bind_texture(GLenum target, GLuint texture); static void gl_wrap_manager_blit_framebuffer( GLint src_x0, GLint src_y0, GLint src_x1, GLint src_y1, GLint dst_x0, GLint dst_y0, GLint dst_x1, GLint dst_y1, GLbitfield mask, GLenum filter); static void gl_wrap_manager_blit_named_framebuffer(GLuint readFramebuffer, GLuint drawFramebuffer, GLint src_x0, GLint src_y0, GLint src_x1, GLint src_y1, GLint dst_x0, GLint dst_y0, GLint dst_x1, GLint dst_y1, GLbitfield mask, GLenum filter); static void gl_wrap_manager_buffer_data( GLenum target, GLsizeiptr size, const void* data, GLenum usage); static void gl_wrap_manager_buffer_storage( GLenum target, GLsizeiptr size, const void* data, GLbitfield flags); static void gl_wrap_manager_buffer_sub_data( GLenum target, GLintptr offset, GLsizeiptr size, const void* data); static GLenum gl_wrap_manager_check_framebuffer_status(GLenum target); static void gl_wrap_manager_clear(GLbitfield mask); static void gl_wrap_manager_clear_buffer(GLenum buffer, GLint drawbuffer, const GLfloat* value); static void gl_wrap_manager_clear_color(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); static void gl_wrap_manager_clear_depth(GLfloat depth); static void gl_wrap_manager_clear_stencil(GLint s); static void gl_wrap_manager_clear_named_framebuffer(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat* value); static void gl_wrap_manager_compressed_tex_image_2d(GLenum target, GLint level, GLenum internal_format, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); static void gl_wrap_manager_compressed_tex_sub_image_2d(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); static void gl_wrap_manager_copy_image_sub_data( GLuint src_name, GLenum src_target, GLint src_level, GLint src_x, GLint src_y, GLint src_z, GLuint dst_name, GLenum dst_target, GLint dst_level, GLint dst_x, GLint dst_y, GLint dst_z, GLsizei src_width, GLsizei src_height, GLsizei src_depth); static void gl_wrap_manager_copy_tex_sub_image_2d(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); static void gl_wrap_manager_create_buffers(GLsizei n, GLuint* buffers); static GLuint gl_wrap_manager_create_program(); static void gl_wrap_manager_delete_buffers(GLsizei n, const GLuint* buffers); static void gl_wrap_manager_delete_framebuffers(GLsizei n, const GLuint* framebuffers); static void gl_wrap_manager_delete_program(GLuint program); static void gl_wrap_manager_delete_queries(GLsizei n, const GLuint* ids); static void gl_wrap_manager_delete_samplers(GLsizei n, const GLuint* samplers); static void gl_wrap_manager_delete_textures(GLsizei n, const GLuint* textures); static void gl_wrap_manager_delete_vertex_arrays(GLsizei n, const GLuint* arrays); static void gl_wrap_manager_disable_vertex_attrib_array(GLuint index); static void gl_wrap_manager_draw_buffer(GLenum buf); static void gl_wrap_manager_draw_buffers(GLsizei n, const GLenum* bufs); static void gl_wrap_manager_enable_vertex_attrib_array(GLuint index); static void gl_wrap_manager_end_query(GLenum target); static void gl_wrap_manager_finish(); static void gl_wrap_manager_framebuffer_texture(GLenum target, GLenum attachment, GLuint texture, GLint level); static void gl_wrap_manager_gen_buffers(GLsizei n, GLuint* buffers); static void gl_wrap_manager_gen_framebuffers(GLsizei n, GLuint* framebuffers); static void gl_wrap_manager_gen_queries(GLsizei n, GLuint* ids); static void gl_wrap_manager_gen_samplers(GLsizei n, GLuint* samplers); static void gl_wrap_manager_gen_textures(GLsizei n, GLuint* textures); static void gl_wrap_manager_gen_vertex_arrays(GLsizei n, GLuint* arrays); static void gl_wrap_manager_generate_mipmap(GLenum target); static void gl_wrap_manager_generate_texture_mipmap(GLuint texture); static void gl_wrap_manager_get_compressed_tex_image(GLenum target, GLint level, void* img); static GLenum gl_wrap_manager_get_error(); static void gl_wrap_manager_get_float(GLenum pname, GLfloat* data); static void gl_wrap_manager_get_query_object(GLuint id, GLenum pname, GLint* params); static void gl_wrap_manager_get_query_object(GLuint id, GLenum pname, GLuint* params); static void gl_wrap_manager_get_tex_image(GLenum target, GLint level, GLenum format, GLenum type, void* pixels); static void* gl_wrap_manager_map_buffer(GLenum target, GLenum access); static void* gl_wrap_manager_map_named_buffer(GLuint buffer, GLenum access); static void gl_wrap_manager_named_buffer_data( GLuint buffer, GLsizeiptr size, const void* data, GLenum usage); static void gl_wrap_manager_named_buffer_storage( GLuint buffer, GLsizeiptr size, const void* data, GLbitfield flags); static void gl_wrap_manager_named_buffer_sub_data( GLuint buffer, GLintptr offset, GLsizeiptr size, const void* data); static void gl_wrap_manager_pixel_store(GLenum pname, GLint param); static void gl_wrap_manager_pop_debug_group(); static void gl_wrap_manager_push_debug_group(GLenum source, GLuint id, GLsizei length, const GLchar* message); static void gl_wrap_manager_read_buffer(GLenum src); static void gl_wrap_manager_sampler_parameter(GLuint sampler, GLenum pname, GLfloat param); static void gl_wrap_manager_sampler_parameter(GLuint sampler, GLenum pname, GLint param); static void gl_wrap_manager_sampler_parameter(GLuint sampler, GLenum pname, const GLfloat* params); static void gl_wrap_manager_sampler_parameter(GLuint sampler, GLenum pname, const GLint* params); static void gl_wrap_manager_tex_image_2d(GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels); static void gl_wrap_manager_tex_parameter(GLenum target, GLenum pname, GLfloat param); static void gl_wrap_manager_tex_parameter(GLenum target, GLenum pname, GLint param); static void gl_wrap_manager_tex_parameter(GLenum target, GLenum pname, const GLfloat* params); static void gl_wrap_manager_tex_parameter(GLenum target, GLenum pname, const GLint* params); static void gl_wrap_manager_tex_sub_image_2d(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); static void gl_wrap_manager_texture_parameter(GLuint texture, GLenum pname, GLfloat param); static void gl_wrap_manager_texture_parameter(GLuint texture, GLenum pname, GLint param); static void gl_wrap_manager_texture_parameter(GLuint texture, GLenum pname, const GLfloat* params); static void gl_wrap_manager_texture_parameter(GLuint texture, GLenum pname, const GLint* params); static void gl_wrap_manager_texture_sub_image_2d(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); static GLboolean gl_wrap_manager_unmap_buffer(GLenum target); static GLboolean gl_wrap_manager_unmap_named_buffer(GLuint buffer); static void gl_wrap_manager_vertex_attrib(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); static void gl_wrap_manager_vertex_attrib_int_pointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer); static void gl_wrap_manager_vertex_attrib_pointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); gl_buffer::gl_buffer() : target(), flags() { } gl_buffer::~gl_buffer() { } gl_buffer& gl_buffer::operator=(const gl_buffer& other) { target = other.target; flags = other.flags; data.assign(other.data.begin(), other.data.end()); return *this; } gl_buffer* gl_buffer::get(GLuint buffer) { if (!buffer) return 0; auto elem = gl_wrap_manager_ptr->gl_buffers.find(buffer); if (elem != gl_wrap_manager_ptr->gl_buffers.end()) return &elem->second; return 0; } gl_framebuffer::gl_framebuffer() : render_pass(), color_attachments(), color_attachment_levels(), depth_attachment(), depth_attachment_level(), draw_buffers(), update_color_attachment(), update_depth_attachment(), update_framebuffer() { draw_buffers[0] = GL_COLOR_ATTACHMENT0; for (uint32_t i = 1; i < Vulkan::MAX_DRAW_BUFFERS; i++) draw_buffers[i] = GL_NONE; read_buffer = GL_COLOR_ATTACHMENT0; } GLuint gl_framebuffer::get_draw_buffer_texture(uint32_t index) { if (index >= Vulkan::MAX_DRAW_BUFFERS) return 0; GLenum draw_buffer = draw_buffers[index]; if (draw_buffer && draw_buffer >= GL_COLOR_ATTACHMENT0 && draw_buffer < GL_COLOR_ATTACHMENT0 + Vulkan::MAX_COLOR_ATTACHMENTS) return color_attachments[draw_buffer - GL_COLOR_ATTACHMENT0]; return 0; } GLuint gl_framebuffer::get_read_buffer_texture() { if (read_buffer && read_buffer >= GL_COLOR_ATTACHMENT0 && read_buffer < GL_COLOR_ATTACHMENT0 + Vulkan::MAX_COLOR_ATTACHMENTS) return color_attachments[read_buffer - GL_COLOR_ATTACHMENT0]; return 0; } void gl_framebuffer::release() { framebuffer[1].Destroy(); framebuffer[0].Destroy(); render_pass[1].reset(); render_pass[0].reset(); update_framebuffer = false; update_depth_attachment = false; update_color_attachment = false; read_buffer = GL_COLOR_ATTACHMENT0; draw_buffers[0] = GL_COLOR_ATTACHMENT0; for (uint32_t i = 1; i < Vulkan::MAX_DRAW_BUFFERS; i++) draw_buffers[i] = GL_NONE; depth_attachment_image_view.Destroy(); depth_attachment_level = 0; depth_attachment = 0; for (uint32_t i = 0; i < Vulkan::MAX_COLOR_ATTACHMENTS; i++) { color_attachment_image_views[i].Destroy(); color_attachment_levels[i] = 0; color_attachments[i] = 0; } } gl_framebuffer* gl_framebuffer::get(GLuint framebuffer, bool update_data) { if (!framebuffer) return 0; auto elem = gl_wrap_manager_ptr->gl_framebuffers.find(framebuffer); if (elem == gl_wrap_manager_ptr->gl_framebuffers.end()) return 0; gl_framebuffer* vk_fbo = &elem->second; if (!update_data) return vk_fbo; if (vk_fbo->update_color_attachment) { for (uint32_t i = 0; i < Vulkan::MAX_COLOR_ATTACHMENTS; i++) vk_fbo->color_attachment_image_views[i].Destroy(); for (int32_t i = 0; i < Vulkan::MAX_COLOR_ATTACHMENTS; i++) { gl_texture* vk_tex = gl_texture::get(vk_fbo->color_attachments[i], true, true); if (vk_tex && vk_tex->get_level_count() > 0) { const VkImageViewType image_view_type = Vulkan::get_image_view_type(vk_tex->target); const VkFormat format = Vulkan::get_format(vk_tex->internal_format); const VkImageAspectFlags aspect_mask = Vulkan::get_aspect_mask(vk_tex->internal_format); const int32_t layer_count = vk_tex->get_layer_count(); vk_fbo->color_attachment_image_views[i].Create(Vulkan::current_device, 0, vk_tex->image, image_view_type, format, aspect_mask, 0, 1, 0, layer_count); } } vk_fbo->update_color_attachment = false; vk_fbo->update_framebuffer = true; } if (vk_fbo->update_depth_attachment) { vk_fbo->depth_attachment_image_view.Destroy(); gl_texture* vk_tex = gl_texture::get(vk_fbo->depth_attachment, true, true); if (vk_tex && vk_tex->get_level_count() > 0) { const VkImageViewType image_view_type = Vulkan::get_image_view_type(vk_tex->target); const VkFormat format = Vulkan::get_format(vk_tex->internal_format); const VkImageAspectFlags aspect_mask = Vulkan::get_aspect_mask(vk_tex->internal_format); const int32_t layer_count = vk_tex->get_layer_count(); vk_fbo->depth_attachment_image_view.Create(Vulkan::current_device, 0, vk_tex->image, image_view_type, format, aspect_mask, 0, 1, 0, layer_count); } vk_fbo->update_depth_attachment = false; vk_fbo->update_framebuffer = true; } if (vk_fbo->update_framebuffer) { GLenum color_formats[Vulkan::MAX_DRAW_BUFFERS] = {}; uint32_t color_format_count = 0; VkImageView image_views[Vulkan::MAX_DRAW_BUFFERS + 1] = {}; uint32_t image_view_count = 0; uint32_t width = 0; uint32_t height = 0; for (uint32_t i = 0; i < Vulkan::MAX_DRAW_BUFFERS; i++) { GLuint texture = vk_fbo->get_draw_buffer_texture(i); gl_texture* vk_tex = gl_texture::get(texture, true, true); if (!vk_tex) continue; if (!width && !height) { width = vk_tex->width; height = vk_tex->height; } color_formats[color_format_count] = vk_tex->internal_format; image_views[image_view_count] = vk_tex->image_view; for (uint32_t j = 0; j < Vulkan::MAX_COLOR_ATTACHMENTS; j++) if (vk_fbo->color_attachments[j] == texture) { if (vk_fbo->color_attachment_image_views[j]) image_views[color_format_count] = vk_fbo->color_attachment_image_views[j]; break; } color_format_count++; image_view_count++; } GLenum depth_format = GL_ZERO; if (vk_fbo->depth_attachment) { gl_texture* vk_tex = gl_texture::get(vk_fbo->depth_attachment, true, true); if (vk_tex) { depth_format = vk_tex->internal_format; image_views[image_view_count] = vk_tex->image_view; if (!width && !height) { width = vk_tex->width; height = vk_tex->height; } if (vk_fbo->depth_attachment_image_view) image_views[image_view_count] = vk_fbo->depth_attachment_image_view; image_view_count++; } } vk_fbo->render_pass[0] = Vulkan::manager_get_render_pass( color_formats, color_format_count, depth_format, false); vk_fbo->render_pass[1] = Vulkan::manager_get_render_pass( color_formats, color_format_count, depth_format, true); vk_fbo->framebuffer[0].Create(Vulkan::current_device, 0, *vk_fbo->render_pass[0].get(), image_view_count, image_views, width, height); vk_fbo->framebuffer[1].Create(Vulkan::current_device, 0, *vk_fbo->render_pass[1].get(), image_view_count, image_views, width, height); vk_fbo->update_framebuffer = false; } return vk_fbo; } gl_index_buffer::gl_index_buffer() : copy_working_buffer() { } gl_index_buffer* gl_index_buffer::get(GLuint buffer) { if (!buffer) return 0; auto elem_buffer = gl_wrap_manager_ptr->gl_buffers.find(buffer); if (elem_buffer == gl_wrap_manager_ptr->gl_buffers.end()) return 0; gl_buffer* vk_buf = &elem_buffer->second; auto elem = gl_wrap_manager_ptr->gl_index_buffers.find(buffer); if (elem == gl_wrap_manager_ptr->gl_index_buffers.end()) { vk_buf->target = GL_ELEMENT_ARRAY_BUFFER; elem = gl_wrap_manager_ptr->gl_index_buffers.insert({ buffer, {} }).first; } gl_index_buffer* vk_ib = &elem->second; const VkDeviceSize size = vk_buf->data.size(); const VkDeviceSize alignment = 0x40; if (!vk_ib->index_buffer || vk_ib->index_buffer.GetSize() < size) vk_ib->index_buffer.Create(Vulkan::current_allocator, size); if (elem_buffer->second.flags & Vulkan::GL_BUFFER_FLAG_UPDATE_DATA) { const uint64_t hash = hash_xxh3_64bits(vk_buf->data.data(), size); if (vk_ib->copy_working_buffer && vk_ib->working_buffer.FindBuffer(hash, size)) return vk_ib; Vulkan::Buffer dynamic_buffer = Vulkan::manager_get_dynamic_buffer(size, alignment); dynamic_buffer.WriteMemory(dynamic_buffer.GetOffset(), size, vk_buf->data.data()); enum_and(elem_buffer->second.flags, ~Vulkan::GL_BUFFER_FLAG_UPDATE_DATA); vk_ib->working_buffer.AddBuffer(hash, dynamic_buffer); vk_ib->copy_working_buffer = true; } else if (!vk_ib->copy_working_buffer) vk_ib->working_buffer.SetBuffer(vk_ib->index_buffer); return vk_ib; } gl_program::gl_program() { } gl_program* gl_program::get(GLuint program) { if (!program) return 0; auto elem = gl_wrap_manager_ptr->gl_programs.find(program); if (elem != gl_wrap_manager_ptr->gl_programs.end()) return &elem->second; return 0; } gl_query::gl_query() : target() { } gl_query* gl_query::get(GLuint query) { if (!query) return 0; auto elem = gl_wrap_manager_ptr->gl_queries.find(query); if (elem != gl_wrap_manager_ptr->gl_queries.end()) return &elem->second; return 0; } gl_sampler::gl_sampler() { mag_filter = GL_NEAREST_MIPMAP_LINEAR; min_filter = GL_LINEAR; wrap_s = GL_REPEAT; wrap_t = GL_REPEAT; wrap_r = GL_REPEAT; border_color = 0.0f; max_anisotropy = 1.0f; } gl_sampler::gl_sampler(GLenum min_filter, GLenum mag_filter, GLenum wrap_s, GLenum wrap_t, GLenum wrap_r, const vec4& border_color, float_t max_anisotropy) { this->mag_filter = mag_filter; this->min_filter = min_filter; this->wrap_s = wrap_s; this->wrap_t = wrap_t; this->wrap_r = wrap_r; this->border_color = border_color; this->max_anisotropy = max_anisotropy; } gl_sampler* gl_sampler::get(GLuint sampler) { if (!sampler) return 0; auto elem = gl_wrap_manager_ptr->gl_samplers.find(sampler); if (elem != gl_wrap_manager_ptr->gl_samplers.end()) return &elem->second; return 0; } gl_storage_buffer::gl_storage_buffer() : copy_working_buffer() { } gl_storage_buffer* gl_storage_buffer::get(GLuint buffer) { if (!buffer) return 0; auto elem_buffer = gl_wrap_manager_ptr->gl_buffers.find(buffer); if (elem_buffer == gl_wrap_manager_ptr->gl_buffers.end()) return 0; gl_buffer* vk_buf = &elem_buffer->second; auto elem = gl_wrap_manager_ptr->gl_storage_buffers.find(buffer); if (elem == gl_wrap_manager_ptr->gl_storage_buffers.end()) { vk_buf->target = GL_SHADER_STORAGE_BUFFER; elem = gl_wrap_manager_ptr->gl_storage_buffers.insert({ buffer, {} }).first; } gl_storage_buffer* vk_sb = &elem->second; const VkDeviceSize size = vk_buf->data.size(); const VkDeviceSize alignment = sv_min_storage_buffer_alignment; if (!vk_sb->storage_buffer || vk_sb->storage_buffer.GetSize() < size) vk_sb->storage_buffer.Create(Vulkan::current_allocator, size); if (elem_buffer->second.flags & Vulkan::GL_BUFFER_FLAG_UPDATE_DATA) { const uint64_t hash = hash_xxh3_64bits(vk_buf->data.data(), size); if (vk_sb->copy_working_buffer && vk_sb->working_buffer.FindBuffer(hash, size)) return vk_sb; Vulkan::Buffer dynamic_buffer = Vulkan::manager_get_dynamic_buffer(size, alignment); dynamic_buffer.WriteMemory(dynamic_buffer.GetOffset(), size, vk_buf->data.data()); enum_and(elem_buffer->second.flags, ~Vulkan::GL_BUFFER_FLAG_UPDATE_DATA); vk_sb->working_buffer.AddBuffer(hash, dynamic_buffer); vk_sb->copy_working_buffer = true; } else if (!vk_sb->copy_working_buffer) vk_sb->working_buffer.SetBuffer(vk_sb->storage_buffer); return vk_sb; } gl_texture::gl_texture() : target(), base_mipmap_level(), internal_format(), width(), height(), level_count(), components(), attachment() { max_mipmap_level = 1000; } VkImageView gl_texture::get_image_view() { return sample_image_view ? sample_image_view : image_view; } gl_texture* gl_texture::get(GLuint texture, bool update_data, bool attachment) { if (!texture) return 0; auto elem = gl_wrap_manager_ptr->gl_textures.find(texture); if (elem == gl_wrap_manager_ptr->gl_textures.end()) return 0; gl_texture* vk_tex = &elem->second; gl_texture_data* vk_tex_data = gl_texture_data::get(texture); if (!vk_tex->image && (!vk_tex_data || !vk_tex_data->valid())) return vk_tex; bool create = false; if (!vk_tex->image) { if (!vk_tex_data || !vk_tex_data->valid()) return vk_tex; create = true; } if (vk_tex_data && (vk_tex->internal_format != vk_tex_data->internal_format || vk_tex->width != vk_tex_data->width || vk_tex->height != vk_tex_data->height || vk_tex->level_count != vk_tex_data->level_count) || attachment && vk_tex->attachment != attachment) create = true; if (create && update_data) { vk_tex->sample_image_view.Destroy(); if (vk_tex_data) { vk_tex->internal_format = vk_tex_data->internal_format; vk_tex->width = vk_tex_data->width; vk_tex->height = vk_tex_data->height; vk_tex->level_count = vk_tex_data->level_count; gl_texture_data::tex_data* tex_data = vk_tex_data->get_tex_data(0, 0); vk_tex->attachment = attachment || !tex_data || !tex_data->data.size(); } else vk_tex->attachment = true; const VkImageViewType image_view_type = Vulkan::get_image_view_type(vk_tex->target); const VkFormat format = Vulkan::get_format(vk_tex->internal_format); const VkImageAspectFlags aspect_mask = Vulkan::get_aspect_mask(vk_tex->internal_format); VkImageUsageFlags usage = 0; VkImageLayout layout; switch (format) { case VK_FORMAT_D24_UNORM_S8_UINT: case VK_FORMAT_D32_SFLOAT: if (vk_tex->attachment) { usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; } else layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; break; default: if (vk_tex->attachment) { usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } else layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; break; } usage |= VK_IMAGE_USAGE_SAMPLED_BIT; usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; const VkImageCreateFlags flags = vk_tex->target == GL_TEXTURE_CUBE_MAP ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0; const int32_t level_count = vk_tex->get_level_count(); const int32_t layer_count = vk_tex->get_layer_count(); vk_tex->image.Create(Vulkan::current_allocator, flags, vk_tex->width, vk_tex->height, level_count, layer_count, format, VK_IMAGE_TILING_OPTIMAL, usage, VMA_MEMORY_USAGE_AUTO, vk_tex->attachment ? VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT : 0); vk_tex->image_view.Create(Vulkan::current_device, 0, vk_tex->image, image_view_type, format, aspect_mask, 0, level_count, 0, layer_count); Vulkan::Image::PipelineBarrier(Vulkan::current_command_buffer, vk_tex->image, aspect_mask, level_count, layer_count, layout); } if (vk_tex_data && update_data) { const int32_t level_count = vk_tex->get_level_count(); const int32_t layer_count = vk_tex->get_layer_count(); for (int32_t i = 0; i < layer_count; i++) for (int32_t j = 0; j < level_count; j++) { gl_texture_data::tex_data* tex_data = vk_tex_data->get_tex_data(j, i); if (!tex_data || !tex_data->data.size()) continue; const void* data = tex_data->data.data(); const VkDeviceSize size = tex_data->data.size(); Vulkan::Buffer staging_buffer = Vulkan::manager_get_staging_buffer(size); staging_buffer.WriteMemory(staging_buffer.GetOffset(), size, data); const VkImageViewType image_view_type = Vulkan::get_image_view_type(vk_tex->target); const VkFormat format = Vulkan::get_format(vk_tex->internal_format); const VkImageAspectFlags aspect_mask = Vulkan::get_aspect_mask(vk_tex->internal_format); Vulkan::CommandBuffer cb(Vulkan::current_device, Vulkan::current_command_pool, Vulkan::current_command_buffer); const VkImageLayout old_layout = vk_tex->image.GetImageLayout(j, i); const VkImageLayout new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, vk_tex->image, aspect_mask, j, i, new_layout); cb.CopyBufferToImage(staging_buffer, staging_buffer.GetOffset(), vk_tex->image, aspect_mask, j, i, 0, 0, max_def(vk_tex->width >> j, 1), max_def(vk_tex->height >> j, 1)); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, vk_tex->image, aspect_mask, j, i, old_layout); } gl_wrap_manager_ptr->gl_texture_datas.erase(texture); } if (vk_tex->image && !vk_tex->sample_image_view) { const VkImageViewType image_view_type = Vulkan::get_image_view_type(vk_tex->target); const VkFormat format = Vulkan::get_format(vk_tex->internal_format); const VkImageAspectFlags aspect_mask = Vulkan::get_aspect_mask(vk_tex->internal_format); const uint32_t base_mipmap_level = vk_tex->base_mipmap_level; const uint32_t level_count = min_def((uint32_t)(vk_tex->max_mipmap_level - base_mipmap_level) + 1, vk_tex->get_level_count()); const uint32_t layer_count = vk_tex->get_layer_count(); vk_tex->sample_image_view.Create(Vulkan::current_device, 0, vk_tex->image, image_view_type, format, aspect_mask & ~VK_IMAGE_ASPECT_STENCIL_BIT, base_mipmap_level, level_count, 0, layer_count, vk_tex->components); } return vk_tex; } gl_uniform_buffer::gl_uniform_buffer() : copy_working_buffer() { } gl_uniform_buffer* gl_uniform_buffer::get(GLuint buffer) { if (!buffer) return 0; auto elem_buffer = gl_wrap_manager_ptr->gl_buffers.find(buffer); if (elem_buffer == gl_wrap_manager_ptr->gl_buffers.end()) return 0; gl_buffer* vk_buf = &elem_buffer->second; auto elem = gl_wrap_manager_ptr->gl_uniform_buffers.find(buffer); if (elem == gl_wrap_manager_ptr->gl_uniform_buffers.end()) { vk_buf->target = GL_UNIFORM_BUFFER; elem = gl_wrap_manager_ptr->gl_uniform_buffers.insert({ buffer, {} }).first; } gl_uniform_buffer* vk_ub = &elem->second; const VkDeviceSize size = vk_buf->data.size(); const VkDeviceSize alignment = sv_min_uniform_buffer_alignment; if (!vk_ub->uniform_buffer || vk_ub->uniform_buffer.GetSize() < size) vk_ub->uniform_buffer.Create(Vulkan::current_allocator, size); if (elem_buffer->second.flags & Vulkan::GL_BUFFER_FLAG_UPDATE_DATA) { const uint64_t hash = hash_xxh3_64bits(vk_buf->data.data(), size); if (vk_ub->copy_working_buffer && vk_ub->working_buffer.FindBuffer(hash, size)) return vk_ub; Vulkan::Buffer dynamic_buffer = Vulkan::manager_get_dynamic_buffer(size, alignment); dynamic_buffer.WriteMemory(dynamic_buffer.GetOffset(), size, vk_buf->data.data()); enum_and(elem_buffer->second.flags, ~Vulkan::GL_BUFFER_FLAG_UPDATE_DATA); vk_ub->working_buffer.AddBuffer(hash, dynamic_buffer); vk_ub->copy_working_buffer = true; } else if (!vk_ub->copy_working_buffer) vk_ub->working_buffer.SetBuffer(vk_ub->uniform_buffer); return vk_ub; } gl_vertex_buffer_binding_data::gl_vertex_buffer_binding_data() : buffer(), offset(), stride() { } gl_index_buffer_binding_data::gl_index_buffer_binding_data() : buffer() { } gl_vertex_array_vertex_attrib::gl_vertex_array_vertex_attrib() : format(), offset(), enabled() { binding = -1; generic_value = { 0.0f, 0.0f, 0.0f, 1.0f }; } gl_vertex_array::gl_vertex_array() { } void gl_vertex_array::reset_vertex_attrib(uint32_t index) { const uint32_t binding = vertex_attribs[index].binding; if (binding == -1) return; vertex_attribs[index].binding = -1; for (gl_vertex_array_vertex_attrib& i : vertex_attribs) if (&i - vertex_attribs != index && i.binding != -1 && i.binding == binding) return; vertex_buffer_bindings[binding] = {}; uint32_t binding_count = 0; uint32_t bindings[Vulkan::MAX_VERTEX_ATTRIB_COUNT] = {}; for (uint32_t i = 0; i < Vulkan::MAX_VERTEX_ATTRIB_COUNT; i++) if (vertex_buffer_bindings[i].buffer) bindings[binding_count++] = i; for (uint32_t i = 0; i < binding_count; i++) { const uint32_t old_binding = bindings[i]; const uint32_t new_binding = i; vertex_buffer_bindings[new_binding] = vertex_buffer_bindings[old_binding]; for (gl_vertex_array_vertex_attrib& j : vertex_attribs) if (j.binding != -1 && j.binding == old_binding) j.binding = new_binding; } for (uint32_t i = binding_count; i < Vulkan::MAX_VERTEX_ATTRIB_COUNT; i++) vertex_buffer_bindings[i] = {}; } void gl_vertex_array::set_vertex_attrib(uint32_t index, VkFormat format, uint32_t stride, uint32_t offset) { reset_vertex_attrib(index); uint32_t binding = -1; for (gl_vertex_buffer_binding_data& i : vertex_buffer_bindings) if (i.buffer == gl_state.array_buffer_binding && i.stride == i.stride && i.offset < offset && offset < i.offset + i.stride) { binding = (uint32_t)(&i - vertex_buffer_bindings); offset -= i.offset; break; } if (binding == -1) { bool binding_used[Vulkan::MAX_VERTEX_ATTRIB_COUNT] = {}; for (gl_vertex_array_vertex_attrib& i : vertex_attribs) if (i.binding != -1) binding_used[i.binding] = true; for (uint32_t i = 0; i < Vulkan::MAX_VERTEX_ATTRIB_COUNT; i++) if (!binding_used[i]) { binding = i; vertex_buffer_bindings[binding].buffer = gl_state.array_buffer_binding; vertex_buffer_bindings[binding].offset = offset; vertex_buffer_bindings[binding].stride = stride; offset = 0; break; } if (binding == -1) return; } vertex_attribs[index].binding = binding; vertex_attribs[index].format = format; vertex_attribs[index].offset = offset; } gl_vertex_array* gl_vertex_array::get(GLuint array) { if (!array) return 0; auto elem = gl_wrap_manager_ptr->gl_vertex_arrays.find(array); if (elem != gl_wrap_manager_ptr->gl_vertex_arrays.end()) return &elem->second; return 0; } gl_vertex_buffer::gl_vertex_buffer() : copy_working_buffer() { } gl_vertex_buffer* gl_vertex_buffer::get(GLuint buffer) { if (!buffer) return 0; auto elem_buffer = gl_wrap_manager_ptr->gl_buffers.find(buffer); if (elem_buffer == gl_wrap_manager_ptr->gl_buffers.end()) return 0; gl_buffer* vk_buf = &elem_buffer->second; auto elem = gl_wrap_manager_ptr->gl_vertex_buffers.find(buffer); if (elem == gl_wrap_manager_ptr->gl_vertex_buffers.end()) { vk_buf->target = GL_ELEMENT_ARRAY_BUFFER; elem = gl_wrap_manager_ptr->gl_vertex_buffers.insert({ buffer, {} }).first; } gl_vertex_buffer* vk_vb = &elem->second; const VkDeviceSize size = vk_buf->data.size(); const VkDeviceSize alignment = 0x40; if (!vk_vb->vertex_buffer || vk_vb->vertex_buffer.GetSize() < size) vk_vb->vertex_buffer.Create(Vulkan::current_allocator, size); if (elem_buffer->second.flags & Vulkan::GL_BUFFER_FLAG_UPDATE_DATA) { const uint64_t hash = hash_xxh3_64bits(vk_buf->data.data(), size); if (vk_vb->copy_working_buffer && vk_vb->working_buffer.FindBuffer(hash, size)) return vk_vb; Vulkan::Buffer dynamic_buffer = Vulkan::manager_get_dynamic_buffer(size, alignment); dynamic_buffer.WriteMemory(dynamic_buffer.GetOffset(), size, vk_buf->data.data()); enum_and(elem_buffer->second.flags, ~Vulkan::GL_BUFFER_FLAG_UPDATE_DATA); vk_vb->working_buffer.AddBuffer(hash, dynamic_buffer); vk_vb->copy_working_buffer = true; } else if (!vk_vb->copy_working_buffer) vk_vb->working_buffer.SetBuffer(vk_vb->vertex_buffer); return vk_vb; } void gl_wrap_manager_init(Vulkan::CommandBuffer& command_buffer) { gl_wrap_manager_ptr = new gl_wrap_manager; { const float_t dummy_data[] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, }; const void* data = dummy_data; const VkDeviceSize size = sizeof(dummy_data); gl_wrap_manager_ptr->dummy_vertex_buffer.Create(Vulkan::current_allocator, size); Vulkan::Buffer staging_buffer = Vulkan::manager_get_staging_buffer(size); staging_buffer.WriteMemory(staging_buffer.GetOffset(), size, data); Vulkan::Buffer::Copy(Vulkan::current_command_buffer, staging_buffer, gl_wrap_manager_ptr->dummy_vertex_buffer, staging_buffer.GetOffset(), 0, size); } gl_state.program = 0; gl_state.active_texture = GL_TEXTURE0; gl_state.active_texture_index = 0; for (GLuint i = 0; i < Vulkan::MAX_COLOR_ATTACHMENTS; i++) { gl_state.texture_binding_2d[i] = 0; gl_state.texture_binding_cube_map[i] = 0; gl_state.sampler_binding[i] = 0; } gl_state.blend = GL_FALSE; gl_state.blend_src_rgb = GL_ONE; gl_state.blend_src_alpha = GL_ONE; gl_state.blend_dst_rgb = GL_ZERO; gl_state.blend_dst_alpha = GL_ZERO; gl_state.blend_mode_rgb = GL_FUNC_ADD; gl_state.blend_mode_alpha = GL_FUNC_ADD; gl_state.framebuffer_binding = 0; gl_state.read_framebuffer_binding = 0; gl_state.draw_framebuffer_binding = 0; gl_state.vertex_array_binding = 0; gl_state.array_buffer_binding = 0; gl_state.element_array_buffer_binding = 0; gl_state.uniform_buffer_binding = 0; for (GLuint i = 0; i < 14; i++) { gl_state.uniform_buffer_bindings[i] = 0; gl_state.uniform_buffer_offsets[i] = 0; gl_state.uniform_buffer_sizes[i] = 0; } gl_state.shader_storage_buffer_binding = 0; for (GLuint i = 0; i < 14; i++) { gl_state.shader_storage_buffer_bindings[i] = 0; gl_state.shader_storage_buffer_offsets[i] = 0; gl_state.shader_storage_buffer_sizes[i] = 0; } gl_state.color_mask[0] = GL_TRUE; gl_state.color_mask[1] = GL_TRUE; gl_state.color_mask[2] = GL_TRUE; gl_state.color_mask[3] = GL_TRUE; gl_state.cull_face = GL_FALSE; gl_state.cull_face_mode = GL_BACK; gl_state.depth_test = GL_FALSE; gl_state.depth_func = GL_LESS; gl_state.depth_mask = GL_TRUE; gl_state.line_width = 1.0f; gl_state.multisample = GL_FALSE; gl_state.primitive_restart = GL_FALSE; gl_state.primitive_restart_index = 0; gl_state.scissor_box.x = 0; gl_state.scissor_box.y = 0; gl_state.scissor_box.width = 0; gl_state.scissor_box.height = 0; gl_state.scissor_test = GL_FALSE; gl_state.stencil_test = GL_FALSE; gl_state.stencil_func = GL_ALWAYS; gl_state.stencil_fail = GL_KEEP; gl_state.stencil_dpfail = GL_KEEP; gl_state.stencil_dppass = GL_KEEP; gl_state.stencil_mask = 0x01; gl_state.stencil_ref = 0x00; gl_state.stencil_value_mask = 0x01; gl_state.viewport.x = 0; gl_state.viewport.y = 0; gl_state.viewport.width = 0; gl_state.viewport.height = 0; gl_state.polygon_mode = GL_FILL; } VkBuffer gl_wrap_manager_get_dummy_vertex_buffer() { return gl_wrap_manager_ptr->dummy_vertex_buffer; } GLuint gl_wrap_manager_get_query_samples_passed() { return gl_wrap_manager_ptr->query_samples_passed; } void gl_wrap_manager_update_buffers() { gl_wrap_manager_ptr->update_buffers(); } void gl_wrap_manager_load_funcs() { GLAD_GL_VERSION_1_0 = 1; GLAD_GL_VERSION_1_1 = 1; GLAD_GL_VERSION_1_2 = 1; GLAD_GL_VERSION_1_3 = 1; GLAD_GL_VERSION_1_4 = 1; GLAD_GL_VERSION_1_5 = 1; GLAD_GL_VERSION_2_0 = 1; GLAD_GL_VERSION_2_1 = 1; GLAD_GL_VERSION_3_0 = 1; GLAD_GL_VERSION_3_1 = 1; GLAD_GL_VERSION_3_2 = 1; GLAD_GL_VERSION_3_3 = 1; GLAD_GL_VERSION_3_0 = 1; GLAD_GL_VERSION_4_1 = 1; GLAD_GL_VERSION_4_2 = 1; GLAD_GL_VERSION_4_3 = 1; GLAD_GL_VERSION_4_4 = 1; GLAD_GL_VERSION_4_5 = 1; GLAD_GL_VERSION_4_6 = 1; glBeginQuery = gl_wrap_manager_begin_query; glBindBuffer = gl_wrap_manager_bind_buffer; glBindTexture = gl_wrap_manager_bind_texture; glBlitFramebuffer = gl_wrap_manager_blit_framebuffer; glBlitNamedFramebuffer = gl_wrap_manager_blit_named_framebuffer; glBufferData = gl_wrap_manager_buffer_data; glBufferStorage = gl_wrap_manager_buffer_storage; glBufferSubData = gl_wrap_manager_buffer_sub_data; glCheckFramebufferStatus = gl_wrap_manager_check_framebuffer_status; glClear = gl_wrap_manager_clear; glClearBufferfv = gl_wrap_manager_clear_buffer; glClearColor = gl_wrap_manager_clear_color; glClearDepthf = gl_wrap_manager_clear_depth; glClearStencil = gl_wrap_manager_clear_stencil; glCompressedTexImage2D = gl_wrap_manager_compressed_tex_image_2d; glCompressedTexSubImage2D = gl_wrap_manager_compressed_tex_sub_image_2d; glCopyImageSubData = gl_wrap_manager_copy_image_sub_data; glCopyTexSubImage2D = gl_wrap_manager_copy_tex_sub_image_2d; glCreateBuffers = gl_wrap_manager_create_buffers; glCreateProgram = gl_wrap_manager_create_program; glDeleteBuffers = gl_wrap_manager_delete_buffers; glDeleteFramebuffers = gl_wrap_manager_delete_framebuffers; glDeleteProgram = gl_wrap_manager_delete_program; glDeleteQueries = gl_wrap_manager_delete_queries; glDeleteSamplers = gl_wrap_manager_delete_samplers; glDeleteTextures = gl_wrap_manager_delete_textures; glDeleteVertexArrays = gl_wrap_manager_delete_vertex_arrays; glDisableVertexAttribArray = gl_wrap_manager_disable_vertex_attrib_array; glDrawBuffer = gl_wrap_manager_draw_buffer; glDrawBuffers = gl_wrap_manager_draw_buffers; glEnableVertexAttribArray = gl_wrap_manager_enable_vertex_attrib_array; glEndQuery = gl_wrap_manager_end_query; glFinish = gl_wrap_manager_finish; glFramebufferTexture = gl_wrap_manager_framebuffer_texture; glGenBuffers = gl_wrap_manager_gen_buffers; glGenFramebuffers = gl_wrap_manager_gen_framebuffers; glGenQueries = gl_wrap_manager_gen_queries; glGenSamplers = gl_wrap_manager_gen_samplers; glGenTextures = gl_wrap_manager_gen_textures; glGenVertexArrays = gl_wrap_manager_gen_vertex_arrays; glGenerateMipmap = gl_wrap_manager_generate_mipmap; glGenerateTextureMipmap = gl_wrap_manager_generate_texture_mipmap; glGetCompressedTexImage = gl_wrap_manager_get_compressed_tex_image; glGetError = gl_wrap_manager_get_error; glGetFloatv = gl_wrap_manager_get_float; glGetQueryObjectiv = gl_wrap_manager_get_query_object; glGetQueryObjectuiv = gl_wrap_manager_get_query_object; glGetTexImage = gl_wrap_manager_get_tex_image; glMapBuffer = gl_wrap_manager_map_buffer; glMapNamedBuffer = gl_wrap_manager_map_named_buffer; glNamedBufferData = gl_wrap_manager_named_buffer_data; glNamedBufferStorage = gl_wrap_manager_named_buffer_storage; glNamedBufferSubData = gl_wrap_manager_named_buffer_sub_data; glPixelStorei = gl_wrap_manager_pixel_store; glPopDebugGroup = gl_wrap_manager_pop_debug_group; glPushDebugGroup = gl_wrap_manager_push_debug_group; glReadBuffer = gl_wrap_manager_read_buffer; glSamplerParameterf = gl_wrap_manager_sampler_parameter; glSamplerParameterfv = gl_wrap_manager_sampler_parameter; glSamplerParameteri = gl_wrap_manager_sampler_parameter; glSamplerParameteriv = gl_wrap_manager_sampler_parameter; glTexImage2D = gl_wrap_manager_tex_image_2d; glTexParameterf = gl_wrap_manager_tex_parameter; glTexParameterfv = gl_wrap_manager_tex_parameter; glTexParameteri = gl_wrap_manager_tex_parameter; glTexParameteriv = gl_wrap_manager_tex_parameter; glTexSubImage2D = gl_wrap_manager_tex_sub_image_2d; glTextureParameterf = gl_wrap_manager_texture_parameter; glTextureParameterfv = gl_wrap_manager_texture_parameter; glTextureParameteri = gl_wrap_manager_texture_parameter; glTextureParameteriv = gl_wrap_manager_texture_parameter; glTextureSubImage2D = gl_wrap_manager_texture_sub_image_2d; glUnmapBuffer = gl_wrap_manager_unmap_buffer; glUnmapNamedBuffer = gl_wrap_manager_unmap_named_buffer; glVertexAttrib4f = gl_wrap_manager_vertex_attrib; glVertexAttribIPointer = gl_wrap_manager_vertex_attrib_int_pointer; glVertexAttribPointer = gl_wrap_manager_vertex_attrib_pointer; } void gl_wrap_manager_free() { gl_wrap_manager_ptr->dummy_vertex_buffer.Destroy(); delete gl_wrap_manager_ptr; } VkImageAspectFlags get_aspect_mask(GLenum internal_format) { switch (Vulkan::get_format(internal_format)) { case VK_FORMAT_D24_UNORM_S8_UINT: return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; case VK_FORMAT_D32_SFLOAT: return VK_IMAGE_ASPECT_DEPTH_BIT; default: return VK_IMAGE_ASPECT_COLOR_BIT; } } VkBlendFactor get_blend_factor(GLenum factor) { switch (factor) { case GL_ZERO: return VK_BLEND_FACTOR_ZERO; case GL_ONE: return VK_BLEND_FACTOR_ONE; case GL_SRC_COLOR: return VK_BLEND_FACTOR_SRC_COLOR; case GL_ONE_MINUS_SRC_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; case GL_DST_COLOR: return VK_BLEND_FACTOR_DST_COLOR; case GL_ONE_MINUS_DST_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR; case GL_SRC_ALPHA: return VK_BLEND_FACTOR_SRC_ALPHA; case GL_ONE_MINUS_SRC_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; case GL_DST_ALPHA: return VK_BLEND_FACTOR_DST_ALPHA; case GL_ONE_MINUS_DST_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; case GL_CONSTANT_COLOR: return VK_BLEND_FACTOR_CONSTANT_COLOR; case GL_ONE_MINUS_CONSTANT_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR; case GL_CONSTANT_ALPHA: return VK_BLEND_FACTOR_CONSTANT_ALPHA; case GL_ONE_MINUS_CONSTANT_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA; case GL_SRC_ALPHA_SATURATE: return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE; case GL_SRC1_COLOR: return VK_BLEND_FACTOR_SRC1_COLOR; case GL_ONE_MINUS_SRC1_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR; case GL_SRC1_ALPHA: return VK_BLEND_FACTOR_SRC1_ALPHA; case GL_ONE_MINUS_SRC1_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA; default: return VK_BLEND_FACTOR_MAX_ENUM; } } VkBlendOp get_blend_op(GLenum mode) { switch (mode) { case GL_FUNC_ADD: return VK_BLEND_OP_ADD; case GL_FUNC_SUBTRACT: return VK_BLEND_OP_SUBTRACT; case GL_FUNC_REVERSE_SUBTRACT: return VK_BLEND_OP_REVERSE_SUBTRACT; case GL_MIN: return VK_BLEND_OP_MIN; case GL_MAX: return VK_BLEND_OP_MAX; default: return VK_BLEND_OP_MAX_ENUM; } } VkCompareOp get_compare_op(GLenum func) { switch (func) { case GL_NEVER: return VK_COMPARE_OP_NEVER; case GL_LESS: return VK_COMPARE_OP_LESS; case GL_EQUAL: return VK_COMPARE_OP_EQUAL; case GL_LEQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL; case GL_GREATER: return VK_COMPARE_OP_GREATER; case GL_NOTEQUAL: return VK_COMPARE_OP_NOT_EQUAL; case GL_GEQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL; case GL_ALWAYS: return VK_COMPARE_OP_ALWAYS; default: return VK_COMPARE_OP_MAX_ENUM; } } VkComponentSwizzle get_component_swizzle(GLenum swizzle, GLenum comp) { if (swizzle == comp) return VK_COMPONENT_SWIZZLE_IDENTITY; switch (swizzle) { case GL_ZERO: return VK_COMPONENT_SWIZZLE_ZERO; case GL_ONE: return VK_COMPONENT_SWIZZLE_ONE; case GL_RED: return VK_COMPONENT_SWIZZLE_R; case GL_GREEN: return VK_COMPONENT_SWIZZLE_G; case GL_BLUE: return VK_COMPONENT_SWIZZLE_B; case GL_ALPHA: return VK_COMPONENT_SWIZZLE_A; default: return VK_COMPONENT_SWIZZLE_MAX_ENUM; } } VkCullModeFlags get_cull_mode_flags(GLenum mode) { switch (mode) { case GL_NONE: return VK_CULL_MODE_NONE; case GL_FRONT: return VK_CULL_MODE_FRONT_BIT; case GL_BACK: return VK_CULL_MODE_BACK_BIT; case GL_FRONT_AND_BACK: return VK_CULL_MODE_FRONT_AND_BACK; default: return VK_CULL_MODE_FLAG_BITS_MAX_ENUM; } } VkFormat get_format(GLenum internal_format) { switch (internal_format) { case GL_ALPHA8: return VK_FORMAT_R8_UNORM; case GL_LUMINANCE8: return VK_FORMAT_R8_UNORM; case GL_LUMINANCE8_ALPHA8: return VK_FORMAT_R8G8_UNORM; case GL_INTENSITY8: return VK_FORMAT_R8_UNORM; case GL_RGB5: return VK_FORMAT_R5G6B5_UNORM_PACK16; case GL_RGBA4: return VK_FORMAT_R4G4B4A4_UNORM_PACK16; case GL_RGB5_A1: return VK_FORMAT_R5G5B5A1_UNORM_PACK16; case GL_RGB8: case GL_RGBA8: return VK_FORMAT_R8G8B8A8_UNORM; case GL_DEPTH_COMPONENT24: return VK_FORMAT_D24_UNORM_S8_UINT; case GL_R8: return VK_FORMAT_R8_UNORM; case GL_RG8: return VK_FORMAT_R8G8_UNORM; case GL_R32F: return VK_FORMAT_R32_SFLOAT; case GL_RG16F: return VK_FORMAT_R16G16_SFLOAT; case GL_RG32F: return VK_FORMAT_R32G32_SFLOAT; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return VK_FORMAT_BC1_RGB_UNORM_BLOCK; case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return VK_FORMAT_BC1_RGBA_UNORM_BLOCK; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return VK_FORMAT_BC2_UNORM_BLOCK; case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return VK_FORMAT_BC3_UNORM_BLOCK; case GL_RGBA32F: return VK_FORMAT_R32G32B32A32_SFLOAT; case GL_RGBA16F: return VK_FORMAT_R16G16B16A16_SFLOAT; case GL_DEPTH24_STENCIL8: return VK_FORMAT_D24_UNORM_S8_UINT; case GL_R11F_G11F_B10F: return VK_FORMAT_B10G11R11_UFLOAT_PACK32; case GL_RGB9_E5: return VK_FORMAT_E5B9G9R9_UFLOAT_PACK32; case GL_DEPTH_COMPONENT32F: return VK_FORMAT_D32_SFLOAT; case GL_COMPRESSED_RED_RGTC1: return VK_FORMAT_BC4_UNORM_BLOCK; case GL_COMPRESSED_RG_RGTC2: return VK_FORMAT_BC5_UNORM_BLOCK; default: return VK_FORMAT_UNDEFINED; } } VkImageViewType get_image_view_type(GLenum target) { switch (target) { case GL_TEXTURE_2D: return VK_IMAGE_VIEW_TYPE_2D; case GL_TEXTURE_CUBE_MAP: return VK_IMAGE_VIEW_TYPE_CUBE; default: return VK_IMAGE_VIEW_TYPE_MAX_ENUM; } } VkPolygonMode get_polygon_mode(GLenum mode) { switch (mode) { case GL_POINT: return VK_POLYGON_MODE_POINT; case GL_LINE: return VK_POLYGON_MODE_LINE; case GL_FILL: return VK_POLYGON_MODE_FILL; default: return VK_POLYGON_MODE_MAX_ENUM; } } VkStencilOp get_stencil_op(GLenum op) { switch (op) { case GL_KEEP: return VK_STENCIL_OP_KEEP; case GL_ZERO: return VK_STENCIL_OP_ZERO; case GL_REPLACE: return VK_STENCIL_OP_REPLACE; case GL_INCR: return VK_STENCIL_OP_INCREMENT_AND_CLAMP; case GL_DECR: return VK_STENCIL_OP_DECREMENT_AND_CLAMP; case GL_INVERT: return VK_STENCIL_OP_INVERT; case GL_INCR_WRAP: return VK_STENCIL_OP_INCREMENT_AND_WRAP; case GL_DECR_WRAP: return VK_STENCIL_OP_DECREMENT_AND_WRAP; default: return VK_STENCIL_OP_MAX_ENUM; } } gl_texture_data::tex_data::tex_data() { } gl_texture_data::tex_data::~tex_data() { } void gl_texture_data::tex_data::set_data(GLint internal_format, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data) { this->data.clear(); if (!data) return; GLenum _format; GLenum _type; texture_get_format_type_by_internal_format(internal_format, &_format, &_type); if (_format != format) return; this->data.resize(texture_get_size(internal_format, width, height)); if (!gl_texture_data::tex_data::convert(internal_format, width, height, format, _type, type, data, this->data.data(), gl_wrap_manager_ptr->unpack_alignment, true)) this->data.clear(); } bool gl_texture_data::tex_data::convert(GLenum internal_format, GLsizei width, GLsizei height, GLenum format, GLenum src_type, GLenum dst_type, const void* src_data, void* dst_data, ssize_t alignment, bool unpack) { if (!src_type) { if (!format) return false; int32_t block_size; switch (internal_format) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_RED_RGTC1: block_size = 8; break; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: case GL_COMPRESSED_RG_RGTC2: block_size = 16; break; default: return false; } memmove(dst_data, src_data, texture_get_size(internal_format, width, height)); return true; } if (src_type == GL_UNSIGNED_BYTE && dst_type == GL_UNSIGNED_BYTE && format == GL_RGB) { if (unpack) { const uint8_t* src = (const uint8_t*)src_data; uint8_t* dst = (uint8_t*)dst_data; for (GLsizei y = 0; y < height; y++) { for (GLsizei x = 0; x < width; x++) { *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = 0xFF; } const int32_t src_size = width * 3; if (src_size % alignment) src += (ssize_t)alignment - src_size % alignment; } } else { const uint8_t* src = (const uint8_t*)src_data; uint8_t* dst = (uint8_t*)dst_data; for (GLsizei y = 0; y < height; y++) { for (GLsizei x = 0; x < width; x++) { *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; src++; } const int32_t dst_size = width * 4; if (dst_size % alignment) dst += (ssize_t)alignment - dst_size % alignment; } } } else if (src_type == GL_HALF_FLOAT && dst_type == GL_FLOAT) { int32_t comp_count = 1; if (format == GL_RG) comp_count = 2; else if (format == GL_RGB) comp_count = 3; else if (format == GL_RGBA) comp_count = 4; width *= comp_count; if (unpack) { const uint8_t* src = (const uint8_t*)src_data; uint8_t* dst = (uint8_t*)dst_data; for (GLsizei y = 0; y < height; y++) { GLsizei x = 0; for (; x < width / 4 * 4; x += 4, src += sizeof(vec4), dst += sizeof(vec4h)) vec4_to_vec4h(*(vec4*)src, *(vec4h*)dst); for (; x < width; x++, src += sizeof(float_t), dst += sizeof(half_t)) *(half_t*)dst = float_to_half(*(float_t*)src); const int32_t src_size = width * sizeof(half_t); if (src_size % alignment) src += (ssize_t)alignment - src_size % alignment; } } else { const uint8_t* src = (const uint8_t*)src_data; uint8_t* dst = (uint8_t*)dst_data; for (GLsizei y = 0; y < height; y++) { GLsizei x = 0; for (; x < width / 4 * 4; x += 4, src += sizeof(vec4), dst += sizeof(vec4h)) vec4_to_vec4h(*(vec4*)src, *(vec4h*)dst); for (; x < width; x++, src += sizeof(float_t), dst += sizeof(half_t)) *(half_t*)dst = float_to_half(*(float_t*)src); const int32_t dst_size = width * sizeof(float_t); if (dst_size % alignment) dst += (ssize_t)alignment - dst_size % alignment; } } } else if (src_type == GL_FLOAT && dst_type == GL_HALF_FLOAT) { int32_t comp_count = 1; if (format == GL_RG) comp_count = 2; else if (format == GL_RGB) comp_count = 3; else if (format == GL_RGBA) comp_count = 4; width *= comp_count; if (unpack) { const uint8_t* src = (const uint8_t*)src_data; uint8_t* dst = (uint8_t*)dst_data; for (GLsizei y = 0; y < height; y++) { GLsizei x = 0; for (; x < width / 4 * 4; x += 4, src += sizeof(vec4h), dst += sizeof(vec4)) vec4h_to_vec4(*(vec4h*)src, *(vec4*)dst); for (; x < width; x++, src += sizeof(half_t), dst += sizeof(float_t)) *(float_t*)dst = half_to_float(*(half_t*)src); const int32_t src_size = width * sizeof(float_t); if (src_size % alignment) src += (ssize_t)alignment - src_size % alignment; } } else { const uint8_t* src = (const uint8_t*)src_data; uint8_t* dst = (uint8_t*)dst_data; for (GLsizei y = 0; y < height; y++) { GLsizei x = 0; for (; x < width / 4 * 4; x += 4, src += sizeof(vec4h), dst += sizeof(vec4)) vec4h_to_vec4(*(vec4h*)src, *(vec4*)dst); for (; x < width; x++, src += sizeof(half_t), dst += sizeof(float_t)) *(float_t*)dst = half_to_float(*(half_t*)src); const int32_t dst_size = width * sizeof(half_t); if (dst_size % alignment) dst += (ssize_t)alignment - dst_size % alignment; } } } else { int32_t elem_size; switch (internal_format) { case GL_R8: elem_size = 1; break; case GL_RGB5: case GL_RGBA4: case GL_RGB5_A1: case GL_RG8: elem_size = 2; break; case GL_RGB8: case GL_RGBA8: case GL_R32F: case GL_RG16F: case GL_R11F_G11F_B10F: case GL_RGB9_E5: elem_size = 4; break; case GL_RGBA16F: case GL_RG32F: elem_size = 8; break; case GL_RGBA32F: elem_size = 16; break; default: return false; } if (unpack) { const uint8_t* src = (const uint8_t*)src_data; uint8_t* dst = (uint8_t*)dst_data; for (GLsizei y = 0; y < height; y++) { int32_t size = elem_size * width; memmove(dst, src, size); dst += size; src += size; if (size % alignment) src += (ssize_t)alignment - size % alignment; } } else { const uint8_t* src = (const uint8_t*)src_data; uint8_t* dst = (uint8_t*)dst_data; for (GLsizei y = 0; y < height; y++) { int32_t size = elem_size * width; memmove(dst, src, size); dst += size; src += size; if (size % alignment) dst += (ssize_t)alignment - size % alignment; } } } return true; } gl_texture_data::tex_data& gl_texture_data::tex_data::operator=(const gl_texture_data::tex_data& other) { data.assign(other.data.begin(), other.data.end()); return *this; }; gl_texture_data::gl_texture_data() : target(), level_count(), internal_format(), width(), height() { } gl_texture_data::~gl_texture_data() { } gl_texture_data::tex_data* gl_texture_data::get_tex_data(uint32_t level, uint32_t layer, bool get) { if (target != GL_TEXTURE_CUBE_MAP && layer || target == GL_TEXTURE_CUBE_MAP && (layer < 0 || layer >= 6)) return 0; if (data[layer].size() <= level) { if (get) return 0; data[layer].resize(level + 1ULL); level_count = level + 1; } return &data[layer].data()[level]; } bool gl_texture_data::valid() { return width && height; } gl_texture_data& gl_texture_data::operator=(const gl_texture_data& other) { target = other.target; internal_format = other.internal_format; width = other.width; height = other.height; level_count = other.level_count; for (uint32_t i = 0; i < 6; i++) data[i].assign(other.data[i].begin(), other.data[i].end()); return *this; }; gl_texture_data* gl_texture_data::get(GLuint texture) { if (!texture) return 0; auto elem = gl_wrap_manager_ptr->gl_texture_datas.find(texture); if (elem != gl_wrap_manager_ptr->gl_texture_datas.end()) return &elem->second; return 0; } gl_wrap_manager::gl_wrap_manager() : buffer_counter(), framebuffer_counter(), query_counter(), program_counter(), sampler_counter(), texture_counter(), vertex_array_counter(), query_samples_passed() { clear_color = 0.0f; clear_depth = 1.0f; clear_stencil = 0x00; pack_alignment = 4; unpack_alignment = 4; } gl_wrap_manager::~gl_wrap_manager() { for (auto& i : gl_vertex_buffers) i.second.vertex_buffer.Destroy(); for (auto& i : gl_uniform_buffers) i.second.uniform_buffer.Destroy(); for (auto& i : gl_storage_buffers) i.second.storage_buffer.Destroy(); for (auto& i : gl_queries) i.second.query.Destroy(); for (auto& i : gl_index_buffers) i.second.index_buffer.Destroy(); for (auto& i : gl_framebuffers) i.second.release(); for (auto& i : gl_textures) { i.second.sample_image_view.Destroy(); i.second.image_view.Destroy(); i.second.image.Destroy(); } } GLuint gl_wrap_manager::create_buffer() { if (!++buffer_counter) buffer_counter = 1; gl_buffers.insert({ buffer_counter, {} }); return buffer_counter; } GLuint gl_wrap_manager::create_framebuffer() { if (!++framebuffer_counter) framebuffer_counter = 1; gl_framebuffers.insert({ framebuffer_counter, {} }); return framebuffer_counter; } GLuint gl_wrap_manager::create_program() { if (!++program_counter) program_counter = 1; gl_programs.insert({ program_counter, {} }); return program_counter; } GLuint gl_wrap_manager::create_query() { if (!++query_counter) query_counter = 1; gl_queries.insert({ query_counter, {} }); return query_counter; } GLuint gl_wrap_manager::create_sampler() { if (!++sampler_counter) sampler_counter = 1; gl_samplers.insert({ sampler_counter, {} }); return sampler_counter; } GLuint gl_wrap_manager::create_texture() { if (!++texture_counter) texture_counter = 1; gl_textures.insert({ texture_counter, {} }); return texture_counter; } GLuint gl_wrap_manager::create_vertex_array() { if (!++vertex_array_counter) vertex_array_counter = 1; gl_vertex_arrays.insert({ vertex_array_counter, {} }); return vertex_array_counter; } GLenum gl_wrap_manager::get_error() { if (!this || !gl_errors.size()) return GL_NO_ERROR; GLenum error = gl_errors.back(); gl_errors.pop_back(); return error; } void gl_wrap_manager::push_error(GLenum error) { gl_errors.insert(gl_errors.begin(), error); } void gl_wrap_manager::release_buffer(GLuint buffer) { auto elem = gl_buffers.find(buffer); if (elem != gl_buffers.end()) { switch (elem->second.target) { case GL_ARRAY_BUFFER: { auto elem = gl_vertex_buffers.find(buffer); if (elem != gl_vertex_buffers.end()) { elem->second.vertex_buffer.Destroy(); gl_vertex_buffers.erase(elem); } } break; case GL_ELEMENT_ARRAY_BUFFER: { auto elem = gl_index_buffers.find(buffer); if (elem != gl_index_buffers.end()) { elem->second.index_buffer.Destroy(); gl_index_buffers.erase(elem); } } break; case GL_UNIFORM_BUFFER: { auto elem = gl_uniform_buffers.find(buffer); if (elem != gl_uniform_buffers.end()) { elem->second.uniform_buffer.Destroy(); gl_uniform_buffers.erase(elem); } } break; case GL_SHADER_STORAGE_BUFFER: { auto elem = gl_storage_buffers.find(buffer); if (elem != gl_storage_buffers.end()) { elem->second.storage_buffer.Destroy(); gl_storage_buffers.erase(elem); } } break; } gl_buffers.erase(elem); } } void gl_wrap_manager::release_framebuffer(GLuint framebuffer) { if (!framebuffer) return; auto elem = gl_framebuffers.find(framebuffer); if (elem != gl_framebuffers.end()) { elem->second.release(); gl_framebuffers.erase(elem); } } void gl_wrap_manager::release_program(GLuint program) { if (!program) return; auto elem = gl_programs.find(program); if (elem != gl_programs.end()) { elem->second.vertex_shader_module.reset(); elem->second.fragment_shader_module.reset(); gl_programs.erase(elem); } } void gl_wrap_manager::release_query(GLuint query) { if (!query) return; auto elem = gl_queries.find(query); if (elem != gl_queries.end()) { elem->second.query.Destroy(); gl_queries.erase(elem); } } void gl_wrap_manager::release_sampler(GLuint sampler) { if (!sampler) return; auto elem = gl_samplers.find(sampler); if (elem != gl_samplers.end()) gl_samplers.erase(elem); } void gl_wrap_manager::release_texture(GLuint texture) { if (!texture) return; auto elem = gl_textures.find(texture); if (elem != gl_textures.end()) { elem->second.sample_image_view.Destroy(); elem->second.image_view.Destroy(); elem->second.image.Destroy(); gl_textures.erase(elem); } auto elem_data = gl_texture_datas.find(texture); if (elem_data != gl_texture_datas.end()) gl_texture_datas.erase(elem_data); } void gl_wrap_manager::release_vertex_array(GLuint array) { if (!array) return; auto elem = gl_vertex_arrays.find(array); if (elem != gl_vertex_arrays.end()) gl_vertex_arrays.erase(elem); } void gl_wrap_manager::update_buffers() { for (auto& i : gl_index_buffers) { Vulkan::gl_index_buffer* vk_ib = &i.second; if (vk_ib->copy_working_buffer) { VkBuffer src_buffer = vk_ib->working_buffer; VkBuffer dst_buffer = vk_ib->index_buffer; VkDeviceSize src_offset = vk_ib->working_buffer.GetOffset(); VkDeviceSize dst_offset = vk_ib->index_buffer.GetOffset(); VkDeviceSize size = vk_ib->working_buffer.GetSize(); Vulkan::Buffer::Copy(Vulkan::current_command_buffer, src_buffer, dst_buffer, src_offset, dst_offset, size); VkBufferMemoryBarrier barrier; barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; barrier.pNext = 0; barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_INDEX_READ_BIT; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.buffer = dst_buffer; barrier.offset = dst_offset; barrier.size = size; vkCmdPipelineBarrier(Vulkan::current_command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, 0, 1, &barrier, 0, 0); vk_ib->copy_working_buffer = false; } vk_ib->working_buffer.Reset(); } for (auto& i : gl_storage_buffers) { Vulkan::gl_storage_buffer* vk_sb = &i.second; if (vk_sb->copy_working_buffer) { VkBuffer src_buffer = vk_sb->working_buffer; VkBuffer dst_buffer = vk_sb->storage_buffer; VkDeviceSize src_offset = vk_sb->working_buffer.GetOffset(); VkDeviceSize dst_offset = vk_sb->storage_buffer.GetOffset(); VkDeviceSize size = vk_sb->working_buffer.GetSize(); Vulkan::Buffer::Copy(Vulkan::current_command_buffer, src_buffer, dst_buffer, src_offset, dst_offset, size); VkBufferMemoryBarrier barrier; barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; barrier.pNext = 0; barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.buffer = dst_buffer; barrier.offset = dst_offset; barrier.size = size; vkCmdPipelineBarrier(Vulkan::current_command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, 0, 1, &barrier, 0, 0); vk_sb->copy_working_buffer = false; } vk_sb->working_buffer.Reset(); } for (auto& i : gl_uniform_buffers) { Vulkan::gl_uniform_buffer* vk_ub = &i.second; if (vk_ub->copy_working_buffer) { VkBuffer src_buffer = vk_ub->working_buffer; VkBuffer dst_buffer = vk_ub->uniform_buffer; VkDeviceSize src_offset = vk_ub->working_buffer.GetOffset(); VkDeviceSize dst_offset = vk_ub->uniform_buffer.GetOffset(); VkDeviceSize size = vk_ub->working_buffer.GetSize(); Vulkan::Buffer::Copy(Vulkan::current_command_buffer, src_buffer, dst_buffer, src_offset, dst_offset, size); VkBufferMemoryBarrier barrier; barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; barrier.pNext = 0; barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.buffer = dst_buffer; barrier.offset = dst_offset; barrier.size = size; vkCmdPipelineBarrier(Vulkan::current_command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, 0, 1, &barrier, 0, 0); vk_ub->copy_working_buffer = false; } vk_ub->working_buffer.Reset(); } for (auto& i : gl_vertex_buffers) { Vulkan::gl_vertex_buffer* vk_vb = &i.second; if (vk_vb->copy_working_buffer) { VkBuffer src_buffer = vk_vb->working_buffer; VkBuffer dst_buffer = vk_vb->vertex_buffer; VkDeviceSize src_offset = vk_vb->working_buffer.GetOffset(); VkDeviceSize dst_offset = vk_vb->vertex_buffer.GetOffset(); VkDeviceSize size = vk_vb->working_buffer.GetSize(); Vulkan::Buffer::Copy(Vulkan::current_command_buffer, src_buffer, dst_buffer, src_offset, dst_offset, size); VkBufferMemoryBarrier barrier; barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; barrier.pNext = 0; barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.buffer = dst_buffer; barrier.offset = dst_offset; barrier.size = size; vkCmdPipelineBarrier(Vulkan::current_command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, 0, 1, &barrier, 0, 0); vk_vb->copy_working_buffer = false; } vk_vb->working_buffer.Reset(); } } static void gl_wrap_manager_begin_query(GLenum target, GLuint id) { if (target != GL_SAMPLES_PASSED) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } gl_query* vk_que_curr = gl_query::get(gl_wrap_manager_ptr->query_samples_passed); if (vk_que_curr && vk_que_curr->target == target || !id || gl_wrap_manager_ptr->query_samples_passed == id) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } gl_query* vk_que = gl_query::get(id); if (!vk_que) return; else if (vk_que->target && vk_que->target != target) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } if (!vk_que->target) { vk_que->target = target; vk_que->query.Create(Vulkan::current_device, 0, VK_QUERY_TYPE_OCCLUSION); } gl_wrap_manager_ptr->query_samples_passed = id; } static void gl_wrap_manager_bind_buffer(GLenum target, GLuint buffer) { switch (target) { case GL_ARRAY_BUFFER: { auto elem = gl_wrap_manager_ptr->gl_vertex_buffers.find(buffer); if (elem == gl_wrap_manager_ptr->gl_vertex_buffers.end()) { auto elem = gl_wrap_manager_ptr->gl_buffers.find(buffer); if (elem == gl_wrap_manager_ptr->gl_buffers.end()) { if (buffer) gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } elem->second.target = GL_ARRAY_BUFFER; gl_wrap_manager_ptr->gl_vertex_buffers.insert({ buffer, {} }); } } break; case GL_ELEMENT_ARRAY_BUFFER: { auto elem = gl_wrap_manager_ptr->gl_index_buffers.find(buffer); if (elem == gl_wrap_manager_ptr->gl_index_buffers.end()) { auto elem = gl_wrap_manager_ptr->gl_buffers.find(buffer); if (elem == gl_wrap_manager_ptr->gl_buffers.end()) { if (buffer) gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } elem->second.target = GL_ELEMENT_ARRAY_BUFFER; gl_wrap_manager_ptr->gl_index_buffers.insert({ buffer, {} }); } gl_vertex_array* vk_vao = gl_vertex_array::get(gl_state.vertex_array_binding); if (vk_vao) vk_vao->index_buffer_binding.buffer = buffer; } break; case GL_UNIFORM_BUFFER: { auto elem = gl_wrap_manager_ptr->gl_uniform_buffers.find(buffer); if (elem == gl_wrap_manager_ptr->gl_uniform_buffers.end()) { auto elem = gl_wrap_manager_ptr->gl_buffers.find(buffer); if (elem == gl_wrap_manager_ptr->gl_buffers.end()) { if (buffer) gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } elem->second.target = GL_UNIFORM_BUFFER; gl_wrap_manager_ptr->gl_uniform_buffers.insert({ buffer, {} }); } } break; case GL_SHADER_STORAGE_BUFFER: { auto elem = gl_wrap_manager_ptr->gl_storage_buffers.find(buffer); if (elem == gl_wrap_manager_ptr->gl_storage_buffers.end()) { auto elem = gl_wrap_manager_ptr->gl_buffers.find(buffer); if (elem == gl_wrap_manager_ptr->gl_buffers.end()) { if (buffer) gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } elem->second.target = GL_SHADER_STORAGE_BUFFER; gl_wrap_manager_ptr->gl_storage_buffers.insert({ buffer, {} }); } } break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; } } static void gl_wrap_manager_bind_texture(GLenum target, GLuint texture) { if (!texture) return; switch (target) { case GL_TEXTURE_2D: case GL_TEXTURE_CUBE_MAP: break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } gl_texture* vk_tex = gl_texture::get(texture, false); if (!vk_tex) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } else if (vk_tex->target && vk_tex->target != target) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } vk_tex->target = target; } static void gl_wrap_manager_blit_framebuffer( GLint src_x0, GLint src_y0, GLint src_x1, GLint src_y1, GLint dst_x0, GLint dst_y0, GLint dst_x1, GLint dst_y1, GLbitfield mask, GLenum filter) { gl_wrap_manager_blit_named_framebuffer(gl_state.read_framebuffer_binding, gl_state.draw_framebuffer_binding, src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, mask, filter); } static void gl_wrap_manager_blit_named_framebuffer(GLuint readFramebuffer, GLuint drawFramebuffer, GLint src_x0, GLint src_y0, GLint src_x1, GLint src_y1, GLint dst_x0, GLint dst_y0, GLint dst_x1, GLint dst_y1, GLbitfield mask, GLenum filter) { if (!readFramebuffer && !drawFramebuffer || (mask & ~GL_COLOR_BUFFER_BIT)) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } VkFilter vk_filter; switch (filter) { case GL_NEAREST: vk_filter = VK_FILTER_NEAREST; break; case GL_LINEAR: vk_filter = VK_FILTER_LINEAR; break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } gl_framebuffer* vk_src_fbo = gl_framebuffer::get(readFramebuffer); gl_framebuffer* vk_dst_fbo = gl_framebuffer::get(drawFramebuffer); if (!vk_src_fbo && !vk_dst_fbo) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } VkImage src_image; VkImage dst_image; VkImageLayout src_old_layout; VkImageLayout dst_old_layout; if (!vk_src_fbo) { src_image = Vulkan::current_swapchain_image; src_old_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; } else { Vulkan::Image& vk_src_image = gl_texture::get(vk_src_fbo->get_read_buffer_texture())->image; src_image = vk_src_image; src_old_layout = vk_src_image.GetImageLayout(0, 0); } if (!vk_dst_fbo) { dst_image = Vulkan::current_swapchain_image; dst_old_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; } else { Vulkan::Image& vk_dst_image = gl_texture::get(vk_dst_fbo->get_draw_buffer_texture())->image; dst_image = vk_dst_image; dst_old_layout = vk_dst_image.GetImageLayout(0, 0); } VkImageBlit image_blit_region; image_blit_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; image_blit_region.srcSubresource.mipLevel = 0; image_blit_region.srcSubresource.baseArrayLayer = 0; image_blit_region.srcSubresource.layerCount = 1; image_blit_region.srcOffsets[0].x = src_x0; image_blit_region.srcOffsets[0].y = src_y0; image_blit_region.srcOffsets[0].z = 0; image_blit_region.srcOffsets[1].x = src_x1 - src_x0; image_blit_region.srcOffsets[1].y = src_y1 - src_y0; image_blit_region.srcOffsets[1].z = 1; image_blit_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; image_blit_region.dstSubresource.mipLevel = 0; image_blit_region.dstSubresource.baseArrayLayer = 0; image_blit_region.dstSubresource.layerCount = 1; image_blit_region.dstOffsets[0].x = dst_x0; image_blit_region.dstOffsets[0].y = dst_y0; image_blit_region.dstOffsets[0].z = 0; image_blit_region.dstOffsets[1].x = dst_x1 - dst_x0; image_blit_region.dstOffsets[1].y = dst_y1 - dst_y0; image_blit_region.dstOffsets[1].z = 1; const VkImageLayout src_new_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; const VkImageLayout dst_new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, src_image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, src_old_layout, src_new_layout); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, dst_image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, dst_old_layout, dst_new_layout); vkCmdBlitImage(Vulkan::current_command_buffer, src_image, src_new_layout, dst_image, dst_new_layout, 1, &image_blit_region, vk_filter); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, src_image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, src_new_layout, src_old_layout); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, dst_image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, dst_new_layout, dst_old_layout); } static void gl_wrap_manager_buffer_data( GLenum target, GLsizeiptr size, const void* data, GLenum usage) { switch (target) { case GL_ARRAY_BUFFER: gl_wrap_manager_named_buffer_data( gl_state.array_buffer_binding, size, data, usage); break; case GL_ELEMENT_ARRAY_BUFFER: gl_wrap_manager_named_buffer_data( gl_state.element_array_buffer_binding, size, data, usage); break; case GL_UNIFORM_BUFFER: gl_wrap_manager_named_buffer_data( gl_state.uniform_buffer_binding, size, data, usage); break; case GL_SHADER_STORAGE_BUFFER: gl_wrap_manager_named_buffer_data( gl_state.shader_storage_buffer_binding, size, data, usage); break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; }; } static void gl_wrap_manager_buffer_storage( GLenum target, GLsizeiptr size, const void* data, GLbitfield flags) { switch (target) { case GL_ARRAY_BUFFER: gl_wrap_manager_named_buffer_storage( gl_state.array_buffer_binding, size, data, flags); break; case GL_ELEMENT_ARRAY_BUFFER: gl_wrap_manager_named_buffer_storage( gl_state.element_array_buffer_binding, size, data, flags); break; case GL_UNIFORM_BUFFER: gl_wrap_manager_named_buffer_storage( gl_state.uniform_buffer_binding, size, data, flags); break; case GL_SHADER_STORAGE_BUFFER: gl_wrap_manager_named_buffer_storage( gl_state.shader_storage_buffer_binding, size, data, flags); break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; }; } static void gl_wrap_manager_buffer_sub_data( GLenum target, GLintptr offset, GLsizeiptr size, const void* data) { switch (target) { case GL_ARRAY_BUFFER: gl_wrap_manager_named_buffer_sub_data( gl_state.array_buffer_binding, offset, size, data); break; case GL_ELEMENT_ARRAY_BUFFER: gl_wrap_manager_named_buffer_sub_data( gl_state.element_array_buffer_binding, offset, size, data); break; case GL_UNIFORM_BUFFER: gl_wrap_manager_named_buffer_sub_data( gl_state.uniform_buffer_binding, offset, size, data); break; case GL_SHADER_STORAGE_BUFFER: gl_wrap_manager_named_buffer_sub_data( gl_state.shader_storage_buffer_binding, offset, size, data); break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; }; } static GLenum gl_wrap_manager_check_framebuffer_status(GLenum target) { GLuint framebuffer; switch (target) { case GL_FRAMEBUFFER: framebuffer = gl_state.framebuffer_binding; break; case GL_READ_FRAMEBUFFER: framebuffer = gl_state.read_framebuffer_binding; break; case GL_DRAW_FRAMEBUFFER: framebuffer = gl_state.draw_framebuffer_binding; break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return 0; } gl_framebuffer* vk_fbo = gl_framebuffer::get(framebuffer, false); if (!vk_fbo) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return 0; } uint32_t attachment_count = 0; for (uint32_t i = 0; i <= Vulkan::MAX_COLOR_ATTACHMENTS; i++) { GLuint texture = i == Vulkan::MAX_COLOR_ATTACHMENTS ? vk_fbo->depth_attachment : vk_fbo->color_attachments[i]; if (!texture) continue; gl_texture* vk_tex = gl_texture::get(texture); gl_texture_data* vk_tex_data = gl_texture_data::get(texture); if (!vk_tex->image && (!vk_tex_data || !vk_tex_data->valid())) return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; if (i == Vulkan::MAX_COLOR_ATTACHMENTS) switch (vk_tex->image ? vk_tex->internal_format : vk_tex->internal_format) { case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: case GL_DEPTH24_STENCIL8: case GL_DEPTH_COMPONENT32F: break; default: return GL_FRAMEBUFFER_UNSUPPORTED; } else switch (vk_tex->image ? vk_tex->internal_format : vk_tex->internal_format) { case GL_R8: case GL_RG8: case GL_RGBA8: case GL_R32F: case GL_RG16F: case GL_R11F_G11F_B10F: case GL_RGBA16F: case GL_RG32F: case GL_RGBA32F: break; default: return GL_FRAMEBUFFER_UNSUPPORTED; } attachment_count++; } if (!attachment_count) return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; for (uint32_t i = 0; i < Vulkan::MAX_DRAW_BUFFERS; i++) if (vk_fbo->draw_buffers[i] && !vk_fbo->get_draw_buffer_texture(i)) return GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER; if (vk_fbo->read_buffer && !vk_fbo->get_read_buffer_texture()) return GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER; return GL_FRAMEBUFFER_COMPLETE; } static void gl_wrap_manager_clear(GLbitfield mask) { if (mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } if (mask & GL_COLOR_BUFFER_BIT) { const vec4& clear_color = gl_wrap_manager_ptr->clear_color; gl_framebuffer* vk_fbo = gl_framebuffer::get(gl_state.draw_framebuffer_binding); for (uint32_t i = 0; i < Vulkan::MAX_COLOR_ATTACHMENTS; i++) { VkImage image; VkImageLayout old_layout; if (!vk_fbo) { image = Vulkan::current_swapchain_image; old_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; } else { if (!vk_fbo->color_attachments[i]) continue; Vulkan::Image& vk_image = gl_texture::get(vk_fbo->color_attachments[i])->image; image = vk_image; old_layout = vk_image.GetImageLayout(0, 0); } VkClearColorValue clear_color_value; clear_color_value.float32[0] = clear_color.x; clear_color_value.float32[1] = clear_color.y; clear_color_value.float32[2] = clear_color.z; clear_color_value.float32[3] = clear_color.w; VkImageSubresourceRange range; range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; range.baseMipLevel = 0; range.levelCount = 1; range.baseArrayLayer = 0; range.layerCount = 1; const VkImageLayout new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, old_layout, new_layout); vkCmdClearColorImage(Vulkan::current_command_buffer, image, new_layout, &clear_color_value, 1, &range); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, new_layout, old_layout); if (!vk_fbo) break; } } if (mask & GL_DEPTH_BUFFER_BIT) { gl_framebuffer* vk_fbo = gl_framebuffer::get(gl_state.draw_framebuffer_binding); if (vk_fbo && vk_fbo->depth_attachment) { gl_texture* vk_tex = gl_texture::get(vk_fbo->depth_attachment); VkImage image = vk_tex->image; const VkImageLayout old_layout = vk_tex->image.GetImageLayout(0, 0); const VkImageAspectFlags aspect_mask = Vulkan::get_aspect_mask(vk_tex->internal_format); VkClearDepthStencilValue clear_depth_stencil_value; clear_depth_stencil_value.depth = gl_wrap_manager_ptr->clear_depth; clear_depth_stencil_value.stencil = gl_wrap_manager_ptr->clear_stencil; VkImageSubresourceRange range; range.aspectMask = aspect_mask; range.baseMipLevel = 0; range.levelCount = 1; range.baseArrayLayer = 0; range.layerCount = 1; const VkImageLayout new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, image, aspect_mask, 0, 0, old_layout, new_layout); vkCmdClearDepthStencilImage(Vulkan::current_command_buffer, image, new_layout, &clear_depth_stencil_value, 1, &range); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, image, aspect_mask, 0, 0, new_layout, old_layout); } } } static void gl_wrap_manager_clear_buffer(GLenum buffer, GLint drawbuffer, const GLfloat* value) { gl_wrap_manager_clear_named_framebuffer(gl_state.draw_framebuffer_binding, buffer, drawbuffer, value); } static void gl_wrap_manager_clear_color(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { vec4& clear_color = gl_wrap_manager_ptr->clear_color; clear_color.x = red; clear_color.y = green; clear_color.z = blue; clear_color.w = alpha; } static void gl_wrap_manager_clear_depth(GLfloat depth) { gl_wrap_manager_ptr->clear_depth = depth; } static void gl_wrap_manager_clear_stencil(GLint s) { gl_wrap_manager_ptr->clear_stencil = s; } static void gl_wrap_manager_clear_named_framebuffer(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat* value) { VkImageAspectFlags aspect_mask; switch (buffer) { case GL_COLOR: aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT; if (drawbuffer < 0 || drawbuffer >= Vulkan::MAX_COLOR_ATTACHMENTS) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } break; case GL_DEPTH: aspect_mask = VK_IMAGE_ASPECT_DEPTH_BIT; if (drawbuffer) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } gl_framebuffer* vk_fbo = gl_framebuffer::get(framebuffer); if (framebuffer && !vk_fbo) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } VkImage image; VkImageLayout old_layout; if (!vk_fbo) { if (buffer != GL_COLOR) return; image = Vulkan::current_swapchain_image; old_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; } else { if (buffer == GL_DEPTH) { GLuint texture = vk_fbo->depth_attachment; if (!texture) return; Vulkan::Image& vk_image = gl_texture::get(texture)->image; image = vk_image; old_layout = vk_image.GetImageLayout(0, 0); } else { GLuint texture = vk_fbo->get_draw_buffer_texture(drawbuffer); if (!texture) return; Vulkan::Image& vk_image = gl_texture::get(texture)->image; image = vk_image; old_layout = vk_image.GetImageLayout(0, 0); } } VkImageSubresourceRange range; range.aspectMask = aspect_mask; range.baseMipLevel = 0; range.levelCount = 1; range.baseArrayLayer = 0; range.layerCount = 1; const VkImageLayout new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, image, aspect_mask, 0, 0, old_layout, new_layout); switch (buffer) { case GL_COLOR: { VkClearColorValue clear_color_value; clear_color_value.float32[0] = value[0]; clear_color_value.float32[1] = value[1]; clear_color_value.float32[2] = value[2]; clear_color_value.float32[3] = value[3]; vkCmdClearColorImage(Vulkan::current_command_buffer, image, new_layout, &clear_color_value, 1, &range); } break; case GL_DEPTH: { VkClearDepthStencilValue clear_depth_stencil_value; clear_depth_stencil_value.depth = value[0]; clear_depth_stencil_value.stencil = 0; vkCmdClearDepthStencilImage(Vulkan::current_command_buffer, image, new_layout, &clear_depth_stencil_value, 1, &range); } break; } Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, image, aspect_mask, 0, 0, new_layout, old_layout); } static void gl_wrap_manager_compressed_tex_image_2d(GLenum target, GLint level, GLenum internal_format, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) { uint32_t layer; GLuint texture; switch (target) { case GL_TEXTURE_2D: layer = 0; texture = gl_state.texture_binding_2d[gl_state.active_texture_index]; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: layer = 0; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: layer = 1; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: layer = 2; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: layer = 3; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: layer = 4; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: layer = 5; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if (target == GL_TEXTURE_CUBE_MAP && width != height) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (internal_format) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: case GL_COMPRESSED_RED_RGTC1: case GL_COMPRESSED_RG_RGTC2: break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if (texture_get_size(internal_format, width, height) != imageSize || width < 0 || width > sv_max_texture_size || height < 0 || height > sv_max_texture_size || level < 0 || level >= (int32_t)log2(sv_max_texture_size) || border) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_texture* vk_tex = gl_texture::get(texture, false); if (!vk_tex || vk_tex->target != target || vk_tex->internal_format && vk_tex->internal_format != internal_format) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } if (vk_tex->image && (max_def(vk_tex->width >> level, 1) != width || max_def(vk_tex->height >> level, 1) != height)) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_texture_data* vk_tex_data = gl_texture_data::get(texture); if (!vk_tex_data) { vk_tex_data = &gl_wrap_manager_ptr->gl_texture_datas.insert({ texture, {} }).first->second; vk_tex_data->target = target; vk_tex_data->internal_format = internal_format; } if (!level) { vk_tex_data->width = width; vk_tex_data->height = height; } else if (!vk_tex_data->valid() || vk_tex_data->internal_format != internal_format) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (max_def(vk_tex_data->width >> level, 1) != width || max_def(vk_tex_data->height >> level, 1) != height) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } GLenum format; GLenum type; texture_get_format_type_by_internal_format(internal_format, &format, &type); gl_texture_data::tex_data* tex_data = vk_tex_data->get_tex_data(level, layer); if (tex_data) tex_data->set_data(internal_format, 0, 0, width, height, format, type, data); } static void gl_wrap_manager_compressed_tex_sub_image_2d(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) { uint32_t layer; GLuint texture; switch (target) { case GL_TEXTURE_2D: layer = 0; texture = gl_state.texture_binding_2d[gl_state.active_texture_index]; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: layer = 0; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: layer = 1; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: layer = 2; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: layer = 3; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: layer = 4; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: layer = 5; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if (target == GL_TEXTURE_CUBE_MAP && width != height) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (format) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: case GL_COMPRESSED_RED_RGTC1: case GL_COMPRESSED_RG_RGTC2: break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if (texture_get_size(format, width, height) != imageSize || width < 0 || width > sv_max_texture_size || height < 0 || height > sv_max_texture_size || level < 0 || level >= (int32_t)log2(sv_max_texture_size)) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_texture* vk_tex = gl_texture::get(texture, false); if (!vk_tex) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (vk_tex->target != target) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if (vk_tex->image && (max_def(vk_tex->width >> level, 1) != width || max_def(vk_tex->height >> level, 1) != height) || xoffset || yoffset) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_texture_data* vk_tex_data = gl_texture_data::get(texture); if (!vk_tex_data) { if (!vk_tex->internal_format) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } vk_tex_data = &gl_wrap_manager_ptr->gl_texture_datas.insert({ texture, {} }).first->second; vk_tex_data->target = target; vk_tex_data->internal_format = vk_tex->internal_format; if (!level) { vk_tex_data->width = width; vk_tex_data->height = height; } } else if (!vk_tex_data->valid() || vk_tex_data->internal_format != format) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (max_def(vk_tex_data->width >> level, 1) != width || max_def(vk_tex_data->height >> level, 1) != height) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } GLenum _format; GLenum _type; texture_get_format_type_by_internal_format(vk_tex_data->internal_format, &_format, &_type); gl_texture_data::tex_data* tex_data = vk_tex_data->get_tex_data(level, layer); if (tex_data) tex_data->set_data(vk_tex->internal_format, xoffset, yoffset, width, height, _format, _type, data); } static void gl_wrap_manager_copy_image_sub_data( GLuint src_name, GLenum src_target, GLint src_level, GLint src_x, GLint src_y, GLint src_z, GLuint dst_name, GLenum dst_target, GLint dst_level, GLint dst_x, GLint dst_y, GLint dst_z, GLsizei src_width, GLsizei src_height, GLsizei src_depth) { if (!src_name && !dst_name || src_target != GL_TEXTURE_2D || src_target != dst_target) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } gl_texture* vk_src_tex = gl_texture::get(src_name); gl_texture* vk_dst_tex = gl_texture::get(dst_name); if (!vk_src_tex || !vk_dst_tex) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } else if (vk_src_tex->internal_format != vk_dst_tex->internal_format) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (src_level < 0 || (int64_t)vk_src_tex->get_level_count() <= src_level || dst_level < 0 || (int64_t)vk_dst_tex->get_level_count() <= dst_level || src_x < 0 || src_y < 0 || src_z < 0 || src_x + src_width > vk_src_tex->width || src_y + src_height > vk_src_tex->height || src_z + src_depth > 1 || dst_x < 0 || dst_y < 0 || dst_z < 0 || dst_x + src_width > vk_dst_tex->width || dst_y + src_height > vk_dst_tex->height || dst_z + src_depth > 1) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } switch (vk_src_tex->internal_format) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: case GL_COMPRESSED_RED_RGTC1: case GL_COMPRESSED_RG_RGTC2: if (src_x % 4 || src_y % 4 || src_z % 4 || dst_x % 4 || dst_y % 4 || dst_z % 4 || src_width % 4 || src_height % 4 || src_depth % 4) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } break; } VkImage src_image = vk_src_tex->image; VkImageLayout src_old_layout = vk_src_tex->image.GetImageLayout(0, 0); VkImage dst_image = vk_dst_tex->image; VkImageLayout dst_old_layout = vk_dst_tex->image.GetImageLayout(0, 0); VkImageCopy image_copy_region; image_copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; image_copy_region.srcSubresource.mipLevel = src_level; image_copy_region.srcSubresource.baseArrayLayer = 0; image_copy_region.srcSubresource.layerCount = 1; image_copy_region.srcOffset.x = src_x; image_copy_region.srcOffset.y = src_y; image_copy_region.srcOffset.z = 0; image_copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; image_copy_region.dstSubresource.mipLevel = dst_level; image_copy_region.dstSubresource.baseArrayLayer = 0; image_copy_region.dstSubresource.layerCount = 1; image_copy_region.dstOffset.x = dst_x; image_copy_region.dstOffset.y = dst_y; image_copy_region.dstOffset.z = 0; image_copy_region.extent.width = src_width; image_copy_region.extent.height = src_height; image_copy_region.extent.depth = src_depth; const VkImageLayout src_new_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; const VkImageLayout dst_new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, src_image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, src_old_layout, src_new_layout); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, dst_image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, dst_old_layout, dst_new_layout); vkCmdCopyImage(Vulkan::current_command_buffer, src_image, src_new_layout, dst_image, dst_new_layout, 1, &image_copy_region); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, src_image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, src_new_layout, src_old_layout); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, dst_image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, dst_new_layout, dst_old_layout); } static void gl_wrap_manager_copy_tex_sub_image_2d(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { uint32_t layer; GLuint texture; switch (target) { case GL_TEXTURE_2D: layer = 0; texture = gl_state.texture_binding_2d[gl_state.active_texture_index]; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: layer = 0; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: layer = 1; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: layer = 2; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: layer = 3; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: layer = 4; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: layer = 5; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if (target == GL_TEXTURE_CUBE_MAP && width != height) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } else if (width < 0 || width > sv_max_texture_size || height < 0 || height > sv_max_texture_size || level < 0 || level >= (int32_t)log2(sv_max_texture_size)) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_texture* vk_tex = gl_texture::get(texture); if (!vk_tex || !vk_tex->image) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (xoffset < 0 || (xoffset + width) > vk_tex->width || yoffset < 0 || (yoffset + height) > vk_tex->height) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_framebuffer* vk_fbo = gl_framebuffer::get(gl_state.read_framebuffer_binding, false); VkImage src_image; VkImageLayout src_old_layout; if (!vk_fbo) { src_image = Vulkan::current_swapchain_image; src_old_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; } else { GLuint texture = vk_fbo->get_read_buffer_texture(); if (!texture) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } Vulkan::Image& vk_image = gl_texture::get(texture)->image; src_image = vk_image; src_old_layout = vk_image.GetImageLayout(0, 0); } VkImage dst_image = vk_tex->image; VkImageLayout dst_old_layout = vk_tex->image.GetImageLayout(0, 0); VkImageCopy image_copy_region; image_copy_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; image_copy_region.srcSubresource.mipLevel = 0; image_copy_region.srcSubresource.baseArrayLayer = 0; image_copy_region.srcSubresource.layerCount = 1; image_copy_region.srcOffset.x = x; image_copy_region.srcOffset.y = y; image_copy_region.srcOffset.z = 0; image_copy_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; image_copy_region.dstSubresource.mipLevel = 0; image_copy_region.dstSubresource.baseArrayLayer = 0; image_copy_region.dstSubresource.layerCount = 1; image_copy_region.dstOffset.x = xoffset; image_copy_region.dstOffset.y = yoffset; image_copy_region.dstOffset.z = 0; image_copy_region.extent.width = width; image_copy_region.extent.height = height; image_copy_region.extent.depth = 1; const VkImageLayout src_new_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; const VkImageLayout dst_new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, src_image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, src_old_layout, src_new_layout); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, dst_image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, dst_old_layout, dst_new_layout); vkCmdCopyImage(Vulkan::current_command_buffer, src_image, src_new_layout, dst_image, dst_new_layout, 1, &image_copy_region); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, src_image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, src_new_layout, src_old_layout); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, dst_image, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, dst_new_layout, dst_old_layout); } static void gl_wrap_manager_create_buffers(GLsizei n, GLuint* buffers) { if (n < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } for (GLsizei i = 0; i < n; i++) buffers[i] = gl_wrap_manager_ptr->create_buffer(); } static GLuint gl_wrap_manager_create_program() { return gl_wrap_manager_ptr->create_program(); } static void gl_wrap_manager_delete_buffers(GLsizei n, const GLuint* buffers) { if (n < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } for (GLsizei i = 0; i < n; i++) gl_wrap_manager_ptr->release_buffer(buffers[i]); } static void gl_wrap_manager_delete_framebuffers(GLsizei n, const GLuint* framebuffers) { if (n < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } for (GLsizei i = 0; i < n; i++) gl_wrap_manager_ptr->release_framebuffer(framebuffers[i]); } static void gl_wrap_manager_delete_program(GLuint program) { gl_wrap_manager_ptr->release_program(program); } static void gl_wrap_manager_delete_queries(GLsizei n, const GLuint* ids) { if (n < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } for (GLsizei i = 0; i < n; i++) gl_wrap_manager_ptr->release_query(ids[i]); } static void gl_wrap_manager_delete_samplers(GLsizei n, const GLuint* samplers) { if (n < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } for (GLsizei i = 0; i < n; i++) gl_wrap_manager_ptr->release_sampler(samplers[i]); } static void gl_wrap_manager_delete_textures(GLsizei n, const GLuint* textures) { if (n < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } for (GLsizei i = 0; i < n; i++) gl_wrap_manager_ptr->release_texture(textures[i]); } static void gl_wrap_manager_delete_vertex_arrays(GLsizei n, const GLuint* arrays) { if (n < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } for (GLsizei i = 0; i < n; i++) gl_wrap_manager_ptr->release_vertex_array(arrays[i]); } static void gl_wrap_manager_disable_vertex_attrib_array(GLuint index) { if (index >= Vulkan::MAX_VERTEX_ATTRIB_COUNT) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_vertex_array* vk_vao = gl_vertex_array::get(gl_state.vertex_array_binding); if (!vk_vao) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } vk_vao->reset_vertex_attrib(index); vk_vao->vertex_attribs[index].enabled = false; } static void gl_wrap_manager_draw_buffer(GLenum buf) { gl_wrap_manager_draw_buffers(1, &buf); } static void gl_wrap_manager_draw_buffers(GLsizei n, const GLenum* bufs) { if (n < 0 || n >= Vulkan::MAX_DRAW_BUFFERS) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } gl_framebuffer* vk_fbo = gl_framebuffer::get(gl_state.framebuffer_binding, false); if (!vk_fbo) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } bool color_attachments[Vulkan::MAX_COLOR_ATTACHMENTS] = {}; for (GLsizei i = 0; i < n && i < Vulkan::MAX_DRAW_BUFFERS; i++) { GLenum buf = bufs[i]; if (!buf) continue; if (buf < GL_COLOR_ATTACHMENT0 || buf >= GL_COLOR_ATTACHMENT0 + Vulkan::MAX_COLOR_ATTACHMENTS || color_attachments[buf - GL_COLOR_ATTACHMENT0]) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } color_attachments[buf - GL_COLOR_ATTACHMENT0] = true; } for (GLsizei i = 0; i < n && i < Vulkan::MAX_DRAW_BUFFERS; i++) if (vk_fbo->draw_buffers[i] != bufs[i]) { vk_fbo->draw_buffers[i] = bufs[i]; vk_fbo->update_framebuffer = true; } } static void gl_wrap_manager_enable_vertex_attrib_array(GLuint index) { if (index >= Vulkan::MAX_VERTEX_ATTRIB_COUNT) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_vertex_array* vk_vao = gl_vertex_array::get(gl_state.vertex_array_binding); if (!vk_vao) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } vk_vao->vertex_attribs[index].enabled = true; } static void gl_wrap_manager_end_query(GLenum target) { if (target != GL_SAMPLES_PASSED) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if (!gl_wrap_manager_ptr->query_samples_passed) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } gl_query* vk_que = gl_query::get(gl_wrap_manager_ptr->query_samples_passed); if (!vk_que) return; vk_que->query.End(Vulkan::current_command_buffer); gl_wrap_manager_ptr->query_samples_passed = 0; } static void gl_wrap_manager_finish() { } static void gl_wrap_manager_framebuffer_texture(GLenum target, GLenum attachment, GLuint texture, GLint level) { if (target != GL_FRAMEBUFFER || attachment < GL_COLOR_ATTACHMENT0 && attachment != GL_DEPTH_STENCIL_ATTACHMENT || (attachment > GL_COLOR_ATTACHMENT0 + Vulkan::MAX_COLOR_ATTACHMENTS && attachment != GL_DEPTH_ATTACHMENT)) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } gl_framebuffer* vk_fbo = gl_framebuffer::get(gl_state.framebuffer_binding, false); if (!vk_fbo) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (level < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_texture* vk_tex = gl_texture::get(texture, false); gl_texture_data* vk_tex_data = gl_texture_data::get(texture); if (texture && (!vk_tex || level >= (int64_t)vk_tex->level_count && (!vk_tex_data || !vk_tex_data->valid() || level >= (int64_t)vk_tex_data->level_count))) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } if (attachment == GL_DEPTH_ATTACHMENT || attachment == GL_DEPTH_STENCIL_ATTACHMENT) { vk_fbo->depth_attachment = texture; vk_fbo->depth_attachment_level = texture ? level : 0; vk_fbo->update_depth_attachment = true; } else { uint32_t index = attachment - GL_COLOR_ATTACHMENT0; vk_fbo->color_attachments[index] = texture; vk_fbo->color_attachment_levels[index] = texture ? level : 0; vk_fbo->update_color_attachment = true; } } static void gl_wrap_manager_gen_buffers(GLsizei n, GLuint* buffers) { if (n < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } for (GLsizei i = 0; i < n; i++) buffers[i] = gl_wrap_manager_ptr->create_buffer(); } static void gl_wrap_manager_gen_framebuffers(GLsizei n, GLuint* framebuffers) { if (n < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } for (GLsizei i = 0; i < n; i++) framebuffers[i] = gl_wrap_manager_ptr->create_framebuffer(); } static void gl_wrap_manager_gen_queries(GLsizei n, GLuint* ids) { if (n < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } for (GLsizei i = 0; i < n; i++) ids[i] = gl_wrap_manager_ptr->create_query(); } static void gl_wrap_manager_gen_samplers(GLsizei n, GLuint* samplers) { if (n < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } for (GLsizei i = 0; i < n; i++) samplers[i] = gl_wrap_manager_ptr->create_sampler(); } static void gl_wrap_manager_gen_textures(GLsizei n, GLuint* textures) { if (n < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } for (GLsizei i = 0; i < n; i++) textures[i] = gl_wrap_manager_ptr->create_texture(); } static void gl_wrap_manager_gen_vertex_arrays(GLsizei n, GLuint* arrays) { if (n < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } for (GLsizei i = 0; i < n; i++) arrays[i] = gl_wrap_manager_ptr->create_vertex_array(); } static void gl_wrap_manager_generate_mipmap(GLenum target) { switch (target) { case GL_TEXTURE_2D: gl_wrap_manager_generate_texture_mipmap( gl_state.texture_binding_2d[gl_state.active_texture_index]); break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; } } static void gl_wrap_manager_generate_texture_mipmap(GLuint texture) { gl_texture* vk_tex = gl_texture::get(texture); if (!vk_tex) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (vk_tex->target != GL_TEXTURE_2D || Vulkan::get_aspect_mask(vk_tex->internal_format) != VK_IMAGE_ASPECT_COLOR_BIT) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } const uint32_t level_count = vk_tex->get_level_count(); Vulkan::Image& vk_image = vk_tex->image; VkImage image = vk_image; VkImageLayout old_layout = vk_image.GetImageLayout(0, 0); const VkImageLayout src_new_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; const VkImageLayout dst_new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; for (uint32_t i = 1; i < level_count; i++) { VkImageBlit image_blit_region; image_blit_region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; image_blit_region.srcSubresource.mipLevel = i - 1; image_blit_region.srcSubresource.baseArrayLayer = 0; image_blit_region.srcSubresource.layerCount = 1; image_blit_region.srcOffsets[0].x = 0; image_blit_region.srcOffsets[0].y = 0; image_blit_region.srcOffsets[0].z = 0; image_blit_region.srcOffsets[1].x = (int32_t)(vk_tex->width >> (i - 1)); image_blit_region.srcOffsets[1].y = (int32_t)(vk_tex->height >> (i - 1)); image_blit_region.srcOffsets[1].z = 1; image_blit_region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; image_blit_region.dstSubresource.mipLevel = i; image_blit_region.dstSubresource.baseArrayLayer = 0; image_blit_region.dstSubresource.layerCount = 1; image_blit_region.dstOffsets[0].x = 0; image_blit_region.dstOffsets[0].y = 0; image_blit_region.dstOffsets[0].z = 0; image_blit_region.dstOffsets[1].x = (int32_t)(vk_tex->width >> i); image_blit_region.dstOffsets[1].y = (int32_t)(vk_tex->height >> i); image_blit_region.dstOffsets[1].z = 1; Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, vk_image, VK_IMAGE_ASPECT_COLOR_BIT, i - 1, 0, src_new_layout); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, vk_image, VK_IMAGE_ASPECT_COLOR_BIT, i, 0, dst_new_layout); vkCmdBlitImage(Vulkan::current_command_buffer, image, src_new_layout, image, dst_new_layout, 1, &image_blit_region, VK_FILTER_LINEAR); } Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, vk_image, VK_IMAGE_ASPECT_COLOR_BIT, level_count - 1, 0, src_new_layout); } static void gl_wrap_manager_get_compressed_tex_image(GLenum target, GLint level, void* img) { uint32_t layer; GLuint texture; switch (target) { case GL_TEXTURE_2D: layer = 0; texture = gl_state.texture_binding_2d[gl_state.active_texture_index]; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: layer = 0; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: layer = 1; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: layer = 2; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: layer = 3; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: layer = 4; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: layer = 5; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } gl_texture* vk_tex = gl_texture::get(texture, false); if (!vk_tex || vk_tex->target != target) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } GLenum internal_format = GL_NONE; GLsizei width = 0; GLsizei height = 0; uint32_t level_count = 0; gl_texture_data* vk_tex_data = gl_texture_data::get(texture); if (vk_tex_data && vk_tex_data->valid()) { gl_texture_data::tex_data* tex_data = vk_tex_data->get_tex_data(level, layer, true); if (tex_data && tex_data->data.size()) { internal_format = vk_tex_data->internal_format; width = vk_tex_data->width; height = vk_tex_data->height; level_count = vk_tex_data->level_count; } } if (!internal_format) { internal_format = vk_tex->internal_format; width = vk_tex->width; height = vk_tex->height; level_count = vk_tex->level_count; } if (!internal_format) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (level < 0 || level >= (int64_t)level_count) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } width = max_def(width >> level, 1); height = max_def(height >> level, 1); const int32_t size = texture_get_size(internal_format, width, height); if (vk_tex_data && vk_tex_data->valid()) { gl_texture_data::tex_data* tex_data = vk_tex_data->get_tex_data(level, layer, true); if (tex_data && tex_data->data.size()) { memmove(img, tex_data->data.data(), size); return; } } Vulkan::Buffer staging_buffer = Vulkan::manager_get_staging_buffer(size); const VkImageViewType image_view_type = Vulkan::get_image_view_type(vk_tex->target); const VkFormat format = Vulkan::get_format(vk_tex->internal_format); const VkImageAspectFlags aspect_mask = Vulkan::get_aspect_mask(vk_tex->internal_format); Vulkan::CommandBuffer cb(Vulkan::current_device, Vulkan::current_command_pool, Vulkan::current_command_buffer); const VkImageLayout old_layout = vk_tex->image.GetImageLayout(level, layer); const VkImageLayout new_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, vk_tex->image, aspect_mask, level, layer, new_layout); cb.CopyImageToBuffer(vk_tex->image, staging_buffer, staging_buffer.GetOffset(), aspect_mask, level, layer, 0, 0, width, height); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, vk_tex->image, aspect_mask, level, layer, old_layout); staging_buffer.ReadMemory(staging_buffer.GetOffset(), size, img); } static GLenum gl_wrap_manager_get_error() { return gl_wrap_manager_ptr->get_error(); } static void gl_wrap_manager_get_float(GLenum pname, GLfloat* data) { switch (pname) { case GL_COLOR_CLEAR_VALUE: { const vec4& clear_color = gl_wrap_manager_ptr->clear_color; data[0] = clear_color.x; data[1] = clear_color.y; data[2] = clear_color.z; data[3] = clear_color.w; } break; case GL_DEPTH_CLEAR_VALUE: *data = gl_wrap_manager_ptr->clear_depth; break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; } } static void gl_wrap_manager_get_query_object(GLuint id, GLenum pname, GLint* params) { if (pname != GL_QUERY_RESULT_AVAILABLE) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } gl_query* vk_que = gl_query::get(id); if (!vk_que) return; uint32_t result[2] = {}; vk_que->query.GetResult(sizeof(uint32_t) * 2, result, VK_QUERY_RESULT_WITH_AVAILABILITY_BIT); *params = result[0] ? GL_TRUE : GL_FALSE; } static void gl_wrap_manager_get_query_object(GLuint id, GLenum pname, GLuint* params) { if (pname != GL_QUERY_RESULT) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } gl_query* vk_que = gl_query::get(id); if (!vk_que) return; uint32_t result = 0; vk_que->query.GetResult(sizeof(uint32_t), &result, 0); *params = result; } static void gl_wrap_manager_get_tex_image(GLenum target, GLint level, GLenum format, GLenum type, void* pixels) { uint32_t layer; GLuint texture; switch (target) { case GL_TEXTURE_2D: layer = 0; texture = gl_state.texture_binding_2d[gl_state.active_texture_index]; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: layer = 0; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: layer = 1; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: layer = 2; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: layer = 3; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: layer = 4; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: layer = 5; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (format) { case GL_RED: case GL_RG: case GL_RGB: case GL_RGBA: case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL: break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (type) { case GL_UNSIGNED_BYTE: case GL_HALF_FLOAT: case GL_FLOAT: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5_REV: case GL_UNSIGNED_SHORT_4_4_4_4_REV: case GL_UNSIGNED_SHORT_1_5_5_5_REV: case GL_UNSIGNED_INT_10F_11F_11F_REV: break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } gl_texture* vk_tex = gl_texture::get(texture, false); if (!vk_tex || vk_tex->target != target) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } GLenum internal_format = GL_NONE; GLsizei width = 0; GLsizei height = 0; uint32_t level_count = 0; gl_texture_data* vk_tex_data = gl_texture_data::get(texture); if (vk_tex_data && vk_tex_data->valid()) { gl_texture_data::tex_data* tex_data = vk_tex_data->get_tex_data(level, layer, true); if (tex_data && tex_data->data.size()) { internal_format = vk_tex_data->internal_format; width = vk_tex_data->width; height = vk_tex_data->height; level_count = vk_tex_data->level_count; } } if (!internal_format) { internal_format = vk_tex->internal_format; width = vk_tex->width; height = vk_tex->height; level_count = vk_tex->level_count; } if (!internal_format) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (level < 0 || level >= (int64_t)level_count) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } GLenum _format; GLenum _type; texture_get_format_type_by_internal_format(internal_format, &_format, &_type); if (!_format || !_type || _format != format && _type != type && _type != GL_FLOAT && _type != GL_HALF_FLOAT && type != GL_FLOAT && type != GL_HALF_FLOAT) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } if ((type == GL_UNSIGNED_SHORT_5_6_5 || type == GL_UNSIGNED_SHORT_5_6_5_REV) && format != GL_RGB || (type == GL_UNSIGNED_SHORT_4_4_4_4_REV || type == GL_UNSIGNED_SHORT_1_5_5_5_REV || type == GL_UNSIGNED_INT_5_9_9_9_REV) && format != GL_RGBA) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } width = max_def(width >> level, 1); height = max_def(height >> level, 1); const int32_t size = texture_get_size(internal_format, width, height); void* temp = 0; if (vk_tex_data && vk_tex_data->valid()) { gl_texture_data::tex_data* tex_data = vk_tex_data->get_tex_data(level, layer, true); if (tex_data && tex_data->data.size()) { temp = force_malloc(size); memmove(temp, tex_data->data.data(), size); } } if (!temp) { Vulkan::Buffer staging_buffer = Vulkan::manager_get_staging_buffer(size); const VkImageViewType image_view_type = Vulkan::get_image_view_type(vk_tex->target); const VkFormat format = Vulkan::get_format(vk_tex->internal_format); const VkImageAspectFlags aspect_mask = Vulkan::get_aspect_mask(vk_tex->internal_format); Vulkan::CommandBuffer cb(Vulkan::current_device, Vulkan::current_command_pool, Vulkan::current_command_buffer); const VkImageLayout old_layout = vk_tex->image.GetImageLayout(level, layer); const VkImageLayout new_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, vk_tex->image, aspect_mask, level, layer, new_layout); cb.CopyImageToBuffer(vk_tex->image, staging_buffer, staging_buffer.GetOffset(), aspect_mask, level, layer, 0, 0, width, height); Vulkan::Image::PipelineBarrierSingle(Vulkan::current_command_buffer, vk_tex->image, aspect_mask, level, layer, old_layout); temp = force_malloc(size); staging_buffer.ReadMemory(staging_buffer.GetOffset(), size, temp); } if (!gl_texture_data::tex_data::convert(internal_format, width, height, format, _type, type, temp, pixels, gl_wrap_manager_ptr->pack_alignment, false)) { free_def(temp); gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } free_def(temp); } static void* gl_wrap_manager_map_buffer(GLenum target, GLenum access) { switch (target) { case GL_ARRAY_BUFFER: return gl_wrap_manager_map_named_buffer(gl_state.array_buffer_binding, access); case GL_ELEMENT_ARRAY_BUFFER: return gl_wrap_manager_map_named_buffer(gl_state.element_array_buffer_binding, access); case GL_UNIFORM_BUFFER: return gl_wrap_manager_map_named_buffer(gl_state.uniform_buffer_binding, access); case GL_SHADER_STORAGE_BUFFER: return gl_wrap_manager_map_named_buffer(gl_state.shader_storage_buffer_binding, access); default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return 0; }; } static void* gl_wrap_manager_map_named_buffer(GLuint buffer, GLenum access) { switch (access) { case GL_READ_ONLY: case GL_WRITE_ONLY: case GL_READ_WRITE: break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return 0; } gl_buffer* vk_buf = gl_buffer::get(buffer); if (!vk_buf || (vk_buf->flags & Vulkan::GL_BUFFER_FLAG_MAPPED) || access == GL_READ_ONLY && !(vk_buf->flags & Vulkan::GL_BUFFER_FLAG_MAP_READ_BIT) || access == GL_WRITE_ONLY && !(vk_buf->flags & Vulkan::GL_BUFFER_FLAG_MAP_WRITE_BIT) || access == GL_READ_WRITE && (!(vk_buf->flags & Vulkan::GL_BUFFER_FLAG_MAP_READ_BIT) || !(vk_buf->flags & Vulkan::GL_BUFFER_FLAG_MAP_WRITE_BIT))) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return 0; } else if (!vk_buf->data.size()) { gl_wrap_manager_ptr->push_error(GL_OUT_OF_MEMORY); return 0; } enum_or(vk_buf->flags, Vulkan::GL_BUFFER_FLAG_MAPPED); return vk_buf->data.data(); } static void gl_wrap_manager_named_buffer_data( GLuint buffer, GLsizeiptr size, const void* data, GLenum usage) { switch (usage) { case GL_STREAM_DRAW: case GL_STREAM_READ: case GL_STREAM_COPY: case GL_STATIC_DRAW: case GL_STATIC_READ: case GL_STATIC_COPY: case GL_DYNAMIC_DRAW: case GL_DYNAMIC_READ: case GL_DYNAMIC_COPY: break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if (size < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_buffer* vk_buf = gl_buffer::get(buffer); if (!vk_buf || (vk_buf->flags & Vulkan::GL_BUFFER_FLAG_IMMUTABLE_STORAGE)) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } enum_or(vk_buf->flags, Vulkan::GL_BUFFER_FLAG_DYNAMIC_STORAGE_BIT | Vulkan::GL_BUFFER_FLAG_MAP_WRITE_BIT | Vulkan::GL_BUFFER_FLAG_MAP_READ_BIT); if (data) vk_buf->data.assign((const uint8_t*)data, (const uint8_t*)data + size); else vk_buf->data.assign(size, 0); enum_or(vk_buf->flags, Vulkan::GL_BUFFER_FLAG_UPDATE_DATA); } static void gl_wrap_manager_named_buffer_storage( GLuint buffer, GLsizeiptr size, const void* data, GLbitfield flags) { if (flags & ~(GL_DYNAMIC_STORAGE_BIT | GL_MAP_WRITE_BIT | GL_MAP_READ_BIT)) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } else if (size < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_buffer* vk_buf = gl_buffer::get(buffer); if (!vk_buf || (vk_buf->flags & Vulkan::GL_BUFFER_FLAG_IMMUTABLE_STORAGE)) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } enum_or(vk_buf->flags, Vulkan::GL_BUFFER_FLAG_IMMUTABLE_STORAGE); if (flags & GL_MAP_READ_BIT) enum_or(vk_buf->flags, Vulkan::GL_BUFFER_FLAG_MAP_READ_BIT); if (flags & GL_MAP_WRITE_BIT) enum_or(vk_buf->flags, Vulkan::GL_BUFFER_FLAG_MAP_WRITE_BIT); if (flags & GL_DYNAMIC_STORAGE_BIT) enum_or(vk_buf->flags, Vulkan::GL_BUFFER_FLAG_DYNAMIC_STORAGE_BIT); if (data) vk_buf->data.assign((const uint8_t*)data, (const uint8_t*)data + size); else vk_buf->data.assign(size, 0); enum_or(vk_buf->flags, Vulkan::GL_BUFFER_FLAG_UPDATE_DATA); } static void gl_wrap_manager_named_buffer_sub_data( GLuint buffer, GLintptr offset, GLsizeiptr size, const void* data) { gl_buffer* vk_buf = gl_buffer::get(buffer); if (!vk_buf || (vk_buf->flags & Vulkan::GL_BUFFER_FLAG_MAPPED) || (vk_buf->flags & Vulkan::GL_BUFFER_FLAG_IMMUTABLE_STORAGE) && !(vk_buf->flags & Vulkan::GL_BUFFER_FLAG_DYNAMIC_STORAGE_BIT)) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (offset < 0 || size < 0 || offset + size > (ssize_t)vk_buf->data.size()) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } memmove(vk_buf->data.data() + offset, data, size); enum_or(vk_buf->flags, Vulkan::GL_BUFFER_FLAG_UPDATE_DATA); } static void gl_wrap_manager_pixel_store(GLenum pname, GLint param) { switch (pname) { case GL_PACK_ALIGNMENT: if (param != 1 && param != 2 && param != 4 && param != 8) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_wrap_manager_ptr->pack_alignment = param; break; case GL_UNPACK_ALIGNMENT: if (param != 1 && param != 2 && param != 4 && param != 8) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_wrap_manager_ptr->unpack_alignment = param; break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); break; } } static void gl_wrap_manager_pop_debug_group() { vkCmdEndDebugUtilsLabelEXT(Vulkan::current_command_buffer); } static void gl_wrap_manager_push_debug_group(GLenum source, GLuint id, GLsizei length, const GLchar* message) { VkDebugUtilsLabelEXT debug_utils_label; debug_utils_label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; debug_utils_label.pNext = 0; debug_utils_label.pLabelName = message; debug_utils_label.color[0] = 0.0f; debug_utils_label.color[1] = 0.0f; debug_utils_label.color[2] = 0.0f; debug_utils_label.color[3] = 0.0f; vkCmdBeginDebugUtilsLabelEXT(Vulkan::current_command_buffer, &debug_utils_label); } static void gl_wrap_manager_read_buffer(GLenum src) { if (src && src < GL_COLOR_ATTACHMENT0 || src >= GL_COLOR_ATTACHMENT0 + Vulkan::MAX_COLOR_ATTACHMENTS) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } gl_framebuffer* vk_fbo = gl_framebuffer::get(gl_state.framebuffer_binding, false); if (!vk_fbo) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } vk_fbo->read_buffer = src; } static void gl_wrap_manager_sampler_parameter(GLuint sampler, GLenum pname, GLfloat param) { gl_sampler* vk_samp = gl_sampler::get(sampler); if (!vk_samp) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } switch (pname) { case GL_TEXTURE_MAX_ANISOTROPY_EXT: vk_samp->max_anisotropy = param; break; } } static void gl_wrap_manager_sampler_parameter(GLuint sampler, GLenum pname, GLint param) { gl_sampler* vk_samp = gl_sampler::get(sampler); if (!vk_samp) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } switch (pname) { case GL_TEXTURE_MAG_FILTER: vk_samp->mag_filter = param; break; case GL_TEXTURE_MIN_FILTER: vk_samp->min_filter = param; break; case GL_TEXTURE_WRAP_S: vk_samp->wrap_s = param; break; case GL_TEXTURE_WRAP_T: vk_samp->wrap_t = param; break; case GL_TEXTURE_WRAP_R: vk_samp->wrap_r = param; break; } } static void gl_wrap_manager_sampler_parameter(GLuint sampler, GLenum pname, const GLfloat* params) { gl_sampler* vk_samp = gl_sampler::get(sampler); if (!vk_samp) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } switch (pname) { case GL_TEXTURE_BORDER_COLOR: { vec4& border_color = vk_samp->border_color; border_color.x = params[0]; border_color.y = params[1]; border_color.z = params[2]; border_color.w = params[3]; } break; } } static void gl_wrap_manager_sampler_parameter(GLuint sampler, GLenum pname, const GLint* params) { gl_sampler* vk_samp = gl_sampler::get(sampler); if (!vk_samp) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } } static void gl_wrap_manager_tex_image_2d(GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) { uint32_t layer; GLuint texture; switch (target) { case GL_TEXTURE_2D: layer = 0; texture = gl_state.texture_binding_2d[gl_state.active_texture_index]; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: layer = 0; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: layer = 1; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: layer = 2; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: layer = 3; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: layer = 4; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: layer = 5; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if (target == GL_TEXTURE_CUBE_MAP && width != height) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (format) { case GL_RED: case GL_RG: case GL_RGB: case GL_RGBA: case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL: break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (type) { case GL_UNSIGNED_BYTE: case GL_HALF_FLOAT: case GL_FLOAT: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5_REV: case GL_UNSIGNED_SHORT_4_4_4_4_REV: case GL_UNSIGNED_SHORT_1_5_5_5_REV: case GL_UNSIGNED_INT_24_8: case GL_UNSIGNED_INT_10F_11F_11F_REV: break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (internal_format) { case GL_RGB5: case GL_RGBA4: case GL_RGB5_A1: case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: case GL_R8: case GL_RG8: case GL_RGB8: case GL_RGBA8: case GL_R32F: case GL_RG16F: case GL_RG32F: case GL_RGBA32F: case GL_RGBA16F: case GL_DEPTH24_STENCIL8: case GL_R11F_G11F_B10F: case GL_RGB9_E5: case GL_DEPTH_COMPONENT32F: break; default: printf("e"); gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if ((type == GL_UNSIGNED_SHORT_5_6_5 || type == GL_UNSIGNED_SHORT_5_6_5_REV) && format != GL_RGB || (type == GL_UNSIGNED_SHORT_4_4_4_4_REV || type == GL_UNSIGNED_SHORT_1_5_5_5_REV || type == GL_UNSIGNED_INT_5_9_9_9_REV) && format != GL_RGBA || ((target != GL_TEXTURE_2D || format != GL_DEPTH_COMPONENT || pixels) && internal_format == GL_DEPTH_COMPONENT16 && internal_format != GL_DEPTH_COMPONENT24 && internal_format == GL_DEPTH24_STENCIL8 && internal_format== GL_DEPTH_COMPONENT32F)) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } GLenum _format; GLenum _type; texture_get_format_type_by_internal_format(internal_format, &_format, &_type); if (!_format || !_type || _format != format && _type != type && _type != GL_FLOAT && _type != GL_HALF_FLOAT && type != GL_FLOAT && type != GL_HALF_FLOAT) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } if (width < 0 || width > sv_max_texture_size || height < 0 || height > sv_max_texture_size || level < 0 || level >= (int32_t)log2(sv_max_texture_size) || border) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_texture* vk_tex = gl_texture::get(texture, false); if (!vk_tex || vk_tex->target != target || vk_tex->internal_format && vk_tex->internal_format != internal_format) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } if (vk_tex->image && (max_def(vk_tex->width >> level, 1) != width || max_def(vk_tex->height >> level, 1) != height)) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_texture_data* vk_tex_data = gl_texture_data::get(texture); if (!vk_tex_data) { vk_tex_data = &gl_wrap_manager_ptr->gl_texture_datas.insert({ texture, {} }).first->second; vk_tex_data->target = target; vk_tex_data->internal_format = internal_format; } if (!level) { vk_tex_data->width = width; vk_tex_data->height = height; } else if (vk_tex_data->valid() && (max_def(vk_tex_data->width >> level, 1) != width || max_def(vk_tex_data->height >> level, 1) != height)) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_texture_data::tex_data* tex_data = vk_tex_data->get_tex_data(level, layer); if (tex_data) tex_data->set_data(internal_format, 0, 0, width, height, format, type, pixels); } static void gl_wrap_manager_tex_parameter(GLenum target, GLenum pname, GLfloat param) { switch (target) { case GL_TEXTURE_2D: gl_wrap_manager_texture_parameter( gl_state.texture_binding_2d[gl_state.active_texture_index], pname, param); break; case GL_TEXTURE_CUBE_MAP: gl_wrap_manager_texture_parameter( gl_state.texture_binding_cube_map[gl_state.active_texture_index], pname, param); break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; } } static void gl_wrap_manager_tex_parameter(GLenum target, GLenum pname, GLint param) { switch (target) { case GL_TEXTURE_2D: gl_wrap_manager_texture_parameter( gl_state.texture_binding_2d[gl_state.active_texture_index], pname, param); break; case GL_TEXTURE_CUBE_MAP: gl_wrap_manager_texture_parameter( gl_state.texture_binding_cube_map[gl_state.active_texture_index], pname, param); break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; } } static void gl_wrap_manager_tex_parameter(GLenum target, GLenum pname, const GLfloat* params) { switch (target) { case GL_TEXTURE_2D: gl_wrap_manager_texture_parameter( gl_state.texture_binding_2d[gl_state.active_texture_index], pname, params); break; case GL_TEXTURE_CUBE_MAP: gl_wrap_manager_texture_parameter( gl_state.texture_binding_cube_map[gl_state.active_texture_index], pname, params); break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; } } static void gl_wrap_manager_tex_parameter(GLenum target, GLenum pname, const GLint* params) { switch (target) { case GL_TEXTURE_2D: gl_wrap_manager_texture_parameter( gl_state.texture_binding_2d[gl_state.active_texture_index], pname, params); break; case GL_TEXTURE_CUBE_MAP: gl_wrap_manager_texture_parameter( gl_state.texture_binding_cube_map[gl_state.active_texture_index], pname, params); break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; } } static void gl_wrap_manager_tex_sub_image_2d(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) { uint32_t layer; GLuint texture; switch (target) { case GL_TEXTURE_2D: layer = 0; texture = gl_state.texture_binding_2d[gl_state.active_texture_index]; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: layer = 0; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: layer = 1; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: layer = 2; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: layer = 3; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: layer = 4; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: layer = 5; texture = gl_state.texture_binding_cube_map[gl_state.active_texture_index]; target = GL_TEXTURE_CUBE_MAP; break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if (target == GL_TEXTURE_CUBE_MAP && width != height) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (format) { case GL_RED: case GL_RG: case GL_RGB: case GL_RGBA: break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (type) { case GL_UNSIGNED_BYTE: case GL_HALF_FLOAT: case GL_FLOAT: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5_REV: case GL_UNSIGNED_SHORT_4_4_4_4_REV: case GL_UNSIGNED_SHORT_1_5_5_5_REV: break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if ((type == GL_UNSIGNED_SHORT_5_6_5 || type == GL_UNSIGNED_SHORT_5_6_5_REV) && format != GL_RGB || (type == GL_UNSIGNED_SHORT_4_4_4_4_REV || type == GL_UNSIGNED_SHORT_1_5_5_5_REV || type == GL_UNSIGNED_INT_5_9_9_9_REV) && format != GL_RGBA) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } if (xoffset || yoffset || width < 0 || width > sv_max_texture_size || height < 0 || height > sv_max_texture_size || level < 0 || level >= (int32_t)log2(sv_max_texture_size)) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_texture* vk_tex = gl_texture::get(texture, false); if (!vk_tex) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (vk_tex->target != target) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if (vk_tex->image && (max_def(vk_tex->width >> level, 1) != width || max_def(vk_tex->height >> level, 1) != height || level >= (int64_t)vk_tex->get_level_count())) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_texture_data* vk_tex_data = gl_texture_data::get(texture); if (!vk_tex_data) { if (!vk_tex->internal_format) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } vk_tex_data = &gl_wrap_manager_ptr->gl_texture_datas.insert({ texture, {} }).first->second; vk_tex_data->target = target; vk_tex_data->internal_format = vk_tex->internal_format; if (!level) { vk_tex_data->width = width; vk_tex_data->height = height; } } else if (vk_tex_data->valid() && (max_def(vk_tex_data->width >> level, 1) != width || max_def(vk_tex_data->height >> level, 1) != height)) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } GLenum _format; GLenum _type; texture_get_format_type_by_internal_format(vk_tex_data->internal_format, &_format, &_type); if (!_format || !_type || _format != format && _type != type && _type != GL_FLOAT && _type != GL_HALF_FLOAT && type != GL_FLOAT && type != GL_HALF_FLOAT) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } gl_texture_data::tex_data* tex_data = vk_tex_data->get_tex_data(level, layer); if (tex_data) tex_data->set_data(vk_tex->internal_format, xoffset, yoffset, width, height, format, type, pixels); } static void gl_wrap_manager_texture_parameter(GLuint texture, GLenum pname, GLfloat param) { gl_texture* vk_tex = gl_texture::get(texture, false); if (!vk_tex) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (vk_tex->target != GL_TEXTURE_2D && vk_tex->target != GL_TEXTURE_CUBE_MAP) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (pname) { case GL_TEXTURE_LOD_BIAS: break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: vk_tex->sampler_data.max_anisotropy = param; break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; } } static void gl_wrap_manager_texture_parameter(GLuint texture, GLenum pname, const GLint param) { gl_texture* vk_tex = gl_texture::get(texture, false); if (!vk_tex) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (vk_tex->target != GL_TEXTURE_2D && vk_tex->target != GL_TEXTURE_CUBE_MAP) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (pname) { case GL_TEXTURE_MAG_FILTER: vk_tex->sampler_data.mag_filter = param; break; case GL_TEXTURE_MIN_FILTER: vk_tex->sampler_data.min_filter = param; break; case GL_TEXTURE_WRAP_S: vk_tex->sampler_data.wrap_s = param; break; case GL_TEXTURE_WRAP_T: vk_tex->sampler_data.wrap_t = param; break; case GL_TEXTURE_WRAP_R: vk_tex->sampler_data.wrap_r = param; break; case GL_TEXTURE_BASE_LEVEL: if (vk_tex->base_mipmap_level != param) { vk_tex->sample_image_view.Destroy(); vk_tex->base_mipmap_level = param; } break; case GL_TEXTURE_MAX_LEVEL: if (vk_tex->max_mipmap_level != param) { vk_tex->sample_image_view.Destroy(); vk_tex->max_mipmap_level = param; } break; case GL_TEXTURE_SWIZZLE_R: { VkComponentMapping components = vk_tex->components; components.r = Vulkan::get_component_swizzle(param, GL_RED); if (memcmp(&vk_tex->components, &components, sizeof(VkComponentMapping))) { vk_tex->sample_image_view.Destroy(); vk_tex->components = components; } } break; case GL_TEXTURE_SWIZZLE_G: { VkComponentMapping components = vk_tex->components; components.g = Vulkan::get_component_swizzle(param, GL_GREEN); if (memcmp(&vk_tex->components, &components, sizeof(VkComponentMapping))) { vk_tex->sample_image_view.Destroy(); vk_tex->components = components; } } break; case GL_TEXTURE_SWIZZLE_B: { VkComponentMapping components = vk_tex->components; components.b = Vulkan::get_component_swizzle(param, GL_BLUE); if (memcmp(&vk_tex->components, &components, sizeof(VkComponentMapping))) { vk_tex->sample_image_view.Destroy(); vk_tex->components = components; } } break; case GL_TEXTURE_SWIZZLE_A: { VkComponentMapping components = vk_tex->components; components.a = Vulkan::get_component_swizzle(param, GL_ALPHA); if (memcmp(&vk_tex->components, &components, sizeof(VkComponentMapping))) { vk_tex->sample_image_view.Destroy(); vk_tex->components = components; } } break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; } } static void gl_wrap_manager_texture_parameter(GLuint texture, GLenum pname, const GLfloat* params) { gl_texture* vk_tex = gl_texture::get(texture, false); if (!vk_tex) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (vk_tex->target != GL_TEXTURE_2D && vk_tex->target != GL_TEXTURE_CUBE_MAP) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (pname) { case GL_TEXTURE_BORDER_COLOR: { vec4& border_color = vk_tex->sampler_data.border_color; border_color.x = params[0]; border_color.y = params[1]; border_color.z = params[2]; border_color.w = params[3]; } break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; } } static void gl_wrap_manager_texture_parameter(GLuint texture, GLenum pname, const GLint* params) { gl_texture* vk_tex = gl_texture::get(texture, false); if (!vk_tex) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } else if (vk_tex->target != GL_TEXTURE_2D && vk_tex->target != GL_TEXTURE_CUBE_MAP) { gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (pname) { case GL_TEXTURE_SWIZZLE_RGBA: { VkComponentMapping components; components.r = Vulkan::get_component_swizzle(params[0], GL_RED); components.g = Vulkan::get_component_swizzle(params[1], GL_GREEN); components.b = Vulkan::get_component_swizzle(params[2], GL_BLUE); components.a = Vulkan::get_component_swizzle(params[3], GL_ALPHA); if (memcmp(&vk_tex->components, &components, sizeof(VkComponentMapping))) { vk_tex->sample_image_view.Destroy(); vk_tex->components = components; } } break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); break; } } static void gl_wrap_manager_texture_sub_image_2d(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) { switch (format) { case GL_RED: case GL_RG: case GL_RGB: case GL_RGBA: break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } switch (type) { case GL_UNSIGNED_BYTE: case GL_HALF_FLOAT: case GL_FLOAT: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5_REV: case GL_UNSIGNED_SHORT_4_4_4_4_REV: case GL_UNSIGNED_SHORT_1_5_5_5_REV: break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if ((type == GL_UNSIGNED_SHORT_5_6_5 || type == GL_UNSIGNED_SHORT_5_6_5_REV) && format != GL_RGB || (type == GL_UNSIGNED_SHORT_4_4_4_4_REV || type == GL_UNSIGNED_SHORT_1_5_5_5_REV || type == GL_UNSIGNED_INT_5_9_9_9_REV) && format != GL_RGBA) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } if (width < 0 || width > sv_max_texture_size || height < 0 || height > sv_max_texture_size || level < 0 || level >= (int32_t)log2(sv_max_texture_size)) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_texture* vk_tex = gl_texture::get(texture, false); if (!vk_tex) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } if (vk_tex->image && (max_def(vk_tex->width >> level, 1) != width || max_def(vk_tex->height >> level, 1) != height || level >= (int64_t)vk_tex->get_level_count()) || xoffset || yoffset) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } gl_texture_data* vk_tex_data = gl_texture_data::get(texture); if (!vk_tex_data) { if (!vk_tex->internal_format) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } vk_tex_data = &gl_wrap_manager_ptr->gl_texture_datas.insert({ texture, {} }).first->second; vk_tex_data->target = vk_tex->target; vk_tex_data->internal_format = vk_tex->internal_format; if (!level) { vk_tex_data->width = width; vk_tex_data->height = height; } } else if (vk_tex_data->valid() && (max_def(vk_tex_data->width >> level, 1) != width || max_def(vk_tex_data->height >> level, 1) != height)) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } GLenum _format; GLenum _type; texture_get_format_type_by_internal_format(vk_tex_data->internal_format, &_format, &_type); if (!_format || !_type || _format != format && _type != type && _type != GL_FLOAT && _type != GL_HALF_FLOAT && type != GL_FLOAT && type != GL_HALF_FLOAT) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } gl_texture_data::tex_data* tex_data = vk_tex_data->get_tex_data(level, 0); if (tex_data) tex_data->set_data(vk_tex_data->internal_format, xoffset, yoffset, width, height, format, type, pixels); } static GLboolean gl_wrap_manager_unmap_buffer(GLenum target) { switch (target) { case GL_ARRAY_BUFFER: return gl_wrap_manager_unmap_named_buffer(gl_state.array_buffer_binding); case GL_ELEMENT_ARRAY_BUFFER: return gl_wrap_manager_unmap_named_buffer(gl_state.element_array_buffer_binding); case GL_UNIFORM_BUFFER: return gl_wrap_manager_unmap_named_buffer(gl_state.uniform_buffer_binding); case GL_SHADER_STORAGE_BUFFER: return gl_wrap_manager_unmap_named_buffer(gl_state.shader_storage_buffer_binding); default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return GL_FALSE; }; } static GLboolean gl_wrap_manager_unmap_named_buffer(GLuint buffer) { gl_buffer* vk_buf = gl_buffer::get(buffer); if (!vk_buf || !(vk_buf->flags & Vulkan::GL_BUFFER_FLAG_MAPPED)) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return GL_FALSE; } enum_and(vk_buf->flags, ~Vulkan::GL_BUFFER_FLAG_MAPPED); enum_or(vk_buf->flags, Vulkan::GL_BUFFER_FLAG_UPDATE_DATA); return GL_TRUE; } static void gl_wrap_manager_vertex_attrib(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { if (index >= Vulkan::MAX_VERTEX_ATTRIB_COUNT) return; gl_vertex_array* vk_vao = gl_vertex_array::get(gl_state.vertex_array_binding); if (!vk_vao) return; vec4& generic_value = vk_vao->vertex_attribs[index].generic_value; generic_value.x = x; generic_value.y = y; generic_value.z = z; generic_value.w = w; } static void gl_wrap_manager_vertex_attrib_int_pointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer) { if (index >= Vulkan::MAX_VERTEX_ATTRIB_COUNT) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } VkFormat format = VK_FORMAT_UNDEFINED; switch (type) { case GL_BYTE: switch (size) { case 1: format = VK_FORMAT_R8_SINT; break; case 2: format = VK_FORMAT_R8G8_SINT; break; case 3: format = VK_FORMAT_R8G8B8_SINT; break; case 4: format = VK_FORMAT_R8G8B8A8_SINT; } break; case GL_UNSIGNED_BYTE: switch (size) { case 1: format = VK_FORMAT_R8_UINT; break; case 2: format = VK_FORMAT_R8G8_UINT; break; case 3: format = VK_FORMAT_R8G8B8_UINT; break; case 4: format = VK_FORMAT_R8G8B8A8_UINT; } break; case GL_SHORT: switch (size) { case 1: format = VK_FORMAT_R16_SINT; break; case 2: format = VK_FORMAT_R16G16_SINT; break; case 3: format = VK_FORMAT_R16G16B16_SINT; break; case 4: format = VK_FORMAT_R16G16B16A16_SINT; break; } break; case GL_UNSIGNED_SHORT: switch (size) { case 1: format = VK_FORMAT_R16_UINT; break; case 2: format = VK_FORMAT_R16G16_UINT; break; case 3: format = VK_FORMAT_R16G16B16_UINT; break; case 4: format = VK_FORMAT_R16G16B16A16_UINT; break; } break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if (format == VK_FORMAT_UNDEFINED) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } gl_vertex_array* vk_vao = gl_vertex_array::get(gl_state.vertex_array_binding); if (!vk_vao || !gl_state.array_buffer_binding) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } vk_vao->set_vertex_attrib(index, format, stride, (uint32_t)(size_t)pointer); } static void gl_wrap_manager_vertex_attrib_pointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer) { if (index >= Vulkan::MAX_VERTEX_ATTRIB_COUNT || size < 1 || size > 4 || stride < 0) { gl_wrap_manager_ptr->push_error(GL_INVALID_VALUE); return; } VkFormat format = VK_FORMAT_UNDEFINED; switch (type) { case GL_BYTE: if (normalized) switch (size) { case 1: format = VK_FORMAT_R8_SNORM; break; case 2: format = VK_FORMAT_R8G8_SNORM; break; case 3: format = VK_FORMAT_R8G8B8_SNORM; break; case 4: format = VK_FORMAT_R8G8B8A8_SNORM; break; } else switch (size) { case 1: format = VK_FORMAT_R8_SINT; break; case 2: format = VK_FORMAT_R8G8_SINT; break; case 3: format = VK_FORMAT_R8G8B8_SINT; break; case 4: format = VK_FORMAT_R8G8B8A8_SINT; } break; case GL_UNSIGNED_BYTE: if (normalized) switch (size) { case 1: format = VK_FORMAT_R8_UNORM; break; case 2: format = VK_FORMAT_R8G8_UNORM; break; case 3: format = VK_FORMAT_R8G8B8_UNORM; break; case 4: format = VK_FORMAT_R8G8B8A8_UNORM; break; } else switch (size) { case 1: format = VK_FORMAT_R8_UINT; break; case 2: format = VK_FORMAT_R8G8_UINT; break; case 3: format = VK_FORMAT_R8G8B8_UINT; break; case 4: format = VK_FORMAT_R8G8B8A8_UINT; } break; case GL_SHORT: if (normalized) switch (size) { case 1: format = VK_FORMAT_R16_SNORM; break; case 2: format = VK_FORMAT_R16G16_SNORM; break; case 3: format = VK_FORMAT_R16G16B16_SNORM; break; case 4: format = VK_FORMAT_R16G16B16A16_SNORM; break; } else switch (size) { case 1: format = VK_FORMAT_R16_SINT; break; case 2: format = VK_FORMAT_R16G16_SINT; break; case 3: format = VK_FORMAT_R16G16B16_SINT; break; case 4: format = VK_FORMAT_R16G16B16A16_SINT; break; } break; case GL_UNSIGNED_SHORT: if (normalized) switch (size) { case 1: format = VK_FORMAT_R16_UNORM; break; case 2: format = VK_FORMAT_R16G16_UNORM; break; case 3: format = VK_FORMAT_R16G16B16_UNORM; break; case 4: format = VK_FORMAT_R16G16B16A16_UNORM; break; } else switch (size) { case 1: format = VK_FORMAT_R16_UINT; break; case 2: format = VK_FORMAT_R16G16_UINT; break; case 3: format = VK_FORMAT_R16G16B16_UINT; break; case 4: format = VK_FORMAT_R16G16B16A16_UINT; break; } break; case GL_FLOAT: switch (size) { case 1: format = VK_FORMAT_R32_SFLOAT; break; case 2: format = VK_FORMAT_R32G32_SFLOAT; break; case 3: format = VK_FORMAT_R32G32B32_SFLOAT; break; case 4: format = VK_FORMAT_R32G32B32A32_SFLOAT; break; } break; case GL_HALF_FLOAT: switch (size) { case 1: format = VK_FORMAT_R16_SFLOAT; break; case 2: format = VK_FORMAT_R16G16_SFLOAT; break; case 3: format = VK_FORMAT_R16G16B16_SFLOAT; break; case 4: format = VK_FORMAT_R16G16B16A16_SFLOAT; break; } break; case GL_UNSIGNED_INT_2_10_10_10_REV: if (size == 4) format = VK_FORMAT_A2B10G10R10_UNORM_PACK32; break; case GL_INT_2_10_10_10_REV: if (size == 4) format = VK_FORMAT_A2B10G10R10_SNORM_PACK32; break; default: gl_wrap_manager_ptr->push_error(GL_INVALID_ENUM); return; } if (format == VK_FORMAT_UNDEFINED) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } gl_vertex_array* vk_vao = gl_vertex_array::get(gl_state.vertex_array_binding); if (!vk_vao || !gl_state.array_buffer_binding) { gl_wrap_manager_ptr->push_error(GL_INVALID_OPERATION); return; } vk_vao->set_vertex_attrib(index, format, stride, (uint32_t)(size_t)pointer); } };