Improve performance in Surface::swap

TRAC #12145 - Create the flip RT texture once. - Use state blocks for swap and restore all previous state. Signed-off-by: Nicolas Capens Signed-off-by: Daniel Koch Author: Andrew Lewycky git-svn-id: https://angleproject.googlecode.com/svn/trunk@256 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 4fa08339
...@@ -22,6 +22,9 @@ Surface::Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurf ...@@ -22,6 +22,9 @@ Surface::Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurf
{ {
mBackBuffer = NULL; mBackBuffer = NULL;
mRenderTarget = NULL; mRenderTarget = NULL;
mFlipTexture = NULL;
mFlipState = NULL;
mPreFlipState = NULL;
mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
mRenderBuffer = EGL_BACK_BUFFER; mRenderBuffer = EGL_BACK_BUFFER;
...@@ -49,6 +52,19 @@ Surface::Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurf ...@@ -49,6 +52,19 @@ Surface::Surface(Display *display, IDirect3DSwapChain9 *swapChain, IDirect3DSurf
} }
ASSERT(SUCCEEDED(result)); ASSERT(SUCCEEDED(result));
result = device->CreateTexture(mWidth, mHeight, 1, D3DUSAGE_RENDERTARGET, description.Format, D3DPOOL_DEFAULT, &mFlipTexture, NULL);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
error(EGL_BAD_ALLOC);
mRenderTarget->Release();
return;
}
} }
} }
...@@ -73,6 +89,21 @@ Surface::~Surface() ...@@ -73,6 +89,21 @@ Surface::~Surface()
{ {
mDepthStencil->Release(); mDepthStencil->Release();
} }
if (mFlipTexture)
{
mFlipTexture->Release();
}
if (mFlipState)
{
mFlipState->Release();
}
if (mPreFlipState)
{
mPreFlipState->Release();
}
} }
HWND Surface::getWindowHandle() HWND Surface::getWindowHandle()
...@@ -88,55 +119,121 @@ HWND Surface::getWindowHandle() ...@@ -88,55 +119,121 @@ HWND Surface::getWindowHandle()
return NULL; return NULL;
} }
void Surface::swap() void Surface::writeRecordableFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source)
{ {
if (mSwapChain) // Disable all pipeline operations
device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
device->SetPixelShader(NULL);
device->SetVertexShader(NULL);
// Just sample the texture
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
device->SetTexture(0, source);
device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
}
void Surface::applyFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source)
{
HRESULT hr;
if (mFlipState == NULL)
{ {
IDirect3DDevice9 *device = mDisplay->getDevice(); // Create two state blocks both recording the states that are changed when swapping.
D3DSURFACE_DESC description;
mBackBuffer->GetDesc(&description);
// Copy the render target into a texture // mPreFlipState will record the original state each entry.
IDirect3DTexture9 *texture; hr = device->BeginStateBlock();
HRESULT result = device->CreateTexture(mWidth, mHeight, 1, D3DUSAGE_RENDERTARGET, description.Format, D3DPOOL_DEFAULT, &texture, NULL); ASSERT(SUCCEEDED(hr));
writeRecordableFlipState(device, source);
hr = device->EndStateBlock(&mPreFlipState);
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) if (SUCCEEDED(hr))
{ {
return error(EGL_BAD_ALLOC); mPreFlipState->Capture();
} }
ASSERT(SUCCEEDED(result)); // mFlipState will record the state for the swap operation.
hr = device->BeginStateBlock();
ASSERT(SUCCEEDED(hr));
writeRecordableFlipState(device, source);
hr = device->EndStateBlock(&mFlipState);
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
if (FAILED(hr))
{
mFlipState = NULL;
mPreFlipState->Release();
mPreFlipState = NULL;
}
else
{
hr = mFlipState->Apply();
ASSERT(SUCCEEDED(hr));
}
}
else
{
hr = mPreFlipState->Capture();
ASSERT(SUCCEEDED(hr));
hr = mFlipState->Apply();
ASSERT(SUCCEEDED(hr));
}
device->GetRenderTarget(0, &mPreFlipBackBuffer);
device->GetDepthStencilSurface(&mPreFlipDepthStencil);
device->SetRenderTarget(0, mBackBuffer);
device->SetDepthStencilSurface(NULL);
}
void Surface::restoreState(IDirect3DDevice9 *device)
{
mPreFlipState->Apply();
device->SetRenderTarget(0, mPreFlipBackBuffer);
device->SetDepthStencilSurface(mPreFlipDepthStencil);
if (mPreFlipBackBuffer)
{
mPreFlipBackBuffer->Release();
mPreFlipBackBuffer = NULL;
}
if (mPreFlipDepthStencil)
{
mPreFlipDepthStencil->Release();
mPreFlipDepthStencil = NULL;
}
}
void Surface::swap()
{
if (mSwapChain)
{
IDirect3DDevice9 *device = mDisplay->getDevice();
IDirect3DSurface9 *textureSurface; IDirect3DSurface9 *textureSurface;
texture->GetSurfaceLevel(0, &textureSurface); mFlipTexture->GetSurfaceLevel(0, &textureSurface);
mDisplay->endScene(); mDisplay->endScene();
device->StretchRect(mRenderTarget, NULL, textureSurface, NULL, D3DTEXF_NONE); device->StretchRect(mRenderTarget, NULL, textureSurface, NULL, D3DTEXF_NONE);
// Disable all pipeline operations applyFlipState(device, mFlipTexture);
device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
device->SetRenderState(D3DRS_ALPHATESTENABLE , FALSE);
device->SetRenderState(D3DRS_ALPHABLENDENABLE , FALSE);
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
device->SetPixelShader(NULL);
device->SetVertexShader(NULL);
// Just sample the texture
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
device->SetTexture(0, texture);
device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
device->SetRenderTarget(0, mBackBuffer);
device->SetDepthStencilSurface(NULL);
// Render the texture upside down into the back buffer // Render the texture upside down into the back buffer
float quad[4][6] = {{ 0 - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f}, float quad[4][6] = {{ 0 - 0.5f, 0 - 0.5f, 0.0f, 1.0f, 0.0f, 1.0f},
...@@ -148,10 +245,11 @@ void Surface::swap() ...@@ -148,10 +245,11 @@ void Surface::swap()
device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
textureSurface->Release(); textureSurface->Release();
texture->Release();
restoreState(device);
mDisplay->endScene(); mDisplay->endScene();
result = mSwapChain->Present(NULL, NULL, NULL, NULL, mDisplay->getPresentInterval()); HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, mDisplay->getPresentInterval());
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
{ {
......
...@@ -40,11 +40,21 @@ class Surface ...@@ -40,11 +40,21 @@ class Surface
private: private:
DISALLOW_COPY_AND_ASSIGN(Surface); DISALLOW_COPY_AND_ASSIGN(Surface);
Display *const mDisplay; Display *const mDisplay;
IDirect3DSwapChain9 *const mSwapChain; IDirect3DSwapChain9 *const mSwapChain;
IDirect3DSurface9 *mBackBuffer; IDirect3DSurface9 *mBackBuffer;
IDirect3DSurface9 *mRenderTarget; IDirect3DSurface9 *mRenderTarget;
IDirect3DSurface9 *mDepthStencil; IDirect3DSurface9 *mDepthStencil;
IDirect3DTexture9 *mFlipTexture;
void applyFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source);
void restoreState(IDirect3DDevice9 *device);
void writeRecordableFlipState(IDirect3DDevice9 *device, IDirect3DTexture9 *source);
IDirect3DStateBlock9 *mFlipState;
IDirect3DStateBlock9 *mPreFlipState;
IDirect3DSurface9 *mPreFlipBackBuffer;
IDirect3DSurface9 *mPreFlipDepthStencil;
const egl::Config *mConfig; // EGL config surface was created with const egl::Config *mConfig; // EGL config surface was created with
EGLint mHeight; // Height of surface EGLint mHeight; // Height of surface
......
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