D3D: Add 3D vision support.

This commit is contained in:
Jules Blok 2014-11-14 00:24:53 +01:00
parent e53705784b
commit a689db0e48
7 changed files with 64 additions and 5 deletions

View File

@ -453,7 +453,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
{
wxFlexGridSizer* const szr_stereo = new wxFlexGridSizer(2, 5, 5);
const wxString stereo_choices[] = { "Off", "Side-by-Side", "Top-and-Bottom", "Anaglyph" };
const wxString stereo_choices[] = { "Off", "Side-by-Side", "Top-and-Bottom", vconfig.backend_info.bSupports3DVision ? "Nvidia 3D Vision" : "Anaglyph" };
szr_stereo->Add(new wxStaticText(page_enh, wxID_ANY, _("Stereoscopic 3D Mode:")), 1, wxALIGN_CENTER_VERTICAL, 0);
szr_stereo->Add(CreateChoice(page_enh, vconfig.iStereoMode, wxGetTranslation(stereo_3d_desc), 4, stereo_choices));

View File

@ -37,7 +37,7 @@ void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned
} // namespace
D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels, unsigned int slices)
D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels, unsigned int slices, D3D11_SUBRESOURCE_DATA* data)
{
ID3D11Texture2D* pTexture = nullptr;
HRESULT hr;
@ -50,7 +50,7 @@ D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D1
else
cpuflags = (D3D11_CPU_ACCESS_FLAG)0;
D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(fmt, width, height, slices, levels, bind, usage, cpuflags);
hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &pTexture);
hr = D3D::device->CreateTexture2D(&texdesc, data, &pTexture);
if (FAILED(hr))
{
PanicAlert("Failed to create texture at %s, line %d: hr=%#x\n", __FILE__, __LINE__, hr);

View File

@ -22,7 +22,7 @@ public:
// or let the texture automatically be created by D3DTexture2D::Create
D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN, bool multisampled = false);
static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1, unsigned int slices = 1);
static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1, unsigned int slices = 1, D3D11_SUBRESOURCE_DATA* data = nullptr);
// reference counting, use AddRef() when creating a new reference and Release() it when you don't need it anymore
void AddRef();

View File

@ -55,6 +55,18 @@ ID3D11DepthStencilState* resetdepthstate = nullptr;
ID3D11RasterizerState* resetraststate = nullptr;
static ID3D11Texture2D* s_screenshot_texture = nullptr;
static D3DTexture2D* s_3d_vision_texture = nullptr;
typedef struct _Nv_Stereo_Image_Header
{
unsigned int dwSignature;
unsigned int dwWidth;
unsigned int dwHeight;
unsigned int dwBPP;
unsigned int dwFlags;
} NVSTEREOIMAGEHEADER, *LPNVSTEREOIMAGEHEADER;
#define NVSTEREO_IMAGE_SIGNATURE 0x4433564e
// GX pipeline state
struct
@ -183,6 +195,24 @@ void CreateScreenshotTexture(const TargetRectangle& rc)
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_screenshot_texture, "staging screenshot texture");
}
void Create3DVisionTexture(int width, int height)
{
// Create a staging texture for 3D vision with signature information in the last row.
// Nvidia 3D Vision supports full SBS, so there is no loss in resolution during this process.
D3D11_SUBRESOURCE_DATA sysData;
sysData.SysMemPitch = 4 * width * 2;
sysData.pSysMem = new u8[(height + 1) * sysData.SysMemPitch];
LPNVSTEREOIMAGEHEADER header = (LPNVSTEREOIMAGEHEADER)((u8*)sysData.pSysMem + height * sysData.SysMemPitch);
header->dwSignature = NVSTEREO_IMAGE_SIGNATURE;
header->dwWidth = width * 2;
header->dwHeight = height + 1;
header->dwBPP = 32;
header->dwFlags = 0;
s_3d_vision_texture = D3DTexture2D::Create(width * 2, height + 1, D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, &sysData);
delete[] sysData.pSysMem;
}
Renderer::Renderer(void *&window_handle)
{
D3D::Create((HWND)window_handle);
@ -776,6 +806,30 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
D3D::context->RSSetViewports(1, &rightVp);
D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma, 1);
}
else if (g_ActiveConfig.iStereoMode == STEREO_3DVISION)
{
if (!s_3d_vision_texture)
Create3DVisionTexture(s_backbuffer_width, s_backbuffer_height);
D3D11_VIEWPORT leftVp = CD3D11_VIEWPORT((float)X, (float)Y, (float)Width, (float)Height);
D3D11_VIEWPORT rightVp = CD3D11_VIEWPORT((float)(X + s_backbuffer_width), (float)Y, (float)Width, (float)Height);
// Render to staging texture which is double the width of the backbuffer
D3D::context->OMSetRenderTargets(1, &s_3d_vision_texture->GetRTV(), nullptr);
D3D::context->RSSetViewports(1, &leftVp);
D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma, 0);
D3D::context->RSSetViewports(1, &rightVp);
D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma, 1);
// Copy the left eye to the backbuffer, if Nvidia 3D Vision is enabled it should
// recognize the signature and automatically include the right eye frame.
D3D11_BOX box = CD3D11_BOX(0, 0, 0, s_backbuffer_width, s_backbuffer_height, 1);
D3D::context->CopySubresourceRegion(D3D::GetBackBuffer()->GetTex(), 0, 0, 0, 0, s_3d_vision_texture->GetTex(), 0, &box);
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), nullptr);
}
else
{
D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma);
@ -972,6 +1026,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
// TODO: Aren't we still holding a reference to the back buffer right now?
D3D::Reset();
SAFE_RELEASE(s_screenshot_texture);
SAFE_RELEASE(s_3d_vision_texture);
s_backbuffer_width = D3D::GetBackBufferWidth();
s_backbuffer_height = D3D::GetBackBufferHeight();
}

View File

@ -80,6 +80,7 @@ void InitBackendInfo()
g_Config.backend_info.bSupportsPrimitiveRestart = true;
g_Config.backend_info.bSupportsOversizedViewports = false;
g_Config.backend_info.bSupportsStereoscopy = true;
g_Config.backend_info.bSupports3DVision = true;
g_Config.backend_info.bSupportsGSInstancing = false;
IDXGIFactory* factory;

View File

@ -139,6 +139,7 @@ static void InitBackendInfo()
//g_Config.backend_info.bSupportsEarlyZ = true; // is gpu dependent and must be set in renderer
g_Config.backend_info.bSupportsOversizedViewports = true;
g_Config.backend_info.bSupportsStereoscopy = true;
g_Config.backend_info.bSupports3DVision = false;
g_Config.backend_info.Adapters.clear();

View File

@ -49,7 +49,8 @@ enum StereoMode
STEREO_OFF = 0,
STEREO_SBS,
STEREO_TAB,
STEREO_ANAGLYPH
STEREO_ANAGLYPH,
STEREO_3DVISION = STEREO_ANAGLYPH
};
// NEVER inherit from this class.
@ -151,6 +152,7 @@ struct VideoConfig final
bool bSupportsPrimitiveRestart;
bool bSupportsOversizedViewports;
bool bSupportsStereoscopy;
bool bSupports3DVision;
bool bSupportsEarlyZ; // needed by PixelShaderGen, so must stay in VideoCommon
bool bSupportsBindingLayout; // Needed by ShaderGen, so must stay in VideoCommon
bool bSupportsBBox;