From 9a312e2b8366bc64a3f3a5e69509b6aab15dc564 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 2 Nov 2014 14:51:12 +0100 Subject: [PATCH 01/24] D3D: Use two slices for most of our textures. --- Source/Core/VideoBackends/D3D/D3DTexture.cpp | 4 ++-- Source/Core/VideoBackends/D3D/D3DTexture.h | 2 +- .../VideoBackends/D3D/FramebufferManager.cpp | 20 ++++++++++--------- .../VideoBackends/D3D/FramebufferManager.h | 7 ++++++- .../Core/VideoBackends/D3D/TextureCache.cpp | 2 +- 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DTexture.cpp b/Source/Core/VideoBackends/D3D/D3DTexture.cpp index e1c94d5974..a24a54bc2a 100644 --- a/Source/Core/VideoBackends/D3D/D3DTexture.cpp +++ b/Source/Core/VideoBackends/D3D/D3DTexture.cpp @@ -37,7 +37,7 @@ void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned } // namespace -D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels) +D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels, unsigned int slices) { ID3D11Texture2D* pTexture = nullptr; HRESULT hr; @@ -49,7 +49,7 @@ 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); + D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(fmt, width, height, slices, levels, bind, usage, cpuflags); hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &pTexture); if (FAILED(hr)) { diff --git a/Source/Core/VideoBackends/D3D/D3DTexture.h b/Source/Core/VideoBackends/D3D/D3DTexture.h index 5c2aa57f4a..e865b0451d 100644 --- a/Source/Core/VideoBackends/D3D/D3DTexture.h +++ b/Source/Core/VideoBackends/D3D/D3DTexture.h @@ -22,7 +22,7 @@ public: // or let the texture automatically be created by D3DTexture2D::Create D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN, bool multisampled = false); - static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1); + static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1, unsigned int slices = 1); // reference counting, use AddRef() when creating a new reference and Release() it when you don't need it anymore void AddRef(); diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp index aeaaf6b8e8..407e0d31c8 100644 --- a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp @@ -57,8 +57,10 @@ FramebufferManager::FramebufferManager() D3D11_TEXTURE2D_DESC texdesc; HRESULT hr; + m_efb.slices = 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::GetEFBSlices()), FramebufferManager::GetEFBSlices()); } void FramebufferManager::GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc) diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.h b/Source/Core/VideoBackends/D3D/FramebufferManager.h index 45f43f7357..ef105894c9 100644 --- a/Source/Core/VideoBackends/D3D/FramebufferManager.h +++ b/Source/Core/VideoBackends/D3D/FramebufferManager.h @@ -45,7 +45,7 @@ namespace DX11 { struct XFBSource : public XFBSourceBase { - XFBSource(D3DTexture2D *_tex) : tex(_tex) {} + XFBSource(D3DTexture2D *_tex, int slices) : tex(_tex), m_slices(slices) {} ~XFBSource() { tex->Release(); } void Draw(const MathUtil::Rectangle &sourcerc, @@ -54,6 +54,7 @@ struct XFBSource : public XFBSourceBase void CopyEFB(float Gamma) override; D3DTexture2D* const tex; + const int m_slices; }; class FramebufferManager : public FramebufferManagerBase @@ -80,6 +81,8 @@ public: m_efb.color_tex = swaptex; } + static int GetEFBSlices() { return m_efb.slices; } + private: XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height) override; void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc) override; @@ -99,6 +102,8 @@ private: D3DTexture2D* resolved_color_tex; D3DTexture2D* resolved_depth_tex; + + int slices; } m_efb; }; diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp index 4ed4d6045f..7d81f8b4de 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp @@ -192,7 +192,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::GetEFBSlices())); } TextureCache::TextureCache() From d5ebdf7a9755217ed599d0e02d8a6ae2343410c3 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 3 Dec 2014 22:17:56 +0100 Subject: [PATCH 02/24] D3D: Add GeometryShaderCache. --- Source/Core/VideoBackends/D3D/D3D.vcxproj | 2 + .../VideoBackends/D3D/D3D.vcxproj.filters | 6 + .../VideoBackends/D3D/GeometryShaderCache.cpp | 160 ++++++++++++++++++ .../VideoBackends/D3D/GeometryShaderCache.h | 46 +++++ .../Core/VideoBackends/D3D/VertexManager.cpp | 1 + Source/Core/VideoBackends/D3D/main.cpp | 3 + Source/Core/VideoCommon/GeometryShaderGen.cpp | 2 +- 7 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp create mode 100644 Source/Core/VideoBackends/D3D/GeometryShaderCache.h diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj b/Source/Core/VideoBackends/D3D/D3D.vcxproj index 7ea9e09d07..f70efea502 100644 --- a/Source/Core/VideoBackends/D3D/D3D.vcxproj +++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj @@ -43,6 +43,7 @@ + @@ -66,6 +67,7 @@ + diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters index c0158038b2..a83db06c6a 100644 --- a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters +++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters @@ -30,6 +30,9 @@ Render + + Render + Render @@ -93,6 +96,9 @@ Render + + Render + Render diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp new file mode 100644 index 0000000000..a7bc1a470e --- /dev/null +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp @@ -0,0 +1,160 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include + +#include "Common/FileUtil.h" +#include "Common/LinearDiskCache.h" +#include "Common/StringUtil.h" + +#include "Core/ConfigManager.h" + +#include "VideoBackends/D3D/D3DBase.h" +#include "VideoBackends/D3D/D3DShader.h" +#include "VideoBackends/D3D/GeometryShaderCache.h" +#include "VideoBackends/D3D/Globals.h" + +#include "VideoCommon/Debugger.h" +#include "VideoCommon/GeometryShaderGen.h" +#include "VideoCommon/VideoConfig.h" + +namespace DX11 +{ + +GeometryShaderCache::GSCache GeometryShaderCache::GeometryShaders; +const GeometryShaderCache::GSCacheEntry* GeometryShaderCache::last_entry; +GeometryShaderUid GeometryShaderCache::last_uid; +UidChecker GeometryShaderCache::geometry_uid_checker; + +LinearDiskCache g_gs_disk_cache; + +ID3D11Buffer* gscbuf = nullptr; + +// this class will load the precompiled shaders into our cache +class GeometryShaderCacheInserter : public LinearDiskCacheReader +{ +public: + void Read(const GeometryShaderUid &key, const u8 *value, u32 value_size) + { + GeometryShaderCache::InsertByteCode(key, value, value_size); + } +}; + +void GeometryShaderCache::Init() +{ + 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() +{ + Clear(); + g_gs_disk_cache.Sync(); + g_gs_disk_cache.Close(); +} + +bool GeometryShaderCache::SetShader(u32 components) +{ + GeometryShaderUid uid; + GetGeometryShaderUid(uid, components, API_D3D); + if (g_ActiveConfig.bEnableShaderDebugging) + { + ShaderCode code; + GenerateGeometryShaderCode(code, components, API_D3D); + geometry_uid_checker.AddToIndexAndCheck(code, uid, "Geometry", "g"); + } + + // Check if the shader is already set + if (last_entry) + { + if (uid == last_uid) + { + GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true); + return (last_entry->shader != nullptr); + } + } + + last_uid = uid; + + // Check if the shader is already in the cache + GSCache::iterator iter; + iter = GeometryShaders.find(uid); + if (iter != GeometryShaders.end()) + { + const GSCacheEntry &entry = iter->second; + last_entry = &entry; + + return (entry.shader != nullptr); + } + + // Need to compile a new shader + ShaderCode code; + GenerateGeometryShaderCode(code, components, API_D3D); + + D3DBlob* pbytecode; + if (!D3D::CompileGeometryShader(code.GetBuffer(), &pbytecode)) + { + GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); + return false; + } + + // Insert the bytecode into the caches + g_gs_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size()); + + bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size()); + pbytecode->Release(); + + if (g_ActiveConfig.bEnableShaderDebugging && success) + { + GeometryShaders[uid].code = code.GetBuffer(); + } + + return success; +} + +bool GeometryShaderCache::InsertByteCode(const GeometryShaderUid &uid, const void* bytecode, unsigned int bytecodelen) +{ + ID3D11GeometryShader* shader = D3D::CreateGeometryShaderFromByteCode(bytecode, bytecodelen); + if (shader == nullptr) + return false; + + // TODO: Somehow make the debug name a bit more specific + D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a pixel shader of GeometryShaderCache"); + + // Make an entry in the table + GSCacheEntry newentry; + newentry.shader = shader; + GeometryShaders[uid] = newentry; + last_entry = &GeometryShaders[uid]; + + if (!shader) + return false; + + return true; +} + +} // DX11 diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h new file mode 100644 index 0000000000..b200323be8 --- /dev/null +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h @@ -0,0 +1,46 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +#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* GetActiveShader() { return last_entry->shader; } + +private: + struct GSCacheEntry + { + ID3D11GeometryShader* shader; + + std::string code; + + GSCacheEntry() : shader(nullptr) {} + void Destroy() { SAFE_RELEASE(shader); } + }; + + typedef std::map GSCache; + + static GSCache GeometryShaders; + static const GSCacheEntry* last_entry; + static GeometryShaderUid last_uid; + + static UidChecker geometry_uid_checker; +}; + +} // namespace DX11 \ No newline at end of file diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp index 7ab4f950bc..c782586a65 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp @@ -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" diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 34a11d493f..c840c2a9bc 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -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" @@ -168,6 +169,7 @@ void VideoBackend::Video_Prepare() g_perf_query = new PerfQuery; VertexShaderCache::Init(); PixelShaderCache::Init(); + GeometryShaderCache::Init(); D3D::InitUtils(); // VideoCommon @@ -205,6 +207,7 @@ void VideoBackend::Shutdown() D3D::ShutdownUtils(); PixelShaderCache::Shutdown(); VertexShaderCache::Shutdown(); + GeometryShaderCache::Shutdown(); BBox::Shutdown(); delete g_perf_query; diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index f9a8704269..424768e2ec 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -69,7 +69,7 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy out.Write("\tfor (int l = 0; l < %d; ++l) {\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\tgs.layer = l;\n"); out.Write("\t\tgl_Layer = l;\n"); out.Write("\t\tf = o[i];\n"); out.Write("\t\tfloat4 pos = o[i].pos;\n"); From 9253bb7d9651f3062e4b7002a2caff377e2290b7 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 2 Nov 2014 23:40:52 +0100 Subject: [PATCH 03/24] D3D: Add geometry shader stereoscopy support. --- .../VideoBackends/D3D/FramebufferManager.cpp | 2 +- .../VideoBackends/D3D/LineGeometryShader.cpp | 2 +- .../VideoBackends/D3D/PointGeometryShader.cpp | 2 +- .../Core/VideoBackends/D3D/VertexManager.cpp | 10 ++++ Source/Core/VideoBackends/D3D/main.cpp | 3 +- Source/Core/VideoCommon/GeometryShaderGen.cpp | 45 ++++++++++++---- Source/Core/VideoCommon/PixelShaderGen.cpp | 18 +++---- Source/Core/VideoCommon/ShaderGenCommon.h | 51 +++++++++++++++++++ Source/Core/VideoCommon/VertexShaderGen.cpp | 49 +----------------- Source/Core/VideoCommon/VertexShaderGen.h | 3 -- 10 files changed, 112 insertions(+), 73 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp index 407e0d31c8..508e2cb1e8 100644 --- a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp @@ -57,7 +57,7 @@ FramebufferManager::FramebufferManager() D3D11_TEXTURE2D_DESC texdesc; HRESULT hr; - m_efb.slices = 1; + 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, m_efb.slices, 1, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality); diff --git a/Source/Core/VideoBackends/D3D/LineGeometryShader.cpp b/Source/Core/VideoBackends/D3D/LineGeometryShader.cpp index cd2b11e2b3..7fcb02ff8d 100644 --- a/Source/Core/VideoBackends/D3D/LineGeometryShader.cpp +++ b/Source/Core/VideoBackends/D3D/LineGeometryShader.cpp @@ -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(code, API_D3D); code.Write("\n%s", LINE_GS_COMMON); std::stringstream numTexCoordsStream; diff --git a/Source/Core/VideoBackends/D3D/PointGeometryShader.cpp b/Source/Core/VideoBackends/D3D/PointGeometryShader.cpp index cfaca95cf3..3f874b3915 100644 --- a/Source/Core/VideoBackends/D3D/PointGeometryShader.cpp +++ b/Source/Core/VideoBackends/D3D/PointGeometryShader.cpp @@ -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(code, API_D3D); code.Write("\n%s", POINT_GS_COMMON); std::stringstream numTexCoordsStream; diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp index c782586a65..526cc30a0b 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp @@ -214,10 +214,20 @@ 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"); }); + } + } + 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); diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index c840c2a9bc..d5ce0f8dab 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -79,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.bSupportsGSInstancing = false; IDXGIFactory* factory; IDXGIAdapter* ad; diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 424768e2ec..3ebea24585 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -52,14 +52,25 @@ 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(out, ApiType); + GenerateGSOutputStruct(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 GS_OUTPUT gs;\n"); - out.Write("flat out int layer;\n"); + out.Write("void main()\n{\n"); + } + else // D3D + { + out.Write("[maxvertexcount(6)]\n"); + out.Write("void main(triangle VS_OUTPUT o[3], inout TriangleStream Output)\n{\n"); - out.Write("void main()\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. @@ -70,7 +81,10 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy out.Write("\tfor (int i = 0; i < 3; ++i) {\n"); out.Write("\t\tgs.layer = l;\n"); - out.Write("\t\tgl_Layer = l;\n"); + + if (ApiType == API_OPENGL) + out.Write("\t\tgl_Layer = l;\n"); + out.Write("\t\tf = o[i];\n"); out.Write("\t\tfloat4 pos = o[i].pos;\n"); @@ -88,10 +102,23 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy } 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\tgs.vs = f;\n"); + + 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("\t\tOutput.RestartStrip();\n"); if (!g_ActiveConfig.backend_info.bSupportsGSInstancing) out.Write("\t}\n"); diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 0e0e9d214c..bf48b29666 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -264,7 +264,8 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T } } - GenerateVSOutputStruct(out, ApiType); + GenerateVSOutputStruct(out, ApiType); + GenerateGSOutputStruct(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,8 +320,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("flat in int layer;\n"); + out.Write("centroid in GS_OUTPUT gs;\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 = gs.vs.tex%d;\n", i, i); } - out.Write("\tfloat4 clipPos = f.clipPos;\n"); + out.Write("\tfloat4 clipPos = gs.vs.clipPos;\n"); if (g_ActiveConfig.bEnablePixelLighting) { - out.Write("\tfloat4 Normal = f.Normal;\n"); + out.Write("\tfloat4 Normal = gs.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) ? "gs.vs.colors_0" : "colors_02"); + out.Write("\tfloat4 colors_1 = %s;\n", (g_ActiveConfig.iStereoMode > 0) ? "gs.vs.colors_1" : "colors_12"); out.Write("\tfloat4 rawpos = gl_FragCoord;\n"); } @@ -940,7 +940,7 @@ static inline void SampleTexture(T& out, const char *texcoords, const char *texs 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); 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); + 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 ? "gs.layer" : "0.0", texswap); } static const char *tevAlphaFuncsTable[] = diff --git a/Source/Core/VideoCommon/ShaderGenCommon.h b/Source/Core/VideoCommon/ShaderGenCommon.h index 4d22048ee6..ed9bab9fca 100644 --- a/Source/Core/VideoCommon/ShaderGenCommon.h +++ b/Source/Core/VideoCommon/ShaderGenCommon.h @@ -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,55 @@ private: std::vector m_uids; }; +template +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 +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"); +} + +template +static inline void GenerateGSOutputStruct(T& object, API_TYPE api_type) +{ + object.Write("struct GS_OUTPUT {\n"); + + DefineOutputStructMember(object, api_type, "VS_OUTPUT", "vs", -1, ""); + DefineOutputStructMember(object, api_type, (api_type == API_OPENGL) ? "flat int" : "uint", "layer", -1, "SV_RenderTargetArrayIndex"); + + object.Write("};\n"); +} + // Constant variable names #define I_COLORS "color" #define I_KCOLORS "k" diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 6ce3a453b9..00db2b0f02 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -14,43 +14,6 @@ static char text[16768]; -template -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 -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 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(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(object, components, api_type); } - -void GenerateVSOutputStruct(ShaderCode& object, API_TYPE api_type) -{ - GenerateVSOutputStruct(object, api_type); -} - -void GenerateVSOutputStruct(ShaderGeneratorInterface& object, API_TYPE api_type) -{ - // Ignore unknown types -} diff --git a/Source/Core/VideoCommon/VertexShaderGen.h b/Source/Core/VideoCommon/VertexShaderGen.h index b5e9e33f29..1f08c1963a 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.h +++ b/Source/Core/VideoCommon/VertexShaderGen.h @@ -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); From e53705784b8717d9c7a5e9d8de1aa2d2fe7b5624 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 3 Nov 2014 13:10:41 +0100 Subject: [PATCH 04/24] D3D: Add SBS/TAB output support. --- Source/Core/VideoBackends/D3D/D3DUtil.cpp | 42 +++++++++++-------- Source/Core/VideoBackends/D3D/D3DUtil.h | 6 ++- .../VideoBackends/D3D/PixelShaderCache.cpp | 10 ++--- Source/Core/VideoBackends/D3D/Render.cpp | 20 ++++++++- .../VideoBackends/D3D/VertexShaderCache.cpp | 8 ++-- 5 files changed, 57 insertions(+), 29 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DUtil.cpp b/Source/Core/VideoBackends/D3D/D3DUtil.cpp index 57524a49d3..89bdbcee97 100644 --- a/Source/Core/VideoBackends/D3D/D3DUtil.cpp +++ b/Source/Core/VideoBackends/D3D/D3DUtil.cpp @@ -422,20 +422,20 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw ID3D11SamplerState* linear_copy_sampler = nullptr; ID3D11SamplerState* point_copy_sampler = nullptr; -struct STQVertex { float x, y, z, u, v, w; }; -struct STSQVertex { float x, y, z, u, v, w; }; +struct STQVertex { float x, y, z, u, v, w, g; }; +struct STSQVertex { float x, y, z, u, v, w, g; }; struct ClearVertex { float x, y, z; u32 col; }; struct ColVertex { float x, y, z; u32 col; }; struct { - float u1, v1, u2, v2, G; + float u1, v1, u2, v2, S, G; } tex_quad_data; struct { MathUtil::Rectangle rdest; - float u1, v1, u2, v2, G; + float u1, v1, u2, v2, S, G; } tex_sub_quad_data; struct @@ -512,7 +512,8 @@ void drawShadedTexQuad(ID3D11ShaderResourceView* texture, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout, - float Gamma) + float Gamma, + u32 slice) { float sw = 1.0f /(float) SourceWidth; float sh = 1.0f /(float) SourceHeight; @@ -520,19 +521,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 +544,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; @@ -568,7 +572,8 @@ void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout, - float Gamma) + float Gamma, + u32 slice) { float sw = 1.0f /(float) SourceWidth; float sh = 1.0f /(float) SourceHeight; @@ -576,20 +581,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 +605,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)); } diff --git a/Source/Core/VideoBackends/D3D/D3DUtil.h b/Source/Core/VideoBackends/D3D/D3DUtil.h index bd47d9ff0e..53706847c2 100644 --- a/Source/Core/VideoBackends/D3D/D3DUtil.h +++ b/Source/Core/VideoBackends/D3D/D3DUtil.h @@ -62,7 +62,8 @@ namespace D3D ID3D11PixelShader* PShader, ID3D11VertexShader* VShader, ID3D11InputLayout* layout, - float Gamma = 1.0f); + float Gamma = 1.0f, + u32 slice = 0); void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture, const MathUtil::Rectangle* rSource, int SourceWidth, @@ -71,7 +72,8 @@ namespace D3D ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout, - float Gamma = 1.0f); + float Gamma = 1.0f, + u32 slice = 0); void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout); void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2); } diff --git a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp index a42d1a4103..94c53beda3 100644 --- a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp @@ -51,11 +51,11 @@ 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" }; @@ -63,16 +63,16 @@ const char color_copy_program_code[] = { // TODO: Improve sampling algorithm! const char color_copy_program_code_msaa[] = { "sampler samp0 : register(s0);\n" - "Texture2DMS Tex0 : register(t0);\n" + "Texture2DMSArray 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" "int width, height, samples;\n" "Tex0.GetDimensions(width, height, 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" }; diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 9d5802ebd8..7593d2810f 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -761,7 +761,25 @@ 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(), Gamma, 0); + + D3D::context->RSSetViewports(1, &rightVp); + D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma, 1); + } + else + { + D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma); + } } // done with drawing the game stuff, good moment to save a screenshot diff --git a/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp b/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp index d565d50c03..0abe6f1586 100644 --- a/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp @@ -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" }; From a689db0e48f399974ae3cc0c75f9e54a7423afe0 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 14 Nov 2014 00:24:53 +0100 Subject: [PATCH 05/24] D3D: Add 3D vision support. --- Source/Core/DolphinWX/VideoConfigDiag.cpp | 2 +- Source/Core/VideoBackends/D3D/D3DTexture.cpp | 4 +- Source/Core/VideoBackends/D3D/D3DTexture.h | 2 +- Source/Core/VideoBackends/D3D/Render.cpp | 55 ++++++++++++++++++++ Source/Core/VideoBackends/D3D/main.cpp | 1 + Source/Core/VideoBackends/OGL/main.cpp | 1 + Source/Core/VideoCommon/VideoConfig.h | 4 +- 7 files changed, 64 insertions(+), 5 deletions(-) diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index d8cfb12e59..5c5e253888 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -453,7 +453,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con { wxFlexGridSizer* const szr_stereo = new wxFlexGridSizer(2, 5, 5); - const wxString stereo_choices[] = { "Off", "Side-by-Side", "Top-and-Bottom", "Anaglyph" }; + const wxString stereo_choices[] = { "Off", "Side-by-Side", "Top-and-Bottom", vconfig.backend_info.bSupports3DVision ? "Nvidia 3D Vision" : "Anaglyph" }; szr_stereo->Add(new wxStaticText(page_enh, wxID_ANY, _("Stereoscopic 3D Mode:")), 1, wxALIGN_CENTER_VERTICAL, 0); szr_stereo->Add(CreateChoice(page_enh, vconfig.iStereoMode, wxGetTranslation(stereo_3d_desc), 4, stereo_choices)); diff --git a/Source/Core/VideoBackends/D3D/D3DTexture.cpp b/Source/Core/VideoBackends/D3D/D3DTexture.cpp index a24a54bc2a..b60738c286 100644 --- a/Source/Core/VideoBackends/D3D/D3DTexture.cpp +++ b/Source/Core/VideoBackends/D3D/D3DTexture.cpp @@ -37,7 +37,7 @@ void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned } // namespace -D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels, unsigned int slices) +D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels, unsigned int slices, D3D11_SUBRESOURCE_DATA* data) { ID3D11Texture2D* pTexture = nullptr; HRESULT hr; @@ -50,7 +50,7 @@ D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D1 else cpuflags = (D3D11_CPU_ACCESS_FLAG)0; D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(fmt, width, height, slices, levels, bind, usage, cpuflags); - hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &pTexture); + hr = D3D::device->CreateTexture2D(&texdesc, data, &pTexture); if (FAILED(hr)) { PanicAlert("Failed to create texture at %s, line %d: hr=%#x\n", __FILE__, __LINE__, hr); diff --git a/Source/Core/VideoBackends/D3D/D3DTexture.h b/Source/Core/VideoBackends/D3D/D3DTexture.h index e865b0451d..6be15b6102 100644 --- a/Source/Core/VideoBackends/D3D/D3DTexture.h +++ b/Source/Core/VideoBackends/D3D/D3DTexture.h @@ -22,7 +22,7 @@ public: // or let the texture automatically be created by D3DTexture2D::Create D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN, bool multisampled = false); - static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1, unsigned int slices = 1); + static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1, unsigned int slices = 1, D3D11_SUBRESOURCE_DATA* data = nullptr); // reference counting, use AddRef() when creating a new reference and Release() it when you don't need it anymore void AddRef(); diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 7593d2810f..a76b14e29c 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -55,6 +55,18 @@ ID3D11DepthStencilState* resetdepthstate = nullptr; ID3D11RasterizerState* resetraststate = nullptr; static ID3D11Texture2D* s_screenshot_texture = nullptr; +static D3DTexture2D* s_3d_vision_texture = nullptr; + +typedef struct _Nv_Stereo_Image_Header +{ + unsigned int dwSignature; + unsigned int dwWidth; + unsigned int dwHeight; + unsigned int dwBPP; + unsigned int dwFlags; +} NVSTEREOIMAGEHEADER, *LPNVSTEREOIMAGEHEADER; + +#define NVSTEREO_IMAGE_SIGNATURE 0x4433564e // GX pipeline state struct @@ -183,6 +195,24 @@ void CreateScreenshotTexture(const TargetRectangle& rc) D3D::SetDebugObjectName((ID3D11DeviceChild*)s_screenshot_texture, "staging screenshot texture"); } +void Create3DVisionTexture(int width, int height) +{ + // Create a staging texture for 3D vision with signature information in the last row. + // Nvidia 3D Vision supports full SBS, so there is no loss in resolution during this process. + D3D11_SUBRESOURCE_DATA sysData; + sysData.SysMemPitch = 4 * width * 2; + sysData.pSysMem = new u8[(height + 1) * sysData.SysMemPitch]; + LPNVSTEREOIMAGEHEADER header = (LPNVSTEREOIMAGEHEADER)((u8*)sysData.pSysMem + height * sysData.SysMemPitch); + header->dwSignature = NVSTEREO_IMAGE_SIGNATURE; + header->dwWidth = width * 2; + header->dwHeight = height + 1; + header->dwBPP = 32; + header->dwFlags = 0; + + s_3d_vision_texture = D3DTexture2D::Create(width * 2, height + 1, D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, &sysData); + delete[] sysData.pSysMem; +} + Renderer::Renderer(void *&window_handle) { D3D::Create((HWND)window_handle); @@ -776,6 +806,30 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co D3D::context->RSSetViewports(1, &rightVp); D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma, 1); } + else if (g_ActiveConfig.iStereoMode == STEREO_3DVISION) + { + if (!s_3d_vision_texture) + Create3DVisionTexture(s_backbuffer_width, s_backbuffer_height); + + D3D11_VIEWPORT leftVp = CD3D11_VIEWPORT((float)X, (float)Y, (float)Width, (float)Height); + D3D11_VIEWPORT rightVp = CD3D11_VIEWPORT((float)(X + s_backbuffer_width), (float)Y, (float)Width, (float)Height); + + // Render to staging texture which is double the width of the backbuffer + D3D::context->OMSetRenderTargets(1, &s_3d_vision_texture->GetRTV(), nullptr); + + D3D::context->RSSetViewports(1, &leftVp); + D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma, 0); + + D3D::context->RSSetViewports(1, &rightVp); + D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma, 1); + + // Copy the left eye to the backbuffer, if Nvidia 3D Vision is enabled it should + // recognize the signature and automatically include the right eye frame. + D3D11_BOX box = CD3D11_BOX(0, 0, 0, s_backbuffer_width, s_backbuffer_height, 1); + D3D::context->CopySubresourceRegion(D3D::GetBackBuffer()->GetTex(), 0, 0, 0, 0, s_3d_vision_texture->GetTex(), 0, &box); + + D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), nullptr); + } else { D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma); @@ -972,6 +1026,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co // TODO: Aren't we still holding a reference to the back buffer right now? D3D::Reset(); SAFE_RELEASE(s_screenshot_texture); + SAFE_RELEASE(s_3d_vision_texture); s_backbuffer_width = D3D::GetBackBufferWidth(); s_backbuffer_height = D3D::GetBackBufferHeight(); } diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index d5ce0f8dab..5a371396d2 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -80,6 +80,7 @@ void InitBackendInfo() g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsOversizedViewports = false; g_Config.backend_info.bSupportsStereoscopy = true; + g_Config.backend_info.bSupports3DVision = true; g_Config.backend_info.bSupportsGSInstancing = false; IDXGIFactory* factory; diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index 0fb36ab8d1..eb486c811b 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -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(); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index c825f8ec53..879c0726a9 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -49,7 +49,8 @@ enum StereoMode STEREO_OFF = 0, STEREO_SBS, STEREO_TAB, - STEREO_ANAGLYPH + STEREO_ANAGLYPH, + STEREO_3DVISION = STEREO_ANAGLYPH }; // NEVER inherit from this class. @@ -151,6 +152,7 @@ struct VideoConfig final bool bSupportsPrimitiveRestart; bool bSupportsOversizedViewports; bool bSupportsStereoscopy; + bool bSupports3DVision; bool bSupportsEarlyZ; // needed by PixelShaderGen, so must stay in VideoCommon bool bSupportsBindingLayout; // Needed by ShaderGen, so must stay in VideoCommon bool bSupportsBBox; From 9d9bd5341d59792573db9aa214f677dcb8ea957b Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 14 Nov 2014 00:35:28 +0100 Subject: [PATCH 06/24] D3D: Restore viewport after stereo blitting. --- Source/Core/VideoBackends/D3D/Render.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index a76b14e29c..da9cbe6804 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -805,6 +805,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co D3D::context->RSSetViewports(1, &rightVp); D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma, 1); + + D3D::context->RSSetViewports(1, &vp); } else if (g_ActiveConfig.iStereoMode == STEREO_3DVISION) { @@ -828,6 +830,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co 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 From cf12c93c86fdc5892f4d013dfee2463725428dcd Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 14 Nov 2014 11:16:54 +0100 Subject: [PATCH 07/24] D3D: Use common GetEFBLayers() instead of GetEFBSlices(). --- Source/Core/VideoBackends/D3D/FramebufferManager.cpp | 4 ++-- Source/Core/VideoBackends/D3D/FramebufferManager.h | 2 -- Source/Core/VideoBackends/D3D/TextureCache.cpp | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp index 508e2cb1e8..dc2bb0c5cb 100644 --- a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp @@ -57,7 +57,7 @@ FramebufferManager::FramebufferManager() D3D11_TEXTURE2D_DESC texdesc; HRESULT hr; - m_efb.slices = (g_ActiveConfig.iStereoMode > 0) ? 2 : 1; + 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, m_efb.slices, 1, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality); @@ -164,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, 1, FramebufferManager::GetEFBSlices()), FramebufferManager::GetEFBSlices()); + D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM, 1, FramebufferManager::GetEFBLayers()), FramebufferManager::GetEFBLayers()); } void FramebufferManager::GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc) diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.h b/Source/Core/VideoBackends/D3D/FramebufferManager.h index ef105894c9..d7961cb9b8 100644 --- a/Source/Core/VideoBackends/D3D/FramebufferManager.h +++ b/Source/Core/VideoBackends/D3D/FramebufferManager.h @@ -81,8 +81,6 @@ public: m_efb.color_tex = swaptex; } - static int GetEFBSlices() { return m_efb.slices; } - private: XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height) override; void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc) override; diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp index 7d81f8b4de..24ee1c9aa9 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp @@ -192,7 +192,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, 1, FramebufferManager::GetEFBSlices())); + D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM, 1, FramebufferManager::GetEFBLayers())); } TextureCache::TextureCache() From ca766747a88e883d12d3ef8948346ed15e0bbe52 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 14 Nov 2014 11:19:04 +0100 Subject: [PATCH 08/24] D3DTexture: Bind textures as texture arrays. --- Source/Core/VideoBackends/D3D/D3DTexture.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DTexture.cpp b/Source/Core/VideoBackends/D3D/D3DTexture.cpp index b60738c286..8c23a4bd2c 100644 --- a/Source/Core/VideoBackends/D3D/D3DTexture.cpp +++ b/Source/Core/VideoBackends/D3D/D3DTexture.cpp @@ -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); From 4f6ce0f236226fed6677283359723911c329bc38 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 14 Nov 2014 12:39:25 +0100 Subject: [PATCH 09/24] D3D: Add geometry shader instancing support. --- Source/Core/VideoBackends/D3D/main.cpp | 7 +++++- Source/Core/VideoCommon/GeometryShaderGen.cpp | 24 +++++++++++++++---- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 5a371396d2..22782cc41c 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -81,7 +81,6 @@ void InitBackendInfo() g_Config.backend_info.bSupportsOversizedViewports = false; g_Config.backend_info.bSupportsStereoscopy = true; g_Config.backend_info.bSupports3DVision = true; - g_Config.backend_info.bSupportsGSInstancing = false; IDXGIFactory* factory; IDXGIAdapter* ad; @@ -115,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(); diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 3ebea24585..b75eddd87a 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -64,8 +64,16 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy } else // D3D { - out.Write("[maxvertexcount(6)]\n"); - out.Write("void main(triangle VS_OUTPUT o[3], inout TriangleStream Output)\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 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 Output)\n{\n"); + } out.Write("\tGS_OUTPUT gs;\n"); } @@ -75,13 +83,19 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy // 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 l = gl_InvocationID;\n"); + else + out.Write("\tint l = InstanceID;\n"); + } else out.Write("\tfor (int l = 0; l < %d; ++l) {\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1); out.Write("\tfor (int i = 0; i < 3; ++i) {\n"); - out.Write("\t\tgs.layer = l;\n"); + // Select the output layer + out.Write("\t\tgs.layer = l;\n"); if (ApiType == API_OPENGL) out.Write("\t\tgl_Layer = l;\n"); @@ -118,7 +132,7 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy if (ApiType == API_OPENGL) out.Write("\tEndPrimitive();\n"); else - out.Write("\t\tOutput.RestartStrip();\n"); + out.Write("\tOutput.RestartStrip();\n"); if (!g_ActiveConfig.backend_info.bSupportsGSInstancing) out.Write("\t}\n"); From 7c05b9a6d07d5c284497019524d6cf531a8e2f6d Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 15 Nov 2014 01:53:08 +0100 Subject: [PATCH 10/24] D3D: Set the geometry shader for triangle primitives. --- Source/Core/VideoBackends/D3D/Render.cpp | 1 + Source/Core/VideoBackends/D3D/VertexManager.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index da9cbe6804..09355ca851 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -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" diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp index 526cc30a0b..abc7f18e33 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp @@ -140,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) { @@ -220,6 +224,7 @@ void VertexManager::vFlush(bool useDstAlpha) if (!GeometryShaderCache::SetShader(components)) { GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR, true, { printf("Fail to set pixel shader\n"); }); + return; } } From b769da23d09c39a29c3467f63c46037ac688930c Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 16 Nov 2014 13:47:28 +0100 Subject: [PATCH 11/24] PixelShaderGen: Sample the correct texture slice. --- Source/Core/VideoCommon/PixelShaderGen.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index bf48b29666..0e18db536e 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -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"); @@ -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", 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 ? "gs.layer" : "0.0", texswap); } From d58e389f6782a1e548e5191d5a238ddd9ddfe3e0 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 16 Nov 2014 13:55:28 +0100 Subject: [PATCH 12/24] D3D: Recreate the framebuffer when stereoscopic 3D is toggled. --- Source/Core/VideoBackends/D3D/Render.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 09355ca851..0cd5835b60 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -47,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}; @@ -229,6 +230,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(); @@ -1007,7 +1009,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(); @@ -1038,6 +1041,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); From ced733ccdfcb52cc35b71d0a3365798bfea43a23 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 22 Nov 2014 19:52:59 +0100 Subject: [PATCH 13/24] PixelShaderCache: Add texture array support to static shaders. --- .../VideoBackends/D3D/PixelShaderCache.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp index 94c53beda3..7220264367 100644 --- a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp @@ -79,12 +79,12 @@ const char color_copy_program_code_msaa[] = { 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 +93,17 @@ const char color_matrix_program_code[] = { const char color_matrix_program_code_msaa[] = { "sampler samp0 : register(s0);\n" - "Texture2DMS Tex0 : register(t0);\n" + "Texture2DMSArray 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" "int width, height, samples;\n" "Tex0.GetDimensions(width, height, 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(int2(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 +112,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 +147,17 @@ const char depth_matrix_program[] = { const char depth_matrix_program_msaa[] = { "sampler samp0 : register(s0);\n" - "Texture2DMS Tex0 : register(t0);\n" + "Texture2DMSArray 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" " int width, height, samples;\n" " Tex0.GetDimensions(width, height, 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(int2(uv0.x*(width), uv0.y*(height), uv0.z), i);\n" " texcol /= samples;\n" // 255.99998474121 = 16777215/16777216*256 From 799697ad8095fcb364bdbd5e9c49a8adb8beda8d Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 22 Nov 2014 19:56:59 +0100 Subject: [PATCH 14/24] PSTextureEncoder: Add texture array support. We only read the first slice, because EFB2RAM doesn't support texture arrays. --- Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp index 09f124ecc6..be0e6461e8 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp @@ -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));\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));\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));\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)).r;\n" "uint4 bytes = uint4(\n" "(depth24 >> 16) & 0xFF,\n" // r "(depth24 >> 8) & 0xFF,\n" // g From 3355d8086dc449c7d0325273eafcc999cfc649ee Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 23 Nov 2014 02:13:25 +0100 Subject: [PATCH 15/24] D3DUtil: Use a geometry shader to clear all slices. --- Source/Core/VideoBackends/D3D/D3DUtil.cpp | 15 +++++-- Source/Core/VideoBackends/D3D/D3DUtil.h | 2 +- .../VideoBackends/D3D/GeometryShaderCache.cpp | 41 +++++++++++++++++++ .../VideoBackends/D3D/GeometryShaderCache.h | 2 + Source/Core/VideoBackends/D3D/Render.cpp | 2 +- 5 files changed, 56 insertions(+), 6 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DUtil.cpp b/Source/Core/VideoBackends/D3D/D3DUtil.cpp index 89bdbcee97..28b9850902 100644 --- a/Source/Core/VideoBackends/D3D/D3DUtil.cpp +++ b/Source/Core/VideoBackends/D3D/D3DUtil.cpp @@ -10,6 +10,7 @@ #include "VideoBackends/D3D/D3DShader.h" #include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/D3DUtil.h" +#include "VideoBackends/D3D/GeometryShaderCache.h" #include "VideoBackends/D3D/PixelShaderCache.h" #include "VideoBackends/D3D/VertexShaderCache.h" @@ -653,6 +654,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()); @@ -663,9 +665,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}, @@ -683,9 +687,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; @@ -694,6 +699,8 @@ void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexS stateman->Apply(); context->Draw(4, clearq_offset); + + stateman->SetGeometryShader(nullptr); } } // namespace D3D diff --git a/Source/Core/VideoBackends/D3D/D3DUtil.h b/Source/Core/VideoBackends/D3D/D3DUtil.h index 53706847c2..0f2dd72adb 100644 --- a/Source/Core/VideoBackends/D3D/D3DUtil.h +++ b/Source/Core/VideoBackends/D3D/D3DUtil.h @@ -74,7 +74,7 @@ namespace D3D ID3D11InputLayout* layout, float Gamma = 1.0f, u32 slice = 0); - void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout); + void drawClearQuad(u32 Color, float z); void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2); } diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp index a7bc1a470e..087428a200 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp @@ -27,8 +27,12 @@ const GeometryShaderCache::GSCacheEntry* GeometryShaderCache::last_entry; GeometryShaderUid GeometryShaderCache::last_uid; UidChecker GeometryShaderCache::geometry_uid_checker; +ID3D11GeometryShader* ClearGeometryShader = nullptr; + LinearDiskCache g_gs_disk_cache; +ID3D11GeometryShader* GeometryShaderCache::GetClearGeometryShader() { return ClearGeometryShader; } + ID3D11Buffer* gscbuf = nullptr; // this class will load the precompiled shaders into our cache @@ -41,8 +45,43 @@ public: } }; +const char clear_shader_code[] = { + "struct VSOUTPUT\n" + "{\n" + "float4 vPosition : POSITION;\n" + "float4 vColor0 : COLOR0;\n" + "};\n" + "struct GSOUTPUT\n" + "{\n" + "float4 vPosition : POSITION;\n" + "float4 vColor0 : COLOR0;\n" + "uint slice : SV_RenderTargetArrayIndex;\n" + "};\n" + "[maxvertexcount(6)]\n" + "void main(triangle VSOUTPUT o[3], inout TriangleStream Output)\n" + "{\n" + "for(int slice = 0; slice < 2; slice++)\n" + "{\n" + "for(int i = 0; i < 3; i++)\n" + "{\n" + "GSOUTPUT OUT;\n" + "OUT.vPosition = o[i].vPosition;\n" + "OUT.vColor0 = o[i].vColor0;\n" + "OUT.slice = slice;\n" + "Output.Append(OUT);\n" + "}\n" + "Output.RestartStrip();\n" + "}\n" + "}\n" +}; + 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"); + Clear(); if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX))) @@ -72,6 +111,8 @@ void GeometryShaderCache::Clear() void GeometryShaderCache::Shutdown() { + SAFE_RELEASE(ClearGeometryShader); + Clear(); g_gs_disk_cache.Sync(); g_gs_disk_cache.Close(); diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h index b200323be8..38a524c596 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h @@ -21,6 +21,8 @@ public: 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* GetActiveShader() { return last_entry->shader; } private: diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 0cd5835b60..3d0b365242 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -547,7 +547,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(); From 4b3e7849493a6f853ddbeea82348ec9e0e34a166 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 29 Nov 2014 21:31:30 +0100 Subject: [PATCH 16/24] TextureCache: Add stereoscopy support for EFB to texture copies. --- Source/Core/VideoBackends/D3D/D3DUtil.cpp | 16 +++++-- Source/Core/VideoBackends/D3D/D3DUtil.h | 4 +- .../VideoBackends/D3D/FramebufferManager.cpp | 2 +- .../VideoBackends/D3D/GeometryShaderCache.cpp | 42 +++++++++++++++++++ .../VideoBackends/D3D/GeometryShaderCache.h | 1 + Source/Core/VideoBackends/D3D/Render.cpp | 10 ++--- .../Core/VideoBackends/D3D/TextureCache.cpp | 4 +- 7 files changed, 67 insertions(+), 12 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DUtil.cpp b/Source/Core/VideoBackends/D3D/D3DUtil.cpp index 28b9850902..50eac8665b 100644 --- a/Source/Core/VideoBackends/D3D/D3DUtil.cpp +++ b/Source/Core/VideoBackends/D3D/D3DUtil.cpp @@ -511,8 +511,9 @@ void drawShadedTexQuad(ID3D11ShaderResourceView* texture, int SourceWidth, int SourceHeight, ID3D11PixelShader* PShader, - ID3D11VertexShader* Vshader, + ID3D11VertexShader* VShader, ID3D11InputLayout* layout, + ID3D11GeometryShader* GShader, float Gamma, u32 slice) { @@ -556,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, @@ -571,8 +575,9 @@ void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture, int SourceHeight, const MathUtil::Rectangle* rDest, ID3D11PixelShader* PShader, - ID3D11VertexShader* Vshader, + ID3D11VertexShader* VShader, ID3D11InputLayout* layout, + ID3D11GeometryShader* GShader, float Gamma, u32 slice) { @@ -618,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 diff --git a/Source/Core/VideoBackends/D3D/D3DUtil.h b/Source/Core/VideoBackends/D3D/D3DUtil.h index 0f2dd72adb..883f232b28 100644 --- a/Source/Core/VideoBackends/D3D/D3DUtil.h +++ b/Source/Core/VideoBackends/D3D/D3DUtil.h @@ -62,6 +62,7 @@ namespace D3D ID3D11PixelShader* PShader, ID3D11VertexShader* VShader, ID3D11InputLayout* layout, + ID3D11GeometryShader* GShader = nullptr, float Gamma = 1.0f, u32 slice = 0); void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture, @@ -70,8 +71,9 @@ namespace D3D int SourceHeight, const MathUtil::Rectangle* rDest, ID3D11PixelShader* PShader, - ID3D11VertexShader* Vshader, + ID3D11VertexShader* VShader, ID3D11InputLayout* layout, + ID3D11GeometryShader* GShader = nullptr, float Gamma = 1.0f, u32 slice = 0); void drawClearQuad(u32 Color, float z); diff --git a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp index dc2bb0c5cb..a1b66dc3e7 100644 --- a/Source/Core/VideoBackends/D3D/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/D3D/FramebufferManager.cpp @@ -208,7 +208,7 @@ void XFBSource::CopyEFB(float Gamma) D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), sourceRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(true), VertexShaderCache::GetSimpleVertexShader(), - VertexShaderCache::GetSimpleInputLayout(),Gamma); + VertexShaderCache::GetSimpleInputLayout(), nullptr, Gamma); D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp index 087428a200..03facfb674 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp @@ -28,10 +28,12 @@ GeometryShaderUid GeometryShaderCache::last_uid; UidChecker GeometryShaderCache::geometry_uid_checker; ID3D11GeometryShader* ClearGeometryShader = nullptr; +ID3D11GeometryShader* CopyGeometryShader = nullptr; LinearDiskCache g_gs_disk_cache; ID3D11GeometryShader* GeometryShaderCache::GetClearGeometryShader() { return ClearGeometryShader; } +ID3D11GeometryShader* GeometryShaderCache::GetCopyGeometryShader() { return CopyGeometryShader; } ID3D11Buffer* gscbuf = nullptr; @@ -75,6 +77,40 @@ const char clear_shader_code[] = { "}\n" }; +const char copy_shader_code[] = { + "struct VSOUTPUT\n" + "{\n" + "float4 vPosition : POSITION;\n" + "float3 vTexCoord : TEXCOORD0;\n" + "float vTexCoord1 : TEXCOORD1;\n" + "};\n" + "struct GSOUTPUT\n" + "{\n" + "float4 vPosition : POSITION;\n" + "float3 vTexCoord : TEXCOORD0;\n" + "float vTexCoord1 : TEXCOORD1;\n" + "uint slice : SV_RenderTargetArrayIndex;\n" + "};\n" + "[maxvertexcount(6)]\n" + "void main(triangle VSOUTPUT o[3], inout TriangleStream Output)\n" + "{\n" + "for(int slice = 0; slice < 2; slice++)\n" + "{\n" + "for(int i = 0; i < 3; i++)\n" + "{\n" + "GSOUTPUT OUT;\n" + "OUT.vPosition = o[i].vPosition;\n" + "OUT.vTexCoord = o[i].vTexCoord;\n" + "OUT.vTexCoord.z = slice;\n" + "OUT.vTexCoord1 = o[i].vTexCoord1;\n" + "OUT.slice = slice;\n" + "Output.Append(OUT);\n" + "}\n" + "Output.RestartStrip();\n" + "}\n" + "}\n" +}; + void GeometryShaderCache::Init() { // used when drawing clear quads @@ -82,6 +118,11 @@ void GeometryShaderCache::Init() 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))) @@ -112,6 +153,7 @@ void GeometryShaderCache::Clear() void GeometryShaderCache::Shutdown() { SAFE_RELEASE(ClearGeometryShader); + SAFE_RELEASE(CopyGeometryShader); Clear(); g_gs_disk_cache.Sync(); diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h index 38a524c596..95672a0087 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h @@ -22,6 +22,7 @@ public: 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; } diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 3d0b365242..2dcb8ee6b7 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -804,10 +804,10 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co 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(), Gamma, 0); + 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(), Gamma, 1); + 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); } @@ -823,10 +823,10 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co D3D::context->OMSetRenderTargets(1, &s_3d_vision_texture->GetRTV(), nullptr); D3D::context->RSSetViewports(1, &leftVp); - D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma, 0); + D3D::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(), Gamma, 1); + 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. @@ -838,7 +838,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co } else { - D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), Gamma); + D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), nullptr, Gamma); } } diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp index 24ee1c9aa9..bef632e4fd 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp @@ -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()); From b06280e86696903438f11afbb06d8935b2dc8503 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 29 Nov 2014 21:55:14 +0100 Subject: [PATCH 17/24] D3D: Add anaglyph stereoscopy support. --- Source/Core/DolphinWX/VideoConfigDiag.cpp | 4 +-- .../VideoBackends/D3D/PixelShaderCache.cpp | 25 +++++++++++++++++++ .../Core/VideoBackends/D3D/PixelShaderCache.h | 1 + Source/Core/VideoBackends/D3D/Render.cpp | 2 +- Source/Core/VideoCommon/VideoConfig.h | 2 +- 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index 5c5e253888..6ccba4251d 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -453,9 +453,9 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con { wxFlexGridSizer* const szr_stereo = new wxFlexGridSizer(2, 5, 5); - const wxString stereo_choices[] = { "Off", "Side-by-Side", "Top-and-Bottom", vconfig.backend_info.bSupports3DVision ? "Nvidia 3D Vision" : "Anaglyph" }; + const wxString stereo_choices[] = { "Off", "Side-by-Side", "Top-and-Bottom", "Anaglyph", "Nvidia 3D Vision" }; szr_stereo->Add(new wxStaticText(page_enh, wxID_ANY, _("Stereoscopic 3D Mode:")), 1, wxALIGN_CENTER_VERTICAL, 0); - szr_stereo->Add(CreateChoice(page_enh, vconfig.iStereoMode, wxGetTranslation(stereo_3d_desc), 4, stereo_choices)); + szr_stereo->Add(CreateChoice(page_enh, vconfig.iStereoMode, wxGetTranslation(stereo_3d_desc), vconfig.backend_info.bSupports3DVision ? 5 : 4, stereo_choices)); wxSlider* const sep_slider = new wxSlider(page_enh, wxID_ANY, vconfig.iStereoSeparation, 0, 100, wxDefaultPosition, wxDefaultSize); sep_slider->Bind(wxEVT_SLIDER, &VideoConfigDiag::Event_StereoSep, this); diff --git a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp index 7220264367..621ae34cea 100644 --- a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp @@ -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; @@ -60,6 +61,19 @@ const char color_copy_program_code[] = { "}\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));\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" @@ -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 @@ -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]); diff --git a/Source/Core/VideoBackends/D3D/PixelShaderCache.h b/Source/Core/VideoBackends/D3D/PixelShaderCache.h index 55a31379e3..413a7c31a4 100644 --- a/Source/Core/VideoBackends/D3D/PixelShaderCache.h +++ b/Source/Core/VideoBackends/D3D/PixelShaderCache.h @@ -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); diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 2dcb8ee6b7..9db7d2ac0d 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -838,7 +838,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co } else { - D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), nullptr, Gamma); + 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); } } diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 879c0726a9..fa5a52772b 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -50,7 +50,7 @@ enum StereoMode STEREO_SBS, STEREO_TAB, STEREO_ANAGLYPH, - STEREO_3DVISION = STEREO_ANAGLYPH + STEREO_3DVISION }; // NEVER inherit from this class. From b2e73400be47fe7765fc6a7a7fb6516e24c78b7d Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 29 Nov 2014 21:37:34 +0100 Subject: [PATCH 18/24] Cosmetics --- Source/Core/VideoBackends/D3D/Render.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 9db7d2ac0d..ef5a3d8894 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -59,6 +59,7 @@ 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; @@ -808,14 +809,14 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co D3D::context->RSSetViewports(1, &rightVp); D3D::drawShadedTexQuad(read_texture->GetSRV(), targetRc.AsRECT(), Renderer::GetTargetWidth(), Renderer::GetTargetHeight(), PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(), 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); From 6fe7d530ed4e0eec54deb509745a5c17c2c50ae5 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 3 Dec 2014 14:20:46 +0100 Subject: [PATCH 19/24] PixelShaderCache: Fix MSAA shaders. Various typos were introduced due to lack of testing. --- .../VideoBackends/D3D/PixelShaderCache.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp index 621ae34cea..17290a5ba0 100644 --- a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp @@ -81,9 +81,9 @@ const char color_copy_program_code_msaa[] = { "void main(\n" "out float4 ocol0 : SV_Target,\n" "in float4 pos : SV_Position,\n" - "in float3 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(int3(uv0.x*(width), uv0.y*(height), uv0.z), i);\n" @@ -113,11 +113,11 @@ const char color_matrix_program_code_msaa[] = { "out float4 ocol0 : SV_Target,\n" "in float4 pos : SV_Position,\n" "in float3 uv0 : TEXCOORD0){\n" - "int width, height, samples;\n" - "Tex0.GetDimensions(width, height, samples);\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), uv0.z), 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" @@ -167,11 +167,11 @@ const char depth_matrix_program_msaa[] = { "out float4 ocol0 : SV_Target,\n" " in float4 pos : SV_Position,\n" " in float3 uv0 : TEXCOORD0){\n" - " int width, height, samples;\n" - " Tex0.GetDimensions(width, height, samples);\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), uv0.z), i);\n" + " texcol += Tex0.Load(int3(uv0.x*(width), uv0.y*(height), uv0.z), i);\n" " texcol /= samples;\n" // 255.99998474121 = 16777215/16777216*256 From ea2bcb44f0d860355fd60521d5fa9a37b6fb15a1 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 3 Dec 2014 22:35:34 +0100 Subject: [PATCH 20/24] Cosmetics --- Source/Core/VideoCommon/GeometryShaderGen.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index b75eddd87a..187af8b088 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -85,19 +85,19 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy if (g_ActiveConfig.backend_info.bSupportsGSInstancing) { if (ApiType == API_OPENGL) - out.Write("\tint l = gl_InvocationID;\n"); + out.Write("\tint layer = gl_InvocationID;\n"); else - out.Write("\tint l = InstanceID;\n"); + out.Write("\tint layer = InstanceID;\n"); } else - out.Write("\tfor (int l = 0; l < %d; ++l) {\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1); + out.Write("\tfor (int layer = 0; layer < %d; ++layer) {\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1); out.Write("\tfor (int i = 0; i < 3; ++i) {\n"); // Select the output layer - out.Write("\t\tgs.layer = l;\n"); + out.Write("\t\tgs.layer = layer;\n"); if (ApiType == API_OPENGL) - out.Write("\t\tgl_Layer = l;\n"); + out.Write("\t\tgl_Layer = layer;\n"); out.Write("\t\tf = o[i];\n"); out.Write("\t\tfloat4 pos = o[i].pos;\n"); @@ -111,8 +111,8 @@ 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"[layer] * (o[i].clipPos.w - " I_STEREOPARAMS"[2]);\n"); + out.Write("\t\tpos.x = o[i].pos.x + " I_STEREOPARAMS"[layer] * (o[i].pos.w - " I_STEREOPARAMS"[2]);\n"); } out.Write("\t\tf.pos.x = pos.x;\n"); From a6ac7dd5bd9c68c006502d4f3e6342e2d01a6a2b Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 3 Dec 2014 22:39:00 +0100 Subject: [PATCH 21/24] D3D: Fix Nvidia 3D Vision memory leak --- Source/Core/VideoBackends/D3D/Render.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index ef5a3d8894..86f93fc9ad 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -184,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(); From fd6b5886270a1433cc315895f30036e4bd4729f0 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 5 Dec 2014 13:53:30 +0100 Subject: [PATCH 22/24] D3D: Define decimals in floating point numbers --- Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp | 8 ++++---- Source/Core/VideoBackends/D3D/PixelShaderCache.cpp | 2 +- Source/Core/VideoCommon/PixelShaderGen.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp index be0e6461e8..fcc40cc9e5 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp @@ -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, float3(texCoord.xy, 0));\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, float3(texCoord.xy, 0));\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, float3(texCoord.xy, 0));\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, float3(texCoord.xy, 0)).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 diff --git a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp index 17290a5ba0..02a373e709 100644 --- a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp @@ -68,7 +68,7 @@ const char anaglyph_program_code[] = { "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));\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" diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 0e18db536e..b925b826d3 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -941,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, float3(%s.xy * " I_TEXDIMS"[%d].xy, %s))).%s;\n", texmap, texmap, texcoords, texmap, g_ActiveConfig.iStereoMode > 0 ? "layer" : "0", 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 ? "gs.layer" : "0.0", texswap); } From cec5b0ce01abbcee654c7c8ca609cb66d5af4cf0 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 3 Dec 2014 22:35:34 +0100 Subject: [PATCH 23/24] ShaderGen: Remove the GS_OUTPUT struct for OpenGL. And remove the generator for it since it is no longer used outside of the geometry shader. --- Source/Core/VideoCommon/GeometryShaderGen.cpp | 29 ++++++++++++------- Source/Core/VideoCommon/PixelShaderGen.cpp | 16 +++++----- Source/Core/VideoCommon/ShaderGenCommon.h | 11 ------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 187af8b088..57009aedaa 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -53,17 +53,22 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting; GenerateVSOutputStruct(out, ApiType); - GenerateGSOutputStruct(out, ApiType); if (ApiType == API_OPENGL) { out.Write("centroid in VS_OUTPUT o[3];\n"); - out.Write("centroid out GS_OUTPUT gs;\n"); + out.Write("centroid out VS_OUTPUT vs;\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"); + if (g_ActiveConfig.backend_info.bSupportsGSInstancing) { out.Write("[maxvertexcount(3)]\n[instance(%d)]\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1); @@ -85,19 +90,23 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy if (g_ActiveConfig.backend_info.bSupportsGSInstancing) { if (ApiType == API_OPENGL) - out.Write("\tint layer = gl_InvocationID;\n"); + out.Write("\tint eye = gl_InvocationID;\n"); else - out.Write("\tint layer = InstanceID;\n"); + out.Write("\tint eye = InstanceID;\n"); } else - out.Write("\tfor (int layer = 0; layer < %d; ++layer) {\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"); // Select the output layer - out.Write("\t\tgs.layer = layer;\n"); if (ApiType == API_OPENGL) - out.Write("\t\tgl_Layer = layer;\n"); + { + 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"); @@ -111,8 +120,8 @@ 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"[layer] * (o[i].clipPos.w - " I_STEREOPARAMS"[2]);\n"); - out.Write("\t\tpos.x = o[i].pos.x + " I_STEREOPARAMS"[layer] * (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"); @@ -120,7 +129,7 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy if (ApiType == API_OPENGL) out.Write("\t\tgl_Position = pos;\n"); - out.Write("\t\tgs.vs = f;\n"); + out.Write("\t\t%s = f;\n", (ApiType == API_OPENGL) ? "vs" : "gs.vs"); if (ApiType == API_OPENGL) out.Write("\t\tEmitVertex();\n"); diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index b925b826d3..48cd5b8fec 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -265,7 +265,6 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T } GenerateVSOutputStruct(out, ApiType); - GenerateGSOutputStruct(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); @@ -320,7 +319,8 @@ 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 GS_OUTPUT gs;\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 = gs.vs.tex%d;\n", i, i); + out.Write("\tfloat3 uv%d = vs.tex%d;\n", i, i); } - out.Write("\tfloat4 clipPos = gs.vs.clipPos;\n"); + out.Write("\tfloat4 clipPos = vs.clipPos;\n"); if (g_ActiveConfig.bEnablePixelLighting) { - out.Write("\tfloat4 Normal = gs.vs.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) ? "gs.vs.colors_0" : "colors_02"); - out.Write("\tfloat4 colors_1 = %s;\n", (g_ActiveConfig.iStereoMode > 0) ? "gs.vs.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"); } @@ -943,7 +943,7 @@ static inline void SampleTexture(T& out, const char *texcoords, const char *texs if (ApiType == API_D3D) 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 ? "gs.layer" : "0.0", texswap); + 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); } static const char *tevAlphaFuncsTable[] = diff --git a/Source/Core/VideoCommon/ShaderGenCommon.h b/Source/Core/VideoCommon/ShaderGenCommon.h index ed9bab9fca..618d262374 100644 --- a/Source/Core/VideoCommon/ShaderGenCommon.h +++ b/Source/Core/VideoCommon/ShaderGenCommon.h @@ -258,17 +258,6 @@ static inline void GenerateVSOutputStruct(T& object, API_TYPE api_type) object.Write("};\n"); } -template -static inline void GenerateGSOutputStruct(T& object, API_TYPE api_type) -{ - object.Write("struct GS_OUTPUT {\n"); - - DefineOutputStructMember(object, api_type, "VS_OUTPUT", "vs", -1, ""); - DefineOutputStructMember(object, api_type, (api_type == API_OPENGL) ? "flat int" : "uint", "layer", -1, "SV_RenderTargetArrayIndex"); - - object.Write("};\n"); -} - // Constant variable names #define I_COLORS "color" #define I_KCOLORS "k" From 6c7bed25a541a3093a9e9e6c43751b34592e42c0 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 12 Dec 2014 17:25:16 +0100 Subject: [PATCH 24/24] Cosmetics --- Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp | 2 +- Source/Core/VideoBackends/D3D/GeometryShaderCache.h | 2 +- Source/Core/VideoBackends/D3D/PixelShaderCache.cpp | 2 +- Source/Core/VideoBackends/D3D/VertexShaderCache.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp index 03facfb674..29172f91a1 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp @@ -41,7 +41,7 @@ ID3D11Buffer* gscbuf = nullptr; class GeometryShaderCacheInserter : public LinearDiskCacheReader { public: - void Read(const GeometryShaderUid &key, const u8 *value, u32 value_size) + void Read(const GeometryShaderUid &key, const u8* value, u32 value_size) { GeometryShaderCache::InsertByteCode(key, value, value_size); } diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h index 95672a0087..9d38922d04 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h @@ -46,4 +46,4 @@ private: static UidChecker geometry_uid_checker; }; -} // namespace DX11 \ No newline at end of file +} // namespace DX11 diff --git a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp index 02a373e709..d8fbd62158 100644 --- a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp @@ -424,7 +424,7 @@ ID3D11Buffer* &PixelShaderCache::GetConstantBuffer() class PixelShaderCacheInserter : public LinearDiskCacheReader { 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); } diff --git a/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp b/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp index 0abe6f1586..9dfd87691e 100644 --- a/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp @@ -60,7 +60,7 @@ ID3D11Buffer* &VertexShaderCache::GetConstantBuffer() class VertexShaderCacheInserter : public LinearDiskCacheReader { 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);