From aeea0eadc95cdf4b346d42385a4a418e349e73eb Mon Sep 17 00:00:00 2001 From: jp9000 Date: Fri, 11 Oct 2013 20:14:26 -0700 Subject: [PATCH] added shader attributes and added vertex buffer loading --- libobs-d3d11/d3d11-subsystem.hpp | 2 +- libobs-opengl/gl-exports.h | 4 -- libobs-opengl/gl-shader.c | 72 ++++++++++++++++++++++++-- libobs-opengl/gl-shaderparser.c | 13 +++-- libobs-opengl/gl-shaderparser.h | 27 ++++++++-- libobs-opengl/gl-subsystem.c | 24 ++++----- libobs-opengl/gl-subsystem.h | 87 ++++++++++++++++++++------------ libobs-opengl/gl-vertexbuffer.c | 83 ++++++++++++++++++++++++++++++ 8 files changed, 251 insertions(+), 61 deletions(-) diff --git a/libobs-d3d11/d3d11-subsystem.hpp b/libobs-d3d11/d3d11-subsystem.hpp index f3baec812..d6dea75db 100644 --- a/libobs-d3d11/d3d11-subsystem.hpp +++ b/libobs-d3d11/d3d11-subsystem.hpp @@ -575,8 +575,8 @@ struct gs_device { gs_texture *curTextures[GS_MAX_TEXTURES]; gs_sampler_state *curSamplers[GS_MAX_TEXTURES]; gs_vertex_buffer *curVertexBuffer; - gs_vertex_shader *curVertexShader; gs_index_buffer *curIndexBuffer; + gs_vertex_shader *curVertexShader; gs_pixel_shader *curPixelShader; gs_swap_chain *curSwapChain; diff --git a/libobs-opengl/gl-exports.h b/libobs-opengl/gl-exports.h index d366cccd4..f27608f73 100644 --- a/libobs-opengl/gl-exports.h +++ b/libobs-opengl/gl-exports.h @@ -60,10 +60,6 @@ EXPORT enum gs_texture_type device_gettexturetype(device_t device, EXPORT void device_load_vertexbuffer(device_t device, vertbuffer_t vertbuffer); EXPORT void device_load_indexbuffer(device_t device, indexbuffer_t indexbuffer); EXPORT void device_load_texture(device_t device, texture_t tex, int unit); -EXPORT void device_load_cubetexture(device_t device, texture_t cubetex, - int unit); -EXPORT void device_load_volumetexture(device_t device, texture_t voltex, - int unit); EXPORT void device_load_samplerstate(device_t device, samplerstate_t samplerstate, int unit); EXPORT void device_load_vertexshader(device_t device, shader_t vertshader); diff --git a/libobs-opengl/gl-shader.c b/libobs-opengl/gl-shader.c index 1222d8f01..564ae932a 100644 --- a/libobs-opengl/gl-shader.c +++ b/libobs-opengl/gl-shader.c @@ -108,13 +108,69 @@ static inline void gl_add_samplers(struct gs_shader *shader, struct gl_shader_parser *glsp) { size_t i; - for (i = 0; i < glsp->parser.samplers.num; i++) { struct shader_sampler *sampler = glsp->parser.samplers.array+i; gl_add_sampler(shader, sampler); } } +static void get_attrib_type(const char *mapping, enum attrib_type *type, + size_t *index) +{ + if (strcmp(mapping, "POSITION") == 0) { + *type = ATTRIB_POSITION; + + } else if (strcmp(mapping, "NORMAL") == 0) { + *type = ATTRIB_NORMAL; + + } else if (strcmp(mapping, "TANGENT") == 0) { + *type = ATTRIB_TANGENT; + + } else if (strcmp(mapping, "COLOR") == 0) { + *type = ATTRIB_COLOR; + + } else if (astrcmp_n(mapping, "TEXCOORD", 8) == 0) { + *type = ATTRIB_TEXCOORD; + *index = (*(mapping+8)) - '0'; + return; + + } else if (strcmp(mapping, "TARGET") == 0) { + *type = ATTRIB_TARGET; + } + + *index = 0; +} + +static inline bool gl_add_attrib(struct gs_shader *shader, + struct gl_parser_attrib *pa) +{ + struct shader_attrib attrib = {0}; + get_attrib_type(pa->mapping, &attrib.type, &attrib.index); + + attrib.attrib = glGetAttribLocation(shader->program, pa->name.array); + if (!gl_success("glGetAttribLocation")) + return false; + + if (attrib.attrib == -1) + return false; + + da_push_back(shader->attribs, &attrib); + return true; +} + +static inline bool gl_add_attribs(struct gs_shader *shader, + struct gl_shader_parser *glsp) +{ + size_t i; + for (i = 0; i < glsp->attribs.num; i++) { + struct gl_parser_attrib *pa = glsp->attribs.array+i; + if (!gl_add_attrib(shader, pa)) + return false; + } + + return true; +} + static bool gl_shader_init(struct gs_shader *shader, struct gl_shader_parser *glsp, const char *file, char **error_string) @@ -140,6 +196,8 @@ static bool gl_shader_init(struct gs_shader *shader, if (success) success = gl_add_params(shader, glsp); + if (success) + success = gl_add_attribs(shader, glsp); if (success) gl_add_samplers(shader, glsp); @@ -176,14 +234,22 @@ shader_t device_create_vertexshader(device_t device, const char *shader, const char *file, char **error_string) { - return shader_create(device, SHADER_VERTEX, shader, file, error_string); + struct gs_shader *ptr; + ptr = shader_create(device, SHADER_VERTEX, shader, file, error_string); + if (!ptr) + blog(LOG_ERROR, "device_create_vertexshader (GL) failed"); + return ptr; } shader_t device_create_pixelshader(device_t device, const char *shader, const char *file, char **error_string) { - return shader_create(device, SHADER_PIXEL, shader, file, error_string); + struct gs_shader *ptr; + ptr = shader_create(device, SHADER_PIXEL, shader, file, error_string); + if (!ptr) + blog(LOG_ERROR, "device_create_pixelshader (GL) failed"); + return ptr; } void shader_destroy(shader_t shader) diff --git a/libobs-opengl/gl-shaderparser.c b/libobs-opengl/gl-shaderparser.c index d1b08e25e..161d1a4be 100644 --- a/libobs-opengl/gl-shaderparser.c +++ b/libobs-opengl/gl-shaderparser.c @@ -146,17 +146,24 @@ static void gl_write_storage_var(struct gl_shader_parser *glsp, if (st) { gl_unwrap_storage_struct(glsp, st, var->name, storage, prefix); } else { + struct gl_parser_attrib attrib = {0}; + if (storage) { dstr_cat(&glsp->gl_string, storage); dstr_cat(&glsp->gl_string, " "); } + if (prefix) + dstr_cat(&attrib.name, prefix); + dstr_cat(&attrib.name, var->name); + gl_write_type(glsp, var->type); dstr_cat(&glsp->gl_string, " "); - if (prefix) - dstr_cat(&glsp->gl_string, prefix); - dstr_cat(&glsp->gl_string, var->name); + dstr_cat_dstr(&glsp->gl_string, &attrib.name); dstr_cat(&glsp->gl_string, ";\n"); + + attrib.mapping = var->mapping; + da_push_back(glsp->attribs, &attrib); } } diff --git a/libobs-opengl/gl-shaderparser.h b/libobs-opengl/gl-shaderparser.h index 6bdc4402c..f6a1165ae 100644 --- a/libobs-opengl/gl-shaderparser.h +++ b/libobs-opengl/gl-shaderparser.h @@ -27,21 +27,40 @@ #include "util/dstr.h" #include "graphics/shader-parser.h" -struct gl_shader_parser { - struct dstr gl_string; - struct shader_parser parser; +struct gl_parser_attrib { + struct dstr name; + const char *mapping; +}; - DARRAY(uint32_t) texture_samplers; +static inline gl_parser_attrib_free(struct gl_parser_attrib *attr) +{ + dstr_free(&attr->name); +} + +struct gl_shader_parser { + struct shader_parser parser; + struct dstr gl_string; + + DARRAY(uint32_t) texture_samplers; + DARRAY(struct gl_parser_attrib) attribs; }; static inline void gl_shader_parser_init(struct gl_shader_parser *glsp) { shader_parser_init(&glsp->parser); dstr_init(&glsp->gl_string); + da_init(glsp->texture_samplers); + da_init(glsp->attribs); } static inline void gl_shader_parser_free(struct gl_shader_parser *glsp) { + size_t i; + for (i = 0; i < glsp->attribs.num; i++) + gl_parser_attrib_free(glsp->attribs.array+i); + + da_free(glsp->attribs); + da_free(glsp->texture_samplers); dstr_free(&glsp->gl_string); shader_parser_free(&glsp->parser); } diff --git a/libobs-opengl/gl-subsystem.c b/libobs-opengl/gl-subsystem.c index 0b7572406..962e7e6b5 100644 --- a/libobs-opengl/gl-subsystem.c +++ b/libobs-opengl/gl-subsystem.c @@ -115,10 +115,7 @@ samplerstate_t device_create_samplerstate(device_t device, enum gs_texture_type device_gettexturetype(device_t device, texture_t texture) { -} - -void device_load_vertexbuffer(device_t device, vertbuffer_t vertbuffer) -{ + return texture->type; } void device_load_indexbuffer(device_t device, indexbuffer_t indexbuffer) @@ -129,16 +126,6 @@ void device_load_texture(device_t device, texture_t tex, int unit) { } -void device_load_cubetexture(device_t device, texture_t cubetex, - int unit) -{ -} - -void device_load_volumetexture(device_t device, texture_t voltex, - int unit) -{ -} - void device_load_samplerstate(device_t device, samplerstate_t samplerstate, int unit) { @@ -331,22 +318,31 @@ void swapchain_destroy(swapchain_t swapchain) void volumetexture_destroy(texture_t voltex) { + /* TODO */ } uint32_t volumetexture_getwidth(texture_t voltex) { + /* TODO */ + return 0; } uint32_t volumetexture_getheight(texture_t voltex) { + /* TODO */ + return 0; } uint32_t volumetexture_getdepth(texture_t voltex) { + /* TODO */ + return 0; } enum gs_color_format volumetexture_getcolorformat(texture_t voltex) { + /* TODO */ + return GS_UNKNOWN; } void samplerstate_destroy(samplerstate_t samplerstate) diff --git a/libobs-opengl/gl-subsystem.h b/libobs-opengl/gl-subsystem.h index ab03db6a8..68f5a1dc7 100644 --- a/libobs-opengl/gl-subsystem.h +++ b/libobs-opengl/gl-subsystem.h @@ -185,37 +185,54 @@ extern void convert_sampler_info(struct gs_sampler_state *sampler, struct gs_sampler_info *info); struct gs_sampler_state { - GLint min_filter; - GLint mag_filter; - GLint address_u; - GLint address_v; - GLint address_w; - GLint max_anisotropy; + GLint min_filter; + GLint mag_filter; + GLint address_u; + GLint address_v; + GLint address_w; + GLint max_anisotropy; }; struct shader_param { - char *name; enum shader_param_type type; - GLint param; - GLint texture_id; - size_t sampler_id; - int array_count; - struct gs_texture *texture; + char *name; + GLint param; + GLint texture_id; + size_t sampler_id; + int array_count; - DARRAY(uint8_t) cur_value; - DARRAY(uint8_t) def_value; - bool changed; + struct gs_texture *texture; + + DARRAY(uint8_t) cur_value; + DARRAY(uint8_t) def_value; + bool changed; +}; + +enum attrib_type { + ATTRIB_POSITION, + ATTRIB_NORMAL, + ATTRIB_TANGENT, + ATTRIB_COLOR, + ATTRIB_TEXCOORD, + ATTRIB_TARGET +}; + +struct shader_attrib { + GLint attrib; + size_t index; + enum attrib_type type; }; struct gs_shader { - device_t device; - enum shader_type type; - GLuint program; + device_t device; + enum shader_type type; + GLuint program; - struct shader_param *viewproj; - struct shader_param *world; + struct shader_param *viewproj; + struct shader_param *world; + DARRAY(struct shader_attrib) attribs; DARRAY(struct gs_sampler_state) samplers; DARRAY(struct shader_param) params; }; @@ -226,6 +243,7 @@ struct gs_vertex_buffer { GLuint tangent_buffer; GLuint color_buffer; DARRAY(GLuint) uv_buffers; + DARRAY(size_t) uv_sizes; device_t device; bool dynamic; @@ -233,15 +251,15 @@ struct gs_vertex_buffer { }; struct gs_index_buffer { - GLuint buffer; - enum gs_index_type type; - GLuint gl_type; + GLuint buffer; + enum gs_index_type type; + GLuint gl_type; - device_t device; - void *data; - size_t num; - size_t size; - bool dynamic; + device_t device; + void *data; + size_t num; + size_t size; + bool dynamic; }; struct gs_texture { @@ -302,11 +320,16 @@ struct gs_device { struct gl_platform *plat; enum copy_type copy_type; - struct gs_texture *cur_render_texture; + texture_t cur_render_target; + zstencil_t cur_zstencil_buffer; int cur_render_side; - struct gs_texture *cur_textures[GS_MAX_TEXTURES]; - struct gs_sampler *cur_samplers[GS_MAX_TEXTURES]; - struct gs_swap_chain *cur_swap; + texture_t cur_textures[GS_MAX_TEXTURES]; + samplerstate_t cur_samplers[GS_MAX_TEXTURES]; + vertbuffer_t cur_vertex_buffer; + indexbuffer_t cur_index_buffer; + shader_t cur_vertex_shader; + shader_t cur_pixel_shader; + swapchain_t cur_swap; }; extern struct gl_platform *gl_platform_create(device_t device, diff --git a/libobs-opengl/gl-vertexbuffer.c b/libobs-opengl/gl-vertexbuffer.c index 06ae096b2..79feec420 100644 --- a/libobs-opengl/gl-vertexbuffer.c +++ b/libobs-opengl/gl-vertexbuffer.c @@ -50,6 +50,7 @@ static bool init_vb(struct gs_vertex_buffer *vb) } da_reserve(vb->uv_buffers, vb->data->num_tex); + da_reserve(vb->uv_sizes, vb->data->num_tex); for (i = 0; i < vb->data->num_tex; i++) { GLuint tex_buffer; @@ -61,6 +62,7 @@ static bool init_vb(struct gs_vertex_buffer *vb) return false; da_push_back(vb->uv_buffers, &tex_buffer); + da_push_back(vb->uv_sizes, &tv->width); } if (!vb->dynamic) { @@ -109,6 +111,7 @@ void vertexbuffer_destroy(vertbuffer_t vb) gl_delete_buffers((GLsizei)vb->uv_buffers.num, vb->uv_buffers.array); + da_free(vb->uv_sizes); da_free(vb->uv_buffers); vbdata_destroy(vb->data); @@ -170,3 +173,83 @@ struct vb_data *vertexbuffer_getdata(vertbuffer_t vb) { return vb->data; } + +static inline GLuint get_vb_buffer(struct gs_vertex_buffer *vb, + enum attrib_type type, size_t index, GLint *width, + GLenum *gl_type) +{ + *gl_type = GL_FLOAT; + *width = 4; + + if (type == ATTRIB_POSITION) { + return vb->vertex_buffer; + } else if (type == ATTRIB_NORMAL) { + return vb->normal_buffer; + } else if (type == ATTRIB_TANGENT) { + return vb->tangent_buffer; + } else if (type == ATTRIB_COLOR) { + *gl_type = GL_UNSIGNED_BYTE; + return vb->color_buffer; + } else if (type == ATTRIB_TEXCOORD) { + if (vb->uv_buffers.num <= index) + return 0; + + *width = (GLint)vb->uv_sizes.array[index]; + return vb->uv_buffers.array[index]; + } + + return 0; +} + +static bool load_vb_buffer(struct gs_shader *shader, + struct shader_attrib *attrib, + struct gs_vertex_buffer *vb) +{ + GLenum type; + GLint width; + GLuint buffer; + bool success = true; + + buffer = get_vb_buffer(vb, attrib->type, attrib->index, &width, &type); + if (!buffer) { + blog(LOG_ERROR, "Vertex buffer does not have the required " + "inputs for vertex shader"); + return false; + } + + if (!gl_bind_buffer(GL_ARRAY_BUFFER, buffer)) + return false; + + glVertexAttribPointer(attrib->attrib, width, type, GL_TRUE, 0, 0); + if (!gl_success("glVertexAttribPointer")) + success = false; + + gl_bind_buffer(GL_ARRAY_BUFFER, 0); + return success; +} + +static inline bool load_vb_buffers(struct gs_shader *shader, + struct gs_vertex_buffer *vb) +{ + size_t i; + for (i = 0; i < shader->attribs.num; i++) { + struct shader_attrib *attrib = shader->attribs.array+i; + if (!load_vb_buffer(shader, attrib, vb)) + return false; + } + + return true; +} + +void device_load_vertexbuffer(device_t device, vertbuffer_t vb) +{ + if (device->cur_vertex_buffer == vb) + return; + + device->cur_vertex_buffer = vb; + if (!device->cur_vertex_shader) + return; + + if (!load_vb_buffers(device->cur_vertex_shader, vb)) + blog(LOG_ERROR, "device_load_vertexbuffer (GL) failed"); +}