diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp
index d8cfb12e59..6ccba4251d 100644
--- a/Source/Core/DolphinWX/VideoConfigDiag.cpp
+++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp
@@ -453,9 +453,9 @@ 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", "Anaglyph", "Nvidia 3D Vision" };
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));
+ szr_stereo->Add(CreateChoice(page_enh, vconfig.iStereoMode, wxGetTranslation(stereo_3d_desc), vconfig.backend_info.bSupports3DVision ? 5 : 4, stereo_choices));
wxSlider* const sep_slider = new wxSlider(page_enh, wxID_ANY, vconfig.iStereoSeparation, 0, 100, wxDefaultPosition, wxDefaultSize);
sep_slider->Bind(wxEVT_SLIDER, &VideoConfigDiag::Event_StereoSep, this);
diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj b/Source/Core/VideoBackends/D3D/D3D.vcxproj
index 7ea9e09d07..f70efea502 100644
--- a/Source/Core/VideoBackends/D3D/D3D.vcxproj
+++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj
@@ -43,6 +43,7 @@
+
@@ -66,6 +67,7 @@
+
diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters
index c0158038b2..a83db06c6a 100644
--- a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters
+++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters
@@ -30,6 +30,9 @@
Render
+
+ Render
+
Render
@@ -93,6 +96,9 @@
Render
+
+ Render
+
Render
diff --git a/Source/Core/VideoBackends/D3D/D3DTexture.cpp b/Source/Core/VideoBackends/D3D/D3DTexture.cpp
index e1c94d5974..8c23a4bd2c 100644
--- a/Source/Core/VideoBackends/D3D/D3DTexture.cpp
+++ b/Source/Core/VideoBackends/D3D/D3DTexture.cpp
@@ -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)
+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;
@@ -49,8 +49,8 @@ D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D1
cpuflags = D3D11_CPU_ACCESS_WRITE;
else
cpuflags = (D3D11_CPU_ACCESS_FLAG)0;
- D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(fmt, width, height, 1, levels, bind, usage, cpuflags);
- hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &pTexture);
+ D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(fmt, width, height, slices, levels, bind, usage, cpuflags);
+ 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);
@@ -87,9 +87,9 @@ D3DTexture2D::D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind,
DXGI_FORMAT srv_format, DXGI_FORMAT dsv_format, DXGI_FORMAT rtv_format, bool multisampled)
: ref(1), tex(texptr), srv(nullptr), rtv(nullptr), dsv(nullptr)
{
- D3D11_SRV_DIMENSION srv_dim = multisampled ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
- D3D11_DSV_DIMENSION dsv_dim = multisampled ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
- D3D11_RTV_DIMENSION rtv_dim = multisampled ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
+ D3D11_SRV_DIMENSION srv_dim = multisampled ? D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY : D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ D3D11_DSV_DIMENSION dsv_dim = multisampled ? D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY : D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+ D3D11_RTV_DIMENSION rtv_dim = multisampled ? D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY : D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = CD3D11_SHADER_RESOURCE_VIEW_DESC(srv_dim, srv_format);
D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = CD3D11_DEPTH_STENCIL_VIEW_DESC(dsv_dim, dsv_format);
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = CD3D11_RENDER_TARGET_VIEW_DESC(rtv_dim, rtv_format);
diff --git a/Source/Core/VideoBackends/D3D/D3DTexture.h b/Source/Core/VideoBackends/D3D/D3DTexture.h
index 5c2aa57f4a..6be15b6102 100644
--- a/Source/Core/VideoBackends/D3D/D3DTexture.h
+++ b/Source/Core/VideoBackends/D3D/D3DTexture.h
@@ -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);
+ 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();
diff --git a/Source/Core/VideoBackends/D3D/D3DUtil.cpp b/Source/Core/VideoBackends/D3D/D3DUtil.cpp
index 57524a49d3..50eac8665b 100644
--- a/Source/Core/VideoBackends/D3D/D3DUtil.cpp
+++ b/Source/Core/VideoBackends/D3D/D3DUtil.cpp
@@ -10,6 +10,7 @@
#include "VideoBackends/D3D/D3DShader.h"
#include "VideoBackends/D3D/D3DState.h"
#include "VideoBackends/D3D/D3DUtil.h"
+#include "VideoBackends/D3D/GeometryShaderCache.h"
#include "VideoBackends/D3D/PixelShaderCache.h"
#include "VideoBackends/D3D/VertexShaderCache.h"
@@ -422,20 +423,20 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw
ID3D11SamplerState* linear_copy_sampler = nullptr;
ID3D11SamplerState* point_copy_sampler = nullptr;
-struct STQVertex { float x, y, z, u, v, w; };
-struct STSQVertex { float x, y, z, u, v, w; };
+struct STQVertex { float x, y, z, u, v, w, g; };
+struct STSQVertex { float x, y, z, u, v, w, g; };
struct ClearVertex { float x, y, z; u32 col; };
struct ColVertex { float x, y, z; u32 col; };
struct
{
- float u1, v1, u2, v2, G;
+ float u1, v1, u2, v2, S, G;
} tex_quad_data;
struct
{
MathUtil::Rectangle rdest;
- float u1, v1, u2, v2, G;
+ float u1, v1, u2, v2, S, G;
} tex_sub_quad_data;
struct
@@ -510,9 +511,11 @@ void drawShadedTexQuad(ID3D11ShaderResourceView* texture,
int SourceWidth,
int SourceHeight,
ID3D11PixelShader* PShader,
- ID3D11VertexShader* Vshader,
+ ID3D11VertexShader* VShader,
ID3D11InputLayout* layout,
- float Gamma)
+ ID3D11GeometryShader* GShader,
+ float Gamma,
+ u32 slice)
{
float sw = 1.0f /(float) SourceWidth;
float sh = 1.0f /(float) SourceHeight;
@@ -520,19 +523,21 @@ void drawShadedTexQuad(ID3D11ShaderResourceView* texture,
float u2 = ((float)rSource->right) * sw;
float v1 = ((float)rSource->top) * sh;
float v2 = ((float)rSource->bottom) * sh;
+ float S = (float)slice;
float G = 1.0f / Gamma;
STQVertex coords[4] = {
- {-1.0f, 1.0f, 0.0f, u1, v1, G},
- { 1.0f, 1.0f, 0.0f, u2, v1, G},
- {-1.0f,-1.0f, 0.0f, u1, v2, G},
- { 1.0f,-1.0f, 0.0f, u2, v2, G},
+ {-1.0f, 1.0f, 0.0f, u1, v1, S, G},
+ { 1.0f, 1.0f, 0.0f, u2, v1, S, G},
+ {-1.0f,-1.0f, 0.0f, u1, v2, S, G},
+ { 1.0f,-1.0f, 0.0f, u2, v2, S, G},
};
// only upload the data to VRAM if it changed
if (stq_observer ||
tex_quad_data.u1 != u1 || tex_quad_data.v1 != v1 ||
- tex_quad_data.u2 != u2 || tex_quad_data.v2 != v2 || tex_quad_data.G != G)
+ tex_quad_data.u2 != u2 || tex_quad_data.v2 != v2 ||
+ tex_quad_data.S != S || tex_quad_data.G != G)
{
stq_offset = util_vbuf->AppendData(coords, sizeof(coords), sizeof(STQVertex));
stq_observer = false;
@@ -541,7 +546,8 @@ void drawShadedTexQuad(ID3D11ShaderResourceView* texture,
tex_quad_data.v1 = v1;
tex_quad_data.u2 = u2;
tex_quad_data.v2 = v2;
- tex_quad_data.G = G;
+ tex_quad_data.S = S;
+ tex_quad_data.G = G;
}
UINT stride = sizeof(STQVertex);
UINT offset = 0;
@@ -551,13 +557,16 @@ void drawShadedTexQuad(ID3D11ShaderResourceView* texture,
D3D::stateman->SetVertexBuffer(util_vbuf->GetBuffer(), stride, offset);
D3D::stateman->SetPixelShader(PShader);
D3D::stateman->SetTexture(0, texture);
- D3D::stateman->SetVertexShader(Vshader);
+ D3D::stateman->SetVertexShader(VShader);
+ D3D::stateman->SetGeometryShader(GShader);
D3D::stateman->Apply();
D3D::context->Draw(4, stq_offset);
D3D::stateman->SetTexture(0, nullptr); // immediately unbind the texture
D3D::stateman->Apply();
+
+ D3D::stateman->SetGeometryShader(nullptr);
}
void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
@@ -566,9 +575,11 @@ void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
int SourceHeight,
const MathUtil::Rectangle* rDest,
ID3D11PixelShader* PShader,
- ID3D11VertexShader* Vshader,
+ ID3D11VertexShader* VShader,
ID3D11InputLayout* layout,
- float Gamma)
+ ID3D11GeometryShader* GShader,
+ float Gamma,
+ u32 slice)
{
float sw = 1.0f /(float) SourceWidth;
float sh = 1.0f /(float) SourceHeight;
@@ -576,20 +587,22 @@ void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
float u2 = (rSource->right ) * sw;
float v1 = (rSource->top ) * sh;
float v2 = (rSource->bottom) * sh;
+ float S = (float)slice;
float G = 1.0f / Gamma;
STSQVertex coords[4] = {
- { rDest->left , rDest->bottom, 0.0f, u1, v2, G},
- { rDest->right, rDest->bottom, 0.0f, u2, v2, G},
- { rDest->left , rDest->top , 0.0f, u1, v1, G},
- { rDest->right, rDest->top , 0.0f, u2, v1, G},
+ { rDest->left , rDest->bottom, 0.0f, u1, v2, S, G},
+ { rDest->right, rDest->bottom, 0.0f, u2, v2, S, G},
+ { rDest->left , rDest->top , 0.0f, u1, v1, S, G},
+ { rDest->right, rDest->top , 0.0f, u2, v1, S, G},
};
// only upload the data to VRAM if it changed
if (stsq_observer ||
memcmp(rDest, &tex_sub_quad_data.rdest, sizeof(*rDest)) != 0 ||
tex_sub_quad_data.u1 != u1 || tex_sub_quad_data.v1 != v1 ||
- tex_sub_quad_data.u2 != u2 || tex_sub_quad_data.v2 != v2 || tex_sub_quad_data.G != G)
+ tex_sub_quad_data.u2 != u2 || tex_sub_quad_data.v2 != v2 ||
+ tex_sub_quad_data.S != S || tex_sub_quad_data.G != G)
{
stsq_offset = util_vbuf->AppendData(coords, sizeof(coords), sizeof(STSQVertex));
stsq_observer = false;
@@ -598,6 +611,7 @@ void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
tex_sub_quad_data.v1 = v1;
tex_sub_quad_data.u2 = u2;
tex_sub_quad_data.v2 = v2;
+ tex_sub_quad_data.S = S;
tex_sub_quad_data.G = G;
memcpy(&tex_sub_quad_data.rdest, &rDest, sizeof(rDest));
}
@@ -609,13 +623,16 @@ void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
stateman->SetInputLayout(layout);
stateman->SetTexture(0, texture);
stateman->SetPixelShader(PShader);
- stateman->SetVertexShader(Vshader);
+ stateman->SetVertexShader(VShader);
+ stateman->SetGeometryShader(GShader);
stateman->Apply();
context->Draw(4, stsq_offset);
stateman->SetTexture(0, nullptr); // immediately unbind the texture
stateman->Apply();
+
+ stateman->SetGeometryShader(nullptr);
}
// Fills a certain area of the current render target with the specified color
@@ -645,6 +662,7 @@ void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2)
}
stateman->SetVertexShader(VertexShaderCache::GetClearVertexShader());
+ stateman->SetGeometryShader(g_ActiveConfig.iStereoMode > 0 ? GeometryShaderCache::GetClearGeometryShader() : nullptr);
stateman->SetPixelShader(PixelShaderCache::GetClearProgram());
stateman->SetInputLayout(VertexShaderCache::GetClearInputLayout());
@@ -655,9 +673,11 @@ void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2)
stateman->Apply();
context->Draw(4, cq_offset);
+
+ stateman->SetGeometryShader(nullptr);
}
-void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout)
+void drawClearQuad(u32 Color, float z)
{
ClearVertex coords[4] = {
{-1.0f, 1.0f, z, Color},
@@ -675,9 +695,10 @@ void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexS
clear_quad_data.z = z;
}
- stateman->SetVertexShader(Vshader);
- stateman->SetPixelShader(PShader);
- stateman->SetInputLayout(layout);
+ stateman->SetVertexShader(VertexShaderCache::GetClearVertexShader());
+ stateman->SetGeometryShader(g_ActiveConfig.iStereoMode > 0 ? GeometryShaderCache::GetClearGeometryShader() : nullptr);
+ stateman->SetPixelShader(PixelShaderCache::GetClearProgram());
+ stateman->SetInputLayout(VertexShaderCache::GetClearInputLayout());
UINT stride = sizeof(ClearVertex);
UINT offset = 0;
@@ -686,6 +707,8 @@ void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexS
stateman->Apply();
context->Draw(4, clearq_offset);
+
+ stateman->SetGeometryShader(nullptr);
}
} // namespace D3D
diff --git a/Source/Core/VideoBackends/D3D/D3DUtil.h b/Source/Core/VideoBackends/D3D/D3DUtil.h
index bd47d9ff0e..883f232b28 100644
--- a/Source/Core/VideoBackends/D3D/D3DUtil.h
+++ b/Source/Core/VideoBackends/D3D/D3DUtil.h
@@ -62,17 +62,21 @@ namespace D3D
ID3D11PixelShader* PShader,
ID3D11VertexShader* VShader,
ID3D11InputLayout* layout,
- float Gamma = 1.0f);
+ ID3D11GeometryShader* GShader = nullptr,
+ float Gamma = 1.0f,
+ u32 slice = 0);
void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
const MathUtil::Rectangle* rSource,
int SourceWidth,
int SourceHeight,
const MathUtil::Rectangle* rDest,
ID3D11PixelShader* PShader,
- ID3D11VertexShader* Vshader,
+ ID3D11VertexShader* VShader,
ID3D11InputLayout* layout,
- float Gamma = 1.0f);
- void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout);
+ ID3D11GeometryShader* GShader = nullptr,
+ float Gamma = 1.0f,
+ u32 slice = 0);
+ void drawClearQuad(u32 Color, float z);
void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2);
}
diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp
index aeaaf6b8e8..a1b66dc3e7 100644
--- a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp
+++ b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp
@@ -57,8 +57,10 @@ FramebufferManager::FramebufferManager()
D3D11_TEXTURE2D_DESC texdesc;
HRESULT hr;
+ m_EFBLayers = m_efb.slices = (g_ActiveConfig.iStereoMode > 0) ? 2 : 1;
+
// EFB color texture - primary render target
- texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, 1, 1, D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality);
+ texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, m_efb.slices, 1, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality);
hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &buf);
CHECK(hr==S_OK, "create EFB color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
m_efb.color_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET), DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, (sample_desc.Count > 1));
@@ -69,7 +71,7 @@ FramebufferManager::FramebufferManager()
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetRTV(), "EFB color texture render target view");
// Temporary EFB color texture - used in ReinterpretPixelData
- texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, 1, 1, D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality);
+ texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, m_efb.slices, 1, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality);
hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &buf);
CHECK(hr==S_OK, "create EFB color temp texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
m_efb.color_temp_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET), DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, (sample_desc.Count > 1));
@@ -80,13 +82,13 @@ FramebufferManager::FramebufferManager()
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_temp_tex->GetRTV(), "EFB color temp texture render target view");
// AccessEFB - Sysmem buffer used to retrieve the pixel data from color_tex
- texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ);
+ texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, m_efb.slices, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ);
hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &m_efb.color_staging_buf);
CHECK(hr==S_OK, "create EFB color staging buffer (hr=%#x)", hr);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_staging_buf, "EFB color staging texture (used for Renderer::AccessEFB)");
// EFB depth buffer - primary depth buffer
- texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width, target_height, 1, 1, D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality);
+ texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width, target_height, m_efb.slices, 1, D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality);
hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &buf);
CHECK(hr==S_OK, "create EFB depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
m_efb.depth_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE), DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, (sample_desc.Count > 1));
@@ -96,7 +98,7 @@ FramebufferManager::FramebufferManager()
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetSRV(), "EFB depth texture shader resource view");
// Render buffer for AccessEFB (depth data)
- texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 1, 1, 1, 1, D3D11_BIND_RENDER_TARGET);
+ texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 1, 1, m_efb.slices, 1, D3D11_BIND_RENDER_TARGET);
hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &buf);
CHECK(hr==S_OK, "create EFB depth read texture (hr=%#x)", hr);
m_efb.depth_read_texture = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
@@ -105,7 +107,7 @@ FramebufferManager::FramebufferManager()
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_read_texture->GetRTV(), "EFB depth read texture render target view (used in Renderer::AccessEFB)");
// AccessEFB - Sysmem buffer used to retrieve the pixel data from depth_read_texture
- texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 1, 1, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ);
+ texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 1, 1, m_efb.slices, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ);
hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &m_efb.depth_staging_buf);
CHECK(hr==S_OK, "create EFB depth staging buffer (hr=%#x)", hr);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_staging_buf, "EFB depth staging texture (used for Renderer::AccessEFB)");
@@ -113,7 +115,7 @@ FramebufferManager::FramebufferManager()
if (g_ActiveConfig.iMultisampleMode)
{
// Framebuffer resolve textures (color+depth)
- texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, 1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, 1);
+ texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, m_efb.slices, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, 1);
hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &buf);
m_efb.resolved_color_tex = new D3DTexture2D(buf, D3D11_BIND_SHADER_RESOURCE, DXGI_FORMAT_R8G8B8A8_UNORM);
CHECK(m_efb.resolved_color_tex!=nullptr, "create EFB color resolve texture (size: %dx%d)", target_width, target_height);
@@ -121,7 +123,7 @@ FramebufferManager::FramebufferManager()
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.resolved_color_tex->GetTex(), "EFB color resolve texture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.resolved_color_tex->GetSRV(), "EFB color resolve texture shader resource view");
- texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width, target_height, 1, 1, D3D11_BIND_SHADER_RESOURCE);
+ texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width, target_height, m_efb.slices, 1, D3D11_BIND_SHADER_RESOURCE);
hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &buf);
CHECK(hr==S_OK, "create EFB depth resolve texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
m_efb.resolved_depth_tex = new D3DTexture2D(buf, D3D11_BIND_SHADER_RESOURCE, DXGI_FORMAT_R24_UNORM_X8_TYPELESS);
@@ -162,7 +164,7 @@ XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, un
{
return new XFBSource(D3DTexture2D::Create(target_width, target_height,
(D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE),
- D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM));
+ D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM, 1, FramebufferManager::GetEFBLayers()), FramebufferManager::GetEFBLayers());
}
void FramebufferManager::GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc)
@@ -206,7 +208,7 @@ void XFBSource::CopyEFB(float Gamma)
D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), sourceRc.AsRECT(),
Renderer::GetTargetWidth(), Renderer::GetTargetHeight(),
PixelShaderCache::GetColorCopyProgram(true), VertexShaderCache::GetSimpleVertexShader(),
- VertexShaderCache::GetSimpleInputLayout(),Gamma);
+ VertexShaderCache::GetSimpleInputLayout(), nullptr, Gamma);
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(),
FramebufferManager::GetEFBDepthTexture()->GetDSV());
diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.h b/Source/Core/VideoBackends/D3D/FramebufferManager.h
index 45f43f7357..d7961cb9b8 100644
--- a/Source/Core/VideoBackends/D3D/FramebufferManager.h
+++ b/Source/Core/VideoBackends/D3D/FramebufferManager.h
@@ -45,7 +45,7 @@ namespace DX11 {
struct XFBSource : public XFBSourceBase
{
- XFBSource(D3DTexture2D *_tex) : tex(_tex) {}
+ XFBSource(D3DTexture2D *_tex, int slices) : tex(_tex), m_slices(slices) {}
~XFBSource() { tex->Release(); }
void Draw(const MathUtil::Rectangle &sourcerc,
@@ -54,6 +54,7 @@ struct XFBSource : public XFBSourceBase
void CopyEFB(float Gamma) override;
D3DTexture2D* const tex;
+ const int m_slices;
};
class FramebufferManager : public FramebufferManagerBase
@@ -99,6 +100,8 @@ private:
D3DTexture2D* resolved_color_tex;
D3DTexture2D* resolved_depth_tex;
+
+ int slices;
} m_efb;
};
diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp
new file mode 100644
index 0000000000..29172f91a1
--- /dev/null
+++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp
@@ -0,0 +1,243 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include
+
+#include "Common/FileUtil.h"
+#include "Common/LinearDiskCache.h"
+#include "Common/StringUtil.h"
+
+#include "Core/ConfigManager.h"
+
+#include "VideoBackends/D3D/D3DBase.h"
+#include "VideoBackends/D3D/D3DShader.h"
+#include "VideoBackends/D3D/GeometryShaderCache.h"
+#include "VideoBackends/D3D/Globals.h"
+
+#include "VideoCommon/Debugger.h"
+#include "VideoCommon/GeometryShaderGen.h"
+#include "VideoCommon/VideoConfig.h"
+
+namespace DX11
+{
+
+GeometryShaderCache::GSCache GeometryShaderCache::GeometryShaders;
+const GeometryShaderCache::GSCacheEntry* GeometryShaderCache::last_entry;
+GeometryShaderUid GeometryShaderCache::last_uid;
+UidChecker GeometryShaderCache::geometry_uid_checker;
+
+ID3D11GeometryShader* ClearGeometryShader = nullptr;
+ID3D11GeometryShader* CopyGeometryShader = nullptr;
+
+LinearDiskCache g_gs_disk_cache;
+
+ID3D11GeometryShader* GeometryShaderCache::GetClearGeometryShader() { return ClearGeometryShader; }
+ID3D11GeometryShader* GeometryShaderCache::GetCopyGeometryShader() { return CopyGeometryShader; }
+
+ID3D11Buffer* gscbuf = nullptr;
+
+// this class will load the precompiled shaders into our cache
+class GeometryShaderCacheInserter : public LinearDiskCacheReader
+{
+public:
+ void Read(const GeometryShaderUid &key, const u8* value, u32 value_size)
+ {
+ GeometryShaderCache::InsertByteCode(key, value, value_size);
+ }
+};
+
+const char clear_shader_code[] = {
+ "struct VSOUTPUT\n"
+ "{\n"
+ "float4 vPosition : POSITION;\n"
+ "float4 vColor0 : COLOR0;\n"
+ "};\n"
+ "struct GSOUTPUT\n"
+ "{\n"
+ "float4 vPosition : POSITION;\n"
+ "float4 vColor0 : COLOR0;\n"
+ "uint slice : SV_RenderTargetArrayIndex;\n"
+ "};\n"
+ "[maxvertexcount(6)]\n"
+ "void main(triangle VSOUTPUT o[3], inout TriangleStream Output)\n"
+ "{\n"
+ "for(int slice = 0; slice < 2; slice++)\n"
+ "{\n"
+ "for(int i = 0; i < 3; i++)\n"
+ "{\n"
+ "GSOUTPUT OUT;\n"
+ "OUT.vPosition = o[i].vPosition;\n"
+ "OUT.vColor0 = o[i].vColor0;\n"
+ "OUT.slice = slice;\n"
+ "Output.Append(OUT);\n"
+ "}\n"
+ "Output.RestartStrip();\n"
+ "}\n"
+ "}\n"
+};
+
+const char copy_shader_code[] = {
+ "struct VSOUTPUT\n"
+ "{\n"
+ "float4 vPosition : POSITION;\n"
+ "float3 vTexCoord : TEXCOORD0;\n"
+ "float vTexCoord1 : TEXCOORD1;\n"
+ "};\n"
+ "struct GSOUTPUT\n"
+ "{\n"
+ "float4 vPosition : POSITION;\n"
+ "float3 vTexCoord : TEXCOORD0;\n"
+ "float vTexCoord1 : TEXCOORD1;\n"
+ "uint slice : SV_RenderTargetArrayIndex;\n"
+ "};\n"
+ "[maxvertexcount(6)]\n"
+ "void main(triangle VSOUTPUT o[3], inout TriangleStream Output)\n"
+ "{\n"
+ "for(int slice = 0; slice < 2; slice++)\n"
+ "{\n"
+ "for(int i = 0; i < 3; i++)\n"
+ "{\n"
+ "GSOUTPUT OUT;\n"
+ "OUT.vPosition = o[i].vPosition;\n"
+ "OUT.vTexCoord = o[i].vTexCoord;\n"
+ "OUT.vTexCoord.z = slice;\n"
+ "OUT.vTexCoord1 = o[i].vTexCoord1;\n"
+ "OUT.slice = slice;\n"
+ "Output.Append(OUT);\n"
+ "}\n"
+ "Output.RestartStrip();\n"
+ "}\n"
+ "}\n"
+};
+
+void GeometryShaderCache::Init()
+{
+ // used when drawing clear quads
+ ClearGeometryShader = D3D::CompileAndCreateGeometryShader(clear_shader_code);
+ CHECK(ClearGeometryShader != nullptr, "Create clear geometry shader");
+ D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearGeometryShader, "clear geometry shader");
+
+ // used for buffer copy
+ CopyGeometryShader = D3D::CompileAndCreateGeometryShader(copy_shader_code);
+ CHECK(CopyGeometryShader != nullptr, "Create copy geometry shader");
+ D3D::SetDebugObjectName((ID3D11DeviceChild*)CopyGeometryShader, "copy geometry shader");
+
+ Clear();
+
+ if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
+ File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
+
+ std::string cache_filename = StringFromFormat("%sdx11-%s-gs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
+ SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
+ GeometryShaderCacheInserter inserter;
+ g_gs_disk_cache.OpenAndRead(cache_filename, inserter);
+
+ if (g_Config.bEnableShaderDebugging)
+ Clear();
+
+ last_entry = nullptr;
+}
+
+// ONLY to be used during shutdown.
+void GeometryShaderCache::Clear()
+{
+ for (auto& iter : GeometryShaders)
+ iter.second.Destroy();
+ GeometryShaders.clear();
+ geometry_uid_checker.Invalidate();
+
+ last_entry = nullptr;
+}
+
+void GeometryShaderCache::Shutdown()
+{
+ SAFE_RELEASE(ClearGeometryShader);
+ SAFE_RELEASE(CopyGeometryShader);
+
+ Clear();
+ g_gs_disk_cache.Sync();
+ g_gs_disk_cache.Close();
+}
+
+bool GeometryShaderCache::SetShader(u32 components)
+{
+ GeometryShaderUid uid;
+ GetGeometryShaderUid(uid, components, API_D3D);
+ if (g_ActiveConfig.bEnableShaderDebugging)
+ {
+ ShaderCode code;
+ GenerateGeometryShaderCode(code, components, API_D3D);
+ geometry_uid_checker.AddToIndexAndCheck(code, uid, "Geometry", "g");
+ }
+
+ // Check if the shader is already set
+ if (last_entry)
+ {
+ if (uid == last_uid)
+ {
+ GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true);
+ return (last_entry->shader != nullptr);
+ }
+ }
+
+ last_uid = uid;
+
+ // Check if the shader is already in the cache
+ GSCache::iterator iter;
+ iter = GeometryShaders.find(uid);
+ if (iter != GeometryShaders.end())
+ {
+ const GSCacheEntry &entry = iter->second;
+ last_entry = &entry;
+
+ return (entry.shader != nullptr);
+ }
+
+ // Need to compile a new shader
+ ShaderCode code;
+ GenerateGeometryShaderCode(code, components, API_D3D);
+
+ D3DBlob* pbytecode;
+ if (!D3D::CompileGeometryShader(code.GetBuffer(), &pbytecode))
+ {
+ GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
+ return false;
+ }
+
+ // Insert the bytecode into the caches
+ g_gs_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size());
+
+ bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size());
+ pbytecode->Release();
+
+ if (g_ActiveConfig.bEnableShaderDebugging && success)
+ {
+ GeometryShaders[uid].code = code.GetBuffer();
+ }
+
+ return success;
+}
+
+bool GeometryShaderCache::InsertByteCode(const GeometryShaderUid &uid, const void* bytecode, unsigned int bytecodelen)
+{
+ ID3D11GeometryShader* shader = D3D::CreateGeometryShaderFromByteCode(bytecode, bytecodelen);
+ if (shader == nullptr)
+ return false;
+
+ // TODO: Somehow make the debug name a bit more specific
+ D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a pixel shader of GeometryShaderCache");
+
+ // Make an entry in the table
+ GSCacheEntry newentry;
+ newentry.shader = shader;
+ GeometryShaders[uid] = newentry;
+ last_entry = &GeometryShaders[uid];
+
+ if (!shader)
+ return false;
+
+ return true;
+}
+
+} // DX11
diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h
new file mode 100644
index 0000000000..9d38922d04
--- /dev/null
+++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h
@@ -0,0 +1,49 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+#include