wined3d: Use the ftoa helper function in the ARB shader backend.

This is the ARB equivalent to e0494afa00.
This commit is contained in:
Stefan Dösinger 2013-09-05 10:42:12 +02:00 committed by Alexandre Julliard
parent 37c4f3a88c
commit b73464a413
5 changed files with 127 additions and 101 deletions

View File

@ -39,13 +39,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
WINE_DECLARE_DEBUG_CHANNEL(d3d_constants);
WINE_DECLARE_DEBUG_CHANNEL(d3d);
/* sRGB correction constants */
static const float srgb_cmp = 0.0031308f;
static const float srgb_mul_low = 12.92f;
static const float srgb_pow = 0.41666f;
static const float srgb_mul_high = 1.055f;
static const float srgb_sub_high = 0.055f;
static BOOL shader_is_pshader_version(enum wined3d_shader_type type)
{
return type == WINED3D_SHADER_TYPE_PIXEL;
@ -770,6 +763,17 @@ static void shader_arb_update_float_pixel_constants(struct wined3d_device *devic
priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, start + count);
}
static void shader_arb_append_imm_vec4(struct wined3d_shader_buffer *buffer, const float *values)
{
char str[4][16];
wined3d_ftoa(values[0], str[0]);
wined3d_ftoa(values[1], str[1]);
wined3d_ftoa(values[2], str[2]);
wined3d_ftoa(values[3], str[3]);
shader_addline(buffer, "{%s, %s, %s, %s}", str[0], str[1], str[2], str[3]);
}
/* Generate the variable & register declarations for the ARB_vertex_program output target */
static void shader_generate_arb_declarations(const struct wined3d_shader *shader,
const struct wined3d_shader_reg_maps *reg_maps, struct wined3d_shader_buffer *buffer,
@ -874,8 +878,9 @@ static void shader_generate_arb_declarations(const struct wined3d_shader *shader
{
const float *value;
value = (const float *)lconst->value;
shader_addline(buffer, "PARAM C%u = {%.8e, %.8e, %.8e, %.8e};\n", lconst->idx,
value[0], value[1], value[2], value[3]);
shader_addline(buffer, "PARAM C%u = ", lconst->idx);
shader_arb_append_imm_vec4(buffer, value);
shader_addline(buffer, ";\n");
}
}
@ -3448,29 +3453,29 @@ static void arbfp_add_sRGB_correction(struct wined3d_shader_buffer *buffer, cons
if(condcode)
{
/* Sigh. MOVC CC doesn't work, so use one of the temps as dummy dest */
shader_addline(buffer, "SUBC %s, %s.x, srgb_consts1.y;\n", tmp1, fragcolor);
shader_addline(buffer, "SUBC %s, %s.x, srgb_consts1.x;\n", tmp1, fragcolor);
/* Calculate the > 0.0031308 case */
shader_addline(buffer, "POW %s.x (GE), %s.x, srgb_consts1.z;\n", fragcolor, fragcolor);
shader_addline(buffer, "POW %s.y (GE), %s.y, srgb_consts1.z;\n", fragcolor, fragcolor);
shader_addline(buffer, "POW %s.z (GE), %s.z, srgb_consts1.z;\n", fragcolor, fragcolor);
shader_addline(buffer, "MUL %s.xyz (GE), %s, srgb_consts1.w;\n", fragcolor, fragcolor);
shader_addline(buffer, "SUB %s.xyz (GE), %s, srgb_consts2.x;\n", fragcolor, fragcolor);
shader_addline(buffer, "POW %s.x (GE), %s.x, srgb_consts0.x;\n", fragcolor, fragcolor);
shader_addline(buffer, "POW %s.y (GE), %s.y, srgb_consts0.x;\n", fragcolor, fragcolor);
shader_addline(buffer, "POW %s.z (GE), %s.z, srgb_consts0.x;\n", fragcolor, fragcolor);
shader_addline(buffer, "MUL %s.xyz (GE), %s, srgb_consts0.y;\n", fragcolor, fragcolor);
shader_addline(buffer, "SUB %s.xyz (GE), %s, srgb_consts0.z;\n", fragcolor, fragcolor);
/* Calculate the < case */
shader_addline(buffer, "MUL %s.xyz (LT), srgb_consts1.x, %s;\n", fragcolor, fragcolor);
shader_addline(buffer, "MUL %s.xyz (LT), srgb_consts0.w, %s;\n", fragcolor, fragcolor);
}
else
{
/* Calculate the > 0.0031308 case */
shader_addline(buffer, "POW %s.x, %s.x, srgb_consts1.z;\n", tmp1, fragcolor);
shader_addline(buffer, "POW %s.y, %s.y, srgb_consts1.z;\n", tmp1, fragcolor);
shader_addline(buffer, "POW %s.z, %s.z, srgb_consts1.z;\n", tmp1, fragcolor);
shader_addline(buffer, "MUL %s, %s, srgb_consts1.w;\n", tmp1, tmp1);
shader_addline(buffer, "SUB %s, %s, srgb_consts2.x;\n", tmp1, tmp1);
shader_addline(buffer, "POW %s.x, %s.x, srgb_consts0.x;\n", tmp1, fragcolor);
shader_addline(buffer, "POW %s.y, %s.y, srgb_consts0.x;\n", tmp1, fragcolor);
shader_addline(buffer, "POW %s.z, %s.z, srgb_consts0.x;\n", tmp1, fragcolor);
shader_addline(buffer, "MUL %s, %s, srgb_consts0.y;\n", tmp1, tmp1);
shader_addline(buffer, "SUB %s, %s, srgb_consts0.z;\n", tmp1, tmp1);
/* Calculate the < case */
shader_addline(buffer, "MUL %s, srgb_consts1.x, %s;\n", tmp2, fragcolor);
shader_addline(buffer, "MUL %s, srgb_consts0.w, %s;\n", tmp2, fragcolor);
/* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */
shader_addline(buffer, "SLT %s, srgb_consts1.y, %s;\n", tmp3, fragcolor);
shader_addline(buffer, "SGE %s, srgb_consts1.y, %s;\n", tmp4, fragcolor);
shader_addline(buffer, "SLT %s, srgb_consts1.x, %s;\n", tmp3, fragcolor);
shader_addline(buffer, "SGE %s, srgb_consts1.x, %s;\n", tmp4, fragcolor);
/* Store the components > 0.0031308 in the destination */
shader_addline(buffer, "MUL %s.xyz, %s, %s;\n", fragcolor, tmp1, tmp3);
/* Add the components that are < 0.0031308 */
@ -3599,6 +3604,7 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
BOOL custom_linear_fog = FALSE;
char srgbtmp[4][4];
char ftoa_tmp[16];
unsigned int i, found = 0;
for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i)
@ -3724,7 +3730,8 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
if(dcl_td) shader_addline(buffer, "TEMP TD;\n"); /* Used for sRGB writing */
shader_addline(buffer, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
shader_addline(buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
shader_addline(buffer, "PARAM ps_helper_const = { 0.0, 1.0, %1.10f, 0.0 };\n", eps);
wined3d_ftoa(eps, ftoa_tmp);
shader_addline(buffer, "PARAM ps_helper_const = { 0.0, 1.0, %s, 0.0 };\n", ftoa_tmp);
if (reg_maps->shader_version.major < 2)
{
@ -3748,11 +3755,14 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
}
}
if(args->super.srgb_correction) {
shader_addline(buffer, "PARAM srgb_consts1 = {%f, %f, %f, %f};\n",
srgb_mul_low, srgb_cmp, srgb_pow, srgb_mul_high);
shader_addline(buffer, "PARAM srgb_consts2 = {%f, %f, %f, %f};\n",
srgb_sub_high, 0.0, 0.0, 0.0);
if (args->super.srgb_correction)
{
shader_addline(buffer, "PARAM srgb_consts0 = ");
shader_arb_append_imm_vec4(buffer, wined3d_srgb_const0);
shader_addline(buffer, ";\n");
shader_addline(buffer, "PARAM srgb_consts1 = ");
shader_arb_append_imm_vec4(buffer, wined3d_srgb_const1);
shader_addline(buffer, ";\n");
}
/* Base Declarations */
@ -4209,7 +4219,9 @@ static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
shader_addline(buffer, "TEMP TMP_FOGCOORD;\n");
if (need_helper_const(shader_data, reg_maps, gl_info))
{
shader_addline(buffer, "PARAM helper_const = { 0.0, 1.0, 2.0, %1.10f};\n", eps);
char ftoa_tmp[16];
wined3d_ftoa(eps, ftoa_tmp);
shader_addline(buffer, "PARAM helper_const = { 0.0, 1.0, 2.0, %s};\n", ftoa_tmp);
}
if (need_rel_addr_const(shader_data, reg_maps, gl_info))
{
@ -6291,11 +6303,14 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con
}
shader_addline(&buffer, "PARAM specular_enable = program.env[%u];\n", ARB_FFP_CONST_SPECULAR_ENABLE);
if(settings->sRGB_write) {
shader_addline(&buffer, "PARAM srgb_consts1 = {%f, %f, %f, %f};\n",
srgb_mul_low, srgb_cmp, srgb_pow, srgb_mul_high);
shader_addline(&buffer, "PARAM srgb_consts2 = {%f, %f, %f, %f};\n",
srgb_sub_high, 0.0, 0.0, 0.0);
if (settings->sRGB_write)
{
shader_addline(&buffer, "PARAM srgb_consts0 = ");
shader_arb_append_imm_vec4(&buffer, wined3d_srgb_const0);
shader_addline(&buffer, ";\n");
shader_addline(&buffer, "PARAM srgb_consts1 = ");
shader_arb_append_imm_vec4(&buffer, wined3d_srgb_const1);
shader_addline(&buffer, ";\n");
}
if (lowest_disabled_stage < 7 && settings->emul_clipplanes)
@ -6888,6 +6903,8 @@ static BOOL gen_planar_yuv_read(struct wined3d_shader_buffer *buffer, enum compl
static BOOL gen_yv12_read(struct wined3d_shader_buffer *buffer, GLenum textype, char *luminance)
{
const char *tex;
static const float yv12_coef[]
= {2.0f / 3.0f, 1.0f / 6.0f, (2.0f / 3.0f) + (1.0f / 6.0f), 1.0f / 3.0f};
switch(textype) {
case GL_TEXTURE_2D: tex = "2D"; break;
@ -6935,8 +6952,9 @@ static BOOL gen_yv12_read(struct wined3d_shader_buffer *buffer, GLenum textype,
* When reading from rectangle textures, keep in mind that the input y coordinates
* go from 0 to d3d_height, whereas the opengl texture height is 1.5 * d3d_height
*/
shader_addline(buffer, "PARAM yv12_coef = {%f, %f, %f, %f};\n",
2.0f / 3.0f, 1.0f / 6.0f, (2.0f / 3.0f) + (1.0f / 6.0f), 1.0f / 3.0f);
shader_addline(buffer, "PARAM yv12_coef = ");
shader_arb_append_imm_vec4(buffer, yv12_coef);
shader_addline(buffer, ";\n");
shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");
/* the chroma planes have only half the width */

View File

@ -47,9 +47,6 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
#define WINED3D_GLSL_SAMPLE_LOD 0x4
#define WINED3D_GLSL_SAMPLE_GRAD 0x8
static const float srgb_const0[] = {0.41666f, 1.055f, 0.055f, 12.92f}; /* pow, mul_high, sub_high, mul_low */
static const float srgb_const1[] = {0.0031308f, 0.0f, 0.0f, 0.0f}; /* cmp */
struct glsl_dst_param
{
char reg_name[150];
@ -251,61 +248,14 @@ static const char *shader_glsl_get_prefix(enum wined3d_shader_type type)
}
}
/* This should be equivalent to using the %.8e format specifier, but always
* using '.' as decimal separator. This doesn't handle +/-INF or NAN, since
* the GLSL parser wouldn't be able to handle those anyway. */
static void shader_glsl_ftoa(float value, char *s)
{
int x, frac, exponent;
const char *sign = "";
double d;
d = value;
if (copysignf(1.0f, value) < 0.0f)
{
d = -d;
sign = "-";
}
if (d == 0.0f)
{
x = 0;
frac = 0;
exponent = 0;
}
else
{
double t, diff;
exponent = floorf(log10f(d));
d /= pow(10.0, exponent);
x = d;
t = (d - x) * 100000000;
frac = t;
diff = t - frac;
if ((diff > 0.5) || (diff == 0.5 && (frac & 1)))
{
if (++frac >= 100000000)
{
frac = 0;
++x;
}
}
}
sprintf(s, "%s%d.%08de%+03d", sign, x, frac, exponent);
}
static void shader_glsl_append_imm_vec4(struct wined3d_shader_buffer *buffer, const float *values)
{
char str[4][16];
shader_glsl_ftoa(values[0], str[0]);
shader_glsl_ftoa(values[1], str[1]);
shader_glsl_ftoa(values[2], str[2]);
shader_glsl_ftoa(values[3], str[3]);
wined3d_ftoa(values[0], str[0]);
wined3d_ftoa(values[1], str[1]);
wined3d_ftoa(values[2], str[2]);
wined3d_ftoa(values[3], str[3]);
shader_addline(buffer, "vec4(%s, %s, %s, %s)", str[0], str[1], str[2], str[3]);
}
@ -1275,10 +1225,10 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
if (ps_args->srgb_correction)
{
shader_addline(buffer, "const vec4 srgb_const0 = ");
shader_glsl_append_imm_vec4(buffer, srgb_const0);
shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const0);
shader_addline(buffer, ";\n");
shader_addline(buffer, "const vec4 srgb_const1 = ");
shader_glsl_append_imm_vec4(buffer, srgb_const1);
shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const1);
shader_addline(buffer, ";\n");
}
if (reg_maps->vpos || reg_maps->usesdsy)
@ -1661,7 +1611,7 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register *
switch (reg->data_type)
{
case WINED3D_DATA_FLOAT:
shader_glsl_ftoa(*(const float *)reg->immconst_data, register_name);
wined3d_ftoa(*(const float *)reg->immconst_data, register_name);
break;
case WINED3D_DATA_INT:
sprintf(register_name, "%#x", reg->immconst_data[0]);
@ -1681,10 +1631,10 @@ static void shader_glsl_get_register_name(const struct wined3d_shader_register *
switch (reg->data_type)
{
case WINED3D_DATA_FLOAT:
shader_glsl_ftoa(*(const float *)&reg->immconst_data[0], imm_str[0]);
shader_glsl_ftoa(*(const float *)&reg->immconst_data[1], imm_str[1]);
shader_glsl_ftoa(*(const float *)&reg->immconst_data[2], imm_str[2]);
shader_glsl_ftoa(*(const float *)&reg->immconst_data[3], imm_str[3]);
wined3d_ftoa(*(const float *)&reg->immconst_data[0], imm_str[0]);
wined3d_ftoa(*(const float *)&reg->immconst_data[1], imm_str[1]);
wined3d_ftoa(*(const float *)&reg->immconst_data[2], imm_str[2]);
wined3d_ftoa(*(const float *)&reg->immconst_data[3], imm_str[3]);
sprintf(register_name, "vec4(%s, %s, %s, %s)",
imm_str[0], imm_str[1], imm_str[2], imm_str[3]);
break;
@ -5491,10 +5441,10 @@ static GLuint shader_glsl_generate_ffp_fragment_shader(struct wined3d_shader_buf
if (settings->sRGB_write)
{
shader_addline(buffer, "const vec4 srgb_const0 = ");
shader_glsl_append_imm_vec4(buffer, srgb_const0);
shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const0);
shader_addline(buffer, ";\n");
shader_addline(buffer, "const vec4 srgb_const1 = ");
shader_glsl_append_imm_vec4(buffer, srgb_const1);
shader_glsl_append_imm_vec4(buffer, wined3d_srgb_const1);
shader_addline(buffer, ";\n");
}

View File

@ -33,6 +33,11 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
/* pow, mul_high, sub_high, mul_low */
const float wined3d_srgb_const0[] = {0.41666f, 1.055f, 0.055f, 12.92f};
/* cmp */
const float wined3d_srgb_const1[] = {0.0031308f, 0.0f, 0.0f, 0.0f};
static const char * const shader_opcode_names[] =
{
/* WINED3DSIH_ABS */ "abs",

View File

@ -27,6 +27,8 @@
#include "config.h"
#include "wine/port.h"
#include <stdio.h>
#include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
@ -3724,3 +3726,50 @@ const char *wined3d_debug_location(DWORD location)
return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0";
}
/* This should be equivalent to using the %.8e format specifier, but always
* using '.' as decimal separator. This doesn't handle +/-INF or NAN, since
* the GLSL and ARB parsers wouldn't be able to handle those anyway. */
void wined3d_ftoa(float value, char *s)
{
int x, frac, exponent;
const char *sign = "";
double d;
d = value;
if (copysignf(1.0f, value) < 0.0f)
{
d = -d;
sign = "-";
}
if (d == 0.0f)
{
x = 0;
frac = 0;
exponent = 0;
}
else
{
double t, diff;
exponent = floorf(log10f(d));
d /= pow(10.0, exponent);
x = d;
t = (d - x) * 100000000;
frac = t;
diff = t - frac;
if ((diff > 0.5) || (diff == 0.5 && (frac & 1)))
{
if (++frac >= 100000000)
{
frac = 0;
++x;
}
}
}
sprintf(s, "%s%d.%08de%+03d", sign, x, frac, exponent);
}

View File

@ -1710,6 +1710,10 @@ const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *frag
const struct ffp_frag_settings *settings) DECLSPEC_HIDDEN;
void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc) DECLSPEC_HIDDEN;
void wined3d_get_draw_rect(const struct wined3d_state *state, RECT *rect) DECLSPEC_HIDDEN;
void wined3d_ftoa(float value, char *s) DECLSPEC_HIDDEN;
extern const float wined3d_srgb_const0[] DECLSPEC_HIDDEN;
extern const float wined3d_srgb_const1[] DECLSPEC_HIDDEN;
enum wined3d_ffp_vs_fog_mode
{