mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
Merge pull request #1612 from Armada651/d3d-stereo-3d
D3D: Add geometry shader stereoscopy support.
This commit is contained in:
commit
21ac9aa715
@ -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);
|
||||
|
@ -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" />
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
243
Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp
Normal file
243
Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp
Normal 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
|
49
Source/Core/VideoBackends/D3D/GeometryShaderCache.h
Normal file
49
Source/Core/VideoBackends/D3D/GeometryShaderCache.h
Normal 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
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user