From 9cb69d91b2132876bdd3941384408bce91cf884b Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=B3zef=20Kucia?= Date: Wed, 18 Oct 2017 00:25:09 +0200 Subject: [PATCH] wined3d: Pack interpolation modes. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Józef Kucia Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/glsl_shader.c | 25 +++++++++++++++------ dlls/wined3d/shader.c | 18 ++++++++++++---- dlls/wined3d/wined3d_private.h | 49 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 77 insertions(+), 15 deletions(-) diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index e4aa6c501ae..a03f1792272 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -2141,10 +2141,18 @@ static const char *shader_glsl_interpolation_qualifiers(enum wined3d_shader_inte } } +static enum wined3d_shader_interpolation_mode wined3d_extract_interpolation_mode( + const DWORD *packed_interpolation_mode, unsigned int register_idx) +{ + return wined3d_extract_bits(packed_interpolation_mode, + register_idx * WINED3D_PACKED_INTERPOLATION_BIT_COUNT, WINED3D_PACKED_INTERPOLATION_BIT_COUNT); +} + static void shader_glsl_declare_shader_inputs(const struct wined3d_gl_info *gl_info, struct wined3d_string_buffer *buffer, unsigned int element_count, - const enum wined3d_shader_interpolation_mode *interpolation_mode, BOOL unroll) + const DWORD *interpolation_mode, BOOL unroll) { + enum wined3d_shader_interpolation_mode mode; unsigned int i; if (shader_glsl_use_interface_blocks(gl_info)) @@ -2154,8 +2162,8 @@ static void shader_glsl_declare_shader_inputs(const struct wined3d_gl_info *gl_i shader_addline(buffer, "in shader_in_out {\n"); for (i = 0; i < element_count; ++i) { - shader_addline(buffer, "%s vec4 reg%u;\n", - shader_glsl_interpolation_qualifiers(interpolation_mode[i]), i); + mode = wined3d_extract_interpolation_mode(interpolation_mode, i); + shader_addline(buffer, "%s vec4 reg%u;\n", shader_glsl_interpolation_qualifiers(mode), i); } shader_addline(buffer, "} shader_in;\n"); } @@ -2172,8 +2180,9 @@ static void shader_glsl_declare_shader_inputs(const struct wined3d_gl_info *gl_i static void shader_glsl_declare_shader_outputs(const struct wined3d_gl_info *gl_info, struct wined3d_string_buffer *buffer, unsigned int element_count, BOOL rasterizer_setup, - const enum wined3d_shader_interpolation_mode *interpolation_mode) + const DWORD *interpolation_mode) { + enum wined3d_shader_interpolation_mode mode; unsigned int i; if (shader_glsl_use_interface_blocks(gl_info)) @@ -2185,7 +2194,10 @@ static void shader_glsl_declare_shader_outputs(const struct wined3d_gl_info *gl_ { const char *interpolation_qualifiers = ""; if (needs_interpolation_qualifiers_for_shader_outputs(gl_info)) - interpolation_qualifiers = shader_glsl_interpolation_qualifiers(interpolation_mode[i]); + { + mode = wined3d_extract_interpolation_mode(interpolation_mode, i); + interpolation_qualifiers = shader_glsl_interpolation_qualifiers(mode); + } shader_addline(buffer, "%s vec4 reg%u;\n", interpolation_qualifiers, i); } shader_addline(buffer, "} shader_out;\n"); @@ -7063,8 +7075,7 @@ static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl static void shader_glsl_generate_sm4_output_setup(struct shader_glsl_priv *priv, const struct wined3d_shader *shader, unsigned int input_count, - const struct wined3d_gl_info *gl_info, BOOL rasterizer_setup, - const enum wined3d_shader_interpolation_mode *interpolation_mode) + const struct wined3d_gl_info *gl_info, BOOL rasterizer_setup, const DWORD *interpolation_mode) { const char *prefix = shader_glsl_get_prefix(shader->reg_maps.shader_version.type); struct wined3d_string_buffer *buffer = &priv->shader_buffer; diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index 2c741c80854..f80467b46d0 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -961,6 +961,16 @@ static HRESULT shader_record_shader_phase(struct wined3d_shader *shader, return WINED3D_OK; } +static void wined3d_insert_interpolation_mode(DWORD *packed_interpolation_mode, + unsigned int register_idx, enum wined3d_shader_interpolation_mode mode) +{ + if (mode > WINED3DSIM_LINEAR_NOPERSPECTIVE_SAMPLE) + FIXME("Unexpected interpolation mode %#x.\n", mode); + + wined3d_insert_bits(packed_interpolation_mode, + register_idx * WINED3D_PACKED_INTERPOLATION_BIT_COUNT, WINED3D_PACKED_INTERPOLATION_BIT_COUNT, mode); +} + /* Note that this does not count the loop register as an address register. */ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const struct wined3d_shader_frontend *fe, struct wined3d_shader_reg_maps *reg_maps, struct wined3d_shader_signature *input_signature, @@ -1151,13 +1161,13 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st else if (ins.handler_idx == WINED3DSIH_DCL_INPUT_PS) { unsigned int reg_idx = ins.declaration.dst.reg.idx[0].offset; - if (reg_idx >= ARRAY_SIZE(shader->u.ps.interpolation_mode)) + if (reg_idx >= MAX_REG_INPUT) { ERR("Invalid register index %u.\n", reg_idx); break; } if (shader_version.type == WINED3D_SHADER_TYPE_PIXEL) - shader->u.ps.interpolation_mode[reg_idx] = ins.flags; + wined3d_insert_interpolation_mode(shader->u.ps.interpolation_mode, reg_idx, ins.flags); else FIXME("Invalid instruction %#x for shader type %#x.\n", ins.handler_idx, shader_version.type); @@ -3400,13 +3410,13 @@ HRESULT CDECL wined3d_shader_set_local_constants_float(struct wined3d_shader *sh return WINED3D_OK; } -static void init_interpolation_compile_args(enum wined3d_shader_interpolation_mode *interpolation_args, +static void init_interpolation_compile_args(DWORD *interpolation_args, const struct wined3d_shader *pixel_shader, const struct wined3d_gl_info *gl_info) { if (!needs_interpolation_qualifiers_for_shader_outputs(gl_info) || !pixel_shader || pixel_shader->reg_maps.shader_version.major < 4) { - memset(interpolation_args, 0, MAX_REG_INPUT * sizeof(*interpolation_args)); + memset(interpolation_args, 0, sizeof(pixel_shader->u.ps.interpolation_mode)); return; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 26bda615464..fad3fadeeaa 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -561,6 +561,9 @@ enum wined3d_shader_interpolation_mode WINED3DSIM_LINEAR_NOPERSPECTIVE_SAMPLE = 7, }; +#define WINED3D_PACKED_INTERPOLATION_SIZE 3 +#define WINED3D_PACKED_INTERPOLATION_BIT_COUNT 3 + enum wined3d_shader_global_flags { WINED3DSGF_REFACTORING_ALLOWED = 0x1, @@ -1363,7 +1366,7 @@ struct vs_compile_args BYTE padding : 1; WORD swizzle_map; /* MAX_ATTRIBS, 16 */ unsigned int next_shader_input_count; - enum wined3d_shader_interpolation_mode interpolation_mode[MAX_REG_INPUT]; + DWORD interpolation_mode[WINED3D_PACKED_INTERPOLATION_SIZE]; }; struct ds_compile_args @@ -1374,13 +1377,13 @@ struct ds_compile_args unsigned int next_shader_type : 3; unsigned int render_offscreen : 1; unsigned int padding : 12; - enum wined3d_shader_interpolation_mode interpolation_mode[MAX_REG_INPUT]; + DWORD interpolation_mode[WINED3D_PACKED_INTERPOLATION_SIZE]; }; struct gs_compile_args { unsigned int output_count; - enum wined3d_shader_interpolation_mode interpolation_mode[MAX_REG_INPUT]; + DWORD interpolation_mode[WINED3D_PACKED_INTERPOLATION_SIZE]; }; struct wined3d_context; @@ -3916,7 +3919,7 @@ struct wined3d_pixel_shader BOOL force_early_depth_stencil; enum wined3d_shader_register_type depth_output; - enum wined3d_shader_interpolation_mode interpolation_mode[MAX_REG_INPUT]; + DWORD interpolation_mode[WINED3D_PACKED_INTERPOLATION_SIZE]; }; struct wined3d_compute_shader @@ -4293,6 +4296,44 @@ static inline BOOL needs_interpolation_qualifiers_for_shader_outputs(const struc return gl_info->glsl_version < MAKEDWORD_VERSION(4, 40); } +static inline DWORD wined3d_extract_bits(const DWORD *bitstream, + unsigned int offset, unsigned int count) +{ + const unsigned int word_bit_count = sizeof(*bitstream) * CHAR_BIT; + const unsigned int idx = offset / word_bit_count; + const unsigned int shift = offset % word_bit_count; + DWORD mask = (1u << count) - 1; + DWORD ret; + + ret = (bitstream[idx] >> shift) & mask; + if (shift + count > word_bit_count) + { + const unsigned int extracted_bit_count = word_bit_count - shift; + const unsigned int remaining_bit_count = count - extracted_bit_count; + mask = (1u << remaining_bit_count) - 1; + ret |= (bitstream[idx + 1] & mask) << extracted_bit_count; + } + return ret; +} + +static inline void wined3d_insert_bits(DWORD *bitstream, + unsigned int offset, unsigned int count, DWORD bits) +{ + const unsigned int word_bit_count = sizeof(*bitstream) * CHAR_BIT; + const unsigned int idx = offset / word_bit_count; + const unsigned int shift = offset % word_bit_count; + DWORD mask = (1u << count) - 1; + + bitstream[idx] |= (bits & mask) << shift; + if (shift + count > word_bit_count) + { + const unsigned int inserted_bit_count = word_bit_count - shift; + const unsigned int remaining_bit_count = count - inserted_bit_count; + mask = (1u << remaining_bit_count) - 1; + bitstream[idx + 1] |= (bits >> inserted_bit_count) & mask; + } +} + static inline struct wined3d_surface *context_get_rt_surface(const struct wined3d_context *context) { struct wined3d_texture *texture = context->current_rt.texture; -- 2.11.4.GIT