Signed-off-by: Paul Gofman gofmanp@gmail.com --- v2: - combine state_blend_object() and state_alpha_to_coverage() to avoid conflicts.
dlls/d3d9/tests/visual.c | 2 +- dlls/wined3d/glsl_shader.c | 2 ++ dlls/wined3d/state.c | 25 ++++++++++++++++++++++--- dlls/wined3d/wined3d_private.h | 8 +++++++- 4 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 859f3e5f1f..b4991d4e5e 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -27100,7 +27100,7 @@ static void test_alpha_to_coverage(void) colour = get_readback_color(&rb, 64, 64);
/* Nvidia is probably using some proprietary algorithm for averaging sample colour values. */ - todo_wine ok(color_match(colour, 0x9f404080, 1) || color_match(colour, 0x9f485cbc, 1) /* Nvidia */, + ok(color_match(colour, 0x9f404080, 1) || color_match(colour, 0x9f485cbc, 1) /* Nvidia */, "Got unexpected colour %08x.\n", colour); release_surface_readback(&rb);
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index cc7afe5165..4ec882d112 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -12173,6 +12173,8 @@ static void glsl_vertex_pipe_pointsize(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { context->constant_update_mask |= WINED3D_SHADER_CONST_VS_POINTSIZE; + + state_atoc(context, state, state_id); }
static void glsl_vertex_pipe_pointscale(struct wined3d_context *context, diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 87e1ca4bac..856a4c9867 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -613,10 +613,10 @@ static void state_blend_factor(struct wined3d_context *context, const struct win checkGLcall("glBlendColor"); }
-static void state_blend_object(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_atoc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = wined3d_context_gl(context)->gl_info; - BOOL alpha_to_coverage = FALSE; + BOOL alpha_to_coverage;
if (!gl_info->supported[ARB_MULTISAMPLE]) return; @@ -626,6 +626,23 @@ static void state_blend_object(struct wined3d_context *context, const struct win struct wined3d_blend_state_desc *desc = &state->blend_state->desc; alpha_to_coverage = desc->alpha_to_coverage; } + else + { + if (context->amd_atoc_enabled + && state->render_states[WINED3D_RS_POINTSIZE] != WINED3D_ALPHA_TO_COVERAGE_DISABLE) + return; + + if (state->render_states[WINED3D_RS_POINTSIZE] == WINED3D_ALPHA_TO_COVERAGE_ENABLE) + { + alpha_to_coverage = TRUE; + context->amd_atoc_enabled = 1; + } + else + { + alpha_to_coverage = FALSE; + context->amd_atoc_enabled = 0; + } + }
if (alpha_to_coverage) gl_info->gl_ops.gl.p_glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); @@ -1532,6 +1549,8 @@ static void state_pscale(struct wined3d_context *context, const struct wined3d_s
gl_info->gl_ops.gl.p_glPointSize(max(pointsize, FLT_MIN)); checkGLcall("glPointSize(...);"); + + state_atoc(context, state, state_id); }
static void state_debug_monitor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) @@ -4520,7 +4539,7 @@ const struct wined3d_state_entry_template misc_state_template[] = { STATE_RENDER(WINED3D_RS_DESTBLENDALPHA), { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_DESTBLENDALPHA), { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_BLENDOPALPHA), { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, - { STATE_BLEND, { STATE_BLEND, state_blend_object }, WINED3D_GL_EXT_NONE }, + { STATE_BLEND, { STATE_BLEND, state_atoc }, WINED3D_GL_EXT_NONE }, { STATE_BLEND_FACTOR, { STATE_BLEND_FACTOR, state_blend_factor }, EXT_BLEND_COLOR }, { STATE_BLEND_FACTOR, { STATE_BLEND_FACTOR, state_blend_factor_w}, WINED3D_GL_EXT_NONE }, { STATE_STREAMSRC, { STATE_STREAMSRC, streamsrc }, WINED3D_GL_EXT_NONE }, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 3b9b342441..dddf3e120a 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -76,6 +76,9 @@
#define WINED3D_MAX_DIRTY_REGION_COUNT 7
+#define WINED3D_ALPHA_TO_COVERAGE_ENABLE MAKEFOURCC('A','2','M','1') +#define WINED3D_ALPHA_TO_COVERAGE_DISABLE MAKEFOURCC('A','2','M','0') + struct wined3d_fragment_pipe_ops; struct wined3d_adapter; struct wined3d_context; @@ -1974,7 +1977,8 @@ struct wined3d_context DWORD destroyed : 1; DWORD destroy_delayed : 1; DWORD clip_distance_mask : 8; /* WINED3D_MAX_CLIP_DISTANCES, 8 */ - DWORD padding : 14; + DWORD amd_atoc_enabled : 1; + DWORD padding : 13;
DWORD constant_update_mask; DWORD numbered_array_mask; @@ -4608,6 +4612,8 @@ void state_pointsprite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; void state_shademode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN; +void state_atoc(struct wined3d_context *context, + const struct wined3d_state *state, DWORD state_id) DECLSPEC_HIDDEN;
GLenum gl_primitive_type_from_d3d(enum wined3d_primitive_type primitive_type) DECLSPEC_HIDDEN; enum wined3d_primitive_type d3d_primitive_type_from_gl(GLenum primitive_type) DECLSPEC_HIDDEN;
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=37073 Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/wined3d/state.c | 11 ++++++++++- dlls/wined3d/utils.c | 10 ++++++++++ dlls/wined3d/wined3d_private.h | 3 ++- include/wine/wined3d.h | 1 + 4 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 856a4c9867..9db1311cdd 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -628,8 +628,10 @@ void state_atoc(struct wined3d_context *context, const struct wined3d_state *sta } else { - if (context->amd_atoc_enabled + if ((context->amd_atoc_enabled && state->render_states[WINED3D_RS_POINTSIZE] != WINED3D_ALPHA_TO_COVERAGE_DISABLE) + || (context->nv_atoc_enabled + && state->render_states[WINED3D_RS_ADAPTIVETESS_Y] != WINED3DFMT_UNKNOWN)) return;
if (state->render_states[WINED3D_RS_POINTSIZE] == WINED3D_ALPHA_TO_COVERAGE_ENABLE) @@ -637,10 +639,16 @@ void state_atoc(struct wined3d_context *context, const struct wined3d_state *sta alpha_to_coverage = TRUE; context->amd_atoc_enabled = 1; } + else if (state->render_states[WINED3D_RS_ADAPTIVETESS_Y] == WINED3DFMT_ATOC) + { + alpha_to_coverage = TRUE; + context->nv_atoc_enabled = 1; + } else { alpha_to_coverage = FALSE; context->amd_atoc_enabled = 0; + context->nv_atoc_enabled = 0; } }
@@ -1945,6 +1953,7 @@ static void state_nvdb(struct wined3d_context *context, const struct wined3d_sta checkGLcall("glDisable(GL_DEPTH_BOUNDS_TEST_EXT)"); }
+ state_atoc(context, state, state_id); state_tessellation(context, state, STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION)); }
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index a968aa4eea..a476c977c8 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -65,6 +65,7 @@ format_index_remap[] = {WINED3DFMT_R16, WINED3D_FORMAT_FOURCC_BASE + 20}, {WINED3DFMT_AL16, WINED3D_FORMAT_FOURCC_BASE + 21}, {WINED3DFMT_NV12, WINED3D_FORMAT_FOURCC_BASE + 22}, + {WINED3DFMT_ATOC, WINED3D_FORMAT_FOURCC_BASE + 23}, };
#define WINED3D_FORMAT_COUNT (WINED3D_FORMAT_FOURCC_BASE + ARRAY_SIZE(format_index_remap)) @@ -135,6 +136,7 @@ static const struct wined3d_format_channels formats[] = {WINED3DFMT_ATI1N, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {WINED3DFMT_ATI2N, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {WINED3DFMT_NVDB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {WINED3DFMT_ATOC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {WINED3DFMT_INST, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {WINED3DFMT_INTZ, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 8}, {WINED3DFMT_RESZ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, @@ -339,6 +341,7 @@ static const struct wined3d_format_base_flags format_base_flags[] = {WINED3DFMT_INST, WINED3DFMT_FLAG_EXTENSION}, {WINED3DFMT_NULL, WINED3DFMT_FLAG_EXTENSION}, {WINED3DFMT_NVDB, WINED3DFMT_FLAG_EXTENSION}, + {WINED3DFMT_ATOC, WINED3DFMT_FLAG_EXTENSION}, {WINED3DFMT_RESZ, WINED3DFMT_FLAG_EXTENSION}, };
@@ -3709,6 +3712,12 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_ format_set_flag(&format->f, WINED3DFMT_FLAG_TEXTURE); }
+ if (gl_info->supported[ARB_MULTISAMPLE]) + { + format = get_format_gl_internal(adapter, WINED3DFMT_ATOC); + format_set_flag(&format->f, WINED3DFMT_FLAG_TEXTURE); + } + /* RESZ aka AMD DX9-level hack for multisampled depth buffer resolve. You query for RESZ * support by checking for availability of MAKEFOURCC('R','E','S','Z') surfaces with * RENDERTARGET usage. */ @@ -4627,6 +4636,7 @@ const char *debug_d3dformat(enum wined3d_format_id format_id) FMT_TO_STR(WINED3DFMT_R16); FMT_TO_STR(WINED3DFMT_AL16); FMT_TO_STR(WINED3DFMT_NV12); + FMT_TO_STR(WINED3DFMT_ATOC); #undef FMT_TO_STR default: { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index dddf3e120a..f43b13a2a9 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1978,7 +1978,8 @@ struct wined3d_context DWORD destroy_delayed : 1; DWORD clip_distance_mask : 8; /* WINED3D_MAX_CLIP_DISTANCES, 8 */ DWORD amd_atoc_enabled : 1; - DWORD padding : 13; + DWORD nv_atoc_enabled : 1; + DWORD padding : 12;
DWORD constant_update_mask; DWORD numbered_array_mask; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 2b08e7f37a..bbb038d0d3 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -269,6 +269,7 @@ enum wined3d_format_id WINED3DFMT_NV12 = WINEMAKEFOURCC('N','V','1','2'), WINED3DFMT_DF16 = WINEMAKEFOURCC('D','F','1','6'), WINED3DFMT_DF24 = WINEMAKEFOURCC('D','F','2','4'), + WINED3DFMT_ATOC = WINEMAKEFOURCC('A','T','O','C'),
WINED3DFMT_FORCE_DWORD = 0xffffffff };
On Mon, 10 Feb 2020 at 20:41, Paul Gofman gofmanp@gmail.com wrote:
-static void state_blend_object(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_atoc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) {
Why the rename? This is still the handler for blend state objects.
- else
- {
if (context->amd_atoc_enabled
&& state->render_states[WINED3D_RS_POINTSIZE] != WINED3D_ALPHA_TO_COVERAGE_DISABLE)
return;
if (state->render_states[WINED3D_RS_POINTSIZE] == WINED3D_ALPHA_TO_COVERAGE_ENABLE)
{
alpha_to_coverage = TRUE;
context->amd_atoc_enabled = 1;
}
else
{
alpha_to_coverage = FALSE;
context->amd_atoc_enabled = 0;
}
- }
Does this imply that the current alpha to coverage state is supposed to stick as long as WINED3D_RS_POINTSIZE isn't set to either WINED3D_ALPHA_TO_COVERAGE_ENABLE or WINED3D_ALPHA_TO_COVERAGE_DISABLE? (And likewise that setting either of those shouldn't change the current point size?) If that's the case, you can't handle this here; d3d9 state is only flushed to wined3d on draws, so you'd miss intermediate states.
@@ -1532,6 +1549,8 @@ static void state_pscale(struct wined3d_context *context, const struct wined3d_s
gl_info->gl_ops.gl.p_glPointSize(max(pointsize, FLT_MIN)); checkGLcall("glPointSize(...);");
- state_atoc(context, state, state_id);
}
We'd typically guard that by "!isStateDirty(context, STATE_BLEND)", and perhaps a check on the value of WINED3D_RS_POINTSIZE.
On 2/11/20 19:32, Henri Verbeet wrote:
On Mon, 10 Feb 2020 at 20:41, Paul Gofman gofmanp@gmail.com wrote:
-static void state_blend_object(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_atoc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) {
Why the rename? This is still the handler for blend state objects.
I thought the handler is already dealing just with ATOC state, other parts of blend state are handled elsewhere. And now this is extended to different ways of setting ATOC. Should I get the name back?
- else
- {
if (context->amd_atoc_enabled
&& state->render_states[WINED3D_RS_POINTSIZE] != WINED3D_ALPHA_TO_COVERAGE_DISABLE)
return;
if (state->render_states[WINED3D_RS_POINTSIZE] == WINED3D_ALPHA_TO_COVERAGE_ENABLE)
{
alpha_to_coverage = TRUE;
context->amd_atoc_enabled = 1;
}
else
{
alpha_to_coverage = FALSE;
context->amd_atoc_enabled = 0;
}
- }
Does this imply that the current alpha to coverage state is supposed to stick as long as WINED3D_RS_POINTSIZE isn't set to either WINED3D_ALPHA_TO_COVERAGE_ENABLE or WINED3D_ALPHA_TO_COVERAGE_DISABLE? (And likewise that setting either of those shouldn't change the current point size?) If that's the case, you can't handle this here; d3d9 state is only flushed to wined3d on draws, so you'd miss intermediate states.
It is not consistent between the GPUs. I did some more testing lately, Nvidia just considers the state to be enabled if D3DRS_ADAPTIVETESS_Y is 'ATOC' by the moment of the draw (and also requires alpha test to be enabled), and ATOC is not in effect if there is any other value by the moment of the draw. Intel, on the contrary, behaves like Nvidia docs suggest, that is, ATOC state sticks until I set D3DFMT_UNKNOWN to D3DRS_ADAPTIVETESS_Y. It gets reset even if I have something else set by the moment of consequent draw (so yeah, this behaviour is currently not reproduced exactly in these pacthes). I don't have AMD to test but if it follows its own notes on this state and advertises the special value for resetting ATOC state I guess it should behave like Intel (that is, ATOC state is supposed to stick until reset with WINED3D_ALPHA_TO_COVERAGE_DISABLE).
I've tested FC2 game with that 'return' removed, that is, enabling ATOC strictly based on the states at the moment of the draw. It seems to work fine this way both in 'Nvidia' and 'AMD' mode. So maybe it worth to simplify the thing and just check for the currently present state here.
Otherwise I can maybe handle those states changes in wined3d_cs_exec_set_render_state() and put a flag to wined3d_state which will indicate if ATOC needs to be set or reset. STATE_BLEND can also be invalidated there so the handler won't be called from the other places.
@@ -1532,6 +1549,8 @@ static void state_pscale(struct wined3d_context *context, const struct wined3d_s
gl_info->gl_ops.gl.p_glPointSize(max(pointsize, FLT_MIN)); checkGLcall("glPointSize(...);");
- state_atoc(context, state, state_id);
}
We'd typically guard that by "!isStateDirty(context, STATE_BLEND)", and perhaps a check on the value of WINED3D_RS_POINTSIZE.
I will add '!isStateDirty(context, STATE_BLEND)'. I am a bit unsure about WINED3D_RS_POINTSIZE value, as that would probably mean I will have to split (duplicate) the logic from state_blend() in some not very straightforward way. Maybe I should rather introduce a separate handle on WINED3D_RS_POINTSIZE instead (which will call state_pscale), so at least the state_blend() would be called for the required state only?
After thinking a bit more I would suggest to rather keep the "sticky" ATOC state behaviour, as probably the reason AMD introduced the special values as state triggers is that some applications may potentially still want to use _POINTSIZE for its original purpose while keeping ATOC on. Though of course this is not much likely case.
On 2/11/20 20:18, Paul Gofman wrote:
On 2/11/20 19:32, Henri Verbeet wrote:
On Mon, 10 Feb 2020 at 20:41, Paul Gofman gofmanp@gmail.com wrote:
-static void state_blend_object(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_atoc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) {
Why the rename? This is still the handler for blend state objects.
I thought the handler is already dealing just with ATOC state, other parts of blend state are handled elsewhere. And now this is extended to different ways of setting ATOC. Should I get the name back?
- else
- {
if (context->amd_atoc_enabled
&& state->render_states[WINED3D_RS_POINTSIZE] != WINED3D_ALPHA_TO_COVERAGE_DISABLE)
return;
if (state->render_states[WINED3D_RS_POINTSIZE] == WINED3D_ALPHA_TO_COVERAGE_ENABLE)
{
alpha_to_coverage = TRUE;
context->amd_atoc_enabled = 1;
}
else
{
alpha_to_coverage = FALSE;
context->amd_atoc_enabled = 0;
}
- }
Does this imply that the current alpha to coverage state is supposed to stick as long as WINED3D_RS_POINTSIZE isn't set to either WINED3D_ALPHA_TO_COVERAGE_ENABLE or WINED3D_ALPHA_TO_COVERAGE_DISABLE? (And likewise that setting either of those shouldn't change the current point size?) If that's the case, you can't handle this here; d3d9 state is only flushed to wined3d on draws, so you'd miss intermediate states.
It is not consistent between the GPUs. I did some more testing lately, Nvidia just considers the state to be enabled if D3DRS_ADAPTIVETESS_Y is 'ATOC' by the moment of the draw (and also requires alpha test to be enabled), and ATOC is not in effect if there is any other value by the moment of the draw. Intel, on the contrary, behaves like Nvidia docs suggest, that is, ATOC state sticks until I set D3DFMT_UNKNOWN to D3DRS_ADAPTIVETESS_Y. It gets reset even if I have something else set by the moment of consequent draw (so yeah, this behaviour is currently not reproduced exactly in these pacthes). I don't have AMD to test but if it follows its own notes on this state and advertises the special value for resetting ATOC state I guess it should behave like Intel (that is, ATOC state is supposed to stick until reset with WINED3D_ALPHA_TO_COVERAGE_DISABLE).
I've tested FC2 game with that 'return' removed, that is, enabling ATOC strictly based on the states at the moment of the draw. It seems to work fine this way both in 'Nvidia' and 'AMD' mode. So maybe it worth to simplify the thing and just check for the currently present state here.
Otherwise I can maybe handle those states changes in wined3d_cs_exec_set_render_state() and put a flag to wined3d_state which will indicate if ATOC needs to be set or reset. STATE_BLEND can also be invalidated there so the handler won't be called from the other places.
@@ -1532,6 +1549,8 @@ static void state_pscale(struct wined3d_context *context, const struct wined3d_s
gl_info->gl_ops.gl.p_glPointSize(max(pointsize, FLT_MIN)); checkGLcall("glPointSize(...);");
- state_atoc(context, state, state_id);
}
We'd typically guard that by "!isStateDirty(context, STATE_BLEND)", and perhaps a check on the value of WINED3D_RS_POINTSIZE.
I will add '!isStateDirty(context, STATE_BLEND)'. I am a bit unsure about WINED3D_RS_POINTSIZE value, as that would probably mean I will have to split (duplicate) the logic from state_blend() in some not very straightforward way. Maybe I should rather introduce a separate handle on WINED3D_RS_POINTSIZE instead (which will call state_pscale), so at least the state_blend() would be called for the required state only?
On Tue, 11 Feb 2020 at 20:48, Paul Gofman gofmanp@gmail.com wrote:
On 2/11/20 19:32, Henri Verbeet wrote:
On Mon, 10 Feb 2020 at 20:41, Paul Gofman gofmanp@gmail.com wrote:
-static void state_blend_object(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +void state_atoc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) {
Why the rename? This is still the handler for blend state objects.
I thought the handler is already dealing just with ATOC state, other parts of blend state are handled elsewhere. And now this is extended to different ways of setting ATOC. Should I get the name back?
The wined3d_blend_state_desc structure currently only contains the alpha to coverage state, but the idea is for it to become more similar to the d3d11 blend state object.
Otherwise I can maybe handle those states changes in wined3d_cs_exec_set_render_state() and put a flag to wined3d_state which will indicate if ATOC needs to be set or reset.
That won't work; see the way e.g. d3d9_device_SetRenderState() works after Zebediah's recent changes.
I.e., if the application does something like the following:
SetRenderState(..., D3DRS_POINTSIZE, ...); SetRenderState(..., D3DRS_POINTSIZE, ...); SetRenderState(..., D3DRS_POINTSIZE, ...); DrawPrimitive(...);
wined3d will never see the first two D3DRS_POINTSIZE values, and will only see the third one once the DrawPrimitive() call is made.
On 2/12/20 00:02, Henri Verbeet wrote:
That won't work; see the way e.g. d3d9_device_SetRenderState() works after Zebediah's recent changes.
I.e., if the application does something like the following:
SetRenderState(..., D3DRS_POINTSIZE, ...); SetRenderState(..., D3DRS_POINTSIZE, ...); SetRenderState(..., D3DRS_POINTSIZE, ...); DrawPrimitive(...);
wined3d will never see the first two D3DRS_POINTSIZE values, and will only see the third one once the DrawPrimitive() call is made.
Oh yeah, I just realized that too. So maybe it is better to move the logic to d3d9 and provide blend state object from there? Or maybe just ignore this state triggering logic and let those states behave like normal states until we find an application which wants it the other way?
On 2/12/20 00:06, Paul Gofman wrote:
On 2/12/20 00:02, Henri Verbeet wrote:
That won't work; see the way e.g. d3d9_device_SetRenderState() works after Zebediah's recent changes.
I.e., if the application does something like the following:
SetRenderState(..., D3DRS_POINTSIZE, ...); SetRenderState(..., D3DRS_POINTSIZE, ...); SetRenderState(..., D3DRS_POINTSIZE, ...); DrawPrimitive(...);
wined3d will never see the first two D3DRS_POINTSIZE values, and will only see the third one once the DrawPrimitive() call is made.
Oh yeah, I just realized that too. So maybe it is better to move the logic to d3d9 and provide blend state object from there? Or maybe just ignore this state triggering logic and let those states behave like normal states until we find an application which wants it the other way?
After a bit of more testing I found out that state blocks favour ATOC state. So it is no straightforward way to deal with it in d3d9 unless we want to add blend object to wined3d state block. The other solution I can think of is to handle ATOC states in wined3d_stateblock_set_render_state(). That is, to introduce an internal blend state object in wined3d_stateblock, update it from wined3d_stateblock_set_render_state() if necessary, and apply STATE_BLEND on state block application.
On Wed, 12 Feb 2020 at 13:23, Paul Gofman gofmanp@gmail.com wrote:
After a bit of more testing I found out that state blocks favour ATOC state. So it is no straightforward way to deal with it in d3d9 unless we want to add blend object to wined3d state block. The other solution I can think of is to handle ATOC states in wined3d_stateblock_set_render_state(). That is, to introduce an internal blend state object in wined3d_stateblock, update it from wined3d_stateblock_set_render_state() if necessary, and apply STATE_BLEND on state block application.
I think that's more or less what we want eventually. I.e., the idea is that most render states and the like will eventually go away from core wined3d, and will be replaced with d3d10/11 style state objects.
On 2/12/20 13:43, Henri Verbeet wrote:
On Wed, 12 Feb 2020 at 13:23, Paul Gofman gofmanp@gmail.com wrote:
After a bit of more testing I found out that state blocks favour ATOC state. So it is no straightforward way to deal with it in d3d9 unless we want to add blend object to wined3d state block. The other solution I can think of is to handle ATOC states in wined3d_stateblock_set_render_state(). That is, to introduce an internal blend state object in wined3d_stateblock, update it from wined3d_stateblock_set_render_state() if necessary, and apply STATE_BLEND on state block application.
I think that's more or less what we want eventually. I.e., the idea is that most render states and the like will eventually go away from core wined3d, and will be replaced with d3d10/11 style state objects.
So maybe then I introduce wined3d_stateblock_set_blend_state() for now, manage D3DRS_BLENDFACTOR in d3d9 (if I am not missing something this state is d3d9 only) and remove WINED3D_RS_BLENDFACTOR handling from wined3d? I suppose on top of this managing ATOC from d3d9 should be trivial.
On Wed, 12 Feb 2020 at 14:37, Paul Gofman gofmanp@gmail.com wrote:
On 2/12/20 13:43, Henri Verbeet wrote:
On Wed, 12 Feb 2020 at 13:23, Paul Gofman gofmanp@gmail.com wrote:
After a bit of more testing I found out that state blocks favour ATOC state. So it is no straightforward way to deal with it in d3d9 unless we want to add blend object to wined3d state block. The other solution I can think of is to handle ATOC states in wined3d_stateblock_set_render_state(). That is, to introduce an internal blend state object in wined3d_stateblock, update it from wined3d_stateblock_set_render_state() if necessary, and apply STATE_BLEND on state block application.
I think that's more or less what we want eventually. I.e., the idea is that most render states and the like will eventually go away from core wined3d, and will be replaced with d3d10/11 style state objects.
So maybe then I introduce wined3d_stateblock_set_blend_state() for now, manage D3DRS_BLENDFACTOR in d3d9 (if I am not missing something this state is d3d9 only) and remove WINED3D_RS_BLENDFACTOR handling from wined3d? I suppose on top of this managing ATOC from d3d9 should be trivial.
I don't think you need to touch WINED3D_RS_BLENDFACTOR. You'd need to track the AtoC state somewhere in the stateblock, update it in wined3d_stateblock_set_render_state(), and apply the corresponding blend state object in wined3d_device_apply_stateblock().
On 2/12/20 14:28, Henri Verbeet wrote:
So maybe then I introduce wined3d_stateblock_set_blend_state() for now, manage D3DRS_BLENDFACTOR in d3d9 (if I am not missing something this state is d3d9 only) and remove WINED3D_RS_BLENDFACTOR handling from wined3d? I suppose on top of this managing ATOC from d3d9 should be trivial.
I don't think you need to touch WINED3D_RS_BLENDFACTOR.
No, I don't need that for implementing d3d9 ATOC state. I just thought that it is a step towards moving blend states to d3d11 style, which looked natural if I was to implement wined3d_stateblock_set_blend_state().
You'd need to track the AtoC state somewhere in the stateblock, update it in wined3d_stateblock_set_render_state(), and apply the corresponding blend state object in wined3d_device_apply_stateblock().
Yes, that is something close to what I was trying to suggest a bit earlier before considering broader plans of state redesign which you shared. So I should probably go this way now? I suppose I can bypass the proper creation and destruction of blend state object in state block with wined3d_blend_state_create / decref, and just use it as a plain structure.
On Wed, 12 Feb 2020 at 15:17, Paul Gofman gofmanp@gmail.com wrote:
On 2/12/20 14:28, Henri Verbeet wrote:
So maybe then I introduce wined3d_stateblock_set_blend_state() for now, manage D3DRS_BLENDFACTOR in d3d9 (if I am not missing something this state is d3d9 only) and remove WINED3D_RS_BLENDFACTOR handling from wined3d? I suppose on top of this managing ATOC from d3d9 should be trivial.
I don't think you need to touch WINED3D_RS_BLENDFACTOR.
No, I don't need that for implementing d3d9 ATOC state. I just thought that it is a step towards moving blend states to d3d11 style, which looked natural if I was to implement wined3d_stateblock_set_blend_state().
Oh, in case it wasn't quite clear, what we'd do would be to push stateblocks out of core wined3d. So stateblocks would still be dealing with render states, but the wined3d device wouldn't, and translation from render states to state objects would happen in wined3d_device_apply_stateblock().
You'd need to track the AtoC state somewhere in the stateblock, update it in wined3d_stateblock_set_render_state(), and apply the corresponding blend state object in wined3d_device_apply_stateblock().
Yes, that is something close to what I was trying to suggest a bit earlier before considering broader plans of state redesign which you shared. So I should probably go this way now? I suppose I can bypass the proper creation and destruction of blend state object in state block with wined3d_blend_state_create / decref, and just use it as a plain structure.
You could, but I think that's probably best avoided. You'd only need a single blend object anyway, since setting NULL is equivalent to disabling AtoC.