Commit 80bca9bc authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Add constant buffer support to the GLSL shader backend.

parent c654b7be
......@@ -2948,7 +2948,7 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
const struct wined3d_state *state = &device->state;
const struct StateEntry *state_table = context->state_table;
const struct wined3d_fb_state *fb = state->fb;
unsigned int i;
unsigned int i, j;
WORD map;
if (!context_validate_rt_config(context->gl_info->limits.buffers,
......@@ -2985,6 +2985,15 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
buffer_get_sysmem(state->index_buffer, context);
}
for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
{
for (j = 0; j < WINED3D_MAX_CBS; ++j)
{
if (state->cb[i][j])
buffer_internal_preload(state->cb[i][j], context, state);
}
}
for (i = 0; i < context->numDirtyEntries; ++i)
{
DWORD rep = context->dirtyArray[i];
......
......@@ -569,6 +569,8 @@ static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const voi
InterlockedIncrement(&op->buffer->resource.bind_count);
if (prev)
InterlockedDecrement(&prev->resource.bind_count);
device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(op->type));
}
void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type,
......
......@@ -145,6 +145,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
{"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE },
{"GL_ARB_texture_rg", ARB_TEXTURE_RG },
{"GL_ARB_timer_query", ARB_TIMER_QUERY },
{"GL_ARB_uniform_buffer_object", ARB_UNIFORM_BUFFER_OBJECT },
{"GL_ARB_vertex_array_bgra", ARB_VERTEX_ARRAY_BGRA },
{"GL_ARB_vertex_blend", ARB_VERTEX_BLEND },
{"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT },
......@@ -2417,6 +2418,9 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
gl_info->limits.buffers = 1;
gl_info->limits.textures = 1;
gl_info->limits.texture_coords = 1;
gl_info->limits.vertex_uniform_blocks = 0;
gl_info->limits.geometry_uniform_blocks = 0;
gl_info->limits.fragment_uniform_blocks = 0;
gl_info->limits.fragment_samplers = 1;
gl_info->limits.vertex_samplers = 0;
gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers + gl_info->limits.vertex_samplers;
......@@ -2593,6 +2597,19 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
gl_info->limits.glsl_vs_float_constants = gl_max / 4;
TRACE("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->limits.glsl_vs_float_constants);
if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
{
gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, &gl_max);
gl_info->limits.vertex_uniform_blocks = min(gl_max, WINED3D_MAX_CBS);
TRACE("Max vertex uniform blocks: %u (%d).\n", gl_info->limits.vertex_uniform_blocks, gl_max);
}
}
if (gl_info->supported[ARB_GEOMETRY_SHADER4] && gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
{
gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_GEOMETRY_UNIFORM_BLOCKS, &gl_max);
gl_info->limits.geometry_uniform_blocks = min(gl_max, WINED3D_MAX_CBS);
TRACE("Max geometry uniform blocks: %u (%d).\n", gl_info->limits.geometry_uniform_blocks, gl_max);
}
if (gl_info->supported[ARB_FRAGMENT_SHADER])
{
......@@ -2602,6 +2619,20 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
gl_info->limits.glsl_varyings = gl_max;
TRACE("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
{
gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &gl_max);
gl_info->limits.fragment_uniform_blocks = min(gl_max, WINED3D_MAX_CBS);
TRACE("Max fragment uniform blocks: %u (%d).\n", gl_info->limits.fragment_uniform_blocks, gl_max);
}
}
if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
{
gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &gl_max);
TRACE("Max combined uniform blocks: %d.\n", gl_max);
gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &gl_max);
TRACE("Max uniform buffer bindings: %d.\n", gl_max);
}
if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
......
......@@ -1083,7 +1083,8 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
for (i = 0; i < WINED3D_MAX_CBS; ++i)
{
if (reg_maps->cb_sizes[i])
shader_addline(buffer, "uniform vec4 %s_cb%u[%u];\n", prefix, i, reg_maps->cb_sizes[i]);
shader_addline(buffer, "layout(std140) uniform block_%s_cb%u { vec4 %s_cb%u[%u]; };\n",
prefix, i, prefix, i, reg_maps->cb_sizes[i]);
}
/* Declare texture samplers */
......@@ -4488,6 +4489,8 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
* nvidia drivers write a warning if we don't do so. */
if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n");
if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
shader_addline(buffer, "#extension GL_ARB_uniform_buffer_object : enable\n");
if (gl_info->supported[EXT_GPU_SHADER4])
shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n");
......@@ -4541,6 +4544,8 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context
if (gl_info->supported[ARB_SHADER_BIT_ENCODING])
shader_addline(buffer, "#extension GL_ARB_shader_bit_encoding : enable\n");
if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
shader_addline(buffer, "#extension GL_ARB_uniform_buffer_object : enable\n");
if (gl_info->supported[EXT_GPU_SHADER4])
shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n");
......@@ -4614,6 +4619,8 @@ static GLhandleARB shader_glsl_generate_geometry_shader(const struct wined3d_con
shader_addline(buffer, "#extension GL_ARB_geometry_shader4 : enable\n");
if (gl_info->supported[ARB_SHADER_BIT_ENCODING])
shader_addline(buffer, "#extension GL_ARB_shader_bit_encoding : enable\n");
if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
shader_addline(buffer, "#extension GL_ARB_uniform_buffer_object : enable\n");
if (gl_info->supported[EXT_GPU_SHADER4])
shader_addline(buffer, "#extension GL_EXT_gpu_shader4 : enable\n");
......@@ -5755,6 +5762,26 @@ static void shader_glsl_init_ps_uniform_locations(const struct wined3d_gl_info *
ps->ycorrection_location = GL_EXTCALL(glGetUniformLocationARB(program_id, "ycorrection"));
}
static void shader_glsl_init_uniform_block_bindings(const struct wined3d_gl_info *gl_info, GLhandleARB program_id,
const struct wined3d_shader_reg_maps *reg_maps, unsigned int base, unsigned int count)
{
const char *prefix = shader_glsl_get_prefix(reg_maps->shader_version.type);
GLuint block_idx;
unsigned int i;
char name[16];
for (i = 0; i < count; ++i)
{
if (!reg_maps->cb_sizes[i])
continue;
snprintf(name, sizeof(name), "block_%s_cb%u", prefix, i);
block_idx = GL_EXTCALL(glGetUniformBlockIndex(program_id, name));
GL_EXTCALL(glUniformBlockBinding(program_id, block_idx, base + i));
}
checkGLcall("glUniformBlockBinding");
}
/* Context activation is done by the caller. */
static void set_glsl_shader_program(const struct wined3d_context *context, const struct wined3d_state *state,
struct shader_glsl_priv *priv, struct glsl_context_data *ctx_data)
......@@ -5985,8 +6012,15 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
if (vshader->reg_maps.boolean_constants)
entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_B;
entry->constant_update_mask |= WINED3D_SHADER_CONST_VS_POS_FIXUP;
shader_glsl_init_uniform_block_bindings(gl_info, programId, &vshader->reg_maps,
0, gl_info->limits.vertex_uniform_blocks);
}
if (gshader)
shader_glsl_init_uniform_block_bindings(gl_info, programId, &gshader->reg_maps,
gl_info->limits.vertex_uniform_blocks, gl_info->limits.geometry_uniform_blocks);
if (ps_id)
{
if (pshader)
......@@ -5998,6 +6032,10 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_B;
if (entry->ps.ycorrection_location != -1)
entry->constant_update_mask |= WINED3D_SHADER_CONST_PS_Y_CORR;
shader_glsl_init_uniform_block_bindings(gl_info, programId, &pshader->reg_maps,
gl_info->limits.vertex_uniform_blocks + gl_info->limits.geometry_uniform_blocks,
gl_info->limits.fragment_uniform_blocks);
}
else
{
......
......@@ -4896,7 +4896,64 @@ void state_srgbwrite(struct wined3d_context *context, const struct wined3d_state
gl_info->gl_ops.gl.p_glDisable(GL_FRAMEBUFFER_SRGB);
}
const struct StateEntryTemplate misc_state_template[] = {
static void state_cb(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state,
enum wined3d_shader_type type, unsigned int base, unsigned int count)
{
struct wined3d_buffer *buffer;
unsigned int i;
for (i = 0; i < count; ++i)
{
buffer = state->cb[type][i];
GL_EXTCALL(glBindBufferBase(GL_UNIFORM_BUFFER, base + i, buffer ? buffer->buffer_object : 0));
}
checkGLcall("glBindBufferBase");
}
static void state_cb_vs(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
const struct wined3d_gl_limits *limits = &context->gl_info->limits;
TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
state_cb(context->gl_info, state, WINED3D_SHADER_TYPE_VERTEX, 0, limits->vertex_uniform_blocks);
}
static void state_cb_gs(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
const struct wined3d_gl_limits *limits = &context->gl_info->limits;
TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
state_cb(context->gl_info, state, WINED3D_SHADER_TYPE_GEOMETRY,
limits->vertex_uniform_blocks, limits->geometry_uniform_blocks);
}
static void state_cb_ps(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
const struct wined3d_gl_limits *limits = &context->gl_info->limits;
TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
state_cb(context->gl_info, state, WINED3D_SHADER_TYPE_PIXEL,
limits->vertex_uniform_blocks + limits->geometry_uniform_blocks, limits->fragment_uniform_blocks);
}
static void state_cb_warn(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
WARN("Constant buffers (%s) no supported.\n", debug_d3dstate(state_id));
}
const struct StateEntryTemplate misc_state_template[] =
{
{ STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX), { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX), state_cb_vs, }, ARB_UNIFORM_BUFFER_OBJECT },
{ STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX), { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX), state_cb_warn, }, WINED3D_GL_EXT_NONE },
{ STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY),{ STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY),state_cb_gs, }, ARB_UNIFORM_BUFFER_OBJECT },
{ STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY),{ STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY),state_cb_warn, }, WINED3D_GL_EXT_NONE },
{ STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL), { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL), state_cb_ps, }, ARB_UNIFORM_BUFFER_OBJECT },
{ STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL), { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL), state_cb_warn, }, WINED3D_GL_EXT_NONE },
{ STATE_RENDER(WINED3D_RS_SRCBLEND), { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE },
{ STATE_RENDER(WINED3D_RS_DESTBLEND), { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE },
{ STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE), { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE },
......@@ -5825,6 +5882,9 @@ static void validate_state_table(struct StateEntry *state_table)
STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX),
STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY),
STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),
STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX),
STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY),
STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL),
STATE_VIEWPORT,
STATE_LIGHT_TYPE,
STATE_SCISSORRECT,
......
......@@ -2684,6 +2684,8 @@ const char *debug_d3dstate(DWORD state)
return wine_dbg_sprintf("STATE_SAMPLER(%#x)", state - STATE_SAMPLER(0));
if (STATE_IS_SHADER(state))
return wine_dbg_sprintf("STATE_SHADER(%s)", debug_shader_type(state - STATE_SHADER(0)));
if (STATE_IS_CONSTANT_BUFFER(state))
return wine_dbg_sprintf("STATE_CONSTANT_BUFFER(%s)", debug_shader_type(state - STATE_CONSTANT_BUFFER(0)));
if (STATE_IS_TRANSFORM(state))
return wine_dbg_sprintf("STATE_TRANSFORM(%s)", debug_d3dtstype(state - STATE_TRANSFORM(0)));
if (STATE_IS_STREAMSRC(state))
......
......@@ -90,6 +90,7 @@ enum wined3d_gl_extension
ARB_TEXTURE_RECTANGLE,
ARB_TEXTURE_RG,
ARB_TIMER_QUERY,
ARB_UNIFORM_BUFFER_OBJECT,
ARB_VERTEX_ARRAY_BGRA,
ARB_VERTEX_BLEND,
ARB_VERTEX_BUFFER_OBJECT,
......@@ -325,6 +326,17 @@ enum wined3d_gl_extension
/* GL_ARB_timer_query */ \
USE_GL_FUNC(glQueryCounter) \
USE_GL_FUNC(glGetQueryObjectui64v) \
/* GL_ARB_uniform_buffer_object */ \
USE_GL_FUNC(glBindBufferBase) \
USE_GL_FUNC(glBindBufferRange) \
USE_GL_FUNC(glGetActiveUniformBlockName) \
USE_GL_FUNC(glGetActiveUniformBlockiv) \
USE_GL_FUNC(glGetActiveUniformName) \
USE_GL_FUNC(glGetActiveUniformsiv) \
USE_GL_FUNC(glGetIntegeri_v) \
USE_GL_FUNC(glGetUniformBlockIndex) \
USE_GL_FUNC(glGetUniformIndices) \
USE_GL_FUNC(glUniformBlockBinding) \
/* GL_ARB_vertex_blend */ \
USE_GL_FUNC(glVertexBlendARB) \
USE_GL_FUNC(glWeightPointerARB) \
......
......@@ -961,7 +961,10 @@ DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) DECLSPEC_HIDDEN;
#define STATE_SHADER(a) (STATE_SAMPLER(MAX_COMBINED_SAMPLERS) + (a))
#define STATE_IS_SHADER(a) ((a) >= STATE_SHADER(0) && (a) < STATE_SHADER(WINED3D_SHADER_TYPE_COUNT))
#define STATE_TRANSFORM(a) (STATE_SHADER(WINED3D_SHADER_TYPE_COUNT) + (a) - 1)
#define STATE_CONSTANT_BUFFER(a) (STATE_SHADER(WINED3D_SHADER_TYPE_COUNT) + (a))
#define STATE_IS_CONSTANT_BUFFER(a) ((a) >= STATE_CONSTANT_BUFFER(0) && (a) < STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COUNT))
#define STATE_TRANSFORM(a) (STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COUNT) + (a) - 1)
#define STATE_IS_TRANSFORM(a) ((a) >= STATE_TRANSFORM(1) && (a) <= STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(255)))
#define STATE_STREAMSRC (STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(255)) + 1)
......@@ -1576,6 +1579,9 @@ struct wined3d_gl_limits
UINT lights;
UINT textures;
UINT texture_coords;
UINT vertex_uniform_blocks;
UINT geometry_uniform_blocks;
UINT fragment_uniform_blocks;
UINT fragment_samplers;
UINT vertex_samplers;
UINT combined_samplers;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment