mirror of
https://github.com/korenkonder/ReDIVA.git
synced 2026-10-06 13:48:01 +03:00
4854 lines
187 KiB
C++
4854 lines
187 KiB
C++
/*
|
|
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 <list>
|
|
#include <unordered_map>
|
|
|
|
namespace Vulkan {
|
|
struct gl_texture_data {
|
|
struct tex_data {
|
|
std::vector<uint8_t> 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<tex_data> 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<GLuint, gl_buffer> gl_buffers;
|
|
std::vector<GLenum> gl_errors;
|
|
std::unordered_map<GLuint, gl_framebuffer> gl_framebuffers;
|
|
std::unordered_map<GLuint, gl_index_buffer> gl_index_buffers;
|
|
std::unordered_map<GLuint, gl_program> gl_programs;
|
|
std::unordered_map<GLuint, gl_query> gl_queries;
|
|
std::unordered_map<GLuint, gl_sampler> gl_samplers;
|
|
std::unordered_map<GLuint, gl_storage_buffer> gl_storage_buffers;
|
|
std::unordered_map<GLuint, gl_texture> gl_textures;
|
|
std::unordered_map<GLuint, gl_texture_data> gl_texture_datas;
|
|
std::unordered_map<GLuint, gl_uniform_buffer> gl_uniform_buffers;
|
|
std::unordered_map<GLuint, gl_vertex_array> gl_vertex_arrays;
|
|
std::unordered_map<GLuint, gl_vertex_buffer> 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);
|
|
}
|
|
};
|