@@ -94,6 +94,7 @@ class BorderlessToneMapPass
9494 LPD3DXCONSTANTTABLE m_constantTable = nullptr ;
9595 D3DXHANDLE m_toneParamsHandle = nullptr ;
9696 IDirect3DStateBlock9* m_restoreStateBlock = nullptr ;
97+ IDirect3DStateBlock9* m_applyStateBlock = nullptr ;
9798 UINT m_width = 0 ;
9899 UINT m_height = 0 ;
99100 D3DFORMAT m_format = D3DFMT_UNKNOWN;
@@ -216,22 +217,59 @@ bool BorderlessToneMapPass::EnsureStateBlock(IDirect3DDevice9* device)
216217 if (!device)
217218 return false ;
218219
219- if (m_restoreStateBlock)
220+ if (m_restoreStateBlock && m_applyStateBlock )
220221 return true ;
221222
222- // Create and capture state block once on initialization
223- IDirect3DStateBlock9* stateBlock = nullptr ;
224- if (FAILED (device->CreateStateBlock (D3DSBT_ALL, &stateBlock)) || !stateBlock)
225- return false ;
226-
227- // Capture current state immediately after creation
228- if (FAILED (stateBlock->Capture ()))
223+ // Create restore state block (captures current state for restoration)
224+ if (!m_restoreStateBlock)
229225 {
230- stateBlock->Release ();
231- return false ;
226+ IDirect3DStateBlock9* restoreBlock = nullptr ;
227+ if (FAILED (device->CreateStateBlock (D3DSBT_ALL, &restoreBlock)) || !restoreBlock)
228+ return false ;
229+
230+ if (FAILED (restoreBlock->Capture ()))
231+ {
232+ restoreBlock->Release ();
233+ return false ;
234+ }
235+ m_restoreStateBlock = restoreBlock;
236+ }
237+
238+ // Create apply state block (captures our desired rendering state)
239+ if (!m_applyStateBlock)
240+ {
241+ device->BeginStateBlock ();
242+
243+ // Configure all render states for tone mapping pass
244+ device->SetRenderState (D3DRS_ZENABLE, FALSE );
245+ device->SetRenderState (D3DRS_ZWRITEENABLE, FALSE );
246+ device->SetRenderState (D3DRS_CULLMODE, D3DCULL_NONE);
247+ device->SetRenderState (D3DRS_ALPHABLENDENABLE, FALSE );
248+ device->SetRenderState (D3DRS_ALPHATESTENABLE, FALSE );
249+ device->SetRenderState (D3DRS_FOGENABLE, FALSE );
250+ device->SetRenderState (D3DRS_STENCILENABLE, FALSE );
251+ device->SetRenderState (D3DRS_SRGBWRITEENABLE, FALSE );
252+
253+ device->SetPixelShader (m_pixelShader);
254+ device->SetVertexShader (nullptr );
255+ device->SetFVF (SToneMapVertex::FVF);
256+
257+ device->SetTexture (0 , m_sourceTexture);
258+ device->SetSamplerState (0 , D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
259+ device->SetSamplerState (0 , D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
260+ device->SetSamplerState (0 , D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
261+ device->SetSamplerState (0 , D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
262+ device->SetSamplerState (0 , D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
263+ device->SetSamplerState (0 , D3DSAMP_SRGBTEXTURE, FALSE );
264+
265+ IDirect3DStateBlock9* applyBlock = nullptr ;
266+ if (FAILED (device->EndStateBlock (&applyBlock)) || !applyBlock)
267+ {
268+ return false ;
269+ }
270+ m_applyStateBlock = applyBlock;
232271 }
233272
234- m_restoreStateBlock = stateBlock;
235273 return true ;
236274}
237275
@@ -304,40 +342,22 @@ bool BorderlessToneMapPass::Apply(IDirect3DDevice9* device, float gammaPower, fl
304342 return false ;
305343 }
306344
307- // State block is already captured during creation, just apply before drawing
308- device->SetRenderState (D3DRS_ZENABLE, FALSE );
309- device->SetRenderState (D3DRS_ZWRITEENABLE, FALSE );
310- device->SetRenderState (D3DRS_CULLMODE, D3DCULL_NONE);
311- device->SetRenderState (D3DRS_ALPHABLENDENABLE, FALSE );
312- device->SetRenderState (D3DRS_ALPHATESTENABLE, FALSE );
313- device->SetRenderState (D3DRS_FOGENABLE, FALSE );
314- device->SetRenderState (D3DRS_STENCILENABLE, FALSE );
315- device->SetRenderState (D3DRS_SRGBWRITEENABLE, FALSE );
316-
317- device->SetPixelShader (m_pixelShader);
318- device->SetVertexShader (nullptr );
319- device->SetFVF (SToneMapVertex::FVF);
320-
321- device->SetTexture (0 , m_sourceTexture);
322- device->SetSamplerState (0 , D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
323- device->SetSamplerState (0 , D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
324- device->SetSamplerState (0 , D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
325- device->SetSamplerState (0 , D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
326- device->SetSamplerState (0 , D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
327- device->SetSamplerState (0 , D3DSAMP_SRGBTEXTURE, FALSE );
345+ // Apply all rendering state in one call using cached state block
346+ m_applyStateBlock->Apply ();
328347
329348 if (m_constantTable && m_toneParamsHandle)
330349 {
331350 const float toneParams[4 ] = {gammaPower, brightnessScale, contrastScale, saturationScale};
332351 m_constantTable->SetFloatArray (device, m_toneParamsHandle, toneParams, NUMELMS (toneParams));
333352 }
334353
354+ // Pre-compute vertices to avoid per-frame allocation
335355 const float left = -0 .5f ;
336356 const float top = -0 .5f ;
337357 const float right = static_cast <float >(m_width) - 0 .5f ;
338358 const float bottom = static_cast <float >(m_height) - 0 .5f ;
339359
340- const SToneMapVertex vertices[] = {
360+ const SToneMapVertex vertices[6 ] = {
341361 {left, top, 0 .0f , 1 .0f , 0 .0f , 0 .0f },
342362 {right, top, 0 .0f , 1 .0f , 1 .0f , 0 .0f },
343363 {left, bottom, 0 .0f , 1 .0f , 0 .0f , 1 .0f },
@@ -346,7 +366,7 @@ bool BorderlessToneMapPass::Apply(IDirect3DDevice9* device, float gammaPower, fl
346366 {left, bottom, 0 .0f , 1 .0f , 0 .0f , 1 .0f },
347367 };
348368
349- device->DrawPrimitiveUP (D3DPT_TRIANGLELIST, NUMELMS (vertices) / 3 , vertices, sizeof (SToneMapVertex));
369+ device->DrawPrimitiveUP (D3DPT_TRIANGLELIST, 2 , vertices, sizeof (SToneMapVertex));
350370
351371 device->SetPixelShader (nullptr );
352372 device->SetTexture (0 , nullptr );
@@ -364,6 +384,9 @@ void BorderlessToneMapPass::ReleaseTexture()
364384 m_width = 0 ;
365385 m_height = 0 ;
366386 m_format = D3DFMT_UNKNOWN;
387+
388+ // Invalidate apply state block since it captured the old texture pointer
389+ SAFE_RELEASE (m_applyStateBlock);
367390}
368391
369392void BorderlessToneMapPass::ReleaseShader ()
@@ -372,11 +395,15 @@ void BorderlessToneMapPass::ReleaseShader()
372395 SAFE_RELEASE (m_constantTable);
373396 m_toneParamsHandle = nullptr ;
374397 m_shaderFailed = false ;
398+
399+ // Invalidate apply state block since it captured the shader pointer
400+ SAFE_RELEASE (m_applyStateBlock);
375401}
376402
377403void BorderlessToneMapPass::ReleaseStateBlock ()
378404{
379405 SAFE_RELEASE (m_restoreStateBlock);
406+ SAFE_RELEASE (m_applyStateBlock);
380407}
381408
382409void BorderlessToneMapPass::Release ()
0 commit comments