0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-20 04:42:18 +02:00

finish up shader/sampler/texture/buffer loading/unloading/association

This commit is contained in:
jp9000 2013-10-12 12:35:38 -07:00
parent aeea0eadc9
commit 83ddb920a1
9 changed files with 280 additions and 26 deletions

View File

@ -766,7 +766,8 @@ void device_load_vertexshader(device_t device, shader_t vertshader)
if (vertshader) {
if (vertshader->type != SHADER_VERTEX) {
blog(LOG_ERROR, "device_load_vertexshader (D3D11): "
"Shader is not a vertex shader");
"Specified shader is not a vertex "
"shader");
return;
}
@ -809,7 +810,8 @@ void device_load_pixelshader(device_t device, shader_t pixelshader)
if (pixelshader) {
if (pixelshader->type != SHADER_PIXEL) {
blog(LOG_ERROR, "device_load_pixelshader (D3D11): "
"Shader is not a pixel shader");
"Specified shader is not a pixel "
"shader");
return;
}
@ -828,8 +830,7 @@ void device_load_pixelshader(device_t device, shader_t pixelshader)
device->context->PSSetSamplers(0, GS_MAX_TEXTURES, states);
}
void device_load_defaultsamplerstate(device_t device, bool b_3d,
int unit)
void device_load_defaultsamplerstate(device_t device, bool b_3d, int unit)
{
/* TODO */
}

View File

@ -78,6 +78,24 @@ static inline bool gl_bind_renderbuffer(GLenum target, GLuint buffer)
return gl_success("glBindRendebuffer");
}
static inline bool gl_tex_param_f(GLenum target, GLenum param, GLfloat val)
{
glTexParameterf(target, param, val);
return gl_success("glTexParameterf");
}
static inline bool gl_tex_param_i(GLenum target, GLenum param, GLint val)
{
glTexParameteri(target, param, val);
return gl_success("glTexParameteri");
}
static inline bool gl_active_texture(GLenum texture)
{
glActiveTexture(texture);
return gl_success("glActiveTexture");
}
extern bool gl_init_face(GLenum target, GLenum type, uint32_t num_levels,
GLenum format, GLint internal_format, bool compressed,
uint32_t width, uint32_t height, uint32_t size, void ***p_data);

View File

@ -100,3 +100,14 @@ enum gs_index_type indexbuffer_gettype(indexbuffer_t ib)
{
return ib->type;
}
void device_load_indexbuffer(device_t device, indexbuffer_t ib)
{
if (ib == device->cur_index_buffer)
return;
device->cur_index_buffer = ib;
if (!gl_bind_buffer(GL_ELEMENT_ARRAY_BUFFER, ib->buffer))
blog(LOG_ERROR, "device_load_indexbuffer (GL) failed");
}

View File

@ -93,14 +93,15 @@ static inline bool gl_add_params(struct gs_shader *shader,
return true;
}
static void gl_add_sampler(struct gs_shader *shader,
static inline void gl_add_sampler(struct gs_shader *shader,
struct shader_sampler *sampler)
{
struct gs_sampler_state new_sampler = {0};
samplerstate_t new_sampler;
struct gs_sampler_info info;
shader_sampler_convert(sampler, &info);
convert_sampler_info(&new_sampler, &info);
new_sampler = device_create_samplerstate(shader->device, &info);
da_push_back(shader->samplers, &new_sampler);
}
@ -259,6 +260,9 @@ void shader_destroy(shader_t shader)
if (!shader)
return;
for (i = 0; i < shader->samplers.num; i++)
samplerstate_destroy(shader->samplers.array[i]);
for (i = 0; i < shader->params.num; i++)
shader_param_free(shader->params.array+i);

View File

@ -34,18 +34,30 @@ device_t device_create(struct gs_init_data *info)
memset(device, 0, sizeof(struct gs_device));
device->plat = gl_platform_create(device, info);
if (!device->plat) {
blog(LOG_ERROR, "device_create (GL) failed");
bfree(device);
return NULL;
}
if (!device->plat)
goto fail;
glGenProgramPipelines(1, &device->pipeline);
if (!gl_success("glGenProgramPipelines"))
goto fail;
glBindProgramPipeline(device->pipeline);
if (!gl_success("glBindProgramPipeline"))
goto fail;
return device;
fail:
blog(LOG_ERROR, "device_create (GL) failed");
bfree(device);
return NULL;
}
void device_destroy(device_t device)
{
if (device) {
if (device->pipeline)
glDeleteProgramPipelines(1, &device->pipeline);
gl_platform_destroy(device->plat);
bfree(device);
}
@ -107,6 +119,8 @@ samplerstate_t device_create_samplerstate(device_t device,
sampler = bmalloc(sizeof(struct gs_sampler_state));
memset(sampler, 0, sizeof(struct gs_sampler_state));
sampler->device = device;
sampler->ref = 1;
convert_sampler_info(sampler, info);
return sampler;
@ -118,46 +132,220 @@ enum gs_texture_type device_gettexturetype(device_t device,
return texture->type;
}
void device_load_indexbuffer(device_t device, indexbuffer_t indexbuffer)
static bool load_texture_sampler(texture_t tex, samplerstate_t ss)
{
bool success = true;
if (tex->cur_sampler == ss)
return true;
if (tex->cur_sampler)
samplerstate_release(tex->cur_sampler);
tex->cur_sampler = ss;
if (!ss)
return true;
samplerstate_addref(ss);
if (!gl_tex_param_i(tex->gl_target, GL_TEXTURE_MIN_FILTER,
ss->min_filter))
success = false;
if (!gl_tex_param_i(tex->gl_target, GL_TEXTURE_MAG_FILTER,
ss->mag_filter))
success = false;
if (!gl_tex_param_i(tex->gl_target, GL_TEXTURE_WRAP_S, ss->address_u))
success = false;
if (!gl_tex_param_i(tex->gl_target, GL_TEXTURE_WRAP_T, ss->address_v))
success = false;
if (!gl_tex_param_i(tex->gl_target, GL_TEXTURE_WRAP_R, ss->address_w))
success = false;
if (!gl_tex_param_i(tex->gl_target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
ss->max_anisotropy))
success = false;
return success;
}
static inline struct shader_param *get_texture_param(device_t device, int unit)
{
struct gs_shader *shader = device->cur_pixel_shader;
size_t i;
for (i = 0; i < shader->params.num; i++) {
struct shader_param *param = shader->params.array+i;
if (param->type == SHADER_PARAM_TEXTURE) {
if (param->texture_id == unit)
return param;
}
}
return NULL;
}
void device_load_texture(device_t device, texture_t tex, int unit)
{
struct shader_param *param;
struct gs_sampler_state *sampler;
/* need a pixel shader to properly bind textures */
if (!device->cur_pixel_shader)
tex = NULL;
if (device->cur_textures[unit] == tex)
return;
device->cur_textures[unit] = tex;
param = get_texture_param(device, unit);
if (!param)
return;
param->texture = tex;
if (!tex)
return;
sampler = device->cur_samplers[param->sampler_id];
if (!gl_active_texture(GL_TEXTURE0 + unit))
goto fail;
if (!gl_bind_texture(tex->gl_target, tex->texture))
goto fail;
if (sampler && !load_texture_sampler(tex, sampler))
goto fail;
return;
fail:
blog(LOG_ERROR, "device_load_texture (GL) failed");
}
void device_load_samplerstate(device_t device,
samplerstate_t samplerstate, int unit)
static bool load_sampler_on_textures(device_t device, samplerstate_t ss,
int sampler_unit)
{
struct gs_shader *shader = device->cur_pixel_shader;
size_t i;
for (i = 0; i < shader->params.num; i++) {
struct shader_param *param = shader->params.array+i;
if (param->type == SHADER_PARAM_TEXTURE &&
param->sampler_id == sampler_unit &&
param->texture) {
if (!gl_active_texture(GL_TEXTURE0 + param->texture_id))
return false;
if (!load_texture_sampler(param->texture, ss))
return false;
}
}
return true;
}
void device_load_samplerstate(device_t device, samplerstate_t ss, int unit)
{
/* need a pixel shader to properly bind samplers */
if (!device->cur_pixel_shader)
ss = NULL;
if (device->cur_samplers[unit] == ss)
return;
device->cur_samplers[unit] = ss;
if (!ss)
return;
if (!load_sampler_on_textures(device, ss, unit))
blog(LOG_ERROR, "device_load_samplerstate (GL) failed");
return;
}
void device_load_vertexshader(device_t device, shader_t vertshader)
{
GLuint program = 0;
vertbuffer_t cur_vb = device->cur_vertex_buffer;
if (device->cur_vertex_shader == vertshader)
return;
if (vertshader->type != SHADER_VERTEX) {
blog(LOG_ERROR, "Specified shader is not a vertex shader");
goto fail;
}
/* unload and reload the vertex buffer to sync the buffers up with
* the specific shader */
if (cur_vb && !vertexbuffer_load(device, NULL))
goto fail;
device->cur_vertex_shader = vertshader;
if (vertshader)
program = vertshader->program;
glUseProgramStages(device->pipeline, GL_VERTEX_SHADER, program);
if (!gl_success("glUseProgramStages"))
goto fail;
if (cur_vb && !vertexbuffer_load(device, cur_vb))
goto fail;
return;
fail:
blog(LOG_ERROR, "device_load_vertexshader (GL) failed");
}
void device_load_pixelshader(device_t device, shader_t pixelshader)
{
GLuint program = 0;
if (device->cur_pixel_shader == pixelshader)
return;
if (pixelshader->type != SHADER_PIXEL) {
blog(LOG_ERROR, "Specified shader is not a pixel shader");
goto fail;
}
device->cur_pixel_shader = pixelshader;
if (pixelshader)
program = pixelshader->program;
glUseProgramStages(device->pipeline, GL_FRAGMENT_SHADER,
pixelshader->program);
if (!gl_success("glUseProgramStages"))
goto fail;
return;
fail:
blog(LOG_ERROR, "device_load_pixelshader (GL) failed");
}
void device_load_defaultsamplerstate(device_t device, bool b_3d,
int unit)
void device_load_defaultsamplerstate(device_t device, bool b_3d, int unit)
{
/* TODO */
}
shader_t device_getvertexshader(device_t device)
{
return device->cur_vertex_shader;
}
shader_t device_getpixelshader(device_t device)
{
return device->cur_pixel_shader;
}
texture_t device_getrendertarget(device_t device)
{
return device->cur_render_target;
}
zstencil_t device_getzstenciltarget(device_t device)
{
return device->cur_zstencil_buffer;
}
void device_setrendertarget(device_t device, texture_t tex,
@ -347,5 +535,5 @@ enum gs_color_format volumetexture_getcolorformat(texture_t voltex)
void samplerstate_destroy(samplerstate_t samplerstate)
{
bfree(samplerstate);
samplerstate_release(samplerstate);
}

View File

@ -185,6 +185,9 @@ extern void convert_sampler_info(struct gs_sampler_state *sampler,
struct gs_sampler_info *info);
struct gs_sampler_state {
device_t device;
volatile uint32_t ref;
GLint min_filter;
GLint mag_filter;
GLint address_u;
@ -193,6 +196,17 @@ struct gs_sampler_state {
GLint max_anisotropy;
};
static inline void samplerstate_addref(samplerstate_t ss)
{
ss->ref++;
}
static inline void samplerstate_release(samplerstate_t ss)
{
if (--ss->ref == 0)
bfree(ss);
}
struct shader_param {
enum shader_param_type type;
@ -232,9 +246,9 @@ struct gs_shader {
struct shader_param *viewproj;
struct shader_param *world;
DARRAY(struct shader_attrib) attribs;
DARRAY(struct gs_sampler_state) samplers;
DARRAY(struct shader_param) params;
DARRAY(struct shader_attrib) attribs;
DARRAY(struct shader_param) params;
DARRAY(samplerstate_t) samplers;
};
struct gs_vertex_buffer {
@ -250,6 +264,8 @@ struct gs_vertex_buffer {
struct vb_data *data;
};
extern bool vertexbuffer_load(device_t device, vertbuffer_t vb);
struct gs_index_buffer {
GLuint buffer;
enum gs_index_type type;
@ -267,6 +283,7 @@ struct gs_texture {
enum gs_texture_type type;
enum gs_color_format format;
GLenum gl_format;
GLenum gl_target;
GLint gl_internal_format;
GLenum gl_type;
GLuint texture;
@ -274,6 +291,8 @@ struct gs_texture {
bool is_dynamic;
bool is_render_target;
bool gen_mipmaps;
samplerstate_t cur_sampler;
};
struct gs_texture_2d {
@ -318,6 +337,7 @@ struct gs_swap_chain {
struct gs_device {
struct gl_platform *plat;
GLuint pipeline;
enum copy_type copy_type;
texture_t cur_render_target;
@ -330,6 +350,8 @@ struct gs_device {
shader_t cur_vertex_shader;
shader_t cur_pixel_shader;
swapchain_t cur_swap;
bool texture_changed[GS_MAX_TEXTURES];
};
extern struct gl_platform *gl_platform_create(device_t device,

View File

@ -78,6 +78,7 @@ texture_t device_create_texture(device_t device, uint32_t width,
tex->base.gl_format = convert_gs_format(color_format);
tex->base.gl_internal_format = convert_gs_internal_format(color_format);
tex->base.gl_type = get_gl_format_type(color_format);
tex->base.gl_target = GL_TEXTURE_2D;
tex->base.is_dynamic = flags & GS_DYNAMIC;
tex->base.is_render_target = flags & GS_RENDERTARGET;
tex->base.gen_mipmaps = flags & GS_BUILDMIPMAPS;

View File

@ -61,10 +61,11 @@ texture_t device_create_cubetexture(device_t device, uint32_t size,
memset(tex, 0, sizeof(struct gs_texture_2d));
tex->base.device = device;
tex->base.type = GS_TEXTURE_2D;
tex->base.type = GS_TEXTURE_CUBE;
tex->base.format = color_format;
tex->base.gl_format = convert_gs_format(color_format);
tex->base.gl_internal_format = convert_gs_internal_format(color_format);
tex->base.gl_target = GL_TEXTURE_CUBE_MAP;
tex->base.is_render_target = flags & GS_RENDERTARGET;
tex->base.gen_mipmaps = flags & GS_BUILDMIPMAPS;
tex->size = size;

View File

@ -241,15 +241,23 @@ static inline bool load_vb_buffers(struct gs_shader *shader,
return true;
}
void device_load_vertexbuffer(device_t device, vertbuffer_t vb)
bool vertexbuffer_load(device_t device, vertbuffer_t vb)
{
if (device->cur_vertex_buffer == vb)
return;
return true;
device->cur_vertex_buffer = vb;
if (!device->cur_vertex_shader)
return;
if (!device->cur_vertex_shader || !vb)
return true;
if (!load_vb_buffers(device->cur_vertex_shader, vb))
return false;
return true;
}
void device_load_vertexbuffer(device_t device, vertbuffer_t vb)
{
if (vertexbuffer_load(device, vb))
blog(LOG_ERROR, "device_load_vertexbuffer (GL) failed");
}