Merge pull request #1612 from Armada651/d3d-stereo-3d

D3D: Add geometry shader stereoscopy support.
This commit is contained in:
Dolphin Bot 2014-12-14 13:42:45 +01:00
commit 21ac9aa715
28 changed files with 680 additions and 165 deletions

View File

@ -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);

View File

@ -43,6 +43,7 @@
<ClCompile Include="D3DTexture.cpp" />
<ClCompile Include="D3DUtil.cpp" />
<ClCompile Include="FramebufferManager.cpp" />
<ClCompile Include="GeometryShaderCache.cpp" />
<ClCompile Include="LineGeometryShader.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="NativeVertexFormat.cpp" />
@ -66,6 +67,7 @@
<ClInclude Include="D3DTexture.h" />
<ClInclude Include="D3DUtil.h" />
<ClInclude Include="FramebufferManager.h" />
<ClInclude Include="GeometryShaderCache.h" />
<ClInclude Include="Globals.h" />
<ClInclude Include="LineGeometryShader.h" />
<ClInclude Include="main.h" />

View File

@ -30,6 +30,9 @@
<ClCompile Include="FramebufferManager.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="GeometryShaderCache.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="LineGeometryShader.cpp">
<Filter>Render</Filter>
</ClCompile>
@ -93,6 +96,9 @@
<ClInclude Include="FramebufferManager.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="GeometryShaderCache.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="LineGeometryShader.h">
<Filter>Render</Filter>
</ClInclude>

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)
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);

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);
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

@ -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<float> 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<float>* 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

View File

@ -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<int>* rSource,
int SourceWidth,
int SourceHeight,
const MathUtil::Rectangle<float>* 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);
}

View File

@ -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());

View File

@ -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<int> &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;
};

View File

@ -0,0 +1,243 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <string>
#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<GeometryShaderUid,ShaderCode> GeometryShaderCache::geometry_uid_checker;
ID3D11GeometryShader* ClearGeometryShader = nullptr;
ID3D11GeometryShader* CopyGeometryShader = nullptr;
LinearDiskCache<GeometryShaderUid, u8> 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<GeometryShaderUid, u8>
{
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<GSOUTPUT> 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<GSOUTPUT> 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

View File

@ -0,0 +1,49 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include <d3d11.h>
#include <map>
#include "VideoCommon/GeometryShaderGen.h"
namespace DX11
{
class GeometryShaderCache
{
public:
static void Init();
static void Clear();
static void Shutdown();
static bool SetShader(u32 components); // TODO: Should be renamed to LoadShader
static bool InsertByteCode(const GeometryShaderUid &uid, const void* bytecode, unsigned int bytecodelen);
static ID3D11GeometryShader* GeometryShaderCache::GetClearGeometryShader();
static ID3D11GeometryShader* GeometryShaderCache::GetCopyGeometryShader();
static ID3D11GeometryShader* GetActiveShader() { return last_entry->shader; }
private:
struct GSCacheEntry
{
ID3D11GeometryShader* shader;
std::string code;
GSCacheEntry() : shader(nullptr) {}
void Destroy() { SAFE_RELEASE(shader); }
};
typedef std::map<GeometryShaderUid, GSCacheEntry> GSCache;
static GSCache GeometryShaders;
static const GSCacheEntry* last_entry;
static GeometryShaderUid last_uid;
static UidChecker<GeometryShaderUid, ShaderCode> geometry_uid_checker;
};
} // namespace DX11

View File

@ -173,7 +173,7 @@ bool LineGeometryShader::SetShader(u32 components, float lineWidth,
static char buffer[16384];
ShaderCode code;
code.SetBuffer(buffer);
GenerateVSOutputStruct(code, API_D3D);
GenerateVSOutputStruct<ShaderCode>(code, API_D3D);
code.Write("\n%s", LINE_GS_COMMON);
std::stringstream numTexCoordsStream;

View File

@ -100,7 +100,7 @@ static const char EFB_ENCODE_PS[] =
"} Params;\n"
"}\n"
"Texture2D EFBTexture : register(t0);\n"
"Texture2DArray EFBTexture : register(t0);\n"
"sampler EFBSampler : register(s0);\n"
// Constants
@ -183,7 +183,7 @@ static const char EFB_ENCODE_PS[] =
"float4 Fetch_0(float2 coord)\n"
"{\n"
"float2 texCoord = CalcTexCoord(coord);\n"
"float4 result = EFBTexture.Sample(EFBSampler, texCoord);\n"
"float4 result = EFBTexture.Sample(EFBSampler, float3(texCoord.xy, 0.0));\n"
"result.a = 1.0;\n"
"return result;\n"
"}\n"
@ -191,13 +191,13 @@ static const char EFB_ENCODE_PS[] =
"float4 Fetch_1(float2 coord)\n"
"{\n"
"float2 texCoord = CalcTexCoord(coord);\n"
"return EFBTexture.Sample(EFBSampler, texCoord);\n"
"return EFBTexture.Sample(EFBSampler, float3(texCoord.xy, 0.0));\n"
"}\n"
"float4 Fetch_2(float2 coord)\n"
"{\n"
"float2 texCoord = CalcTexCoord(coord);\n"
"float4 result = EFBTexture.Sample(EFBSampler, texCoord);\n"
"float4 result = EFBTexture.Sample(EFBSampler, float3(texCoord.xy, 0.0));\n"
"result.a = 1.0;\n"
"return result;\n"
"}\n"
@ -206,7 +206,7 @@ static const char EFB_ENCODE_PS[] =
"{\n"
"float2 texCoord = CalcTexCoord(coord);\n"
"uint depth24 = 0xFFFFFF * EFBTexture.Sample(EFBSampler, texCoord).r;\n"
"uint depth24 = 0xFFFFFF * EFBTexture.Sample(EFBSampler, float3(texCoord.xy, 0.0)).r;\n"
"uint4 bytes = uint4(\n"
"(depth24 >> 16) & 0xFF,\n" // r
"(depth24 >> 8) & 0xFF,\n" // g

View File

@ -35,6 +35,7 @@ ID3D11PixelShader* s_ColorMatrixProgram[2] = {nullptr};
ID3D11PixelShader* s_ColorCopyProgram[2] = {nullptr};
ID3D11PixelShader* s_DepthMatrixProgram[2] = {nullptr};
ID3D11PixelShader* s_ClearProgram = nullptr;
ID3D11PixelShader* s_AnaglyphProgram = nullptr;
ID3D11PixelShader* s_rgba6_to_rgb8[2] = {nullptr};
ID3D11PixelShader* s_rgb8_to_rgba6[2] = {nullptr};
ID3D11Buffer* pscbuf = nullptr;
@ -51,40 +52,53 @@ const char clear_program_code[] = {
// TODO: Find some way to avoid having separate shaders for non-MSAA and MSAA...
const char color_copy_program_code[] = {
"sampler samp0 : register(s0);\n"
"Texture2D Tex0 : register(t0);\n"
"Texture2DArray Tex0 : register(t0);\n"
"void main(\n"
"out float4 ocol0 : SV_Target,\n"
"in float4 pos : SV_Position,\n"
"in float2 uv0 : TEXCOORD0){\n"
"in float3 uv0 : TEXCOORD0){\n"
"ocol0 = Tex0.Sample(samp0,uv0);\n"
"}\n"
};
const char anaglyph_program_code[] = {
"sampler samp0 : register(s0);\n"
"Texture2DArray Tex0 : register(t0);\n"
"void main(\n"
"out float4 ocol0 : SV_Target,\n"
"in float4 pos : SV_Position,\n"
"in float3 uv0 : TEXCOORD0){\n"
"float4 c0 = Tex0.Sample(samp0, float3(uv0.xy, 0.0));\n"
"float4 c1 = Tex0.Sample(samp0, float3(uv0.xy, 1));\n"
"ocol0 = float4(pow(0.7 * c0.g + 0.3 * c0.b, 1.5), c1.gba);"
"}\n"
};
// TODO: Improve sampling algorithm!
const char color_copy_program_code_msaa[] = {
"sampler samp0 : register(s0);\n"
"Texture2DMS<float4, %d> Tex0 : register(t0);\n"
"Texture2DMSArray<float4, %d> Tex0 : register(t0);\n"
"void main(\n"
"out float4 ocol0 : SV_Target,\n"
"in float4 pos : SV_Position,\n"
"in float2 uv0 : TEXCOORD0){\n"
"int width, height, samples;\n"
"Tex0.GetDimensions(width, height, samples);\n"
"in float3 uv0 : TEXCOORD0){\n"
"int width, height, slices, samples;\n"
"Tex0.GetDimensions(width, height, slices, samples);\n"
"ocol0 = 0;\n"
"for(int i = 0; i < samples; ++i)\n"
" ocol0 += Tex0.Load(int2(uv0.x*(width), uv0.y*(height)), i);\n"
" ocol0 += Tex0.Load(int3(uv0.x*(width), uv0.y*(height), uv0.z), i);\n"
"ocol0 /= samples;\n"
"}\n"
};
const char color_matrix_program_code[] = {
"sampler samp0 : register(s0);\n"
"Texture2D Tex0 : register(t0);\n"
"Texture2DArray Tex0 : register(t0);\n"
"uniform float4 cColMatrix[7] : register(c0);\n"
"void main(\n"
"out float4 ocol0 : SV_Target,\n"
"in float4 pos : SV_Position,\n"
" in float2 uv0 : TEXCOORD0){\n"
"in float3 uv0 : TEXCOORD0){\n"
"float4 texcol = Tex0.Sample(samp0,uv0);\n"
"texcol = round(texcol * cColMatrix[5])*cColMatrix[6];\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
@ -93,17 +107,17 @@ const char color_matrix_program_code[] = {
const char color_matrix_program_code_msaa[] = {
"sampler samp0 : register(s0);\n"
"Texture2DMS<float4, %d> Tex0 : register(t0);\n"
"Texture2DMSArray<float4, %d> Tex0 : register(t0);\n"
"uniform float4 cColMatrix[7] : register(c0);\n"
"void main(\n"
"out float4 ocol0 : SV_Target,\n"
"in float4 pos : SV_Position,\n"
" in float2 uv0 : TEXCOORD0){\n"
"int width, height, samples;\n"
"Tex0.GetDimensions(width, height, samples);\n"
"in float3 uv0 : TEXCOORD0){\n"
"int width, height, slices, samples;\n"
"Tex0.GetDimensions(width, height, slices, samples);\n"
"float4 texcol = 0;\n"
"for(int i = 0; i < samples; ++i)\n"
" texcol += Tex0.Load(int2(uv0.x*(width), uv0.y*(height)), i);\n"
" texcol += Tex0.Load(int3(uv0.x*(width), uv0.y*(height), uv0.z), i);\n"
"texcol /= samples;\n"
"texcol = round(texcol * cColMatrix[5])*cColMatrix[6];\n"
"ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n"
@ -112,12 +126,12 @@ const char color_matrix_program_code_msaa[] = {
const char depth_matrix_program[] = {
"sampler samp0 : register(s0);\n"
"Texture2D Tex0 : register(t0);\n"
"Texture2DArray Tex0 : register(t0);\n"
"uniform float4 cColMatrix[7] : register(c0);\n"
"void main(\n"
"out float4 ocol0 : SV_Target,\n"
" in float4 pos : SV_Position,\n"
" in float2 uv0 : TEXCOORD0){\n"
" in float3 uv0 : TEXCOORD0){\n"
" float4 texcol = Tex0.Sample(samp0,uv0);\n"
// 255.99998474121 = 16777215/16777216*256
@ -147,17 +161,17 @@ const char depth_matrix_program[] = {
const char depth_matrix_program_msaa[] = {
"sampler samp0 : register(s0);\n"
"Texture2DMS<float4, %d> Tex0 : register(t0);\n"
"Texture2DMSArray<float4, %d> Tex0 : register(t0);\n"
"uniform float4 cColMatrix[7] : register(c0);\n"
"void main(\n"
"out float4 ocol0 : SV_Target,\n"
" in float4 pos : SV_Position,\n"
" in float2 uv0 : TEXCOORD0){\n"
" int width, height, samples;\n"
" Tex0.GetDimensions(width, height, samples);\n"
" in float3 uv0 : TEXCOORD0){\n"
" int width, height, slices, samples;\n"
" Tex0.GetDimensions(width, height, slices, samples);\n"
" float4 texcol = 0;\n"
" for(int i = 0; i < samples; ++i)\n"
" texcol += Tex0.Load(int2(uv0.x*(width), uv0.y*(height)), i);\n"
" texcol += Tex0.Load(int3(uv0.x*(width), uv0.y*(height), uv0.z), i);\n"
" texcol /= samples;\n"
// 255.99998474121 = 16777215/16777216*256
@ -385,6 +399,11 @@ ID3D11PixelShader* PixelShaderCache::GetClearProgram()
return s_ClearProgram;
}
ID3D11PixelShader* PixelShaderCache::GetAnaglyphProgram()
{
return s_AnaglyphProgram;
}
ID3D11Buffer* &PixelShaderCache::GetConstantBuffer()
{
// TODO: divide the global variables of the generated shaders into about 5 constant buffers to speed this up
@ -405,7 +424,7 @@ ID3D11Buffer* &PixelShaderCache::GetConstantBuffer()
class PixelShaderCacheInserter : public LinearDiskCacheReader<PixelShaderUid, u8>
{
public:
void Read(const PixelShaderUid &key, const u8 *value, u32 value_size)
void Read(const PixelShaderUid &key, const u8* value, u32 value_size)
{
PixelShaderCache::InsertByteCode(key, value, value_size);
}
@ -424,6 +443,11 @@ void PixelShaderCache::Init()
CHECK(s_ClearProgram!=nullptr, "Create clear pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "clear pixel shader");
// used for anaglyph stereoscopy
s_AnaglyphProgram = D3D::CompileAndCreatePixelShader(anaglyph_program_code);
CHECK(s_AnaglyphProgram != nullptr, "Create anaglyph pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_AnaglyphProgram, "anaglyph pixel shader");
// used when copying/resolving the color buffer
s_ColorCopyProgram[0] = D3D::CompileAndCreatePixelShader(color_copy_program_code);
CHECK(s_ColorCopyProgram[0]!=nullptr, "Create color copy pixel shader");
@ -484,6 +508,7 @@ void PixelShaderCache::Shutdown()
SAFE_RELEASE(pscbuf);
SAFE_RELEASE(s_ClearProgram);
SAFE_RELEASE(s_AnaglyphProgram);
for (int i = 0; i < 2; ++i)
{
SAFE_RELEASE(s_ColorCopyProgram[i]);

View File

@ -30,6 +30,7 @@ public:
static ID3D11PixelShader* GetColorCopyProgram(bool multisampled);
static ID3D11PixelShader* GetDepthMatrixProgram(bool multisampled);
static ID3D11PixelShader* GetClearProgram();
static ID3D11PixelShader* GetAnaglyphProgram();
static ID3D11PixelShader* ReinterpRGBA6ToRGB8(bool multisampled);
static ID3D11PixelShader* ReinterpRGB8ToRGBA6(bool multisampled);

View File

@ -167,7 +167,7 @@ bool PointGeometryShader::SetShader(u32 components, float pointSize,
static char buffer[16384];
ShaderCode code;
code.SetBuffer(buffer);
GenerateVSOutputStruct(code, API_D3D);
GenerateVSOutputStruct<ShaderCode>(code, API_D3D);
code.Write("\n%s", POINT_GS_COMMON);
std::stringstream numTexCoordsStream;

View File

@ -21,6 +21,7 @@
#include "VideoBackends/D3D/D3DState.h"
#include "VideoBackends/D3D/D3DUtil.h"
#include "VideoBackends/D3D/FramebufferManager.h"
#include "VideoBackends/D3D/GeometryShaderCache.h"
#include "VideoBackends/D3D/PixelShaderCache.h"
#include "VideoBackends/D3D/Render.h"
#include "VideoBackends/D3D/Television.h"
@ -46,6 +47,7 @@ static u32 s_LastAA = 0;
static Television s_television;
static bool s_last_fullscreen_mode = false;
static bool s_LastStereo = 0;
ID3D11Buffer* access_efb_cbuf = nullptr;
ID3D11BlendState* clearblendstates[4] = {nullptr};
@ -55,6 +57,19 @@ ID3D11DepthStencilState* resetdepthstate = nullptr;
ID3D11RasterizerState* resetraststate = nullptr;
static ID3D11Texture2D* s_screenshot_texture = nullptr;
static D3DTexture2D* s_3d_vision_texture = nullptr;
// Nvidia stereo blitting struct defined in "nvstereo.h" from the Nvidia SDK
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
@ -169,6 +184,7 @@ void TeardownDeviceObjects()
SAFE_RELEASE(resetdepthstate);
SAFE_RELEASE(resetraststate);
SAFE_RELEASE(s_screenshot_texture);
SAFE_RELEASE(s_3d_vision_texture);
s_television.Shutdown();
@ -183,6 +199,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);
@ -198,6 +232,7 @@ Renderer::Renderer(void *&window_handle)
s_LastAA = g_ActiveConfig.iMultisampleMode;
s_LastEFBScale = g_ActiveConfig.iEFBScale;
s_last_fullscreen_mode = g_ActiveConfig.bFullscreen;
s_LastStereo = g_ActiveConfig.iStereoMode > 0;
CalculateTargetSize(s_backbuffer_width, s_backbuffer_height);
SetupDeviceObjects();
@ -514,7 +549,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE
// Color is passed in bgra mode so we need to convert it to rgba
u32 rgbaColor = (color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000);
D3D::drawClearQuad(rgbaColor, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader(), VertexShaderCache::GetClearInputLayout());
D3D::drawClearQuad(rgbaColor, (z & 0xFFFFFF) / float(0xFFFFFF));
D3D::stateman->PopDepthState();
D3D::stateman->PopBlendState();
@ -761,7 +796,52 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
// TODO: Improve sampling algorithm for the pixel shader so that we can use the multisampled EFB texture as source
D3DTexture2D* read_texture = FramebufferManager::GetResolvedEFBColorTexture();
D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false),VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma);
if (g_ActiveConfig.iStereoMode == STEREO_SBS || g_ActiveConfig.iStereoMode == STEREO_TAB)
{
TargetRectangle leftRc, rightRc;
ConvertStereoRectangle(GetTargetRectangle(), leftRc, rightRc);
D3D11_VIEWPORT leftVp = CD3D11_VIEWPORT((float)leftRc.left, (float)leftRc.top, (float)leftRc.GetWidth(), (float)leftRc.GetHeight());
D3D11_VIEWPORT rightVp = CD3D11_VIEWPORT((float)rightRc.left, (float)rightRc.top, (float)rightRc.GetWidth(), (float)rightRc.GetHeight());
D3D::context->RSSetViewports(1, &leftVp);
D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), nullptr, 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(), nullptr, Gamma, 1);
D3D::context->RSSetViewports(1, &vp);
}
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(), nullptr, 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(), nullptr, 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->RSSetViewports(1, &vp);
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), nullptr);
}
else
{
D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), (g_Config.iStereoMode == STEREO_ANAGLYPH) ? PixelShaderCache::GetAnaglyphProgram() : PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), nullptr, Gamma);
}
}
// done with drawing the game stuff, good moment to save a screenshot
@ -931,7 +1011,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
windowResized ||
fullscreen_changed ||
s_LastEFBScale != g_ActiveConfig.iEFBScale ||
s_LastAA != g_ActiveConfig.iMultisampleMode)
s_LastAA != g_ActiveConfig.iMultisampleMode ||
s_LastStereo != (g_ActiveConfig.iStereoMode > 0))
{
s_LastAA = g_ActiveConfig.iMultisampleMode;
PixelShaderCache::InvalidateMSAAShaders();
@ -954,6 +1035,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();
}
@ -961,6 +1043,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height);
s_LastEFBScale = g_ActiveConfig.iEFBScale;
s_LastStereo = g_ActiveConfig.iStereoMode > 0;
CalculateTargetSize(s_backbuffer_width, s_backbuffer_height);
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), nullptr);

View File

@ -7,6 +7,7 @@
#include "VideoBackends/D3D/D3DState.h"
#include "VideoBackends/D3D/D3DUtil.h"
#include "VideoBackends/D3D/FramebufferManager.h"
#include "VideoBackends/D3D/GeometryShaderCache.h"
#include "VideoBackends/D3D/PixelShaderCache.h"
#include "VideoBackends/D3D/PSTextureEncoder.h"
#include "VideoBackends/D3D/TextureCache.h"
@ -163,7 +164,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
(srcFormat == PEControl::Z24) ? FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBColorTexture()->GetSRV(),
&sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(),
(srcFormat == PEControl::Z24) ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true),
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(),
(g_Config.iStereoMode > 0) ? GeometryShaderCache::GetCopyGeometryShader() : nullptr);
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
@ -192,7 +194,7 @@ TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(
{
return new TCacheEntry(D3DTexture2D::Create(scaled_tex_w, scaled_tex_h,
(D3D11_BIND_FLAG)((int)D3D11_BIND_RENDER_TARGET | (int)D3D11_BIND_SHADER_RESOURCE),
D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM));
D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM, 1, FramebufferManager::GetEFBLayers()));
}
TextureCache::TextureCache()

View File

@ -5,6 +5,7 @@
#include "VideoBackends/D3D/BoundingBox.h"
#include "VideoBackends/D3D/D3DBase.h"
#include "VideoBackends/D3D/D3DState.h"
#include "VideoBackends/D3D/GeometryShaderCache.h"
#include "VideoBackends/D3D/PixelShaderCache.h"
#include "VideoBackends/D3D/Render.h"
#include "VideoBackends/D3D/VertexManager.h"
@ -139,11 +140,15 @@ void VertexManager::Draw(u32 stride)
if (current_primitive_type == PRIMITIVE_TRIANGLES)
{
D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
D3D::stateman->SetGeometryConstants(VertexShaderCache::GetConstantBuffer());
D3D::stateman->SetGeometryShader(g_ActiveConfig.iStereoMode > 0 ? GeometryShaderCache::GetActiveShader() : nullptr);
D3D::stateman->Apply();
D3D::context->DrawIndexed(indices, startIndex, baseVertex);
INCSTAT(stats.thisFrame.numDrawCalls);
D3D::stateman->SetGeometryShader(nullptr);
}
else if (current_primitive_type == PRIMITIVE_LINES)
{
@ -213,10 +218,21 @@ void VertexManager::vFlush(bool useDstAlpha)
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
return;
}
if (g_ActiveConfig.iStereoMode > 0)
{
if (!GeometryShaderCache::SetShader(components))
{
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR, true, { printf("Fail to set pixel shader\n"); });
return;
}
}
if (g_ActiveConfig.backend_info.bSupportsBBox && BoundingBox::active)
{
D3D::context->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, 2, 1, &BBox::GetUAV(), nullptr);
}
u32 stride = VertexLoaderManager::GetCurrentVertexFormat()->GetVertexStride();
PrepareDrawBuffers(stride);

View File

@ -60,7 +60,7 @@ ID3D11Buffer* &VertexShaderCache::GetConstantBuffer()
class VertexShaderCacheInserter : public LinearDiskCacheReader<VertexShaderUid, u8>
{
public:
void Read(const VertexShaderUid &key, const u8 *value, u32 value_size)
void Read(const VertexShaderUid &key, const u8* value, u32 value_size)
{
D3DBlob* blob = new D3DBlob(value_size, value);
VertexShaderCache::InsertByteCode(key, blob);
@ -73,15 +73,15 @@ const char simple_shader_code[] = {
"struct VSOUTPUT\n"
"{\n"
"float4 vPosition : POSITION;\n"
"float2 vTexCoord : TEXCOORD0;\n"
"float3 vTexCoord : TEXCOORD0;\n"
"float vTexCoord1 : TEXCOORD1;\n"
"};\n"
"VSOUTPUT main(float4 inPosition : POSITION,float3 inTEX0 : TEXCOORD0)\n"
"VSOUTPUT main(float4 inPosition : POSITION,float4 inTEX0 : TEXCOORD0)\n"
"{\n"
"VSOUTPUT OUT;\n"
"OUT.vPosition = inPosition;\n"
"OUT.vTexCoord = inTEX0.xy;\n"
"OUT.vTexCoord1 = inTEX0.z;\n"
"OUT.vTexCoord = inTEX0.xyz;\n"
"OUT.vTexCoord1 = inTEX0.w;\n"
"return OUT;\n"
"}\n"
};

View File

@ -16,6 +16,7 @@
#include "VideoBackends/D3D/BoundingBox.h"
#include "VideoBackends/D3D/D3DBase.h"
#include "VideoBackends/D3D/D3DUtil.h"
#include "VideoBackends/D3D/GeometryShaderCache.h"
#include "VideoBackends/D3D/Globals.h"
#include "VideoBackends/D3D/PerfQuery.h"
#include "VideoBackends/D3D/PixelShaderCache.h"
@ -78,7 +79,8 @@ void InitBackendInfo()
g_Config.backend_info.bSupportsDualSourceBlend = true;
g_Config.backend_info.bSupportsPrimitiveRestart = true;
g_Config.backend_info.bSupportsOversizedViewports = false;
g_Config.backend_info.bSupportsStereoscopy = false; // TODO: not implemented
g_Config.backend_info.bSupportsStereoscopy = true;
g_Config.backend_info.bSupports3DVision = true;
IDXGIFactory* factory;
IDXGIAdapter* ad;
@ -112,11 +114,17 @@ void InitBackendInfo()
g_Config.backend_info.AAModes.push_back(samples);
}
bool shader_model_5_supported = (DX11::D3D::GetFeatureLevel(ad) >= D3D_FEATURE_LEVEL_11_0);
// Requires the earlydepthstencil attribute (only available in shader model 5)
g_Config.backend_info.bSupportsEarlyZ = shader_model_5_supported;
// Requires full UAV functionality (only available in shader model 5)
g_Config.backend_info.bSupportsBBox = shader_model_5_supported;
// Requires the instance attribute (only available in shader model 5)
g_Config.backend_info.bSupportsGSInstancing = shader_model_5_supported;
}
g_Config.backend_info.Adapters.push_back(UTF16ToUTF8(desc.Description));
ad->Release();
@ -168,6 +176,7 @@ void VideoBackend::Video_Prepare()
g_perf_query = new PerfQuery;
VertexShaderCache::Init();
PixelShaderCache::Init();
GeometryShaderCache::Init();
D3D::InitUtils();
// VideoCommon
@ -205,6 +214,7 @@ void VideoBackend::Shutdown()
D3D::ShutdownUtils();
PixelShaderCache::Shutdown();
VertexShaderCache::Shutdown();
GeometryShaderCache::Shutdown();
BBox::Shutdown();
delete g_perf_query;

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

@ -52,25 +52,62 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy
uid_data->numTexGens = xfmem.numTexGen.numTexGens;
uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting;
GenerateVSOutputStruct(out, ApiType);
GenerateVSOutputStruct<T>(out, ApiType);
out.Write("centroid in VS_OUTPUT o[3];\n");
out.Write("centroid out VS_OUTPUT f;\n");
if (ApiType == API_OPENGL)
{
out.Write("centroid in VS_OUTPUT o[3];\n");
out.Write("centroid out VS_OUTPUT vs;\n");
out.Write("flat out int layer;\n");
out.Write("flat out int layer;\n");
out.Write("void main()\n{\n");
}
else // D3D
{
out.Write("struct GS_OUTPUT {\n");
out.Write("\tVS_OUTPUT vs;\n");
out.Write("\tuint layer : SV_RenderTargetArrayIndex;\n");
out.Write("};\n");
out.Write("void main()\n{\n");
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
{
out.Write("[maxvertexcount(3)]\n[instance(%d)]\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1);
out.Write("void main(triangle VS_OUTPUT o[3], inout TriangleStream<GS_OUTPUT> Output, in uint InstanceID : SV_GSInstanceID)\n{\n");
}
else
{
out.Write("[maxvertexcount(6)]\n");
out.Write("void main(triangle VS_OUTPUT o[3], inout TriangleStream<GS_OUTPUT> Output)\n{\n");
}
out.Write("\tGS_OUTPUT gs;\n");
}
out.Write("\tVS_OUTPUT f;\n");
// If the GPU supports invocation we don't need a for loop and can simply use the
// invocation identifier to determine which layer we're rendering.
if (g_ActiveConfig.backend_info.bSupportsGSInstancing)
out.Write("\tint l = gl_InvocationID;\n");
{
if (ApiType == API_OPENGL)
out.Write("\tint eye = gl_InvocationID;\n");
else
out.Write("\tint eye = InstanceID;\n");
}
else
out.Write("\tfor (int l = 0; l < %d; ++l) {\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1);
out.Write("\tfor (int eye = 0; eye < %d; ++eye) {\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1);
out.Write("\tfor (int i = 0; i < 3; ++i) {\n");
out.Write("\t\tlayer = l;\n");
out.Write("\t\tgl_Layer = l;\n");
// Select the output layer
if (ApiType == API_OPENGL)
{
out.Write("\t\tgl_Layer = eye;\n");
out.Write("\t\tlayer = eye;\n");
}
else
out.Write("\t\tgs.layer = eye;\n");
out.Write("\t\tf = o[i];\n");
out.Write("\t\tfloat4 pos = o[i].pos;\n");
@ -83,15 +120,28 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy
// the depth value. This results in objects at a distance smaller than the convergence
// distance to seemingly appear in front of the screen.
// This formula is based on page 13 of the "Nvidia 3D Vision Automatic, Best Practices Guide"
out.Write("\t\tf.clipPos.x = o[i].clipPos.x + " I_STEREOPARAMS"[l] * (o[i].clipPos.w - " I_STEREOPARAMS"[2]);\n");
out.Write("\t\tpos.x = o[i].pos.x + " I_STEREOPARAMS"[l] * (o[i].pos.w - " I_STEREOPARAMS"[2]);\n");
out.Write("\t\tf.clipPos.x = o[i].clipPos.x + " I_STEREOPARAMS"[eye] * (o[i].clipPos.w - " I_STEREOPARAMS"[2]);\n");
out.Write("\t\tpos.x = o[i].pos.x + " I_STEREOPARAMS"[eye] * (o[i].pos.w - " I_STEREOPARAMS"[2]);\n");
}
out.Write("\t\tf.pos.x = pos.x;\n");
out.Write("\t\tgl_Position = pos;\n");
out.Write("\t\tEmitVertex();\n");
if (ApiType == API_OPENGL)
out.Write("\t\tgl_Position = pos;\n");
out.Write("\t\t%s = f;\n", (ApiType == API_OPENGL) ? "vs" : "gs.vs");
if (ApiType == API_OPENGL)
out.Write("\t\tEmitVertex();\n");
else
out.Write("\t\tOutput.Append(gs);\n");
out.Write("\t}\n");
out.Write("\tEndPrimitive();\n");
if (ApiType == API_OPENGL)
out.Write("\tEndPrimitive();\n");
else
out.Write("\tOutput.RestartStrip();\n");
if (!g_ActiveConfig.backend_info.bSupportsGSInstancing)
out.Write("\t}\n");

View File

@ -205,7 +205,7 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
out.Write("\n");
for (int i = 0; i < 8; ++i)
out.Write("Texture2D Tex%d : register(t%d);\n", i, i);
out.Write("Texture2DArray Tex%d : register(t%d);\n", i, i);
}
out.Write("\n");
@ -264,7 +264,7 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
}
}
GenerateVSOutputStruct(out, ApiType);
GenerateVSOutputStruct<T>(out, ApiType);
const bool forced_early_z = g_ActiveConfig.backend_info.bSupportsEarlyZ && bpmem.UseEarlyDepthTest() && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED);
const bool per_pixel_depth = (bpmem.ztex2.op != ZTEXTURE_DISABLE && bpmem.UseLateDepthTest()) || (!g_ActiveConfig.bFastDepthCalc && bpmem.zmode.testenable && !forced_early_z);
@ -319,7 +319,7 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
uid_data->stereo = g_ActiveConfig.iStereoMode > 0;
if (g_ActiveConfig.iStereoMode > 0)
{
out.Write("centroid in VS_OUTPUT f;\n");
out.Write("centroid in VS_OUTPUT vs;\n");
out.Write("flat in int layer;\n");
}
else
@ -348,19 +348,19 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
// Let's set up attributes
for (unsigned int i = 0; i < numTexgen; ++i)
{
out.Write("\tfloat3 uv%d = f.tex%d;\n", i, i);
out.Write("\tfloat3 uv%d = vs.tex%d;\n", i, i);
}
out.Write("\tfloat4 clipPos = f.clipPos;\n");
out.Write("\tfloat4 clipPos = vs.clipPos;\n");
if (g_ActiveConfig.bEnablePixelLighting)
{
out.Write("\tfloat4 Normal = f.Normal;\n");
out.Write("\tfloat4 Normal = vs.Normal;\n");
}
}
// On Mali, global variables must be initialized as constants.
// This is why we initialize these variables locally instead.
out.Write("\tfloat4 colors_0 = %s;\n", (g_ActiveConfig.iStereoMode > 0) ? "f.colors_0" : "colors_02");
out.Write("\tfloat4 colors_1 = %s;\n", (g_ActiveConfig.iStereoMode > 0) ? "f.colors_1" : "colors_12");
out.Write("\tfloat4 colors_0 = %s;\n", (g_ActiveConfig.iStereoMode > 0) ? "vs.colors_0" : "colors_02");
out.Write("\tfloat4 colors_1 = %s;\n", (g_ActiveConfig.iStereoMode > 0) ? "vs.colors_1" : "colors_12");
out.Write("\tfloat4 rawpos = gl_FragCoord;\n");
}
@ -372,7 +372,7 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
per_pixel_depth ? "\n out float depth : SV_Depth," : "");
out.Write(" in centroid float4 colors_0 : COLOR0,\n");
out.Write(" in centroid float4 colors_1 : COLOR1");
out.Write(" in centroid float4 colors_1 : COLOR1\n");
// compute window position if needed because binding semantic WPOS is not widely supported
for (unsigned int i = 0; i < numTexgen; ++i)
@ -380,6 +380,9 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
out.Write(",\n in centroid float4 clipPos : TEXCOORD%d", numTexgen);
if (g_ActiveConfig.bEnablePixelLighting)
out.Write(",\n in centroid float4 Normal : TEXCOORD%d", numTexgen + 1);
uid_data->stereo = g_ActiveConfig.iStereoMode > 0;
if (g_ActiveConfig.iStereoMode > 0)
out.Write(",\n in uint layer : SV_RenderTargetArrayIndex\n");
out.Write(" ) {\n");
}
@ -938,7 +941,7 @@ static inline void SampleTexture(T& out, const char *texcoords, const char *texs
out.SetConstantsUsed(C_TEXDIMS+texmap,C_TEXDIMS+texmap);
if (ApiType == API_D3D)
out.Write("iround(255.0 * Tex%d.Sample(samp%d,%s.xy * " I_TEXDIMS"[%d].xy)).%s;\n", texmap,texmap, texcoords, texmap, texswap);
out.Write("iround(255.0 * Tex%d.Sample(samp%d, float3(%s.xy * " I_TEXDIMS"[%d].xy, %s))).%s;\n", texmap, texmap, texcoords, texmap, g_ActiveConfig.iStereoMode > 0 ? "layer" : "0.0", texswap);
else
out.Write("iround(255.0 * texture(samp%d, float3(%s.xy * " I_TEXDIMS"[%d].xy, %s))).%s;\n", texmap, texcoords, texmap, g_ActiveConfig.iStereoMode > 0 ? "layer" : "0.0", texswap);
}

View File

@ -14,6 +14,8 @@
#include "Common/CommonTypes.h"
#include "Common/StringUtil.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
#include "VideoCommon/XFMemory.h"
/**
* Common interface for classes that need to go through the shader generation path (GenerateVertexShader, GeneratePixelShader)
@ -218,6 +220,44 @@ private:
std::vector<UidT> m_uids;
};
template<class T>
static void DefineOutputStructMember(T& object, API_TYPE api_type, const char* type, const char* name, int var_index, const char* semantic = "", int semantic_index = -1)
{
object.Write(" %s %s", type, name);
if (var_index != -1)
object.Write("%d", var_index);
if (api_type == API_D3D && strlen(semantic) > 0)
{
if (semantic_index != -1)
object.Write(" : %s%d", semantic, semantic_index);
else
object.Write(" : %s", semantic);
}
object.Write(";\n");
}
template<class T>
static inline void GenerateVSOutputStruct(T& object, API_TYPE api_type)
{
object.Write("struct VS_OUTPUT {\n");
DefineOutputStructMember(object, api_type, "float4", "pos", -1, "POSITION");
DefineOutputStructMember(object, api_type, "float4", "colors_", 0, "COLOR", 0);
DefineOutputStructMember(object, api_type, "float4", "colors_", 1, "COLOR", 1);
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
DefineOutputStructMember(object, api_type, "float3", "tex", i, "TEXCOORD", i);
DefineOutputStructMember(object, api_type, "float4", "clipPos", -1, "TEXCOORD", xfmem.numTexGen.numTexGens);
if (g_ActiveConfig.bEnablePixelLighting)
DefineOutputStructMember(object, api_type, "float4", "Normal", -1, "TEXCOORD", xfmem.numTexGen.numTexGens + 1);
object.Write("};\n");
}
// Constant variable names
#define I_COLORS "color"
#define I_KCOLORS "k"

View File

@ -14,43 +14,6 @@
static char text[16768];
template<class T>
static void DefineVSOutputStructMember(T& object, API_TYPE api_type, const char* type, const char* name, int var_index, const char* semantic, int semantic_index = -1)
{
object.Write(" %s %s", type, name);
if (var_index != -1)
object.Write("%d", var_index);
if (api_type == API_OPENGL)
object.Write(";\n");
else // D3D
{
if (semantic_index != -1)
object.Write(" : %s%d;\n", semantic, semantic_index);
else
object.Write(" : %s;\n", semantic);
}
}
template<class T>
static inline void GenerateVSOutputStruct(T& object, API_TYPE api_type)
{
object.Write("struct VS_OUTPUT {\n");
DefineVSOutputStructMember(object, api_type, "float4", "pos", -1, "POSITION");
DefineVSOutputStructMember(object, api_type, "float4", "colors_", 0, "COLOR", 0);
DefineVSOutputStructMember(object, api_type, "float4", "colors_", 1, "COLOR", 1);
for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i)
DefineVSOutputStructMember(object, api_type, "float3", "tex", i, "TEXCOORD", i);
DefineVSOutputStructMember(object, api_type, "float4", "clipPos", -1, "TEXCOORD", xfmem.numTexGen.numTexGens);
if (g_ActiveConfig.bEnablePixelLighting)
DefineVSOutputStructMember(object, api_type, "float4", "Normal", -1, "TEXCOORD", xfmem.numTexGen.numTexGens + 1);
object.Write("};\n");
}
template<class T>
static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
{
@ -79,7 +42,7 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ
out.Write(s_shader_uniforms);
out.Write("};\n");
GenerateVSOutputStruct(out, api_type);
GenerateVSOutputStruct<T>(out, api_type);
uid_data->numTexGens = xfmem.numTexGen.numTexGens;
uid_data->components = components;
@ -464,13 +427,3 @@ void GenerateVertexShaderCode(VertexShaderCode& object, u32 components, API_TYPE
{
GenerateVertexShader<VertexShaderCode>(object, components, api_type);
}
void GenerateVSOutputStruct(ShaderCode& object, API_TYPE api_type)
{
GenerateVSOutputStruct<ShaderCode>(object, api_type);
}
void GenerateVSOutputStruct(ShaderGeneratorInterface& object, API_TYPE api_type)
{
// Ignore unknown types
}

View File

@ -7,7 +7,6 @@
#include "VideoCommon/LightingShaderGen.h"
#include "VideoCommon/ShaderGenCommon.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/XFMemory.h"
// TODO should be reordered
#define SHADER_POSITION_ATTRIB 0
@ -64,5 +63,3 @@ typedef ShaderCode VertexShaderCode; // TODO: Obsolete..
void GetVertexShaderUid(VertexShaderUid& object, u32 components, API_TYPE api_type);
void GenerateVertexShaderCode(VertexShaderCode& object, u32 components, API_TYPE api_type);
void GenerateVSOutputStruct(ShaderCode& object, API_TYPE api_type);
void GenerateVSOutputStruct(ShaderGeneratorInterface& object, API_TYPE api_type);

View File

@ -49,7 +49,8 @@ enum StereoMode
STEREO_OFF = 0,
STEREO_SBS,
STEREO_TAB,
STEREO_ANAGLYPH
STEREO_ANAGLYPH,
STEREO_3DVISION
};
// 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;