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

@@ -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);
}