D3D9: Add support for D3D9Ex, which has faster flipping and an option for lower latency, and some other stuff.

MANAGED textures are not allowed though so compensate for that by making them dynamic for now.
This commit is contained in:
Henrik Rydgard 2014-09-09 22:28:35 +02:00
parent 8978182a41
commit 422ae62b63
8 changed files with 129 additions and 61 deletions

View File

@ -129,7 +129,17 @@ namespace DX9 {
// by themselves.
ClearBuffer();
// TODO: Check / use D3DCAPS2_DYNAMICTEXTURES?
pD3Ddevice->CreateTexture(512, 272, 1, 0, D3DFMT(D3DFMT_A8R8G8B8), D3DPOOL_MANAGED, &drawPixelsTex_, NULL);
int usage = 0;
D3DPOOL pool = D3DPOOL_MANAGED;
if (pD3DdeviceEx) {
pool = D3DPOOL_DEFAULT;
usage = D3DUSAGE_DYNAMIC;
}
HRESULT hr = pD3Ddevice->CreateTexture(512, 272, 1, usage, D3DFMT(D3DFMT_A8R8G8B8), pool, &drawPixelsTex_, NULL);
if (!hr) {
drawPixelsTex_ = nullptr;
ERROR_LOG(G3D, "Failed to create drawpixels texture");
}
useBufferedRendering_ = g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
}
@ -158,6 +168,10 @@ namespace DX9 {
u8 * convBuf = NULL;
D3DLOCKED_RECT rect;
if (!drawPixelsTex_) {
return;
}
drawPixelsTex_->LockRect(0, &rect, NULL, 0);
convBuf = (u8*)rect.pBits;

View File

@ -1632,7 +1632,13 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, int level, bool rep
pD3Ddevice->SetTexture(0, entry.texture);
} else {
// Create texture
HRESULT hr = pD3Ddevice->CreateTexture(w, h, 1, 0, (D3DFORMAT)D3DFMT(dstFmt), D3DPOOL_MANAGED, &entry.texture, NULL);
D3DPOOL pool = D3DPOOL_MANAGED;
int usage = 0;
if (pD3DdeviceEx) {
pool = D3DPOOL_DEFAULT;
usage = D3DUSAGE_DYNAMIC; // TODO: Switch to using a staging texture?
}
HRESULT hr = pD3Ddevice->CreateTexture(w, h, 1, usage, (D3DFORMAT)D3DFMT(dstFmt), pool, &entry.texture, NULL);
if (FAILED(hr)) {
INFO_LOG(G3D, "Failed to create D3D texture");
} else {

View File

@ -107,7 +107,7 @@ void VertexDecoderDX9::Step_WeightsU16() const
wt[j] *= (1.0f/65535.f);
}
while (j & 3) // Zero additional weights rounding up to 4.
wt[j++] = 0;
wt[j++] = 0.0f;
#else
u16 *wt = (u16 *)(decoded_ + decFmt.w0off);
const u16_le *wdata = (const u16_le*)(ptr_);
@ -124,26 +124,14 @@ void VertexDecoderDX9::Step_WeightsU16() const
// (PSP uses 0.0-2.0 fixed point numbers for weights)
void VertexDecoderDX9::Step_WeightsFloat() const
{
#if 0
float *wt = (float *)(decoded_ + decFmt.w0off);
const float_le *wdata = (const float_le*)(ptr_);
int j;
for (j = 0; j < nweights; j++) {
wt[j] = wdata[j];
}
while (j & 3) // Zero additional weights rounding up to 4.
wt[j++] = 0.0f;
#else
float *wt = (float *)(decoded_ + decFmt.w0off);
u32 *st = (u32 *)wt;
u32 *st = (u32 *)(decoded_ + decFmt.w0off);
const u32_le *wdata = (const u32_le*)(ptr_);
int j;
for (j = 0; j < nweights; j++) {
st[j] = wdata[j];
}
while (j & 3) // Zero additional weights rounding up to 4.
wt[j++] = 0.0f;
#endif
st[j++] = 0;
}
void VertexDecoderDX9::Step_TcU8() const

View File

@ -5,6 +5,7 @@
namespace DX9 {
LPDIRECT3DDEVICE9 pD3Ddevice = NULL;
LPDIRECT3DDEVICE9EX pD3DdeviceEx = NULL;
LPDIRECT3D9 pD3D = NULL;
static const char * vscode =

View File

@ -17,6 +17,7 @@ struct ID3DXConstantTable;
namespace DX9 {
extern LPDIRECT3DDEVICE9 pD3Ddevice;
extern LPDIRECT3DDEVICE9EX pD3DdeviceEx;
extern LPDIRECT3DVERTEXSHADER9 pFramebufferVertexShader; // Vertex Shader
extern LPDIRECT3DPIXELSHADER9 pFramebufferPixelShader; // Pixel Shader

View File

@ -360,34 +360,34 @@ public:
yAxis_(yAxis), yDevice_(yDevice),
curX_(0.0f), curY_(0.0f),
maxCount_(500) {}
void Draw(UIContext &dc) override;
void Update(const InputState &input_state) override;
void Axis(const AxisInput &input) {
if (input.axisId == xAxis_) {
curX_ = input.value;
} else if (input.axisId == yAxis_) {
curY_ = input.value;
}
}
private:
struct Location {
Location() : x(0.0f), y(0.0f) {}
Location(float xx, float yy) : x(xx), y(yy) {}
float x;
float y;
};
int xAxis_;
int yAxis_;
int xDevice_;
int yDevice_;
float curX_;
float curY_;
std::deque<Location> locations_;
int maxCount_;
void Draw(UIContext &dc) override;
void Update(const InputState &input_state) override;
void Axis(const AxisInput &input) {
if (input.axisId == xAxis_) {
curX_ = input.value;
} else if (input.axisId == yAxis_) {
curY_ = input.value;
}
}
private:
struct Location {
Location() : x(0.0f), y(0.0f) {}
Location(float xx, float yy) : x(xx), y(yy) {}
float x;
float y;
};
int xAxis_;
int yAxis_;
int xDevice_;
int yDevice_;
float curX_;
float curY_;
std::deque<Location> locations_;
int maxCount_;
};
void JoystickHistoryView::Draw(UIContext &dc) {

View File

@ -13,9 +13,12 @@
#include "thin3d/thin3d.h"
#include "thin3d/d3dx9_loader.h"
static bool has9Ex = false;
static LPDIRECT3D9 d3d;
static LPDIRECT3D9EX d3dEx;
static int adapterId;
static LPDIRECT3DDEVICE9 device;
static LPDIRECT3DDEVICE9EX deviceEx;
static HDC hDC; // Private GDI Device Context
static HGLRC hRC; // Permanent Rendering Context
static HWND hWnd; // Holds Our Window Handle
@ -26,27 +29,57 @@ static int xres, yres;
static bool enableGLDebug = true;
void D3D9_SwapBuffers() {
device->EndScene();
device->Present(NULL, NULL, NULL, NULL);
device->BeginScene();
if (has9Ex) {
deviceEx->EndScene();
deviceEx->PresentEx(NULL, NULL, NULL, NULL, 0);
deviceEx->BeginScene();
} else {
device->EndScene();
device->Present(NULL, NULL, NULL, NULL);
device->BeginScene();
}
}
Thin3DContext *D3D9_CreateThin3DContext() {
return T3DCreateDX9Context(d3d, adapterId, device);
return T3DCreateDX9Context(d3d, d3dEx, adapterId, device, deviceEx);
}
typedef HRESULT (*DIRECT3DCREATE9EX)(UINT, IDirect3D9Ex**);
bool IsWin7OrLater() {
DWORD version = GetVersion();
DWORD major = (DWORD)(LOBYTE(LOWORD(version)));
DWORD minor = (DWORD)(HIBYTE(LOWORD(version)));
return (major > 6) || ((major == 6) && (minor >= 1));
}
bool D3D9_Init(HWND hWnd, bool windowed, std::string *error_message) {
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!d3d) {
ELOG("Failed to create D3D context");
return false;
DIRECT3DCREATE9EX g_pfnCreate9ex;
HMODULE hD3D9 = LoadLibrary(TEXT("d3d9.dll"));
g_pfnCreate9ex = (DIRECT3DCREATE9EX)GetProcAddress(hD3D9, "Direct3DCreate9Ex");
has9Ex = (g_pfnCreate9ex != NULL);
FreeLibrary(hD3D9);
// For some reason, can't quite get Ex to work right..
// has9Ex = false;
if (has9Ex) {
HRESULT result = Direct3DCreate9Ex(D3D_SDK_VERSION, &d3dEx);
d3d = d3dEx;
if (FAILED(result)) {
ELOG("Failed to create D3D9Ex context");
return false;
}
} else {
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!d3d) {
ELOG("Failed to create D3D context");
return false;
}
}
RECT rc;
GetClientRect(hWnd, &rc);
int xres = rc.right - rc.left;
int yres = rc.bottom - rc.top;
D3DCAPS9 d3dCaps;
D3DDISPLAYMODE d3ddm;
@ -80,6 +113,11 @@ bool D3D9_Init(HWND hWnd, bool windowed, std::string *error_message) {
else
dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
RECT rc;
GetClientRect(hWnd, &rc);
int xres = rc.right - rc.left;
int yres = rc.bottom - rc.top;
D3DPRESENT_PARAMETERS pp;
memset(&pp, 0, sizeof(pp));
pp.BackBufferWidth = xres;
@ -93,21 +131,41 @@ bool D3D9_Init(HWND hWnd, bool windowed, std::string *error_message) {
pp.AutoDepthStencilFormat = D3DFMT_D24S8;
pp.PresentationInterval = (g_Config.bVSync) ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
hr = d3d->CreateDevice(adapterId, D3DDEVTYPE_HAL, hWnd, dwBehaviorFlags, &pp, &device);
if (has9Ex) {
if (windowed && IsWin7OrLater()) {
// This new flip mode gives higher performance.
pp.BackBufferCount = 2;
pp.SwapEffect = D3DSWAPEFFECT_FLIPEX;
}
hr = d3dEx->CreateDeviceEx(adapterId, D3DDEVTYPE_HAL, hWnd, dwBehaviorFlags, &pp, NULL, &deviceEx);
device = deviceEx;
} else {
hr = d3d->CreateDevice(adapterId, D3DDEVTYPE_HAL, hWnd, dwBehaviorFlags, &pp, &device);
}
if (FAILED(hr)) {
ELOG("Failed to create D3D device");
d3d->Release();
if (has9Ex) {
d3dEx->Release();
} else {
d3d->Release();
}
return false;
}
device->BeginScene();
DX9::pD3Ddevice = device;
DX9::pD3DdeviceEx = deviceEx;
LoadD3DX9Dynamic();
DX9::CompileShaders();
DX9::fbo_init();
if (deviceEx && IsWin7OrLater()) {
deviceEx->SetMaximumFrameLatency(1);
}
return true;
}

2
native

@ -1 +1 @@
Subproject commit 3c0d666e90e528a91d76d0d07b312ae76b4d1c63
Subproject commit 33d496d76f529a6b921c4c8fef70e6c5fd2caef7