mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-29 17:19:44 -06:00
Move most backend functionality to VideoCommon
This commit is contained in:
@ -5,6 +5,7 @@
|
||||
#include "VideoBackends/D3D/BoundingBox.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
namespace DX11
|
||||
@ -54,6 +55,7 @@ void BBox::Init()
|
||||
hr = D3D::device->CreateUnorderedAccessView(s_bbox_buffer, &UAVdesc, &s_bbox_uav);
|
||||
CHECK(SUCCEEDED(hr), "Create BoundingBox UAV.");
|
||||
D3D::SetDebugObjectName(s_bbox_uav, "BoundingBox UAV");
|
||||
D3D::stateman->SetOMUAV(s_bbox_uav);
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,4 +85,4 @@ int BBox::Get(int index)
|
||||
D3D::context->Unmap(s_bbox_staging_buffer, 0);
|
||||
return data;
|
||||
}
|
||||
};
|
||||
}; // namespace DX11
|
||||
|
@ -3,42 +3,22 @@ add_library(videod3d
|
||||
BoundingBox.h
|
||||
D3DBase.cpp
|
||||
D3DBase.h
|
||||
D3DBlob.cpp
|
||||
D3DBlob.h
|
||||
D3DShader.cpp
|
||||
D3DShader.h
|
||||
D3DState.cpp
|
||||
D3DState.h
|
||||
D3DTexture.cpp
|
||||
D3DTexture.h
|
||||
D3DUtil.cpp
|
||||
D3DUtil.h
|
||||
DXPipeline.cpp
|
||||
DXPipeline.h
|
||||
DXShader.cpp
|
||||
DXShader.h
|
||||
DXTexture.cpp
|
||||
DXTexture.h
|
||||
FramebufferManager.cpp
|
||||
FramebufferManager.h
|
||||
GeometryShaderCache.cpp
|
||||
GeometryShaderCache.h
|
||||
main.cpp
|
||||
NativeVertexFormat.cpp
|
||||
PerfQuery.cpp
|
||||
PerfQuery.h
|
||||
PixelShaderCache.cpp
|
||||
PixelShaderCache.h
|
||||
PSTextureEncoder.cpp
|
||||
PSTextureEncoder.h
|
||||
Render.cpp
|
||||
Render.h
|
||||
TextureCache.cpp
|
||||
TextureCache.h
|
||||
VertexManager.cpp
|
||||
VertexManager.h
|
||||
VertexShaderCache.cpp
|
||||
VertexShaderCache.h
|
||||
VideoBackend.h
|
||||
)
|
||||
|
||||
|
@ -38,46 +38,26 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BoundingBox.cpp" />
|
||||
<ClCompile Include="D3DBase.cpp" />
|
||||
<ClCompile Include="D3DBlob.cpp" />
|
||||
<ClCompile Include="D3DShader.cpp" />
|
||||
<ClCompile Include="D3DState.cpp" />
|
||||
<ClCompile Include="D3DTexture.cpp" />
|
||||
<ClCompile Include="D3DUtil.cpp" />
|
||||
<ClCompile Include="DXPipeline.cpp" />
|
||||
<ClCompile Include="DXShader.cpp" />
|
||||
<ClCompile Include="DXTexture.cpp" />
|
||||
<ClCompile Include="FramebufferManager.cpp" />
|
||||
<ClCompile Include="GeometryShaderCache.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="NativeVertexFormat.cpp" />
|
||||
<ClCompile Include="PerfQuery.cpp" />
|
||||
<ClCompile Include="PixelShaderCache.cpp" />
|
||||
<ClCompile Include="PSTextureEncoder.cpp" />
|
||||
<ClCompile Include="Render.cpp" />
|
||||
<ClCompile Include="TextureCache.cpp" />
|
||||
<ClCompile Include="VertexManager.cpp" />
|
||||
<ClCompile Include="VertexShaderCache.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BoundingBox.h" />
|
||||
<ClInclude Include="D3DBase.h" />
|
||||
<ClInclude Include="D3DBlob.h" />
|
||||
<ClInclude Include="D3DShader.h" />
|
||||
<ClInclude Include="D3DState.h" />
|
||||
<ClInclude Include="D3DTexture.h" />
|
||||
<ClInclude Include="D3DUtil.h" />
|
||||
<ClInclude Include="DXPipeline.h" />
|
||||
<ClInclude Include="DXShader.h" />
|
||||
<ClInclude Include="DXTexture.h" />
|
||||
<ClInclude Include="FramebufferManager.h" />
|
||||
<ClInclude Include="GeometryShaderCache.h" />
|
||||
<ClInclude Include="PerfQuery.h" />
|
||||
<ClInclude Include="PixelShaderCache.h" />
|
||||
<ClInclude Include="PSTextureEncoder.h" />
|
||||
<ClInclude Include="Render.h" />
|
||||
<ClInclude Include="TextureCache.h" />
|
||||
<ClInclude Include="VertexManager.h" />
|
||||
<ClInclude Include="VertexShaderCache.h" />
|
||||
<ClInclude Include="VideoBackend.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -12,51 +12,21 @@
|
||||
<ClCompile Include="D3DBase.cpp">
|
||||
<Filter>D3D</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="D3DBlob.cpp">
|
||||
<Filter>D3D</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="D3DShader.cpp">
|
||||
<Filter>D3D</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="D3DTexture.cpp">
|
||||
<Filter>D3D</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="D3DUtil.cpp">
|
||||
<Filter>D3D</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="D3DState.cpp">
|
||||
<Filter>D3D</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FramebufferManager.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GeometryShaderCache.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NativeVertexFormat.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PerfQuery.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PixelShaderCache.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PSTextureEncoder.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Render.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TextureCache.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VertexManager.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VertexShaderCache.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="BoundingBox.cpp">
|
||||
<Filter>Render</Filter>
|
||||
@ -75,48 +45,18 @@
|
||||
<ClInclude Include="D3DBase.h">
|
||||
<Filter>D3D</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="D3DBlob.h">
|
||||
<Filter>D3D</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="D3DShader.h">
|
||||
<Filter>D3D</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="D3DTexture.h">
|
||||
<Filter>D3D</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="D3DUtil.h">
|
||||
<Filter>D3D</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="D3DState.h">
|
||||
<Filter>D3D</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FramebufferManager.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GeometryShaderCache.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PerfQuery.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PixelShaderCache.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PSTextureEncoder.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Render.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TextureCache.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VertexManager.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VertexShaderCache.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VideoBackend.h" />
|
||||
<ClInclude Include="BoundingBox.h">
|
||||
<Filter>Render</Filter>
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/D3DTexture.h"
|
||||
#include "VideoBackends/D3D/DXTexture.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
namespace DX11
|
||||
@ -42,7 +42,8 @@ IDXGISwapChain1* swapchain = nullptr;
|
||||
static IDXGIFactory2* s_dxgi_factory;
|
||||
static ID3D11Debug* s_debug;
|
||||
static D3D_FEATURE_LEVEL s_featlevel;
|
||||
static D3DTexture2D* s_backbuf;
|
||||
static std::unique_ptr<DXTexture> s_swap_chain_texture;
|
||||
static std::unique_ptr<DXFramebuffer> s_swap_chain_framebuffer;
|
||||
|
||||
static std::vector<DXGI_SAMPLE_DESC> s_aa_modes; // supported AA modes of the current adapter
|
||||
|
||||
@ -244,18 +245,40 @@ static bool SupportsBPTCTextures(ID3D11Device* dev)
|
||||
return (bc7_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
|
||||
}
|
||||
|
||||
static bool CreateSwapChainTextures()
|
||||
static bool CreateSwapChainFramebuffer()
|
||||
{
|
||||
ID3D11Texture2D* buf;
|
||||
HRESULT hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf);
|
||||
ID3D11Texture2D* texture;
|
||||
HRESULT hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&texture);
|
||||
CHECK(SUCCEEDED(hr), "GetBuffer for swap chain failed with HRESULT %08X", hr);
|
||||
if (FAILED(hr))
|
||||
return false;
|
||||
|
||||
s_backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
|
||||
SAFE_RELEASE(buf);
|
||||
SetDebugObjectName(s_backbuf->GetTex(), "backbuffer texture");
|
||||
SetDebugObjectName(s_backbuf->GetRTV(), "backbuffer render target view");
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
texture->GetDesc(&desc);
|
||||
|
||||
s_swap_chain_texture = std::make_unique<DXTexture>(
|
||||
TextureConfig(desc.Width, desc.Height, desc.MipLevels, desc.ArraySize, desc.SampleDesc.Count,
|
||||
AbstractTextureFormat::RGBA8, AbstractTextureFlag_RenderTarget),
|
||||
texture, nullptr, nullptr);
|
||||
|
||||
ID3D11RenderTargetView* rtv;
|
||||
CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(texture, D3D11_RTV_DIMENSION_TEXTURE2DARRAY, desc.Format,
|
||||
0, 0, desc.ArraySize);
|
||||
hr = device->CreateRenderTargetView(texture, &rtv_desc, &rtv);
|
||||
CHECK(SUCCEEDED(hr), "Create render target view for swap chain");
|
||||
if (FAILED(hr))
|
||||
{
|
||||
s_swap_chain_texture.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
SetDebugObjectName(texture, "backbuffer texture");
|
||||
SetDebugObjectName(rtv, "backbuffer render target view");
|
||||
s_swap_chain_framebuffer = std::make_unique<DXFramebuffer>(
|
||||
s_swap_chain_texture.get(), nullptr, AbstractTextureFormat::RGBA8,
|
||||
AbstractTextureFormat::Undefined, desc.Width, desc.Height, desc.ArraySize,
|
||||
desc.SampleDesc.Count, rtv, nullptr, nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -300,7 +323,7 @@ static bool CreateSwapChain(HWND hWnd)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateSwapChainTextures())
|
||||
if (!CreateSwapChainFramebuffer())
|
||||
{
|
||||
SAFE_RELEASE(swapchain);
|
||||
return false;
|
||||
@ -451,7 +474,8 @@ void Close()
|
||||
|
||||
// release all bound resources
|
||||
context->ClearState();
|
||||
SAFE_RELEASE(s_backbuf);
|
||||
s_swap_chain_framebuffer.reset();
|
||||
s_swap_chain_texture.reset();
|
||||
SAFE_RELEASE(swapchain);
|
||||
SAFE_DELETE(stateman);
|
||||
context->Flush(); // immediately destroy device objects
|
||||
@ -527,9 +551,13 @@ const char* ComputeShaderVersionString()
|
||||
return "cs_4_0";
|
||||
}
|
||||
|
||||
D3DTexture2D* GetBackBuffer()
|
||||
DXTexture* GetSwapChainTexture()
|
||||
{
|
||||
return s_backbuf;
|
||||
return s_swap_chain_texture.get();
|
||||
}
|
||||
DXFramebuffer* GetSwapChainFramebuffer()
|
||||
{
|
||||
return s_swap_chain_framebuffer.get();
|
||||
}
|
||||
bool BGRATexturesSupported()
|
||||
{
|
||||
@ -568,7 +596,8 @@ u32 GetMaxTextureSize(D3D_FEATURE_LEVEL feature_level)
|
||||
|
||||
void Reset(HWND new_wnd)
|
||||
{
|
||||
SAFE_RELEASE(s_backbuf);
|
||||
s_swap_chain_framebuffer.reset();
|
||||
s_swap_chain_texture.reset();
|
||||
|
||||
if (swapchain)
|
||||
{
|
||||
@ -583,10 +612,11 @@ void Reset(HWND new_wnd)
|
||||
|
||||
void ResizeSwapChain()
|
||||
{
|
||||
SAFE_RELEASE(s_backbuf);
|
||||
s_swap_chain_framebuffer.reset();
|
||||
s_swap_chain_texture.reset();
|
||||
const UINT swap_chain_flags = AllowTearingSupported() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
|
||||
swapchain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_R8G8B8A8_UNORM, swap_chain_flags);
|
||||
if (!CreateSwapChainTextures())
|
||||
if (!CreateSwapChainFramebuffer())
|
||||
{
|
||||
PanicAlert("Failed to get swap chain textures");
|
||||
SAFE_RELEASE(swapchain);
|
||||
|
@ -38,7 +38,8 @@ namespace DX11
|
||||
PanicAlert("%s failed in %s at line %d: " Message, __func__, __FILE__, __LINE__, __VA_ARGS__); \
|
||||
}
|
||||
|
||||
class D3DTexture2D;
|
||||
class DXTexture;
|
||||
class DXFramebuffer;
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
@ -64,7 +65,8 @@ void Reset(HWND new_wnd);
|
||||
void ResizeSwapChain();
|
||||
void Present();
|
||||
|
||||
D3DTexture2D* GetBackBuffer();
|
||||
DXTexture* GetSwapChainTexture();
|
||||
DXFramebuffer* GetSwapChainFramebuffer();
|
||||
const char* PixelShaderVersionString();
|
||||
const char* GeometryShaderVersionString();
|
||||
const char* VertexShaderVersionString();
|
||||
|
@ -1,60 +0,0 @@
|
||||
// Copyright 2010 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <d3d11.h>
|
||||
|
||||
#include "VideoBackends/D3D/D3DBlob.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
D3DBlob::D3DBlob(unsigned int blob_size, const u8* init_data)
|
||||
: ref(1), size(blob_size), blob(nullptr)
|
||||
{
|
||||
data = new u8[blob_size];
|
||||
if (init_data)
|
||||
memcpy(data, init_data, size);
|
||||
}
|
||||
|
||||
D3DBlob::D3DBlob(ID3D10Blob* d3dblob) : ref(1)
|
||||
{
|
||||
blob = d3dblob;
|
||||
data = (u8*)blob->GetBufferPointer();
|
||||
size = (unsigned int)blob->GetBufferSize();
|
||||
d3dblob->AddRef();
|
||||
}
|
||||
|
||||
D3DBlob::~D3DBlob()
|
||||
{
|
||||
if (blob)
|
||||
blob->Release();
|
||||
else
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
void D3DBlob::AddRef()
|
||||
{
|
||||
++ref;
|
||||
}
|
||||
|
||||
unsigned int D3DBlob::Release()
|
||||
{
|
||||
if (--ref == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
unsigned int D3DBlob::Size() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
u8* D3DBlob::Data()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
} // namespace DX11
|
@ -1,39 +0,0 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
struct ID3D10Blob;
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
// use this class instead ID3D10Blob or ID3D11Blob whenever possible
|
||||
class D3DBlob
|
||||
{
|
||||
public:
|
||||
// memory will be copied into an own buffer
|
||||
D3DBlob(unsigned int blob_size, const u8* init_data = nullptr);
|
||||
|
||||
// d3dblob will be AddRef'd
|
||||
D3DBlob(ID3D10Blob* d3dblob);
|
||||
|
||||
void AddRef();
|
||||
unsigned int Release();
|
||||
|
||||
unsigned int Size() const;
|
||||
u8* Data();
|
||||
|
||||
private:
|
||||
~D3DBlob();
|
||||
|
||||
unsigned int ref;
|
||||
unsigned int size;
|
||||
|
||||
u8* data;
|
||||
ID3D10Blob* blob;
|
||||
};
|
||||
|
||||
} // namespace
|
@ -1,304 +0,0 @@
|
||||
// Copyright 2010 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DShader.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
namespace D3D
|
||||
{
|
||||
// bytecode->shader
|
||||
ID3D11VertexShader* CreateVertexShaderFromByteCode(const void* bytecode, size_t len)
|
||||
{
|
||||
ID3D11VertexShader* v_shader;
|
||||
HRESULT hr = D3D::device->CreateVertexShader(bytecode, len, nullptr, &v_shader);
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
|
||||
return v_shader;
|
||||
}
|
||||
|
||||
// code->bytecode
|
||||
bool CompileVertexShader(const std::string& code, D3DBlob** blob)
|
||||
{
|
||||
ID3D10Blob* shaderBuffer = nullptr;
|
||||
ID3D10Blob* errorBuffer = nullptr;
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY | D3D10_SHADER_DEBUG;
|
||||
#else
|
||||
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY | D3D10_SHADER_OPTIMIZATION_LEVEL3 |
|
||||
D3D10_SHADER_SKIP_VALIDATION;
|
||||
#endif
|
||||
HRESULT hr = PD3DCompile(code.c_str(), code.length(), nullptr, nullptr, nullptr, "main",
|
||||
D3D::VertexShaderVersionString(), flags, 0, &shaderBuffer, &errorBuffer);
|
||||
if (errorBuffer)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Vertex shader compiler messages:\n%s",
|
||||
(const char*)errorBuffer->GetBufferPointer());
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
static int num_failures = 0;
|
||||
std::string filename = StringFromFormat("%sbad_vs_%04i.txt",
|
||||
File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
||||
std::ofstream file;
|
||||
File::OpenFStream(file, filename, std::ios_base::out);
|
||||
file << code;
|
||||
file.close();
|
||||
|
||||
PanicAlert("Failed to compile vertex shader: %s\nDebug info (%s):\n%s", filename.c_str(),
|
||||
D3D::VertexShaderVersionString(), (const char*)errorBuffer->GetBufferPointer());
|
||||
|
||||
*blob = nullptr;
|
||||
errorBuffer->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
*blob = new D3DBlob(shaderBuffer);
|
||||
shaderBuffer->Release();
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
// bytecode->shader
|
||||
ID3D11GeometryShader* CreateGeometryShaderFromByteCode(const void* bytecode, size_t len)
|
||||
{
|
||||
ID3D11GeometryShader* g_shader;
|
||||
HRESULT hr = D3D::device->CreateGeometryShader(bytecode, len, nullptr, &g_shader);
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
|
||||
return g_shader;
|
||||
}
|
||||
|
||||
// code->bytecode
|
||||
bool CompileGeometryShader(const std::string& code, D3DBlob** blob,
|
||||
const D3D_SHADER_MACRO* pDefines)
|
||||
{
|
||||
ID3D10Blob* shaderBuffer = nullptr;
|
||||
ID3D10Blob* errorBuffer = nullptr;
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY | D3D10_SHADER_DEBUG;
|
||||
#else
|
||||
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY | D3D10_SHADER_OPTIMIZATION_LEVEL3 |
|
||||
D3D10_SHADER_SKIP_VALIDATION;
|
||||
#endif
|
||||
HRESULT hr =
|
||||
PD3DCompile(code.c_str(), code.length(), nullptr, pDefines, nullptr, "main",
|
||||
D3D::GeometryShaderVersionString(), flags, 0, &shaderBuffer, &errorBuffer);
|
||||
|
||||
if (errorBuffer)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Geometry shader compiler messages:\n%s",
|
||||
(const char*)errorBuffer->GetBufferPointer());
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
static int num_failures = 0;
|
||||
std::string filename = StringFromFormat("%sbad_gs_%04i.txt",
|
||||
File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
||||
std::ofstream file;
|
||||
File::OpenFStream(file, filename, std::ios_base::out);
|
||||
file << code;
|
||||
file.close();
|
||||
|
||||
PanicAlert("Failed to compile geometry shader: %s\nDebug info (%s):\n%s", filename.c_str(),
|
||||
D3D::GeometryShaderVersionString(), (const char*)errorBuffer->GetBufferPointer());
|
||||
|
||||
*blob = nullptr;
|
||||
errorBuffer->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
*blob = new D3DBlob(shaderBuffer);
|
||||
shaderBuffer->Release();
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
// bytecode->shader
|
||||
ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, size_t len)
|
||||
{
|
||||
ID3D11PixelShader* p_shader;
|
||||
HRESULT hr = D3D::device->CreatePixelShader(bytecode, len, nullptr, &p_shader);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("CreatePixelShaderFromByteCode failed at %s %d\n", __FILE__, __LINE__);
|
||||
p_shader = nullptr;
|
||||
}
|
||||
return p_shader;
|
||||
}
|
||||
|
||||
// code->bytecode
|
||||
bool CompilePixelShader(const std::string& code, D3DBlob** blob, const D3D_SHADER_MACRO* pDefines)
|
||||
{
|
||||
ID3D10Blob* shaderBuffer = nullptr;
|
||||
ID3D10Blob* errorBuffer = nullptr;
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
UINT flags = D3D10_SHADER_DEBUG;
|
||||
#else
|
||||
UINT flags = D3D10_SHADER_OPTIMIZATION_LEVEL3;
|
||||
#endif
|
||||
HRESULT hr = PD3DCompile(code.c_str(), code.length(), nullptr, pDefines, nullptr, "main",
|
||||
D3D::PixelShaderVersionString(), flags, 0, &shaderBuffer, &errorBuffer);
|
||||
|
||||
if (errorBuffer)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Pixel shader compiler messages:\n%s",
|
||||
(const char*)errorBuffer->GetBufferPointer());
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
static int num_failures = 0;
|
||||
std::string filename = StringFromFormat("%sbad_ps_%04i.txt",
|
||||
File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
||||
std::ofstream file;
|
||||
File::OpenFStream(file, filename, std::ios_base::out);
|
||||
file << code;
|
||||
file.close();
|
||||
|
||||
PanicAlert("Failed to compile pixel shader: %s\nDebug info (%s):\n%s", filename.c_str(),
|
||||
D3D::PixelShaderVersionString(), (const char*)errorBuffer->GetBufferPointer());
|
||||
|
||||
*blob = nullptr;
|
||||
errorBuffer->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
*blob = new D3DBlob(shaderBuffer);
|
||||
shaderBuffer->Release();
|
||||
}
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
// bytecode->shader
|
||||
ID3D11ComputeShader* CreateComputeShaderFromByteCode(const void* bytecode, size_t len)
|
||||
{
|
||||
ID3D11ComputeShader* shader;
|
||||
HRESULT hr = D3D::device->CreateComputeShader(bytecode, len, nullptr, &shader);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("CreateComputeShaderFromByteCode failed at %s %d\n", __FILE__, __LINE__);
|
||||
return nullptr;
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
// code->bytecode
|
||||
bool CompileComputeShader(const std::string& code, D3DBlob** blob, const D3D_SHADER_MACRO* pDefines)
|
||||
{
|
||||
ID3D10Blob* shaderBuffer = nullptr;
|
||||
ID3D10Blob* errorBuffer = nullptr;
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
UINT flags = D3D10_SHADER_DEBUG;
|
||||
#else
|
||||
UINT flags = D3D10_SHADER_OPTIMIZATION_LEVEL3;
|
||||
#endif
|
||||
HRESULT hr =
|
||||
PD3DCompile(code.c_str(), code.length(), nullptr, pDefines, nullptr, "main",
|
||||
D3D::ComputeShaderVersionString(), flags, 0, &shaderBuffer, &errorBuffer);
|
||||
|
||||
if (errorBuffer)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Compute shader compiler messages:\n%s",
|
||||
(const char*)errorBuffer->GetBufferPointer());
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
static int num_failures = 0;
|
||||
std::string filename = StringFromFormat("%sbad_cs_%04i.txt",
|
||||
File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
|
||||
std::ofstream file;
|
||||
File::OpenFStream(file, filename, std::ios_base::out);
|
||||
file << code;
|
||||
file.close();
|
||||
|
||||
PanicAlert("Failed to compile compute shader: %s\nDebug info (%s):\n%s", filename.c_str(),
|
||||
D3D::ComputeShaderVersionString(),
|
||||
reinterpret_cast<const char*>(errorBuffer->GetBufferPointer()));
|
||||
|
||||
*blob = nullptr;
|
||||
errorBuffer->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
*blob = new D3DBlob(shaderBuffer);
|
||||
shaderBuffer->Release();
|
||||
}
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
ID3D11VertexShader* CompileAndCreateVertexShader(const std::string& code)
|
||||
{
|
||||
D3DBlob* blob = nullptr;
|
||||
if (CompileVertexShader(code, &blob))
|
||||
{
|
||||
ID3D11VertexShader* v_shader = CreateVertexShaderFromByteCode(blob);
|
||||
blob->Release();
|
||||
return v_shader;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ID3D11GeometryShader* CompileAndCreateGeometryShader(const std::string& code,
|
||||
const D3D_SHADER_MACRO* pDefines)
|
||||
{
|
||||
D3DBlob* blob = nullptr;
|
||||
if (CompileGeometryShader(code, &blob, pDefines))
|
||||
{
|
||||
ID3D11GeometryShader* g_shader = CreateGeometryShaderFromByteCode(blob);
|
||||
blob->Release();
|
||||
return g_shader;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ID3D11PixelShader* CompileAndCreatePixelShader(const std::string& code)
|
||||
{
|
||||
D3DBlob* blob = nullptr;
|
||||
CompilePixelShader(code, &blob);
|
||||
if (blob)
|
||||
{
|
||||
ID3D11PixelShader* p_shader = CreatePixelShaderFromByteCode(blob);
|
||||
blob->Release();
|
||||
return p_shader;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ID3D11ComputeShader* CompileAndCreateComputeShader(const std::string& code)
|
||||
{
|
||||
D3DBlob* blob = nullptr;
|
||||
CompileComputeShader(code, &blob);
|
||||
if (blob)
|
||||
{
|
||||
ID3D11ComputeShader* shader = CreateComputeShaderFromByteCode(blob);
|
||||
blob->Release();
|
||||
return shader;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace DX11
|
@ -1,78 +0,0 @@
|
||||
// Copyright 2010 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DBlob.h"
|
||||
|
||||
struct ID3D11PixelShader;
|
||||
struct ID3D11VertexShader;
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
namespace D3D
|
||||
{
|
||||
ID3D11VertexShader* CreateVertexShaderFromByteCode(const void* bytecode, size_t len);
|
||||
ID3D11GeometryShader* CreateGeometryShaderFromByteCode(const void* bytecode, size_t len);
|
||||
ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, size_t len);
|
||||
ID3D11ComputeShader* CreateComputeShaderFromByteCode(const void* bytecode, size_t len);
|
||||
|
||||
// The returned bytecode buffers should be Release()d.
|
||||
bool CompileVertexShader(const std::string& code, D3DBlob** blob);
|
||||
bool CompileGeometryShader(const std::string& code, D3DBlob** blob,
|
||||
const D3D_SHADER_MACRO* pDefines = nullptr);
|
||||
bool CompilePixelShader(const std::string& code, D3DBlob** blob,
|
||||
const D3D_SHADER_MACRO* pDefines = nullptr);
|
||||
bool CompileComputeShader(const std::string& code, D3DBlob** blob,
|
||||
const D3D_SHADER_MACRO* pDefines = nullptr);
|
||||
|
||||
// Utility functions
|
||||
ID3D11VertexShader* CompileAndCreateVertexShader(const std::string& code);
|
||||
ID3D11GeometryShader* CompileAndCreateGeometryShader(const std::string& code,
|
||||
const D3D_SHADER_MACRO* pDefines = nullptr);
|
||||
ID3D11PixelShader* CompileAndCreatePixelShader(const std::string& code);
|
||||
ID3D11ComputeShader* CompileAndCreateComputeShader(const std::string& code);
|
||||
|
||||
inline ID3D11VertexShader* CreateVertexShaderFromByteCode(D3DBlob* bytecode)
|
||||
{
|
||||
return CreateVertexShaderFromByteCode(bytecode->Data(), bytecode->Size());
|
||||
}
|
||||
inline ID3D11GeometryShader* CreateGeometryShaderFromByteCode(D3DBlob* bytecode)
|
||||
{
|
||||
return CreateGeometryShaderFromByteCode(bytecode->Data(), bytecode->Size());
|
||||
}
|
||||
inline ID3D11PixelShader* CreatePixelShaderFromByteCode(D3DBlob* bytecode)
|
||||
{
|
||||
return CreatePixelShaderFromByteCode(bytecode->Data(), bytecode->Size());
|
||||
}
|
||||
inline ID3D11ComputeShader* CreateComputeShaderFromByteCode(D3DBlob* bytecode)
|
||||
{
|
||||
return CreateComputeShaderFromByteCode(bytecode->Data(), bytecode->Size());
|
||||
}
|
||||
|
||||
inline ID3D11VertexShader* CompileAndCreateVertexShader(D3DBlob* code)
|
||||
{
|
||||
return CompileAndCreateVertexShader(reinterpret_cast<const char*>(code->Data()));
|
||||
}
|
||||
|
||||
inline ID3D11GeometryShader*
|
||||
CompileAndCreateGeometryShader(D3DBlob* code, const D3D_SHADER_MACRO* pDefines = nullptr)
|
||||
{
|
||||
return CompileAndCreateGeometryShader(reinterpret_cast<const char*>(code->Data()), pDefines);
|
||||
}
|
||||
|
||||
inline ID3D11PixelShader* CompileAndCreatePixelShader(D3DBlob* code)
|
||||
{
|
||||
return CompileAndCreatePixelShader(reinterpret_cast<const char*>(code->Data()));
|
||||
}
|
||||
inline ID3D11ComputeShader* CompileAndCreateComputeShader(D3DBlob* code)
|
||||
{
|
||||
return CompileAndCreateComputeShader(reinterpret_cast<const char*>(code->Data()));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace DX11
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/DXTexture.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
namespace DX11
|
||||
@ -28,19 +29,31 @@ void StateManager::Apply()
|
||||
if (!m_dirtyFlags)
|
||||
return;
|
||||
|
||||
const int textureMaskShift = Common::LeastSignificantSetBit((u32)DirtyFlag_Texture0);
|
||||
const int samplerMaskShift = Common::LeastSignificantSetBit((u32)DirtyFlag_Sampler0);
|
||||
// Framebuffer changes must occur before texture changes, otherwise the D3D runtime messes with
|
||||
// our bindings and sets them to null to prevent hazards.
|
||||
if (m_dirtyFlags & DirtyFlag_Framebuffer)
|
||||
{
|
||||
if (g_ActiveConfig.backend_info.bSupportsBBox)
|
||||
{
|
||||
D3D::context->OMSetRenderTargetsAndUnorderedAccessViews(
|
||||
m_pending.framebuffer->GetNumRTVs(),
|
||||
m_pending.use_integer_rtv ? m_pending.framebuffer->GetIntegerRTVArray() :
|
||||
m_pending.framebuffer->GetRTVArray(),
|
||||
m_pending.framebuffer->GetDSV(), 2, 1, &m_pending.uav, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::context->OMSetRenderTargets(m_pending.framebuffer->GetNumRTVs(),
|
||||
m_pending.use_integer_rtv ?
|
||||
m_pending.framebuffer->GetIntegerRTVArray() :
|
||||
m_pending.framebuffer->GetRTVArray(),
|
||||
m_pending.framebuffer->GetDSV());
|
||||
}
|
||||
m_current.framebuffer = m_pending.framebuffer;
|
||||
m_current.uav = m_pending.uav;
|
||||
m_current.use_integer_rtv = m_pending.use_integer_rtv;
|
||||
}
|
||||
|
||||
u32 dirtyTextures =
|
||||
(m_dirtyFlags &
|
||||
(DirtyFlag_Texture0 | DirtyFlag_Texture1 | DirtyFlag_Texture2 | DirtyFlag_Texture3 |
|
||||
DirtyFlag_Texture4 | DirtyFlag_Texture5 | DirtyFlag_Texture6 | DirtyFlag_Texture7)) >>
|
||||
textureMaskShift;
|
||||
u32 dirtySamplers =
|
||||
(m_dirtyFlags &
|
||||
(DirtyFlag_Sampler0 | DirtyFlag_Sampler1 | DirtyFlag_Sampler2 | DirtyFlag_Sampler3 |
|
||||
DirtyFlag_Sampler4 | DirtyFlag_Sampler5 | DirtyFlag_Sampler6 | DirtyFlag_Sampler7)) >>
|
||||
samplerMaskShift;
|
||||
u32 dirtyConstants = m_dirtyFlags & (DirtyFlag_PixelConstants | DirtyFlag_VertexConstants |
|
||||
DirtyFlag_GeometryConstants);
|
||||
u32 dirtyShaders =
|
||||
@ -103,30 +116,6 @@ void StateManager::Apply()
|
||||
}
|
||||
}
|
||||
|
||||
while (dirtyTextures)
|
||||
{
|
||||
const int index = Common::LeastSignificantSetBit(dirtyTextures);
|
||||
if (m_current.textures[index] != m_pending.textures[index])
|
||||
{
|
||||
D3D::context->PSSetShaderResources(index, 1, &m_pending.textures[index]);
|
||||
m_current.textures[index] = m_pending.textures[index];
|
||||
}
|
||||
|
||||
dirtyTextures &= ~(1 << index);
|
||||
}
|
||||
|
||||
while (dirtySamplers)
|
||||
{
|
||||
const int index = Common::LeastSignificantSetBit(dirtySamplers);
|
||||
if (m_current.samplers[index] != m_pending.samplers[index])
|
||||
{
|
||||
D3D::context->PSSetSamplers(index, 1, &m_pending.samplers[index]);
|
||||
m_current.samplers[index] = m_pending.samplers[index];
|
||||
}
|
||||
|
||||
dirtySamplers &= ~(1 << index);
|
||||
}
|
||||
|
||||
if (dirtyShaders)
|
||||
{
|
||||
if (m_current.pixelShader != m_pending.pixelShader)
|
||||
@ -164,9 +153,51 @@ void StateManager::Apply()
|
||||
m_current.rasterizerState = m_pending.rasterizerState;
|
||||
}
|
||||
|
||||
ApplyTextures();
|
||||
|
||||
m_dirtyFlags = 0;
|
||||
}
|
||||
|
||||
void StateManager::ApplyTextures()
|
||||
{
|
||||
const int textureMaskShift = Common::LeastSignificantSetBit((u32)DirtyFlag_Texture0);
|
||||
const int samplerMaskShift = Common::LeastSignificantSetBit((u32)DirtyFlag_Sampler0);
|
||||
|
||||
u32 dirtyTextures =
|
||||
(m_dirtyFlags &
|
||||
(DirtyFlag_Texture0 | DirtyFlag_Texture1 | DirtyFlag_Texture2 | DirtyFlag_Texture3 |
|
||||
DirtyFlag_Texture4 | DirtyFlag_Texture5 | DirtyFlag_Texture6 | DirtyFlag_Texture7)) >>
|
||||
textureMaskShift;
|
||||
u32 dirtySamplers =
|
||||
(m_dirtyFlags &
|
||||
(DirtyFlag_Sampler0 | DirtyFlag_Sampler1 | DirtyFlag_Sampler2 | DirtyFlag_Sampler3 |
|
||||
DirtyFlag_Sampler4 | DirtyFlag_Sampler5 | DirtyFlag_Sampler6 | DirtyFlag_Sampler7)) >>
|
||||
samplerMaskShift;
|
||||
while (dirtyTextures)
|
||||
{
|
||||
const int index = Common::LeastSignificantSetBit(dirtyTextures);
|
||||
if (m_current.textures[index] != m_pending.textures[index])
|
||||
{
|
||||
D3D::context->PSSetShaderResources(index, 1, &m_pending.textures[index]);
|
||||
m_current.textures[index] = m_pending.textures[index];
|
||||
}
|
||||
|
||||
dirtyTextures &= ~(1 << index);
|
||||
}
|
||||
|
||||
while (dirtySamplers)
|
||||
{
|
||||
const int index = Common::LeastSignificantSetBit(dirtySamplers);
|
||||
if (m_current.samplers[index] != m_pending.samplers[index])
|
||||
{
|
||||
D3D::context->PSSetSamplers(index, 1, &m_pending.samplers[index]);
|
||||
m_current.samplers[index] = m_pending.samplers[index];
|
||||
}
|
||||
|
||||
dirtySamplers &= ~(1 << index);
|
||||
}
|
||||
}
|
||||
|
||||
u32 StateManager::UnsetTexture(ID3D11ShaderResourceView* srv)
|
||||
{
|
||||
u32 mask = 0;
|
||||
@ -193,6 +224,78 @@ void StateManager::SetTextureByMask(u32 textureSlotMask, ID3D11ShaderResourceVie
|
||||
}
|
||||
}
|
||||
|
||||
void StateManager::SetComputeUAV(ID3D11UnorderedAccessView* uav)
|
||||
{
|
||||
if (m_compute_image == uav)
|
||||
return;
|
||||
|
||||
m_compute_image = uav;
|
||||
D3D::context->CSSetUnorderedAccessViews(0, 1, &uav, nullptr);
|
||||
}
|
||||
|
||||
void StateManager::SetComputeShader(ID3D11ComputeShader* shader)
|
||||
{
|
||||
if (m_compute_shader == shader)
|
||||
return;
|
||||
|
||||
m_compute_shader = shader;
|
||||
D3D::context->CSSetShader(shader, nullptr, 0);
|
||||
}
|
||||
|
||||
void StateManager::SyncComputeBindings()
|
||||
{
|
||||
if (m_compute_constants != m_pending.pixelConstants[0])
|
||||
{
|
||||
m_compute_constants = m_pending.pixelConstants[0];
|
||||
D3D::context->CSSetConstantBuffers(0, 1, &m_compute_constants);
|
||||
}
|
||||
|
||||
for (u32 start = 0; start < static_cast<u32>(m_compute_textures.size());)
|
||||
{
|
||||
if (m_compute_textures[start] == m_pending.textures[start])
|
||||
{
|
||||
start++;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_compute_textures[start] = m_pending.textures[start];
|
||||
|
||||
u32 end = start + 1;
|
||||
for (; end < static_cast<u32>(m_compute_textures.size()); end++)
|
||||
{
|
||||
if (m_compute_textures[end] == m_pending.textures[end])
|
||||
break;
|
||||
|
||||
m_compute_textures[end] = m_pending.textures[end];
|
||||
}
|
||||
|
||||
D3D::context->CSSetShaderResources(start, end - start, &m_compute_textures[start]);
|
||||
start = end;
|
||||
}
|
||||
|
||||
for (u32 start = 0; start < static_cast<u32>(m_compute_samplers.size());)
|
||||
{
|
||||
if (m_compute_samplers[start] == m_pending.samplers[start])
|
||||
{
|
||||
start++;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_compute_samplers[start] = m_pending.samplers[start];
|
||||
|
||||
u32 end = start + 1;
|
||||
for (; end < static_cast<u32>(m_compute_samplers.size()); end++)
|
||||
{
|
||||
if (m_compute_samplers[end] == m_pending.samplers[end])
|
||||
break;
|
||||
|
||||
m_compute_samplers[end] = m_pending.samplers[end];
|
||||
}
|
||||
|
||||
D3D::context->CSSetSamplers(start, end - start, &m_compute_samplers[start]);
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
} // namespace D3D
|
||||
|
||||
StateCache::~StateCache()
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
class DXFramebuffer;
|
||||
|
||||
class StateCache
|
||||
{
|
||||
public:
|
||||
@ -112,14 +114,6 @@ public:
|
||||
m_pending.geometryConstants = buffer;
|
||||
}
|
||||
|
||||
void SetComputeConstants(ID3D11Buffer* buffer)
|
||||
{
|
||||
if (m_current.computeConstants != buffer)
|
||||
m_dirtyFlags |= DirtyFlag_ComputeConstants;
|
||||
|
||||
m_pending.computeConstants = buffer;
|
||||
}
|
||||
|
||||
void SetVertexBuffer(ID3D11Buffer* buffer, u32 stride, u32 offset)
|
||||
{
|
||||
if (m_current.vertexBuffer != buffer || m_current.vertexBufferStride != stride ||
|
||||
@ -187,22 +181,45 @@ public:
|
||||
m_pending.geometryShader = shader;
|
||||
}
|
||||
|
||||
void SetComputeShader(ID3D11ComputeShader* shader)
|
||||
void SetFramebuffer(DXFramebuffer* fb)
|
||||
{
|
||||
if (m_current.computeShader != shader)
|
||||
m_dirtyFlags |= DirtyFlag_ComputeShader;
|
||||
if (m_current.framebuffer != fb)
|
||||
m_dirtyFlags |= DirtyFlag_Framebuffer;
|
||||
|
||||
m_pending.computeShader = shader;
|
||||
m_pending.framebuffer = fb;
|
||||
}
|
||||
|
||||
void SetOMUAV(ID3D11UnorderedAccessView* uav)
|
||||
{
|
||||
if (m_current.uav != uav)
|
||||
m_dirtyFlags |= DirtyFlag_Framebuffer;
|
||||
|
||||
m_pending.uav = uav;
|
||||
}
|
||||
|
||||
void SetIntegerRTV(bool enable)
|
||||
{
|
||||
if (m_current.use_integer_rtv != enable)
|
||||
m_dirtyFlags |= DirtyFlag_Framebuffer;
|
||||
|
||||
m_pending.use_integer_rtv = enable;
|
||||
}
|
||||
|
||||
// removes currently set texture from all slots, returns mask of previously bound slots
|
||||
u32 UnsetTexture(ID3D11ShaderResourceView* srv);
|
||||
void SetTextureByMask(u32 textureSlotMask, ID3D11ShaderResourceView* srv);
|
||||
void ApplyTextures();
|
||||
|
||||
// call this immediately before any drawing operation or to explicitly apply pending resource
|
||||
// state changes
|
||||
void Apply();
|
||||
|
||||
// Binds constant buffers/textures/samplers to the compute shader stage.
|
||||
// We don't track these explicitly because it's not often-used.
|
||||
void SetComputeUAV(ID3D11UnorderedAccessView* uav);
|
||||
void SetComputeShader(ID3D11ComputeShader* shader);
|
||||
void SyncComputeBindings();
|
||||
|
||||
private:
|
||||
enum DirtyFlags
|
||||
{
|
||||
@ -227,20 +244,19 @@ private:
|
||||
DirtyFlag_PixelConstants = 1 << 16,
|
||||
DirtyFlag_VertexConstants = 1 << 17,
|
||||
DirtyFlag_GeometryConstants = 1 << 18,
|
||||
DirtyFlag_ComputeConstants = 1 << 19,
|
||||
|
||||
DirtyFlag_VertexBuffer = 1 << 20,
|
||||
DirtyFlag_IndexBuffer = 1 << 21,
|
||||
DirtyFlag_VertexBuffer = 1 << 19,
|
||||
DirtyFlag_IndexBuffer = 1 << 20,
|
||||
|
||||
DirtyFlag_PixelShader = 1 << 22,
|
||||
DirtyFlag_VertexShader = 1 << 23,
|
||||
DirtyFlag_GeometryShader = 1 << 24,
|
||||
DirtyFlag_ComputeShader = 1 << 25,
|
||||
DirtyFlag_PixelShader = 1 << 21,
|
||||
DirtyFlag_VertexShader = 1 << 22,
|
||||
DirtyFlag_GeometryShader = 1 << 23,
|
||||
|
||||
DirtyFlag_InputAssembler = 1 << 26,
|
||||
DirtyFlag_BlendState = 1 << 27,
|
||||
DirtyFlag_DepthState = 1 << 28,
|
||||
DirtyFlag_RasterizerState = 1 << 29,
|
||||
DirtyFlag_InputAssembler = 1 << 24,
|
||||
DirtyFlag_BlendState = 1 << 25,
|
||||
DirtyFlag_DepthState = 1 << 26,
|
||||
DirtyFlag_RasterizerState = 1 << 27,
|
||||
DirtyFlag_Framebuffer = 1 << 28
|
||||
};
|
||||
|
||||
u32 m_dirtyFlags = ~0u;
|
||||
@ -252,7 +268,6 @@ private:
|
||||
std::array<ID3D11Buffer*, 2> pixelConstants;
|
||||
ID3D11Buffer* vertexConstants;
|
||||
ID3D11Buffer* geometryConstants;
|
||||
ID3D11Buffer* computeConstants;
|
||||
ID3D11Buffer* vertexBuffer;
|
||||
ID3D11Buffer* indexBuffer;
|
||||
u32 vertexBufferStride;
|
||||
@ -262,18 +277,27 @@ private:
|
||||
ID3D11PixelShader* pixelShader;
|
||||
ID3D11VertexShader* vertexShader;
|
||||
ID3D11GeometryShader* geometryShader;
|
||||
ID3D11ComputeShader* computeShader;
|
||||
ID3D11BlendState* blendState;
|
||||
ID3D11DepthStencilState* depthState;
|
||||
ID3D11RasterizerState* rasterizerState;
|
||||
DXFramebuffer* framebuffer;
|
||||
ID3D11UnorderedAccessView* uav;
|
||||
bool use_integer_rtv;
|
||||
};
|
||||
|
||||
Resources m_pending = {};
|
||||
Resources m_current = {};
|
||||
|
||||
// Compute resources are synced with the graphics resources when we need them.
|
||||
ID3D11Buffer* m_compute_constants = nullptr;
|
||||
std::array<ID3D11ShaderResourceView*, 8> m_compute_textures{};
|
||||
std::array<ID3D11SamplerState*, 8> m_compute_samplers{};
|
||||
ID3D11UnorderedAccessView* m_compute_image = nullptr;
|
||||
ID3D11ComputeShader* m_compute_shader = nullptr;
|
||||
};
|
||||
|
||||
extern StateManager* stateman;
|
||||
|
||||
} // namespace
|
||||
} // namespace D3D
|
||||
|
||||
} // namespace DX11
|
||||
|
@ -1,105 +0,0 @@
|
||||
// Copyright 2010 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DTexture.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
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;
|
||||
|
||||
D3D11_CPU_ACCESS_FLAG cpuflags;
|
||||
if (usage == D3D11_USAGE_STAGING)
|
||||
cpuflags = (D3D11_CPU_ACCESS_FLAG)((int)D3D11_CPU_ACCESS_WRITE | (int)D3D11_CPU_ACCESS_READ);
|
||||
else if (usage == D3D11_USAGE_DYNAMIC)
|
||||
cpuflags = D3D11_CPU_ACCESS_WRITE;
|
||||
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, data, &pTexture);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("Failed to create texture at %s, line %d: hr=%#x\n", __FILE__, __LINE__, hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
D3DTexture2D* ret = new D3DTexture2D(pTexture, bind);
|
||||
SAFE_RELEASE(pTexture);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void D3DTexture2D::AddRef()
|
||||
{
|
||||
++ref;
|
||||
}
|
||||
|
||||
UINT D3DTexture2D::Release()
|
||||
{
|
||||
--ref;
|
||||
if (ref == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
ID3D11Texture2D*& D3DTexture2D::GetTex()
|
||||
{
|
||||
return tex;
|
||||
}
|
||||
ID3D11ShaderResourceView*& D3DTexture2D::GetSRV()
|
||||
{
|
||||
return srv;
|
||||
}
|
||||
ID3D11RenderTargetView*& D3DTexture2D::GetRTV()
|
||||
{
|
||||
return rtv;
|
||||
}
|
||||
ID3D11DepthStencilView*& D3DTexture2D::GetDSV()
|
||||
{
|
||||
return dsv;
|
||||
}
|
||||
|
||||
D3DTexture2D::D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format,
|
||||
DXGI_FORMAT dsv_format, DXGI_FORMAT rtv_format, bool multisampled)
|
||||
: tex{texptr}
|
||||
{
|
||||
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);
|
||||
if (bind & D3D11_BIND_SHADER_RESOURCE)
|
||||
D3D::device->CreateShaderResourceView(tex, &srv_desc, &srv);
|
||||
if (bind & D3D11_BIND_RENDER_TARGET)
|
||||
D3D::device->CreateRenderTargetView(tex, &rtv_desc, &rtv);
|
||||
if (bind & D3D11_BIND_DEPTH_STENCIL)
|
||||
D3D::device->CreateDepthStencilView(tex, &dsv_desc, &dsv);
|
||||
tex->AddRef();
|
||||
}
|
||||
|
||||
D3DTexture2D::~D3DTexture2D()
|
||||
{
|
||||
SAFE_RELEASE(srv);
|
||||
SAFE_RELEASE(rtv);
|
||||
SAFE_RELEASE(dsv);
|
||||
SAFE_RELEASE(tex);
|
||||
}
|
||||
|
||||
} // namespace DX11
|
@ -1,48 +0,0 @@
|
||||
// Copyright 2010 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <d3d11.h>
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
class D3DTexture2D
|
||||
{
|
||||
public:
|
||||
// there are two ways to create a D3DTexture2D object:
|
||||
// either create an ID3D11Texture2D object, pass it to the constructor and specify what views
|
||||
// to create
|
||||
// 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, 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();
|
||||
UINT Release();
|
||||
|
||||
ID3D11Texture2D*& GetTex();
|
||||
ID3D11ShaderResourceView*& GetSRV();
|
||||
ID3D11RenderTargetView*& GetRTV();
|
||||
ID3D11DepthStencilView*& GetDSV();
|
||||
|
||||
private:
|
||||
~D3DTexture2D();
|
||||
|
||||
ID3D11Texture2D* tex;
|
||||
ID3D11ShaderResourceView* srv = nullptr;
|
||||
ID3D11RenderTargetView* rtv = nullptr;
|
||||
ID3D11DepthStencilView* dsv = nullptr;
|
||||
UINT ref = 1;
|
||||
};
|
||||
|
||||
} // namespace DX11
|
@ -1,407 +0,0 @@
|
||||
// Copyright 2010 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "VideoBackends/D3D/D3DUtil.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "Common/Align.h"
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DShader.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/GeometryShaderCache.h"
|
||||
#include "VideoBackends/D3D/PixelShaderCache.h"
|
||||
#include "VideoBackends/D3D/VertexShaderCache.h"
|
||||
#include "VideoCommon/VideoBackendBase.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
namespace D3D
|
||||
{
|
||||
// Ring buffer class, shared between the draw* functions
|
||||
class UtilVertexBuffer
|
||||
{
|
||||
public:
|
||||
UtilVertexBuffer(unsigned int size) : max_size(size)
|
||||
{
|
||||
D3D11_BUFFER_DESC desc = CD3D11_BUFFER_DESC(max_size, D3D11_BIND_VERTEX_BUFFER,
|
||||
D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
device->CreateBuffer(&desc, nullptr, &buf);
|
||||
}
|
||||
~UtilVertexBuffer() { buf->Release(); }
|
||||
int GetSize() const { return max_size; }
|
||||
// returns vertex offset to the new data
|
||||
int AppendData(void* data, unsigned int size, unsigned int vertex_size)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
if (offset + size >= max_size)
|
||||
{
|
||||
// wrap buffer around and notify observers
|
||||
offset = 0;
|
||||
context->Map(buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
|
||||
for (bool* observer : observers)
|
||||
*observer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->Map(buf, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map);
|
||||
}
|
||||
offset = Common::AlignUp(offset, vertex_size);
|
||||
memcpy((u8*)map.pData + offset, data, size);
|
||||
context->Unmap(buf, 0);
|
||||
|
||||
offset += size;
|
||||
return (offset - size) / vertex_size;
|
||||
}
|
||||
|
||||
int BeginAppendData(void** write_ptr, unsigned int size, unsigned int vertex_size)
|
||||
{
|
||||
DEBUG_ASSERT(size < max_size);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
unsigned int aligned_offset = Common::AlignUp(offset, vertex_size);
|
||||
if (aligned_offset + size > max_size)
|
||||
{
|
||||
// wrap buffer around and notify observers
|
||||
offset = 0;
|
||||
aligned_offset = 0;
|
||||
context->Map(buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||
|
||||
for (bool* observer : observers)
|
||||
*observer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->Map(buf, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map);
|
||||
}
|
||||
|
||||
*write_ptr = reinterpret_cast<byte*>(map.pData) + aligned_offset;
|
||||
offset = aligned_offset + size;
|
||||
return aligned_offset / vertex_size;
|
||||
}
|
||||
|
||||
void EndAppendData() { context->Unmap(buf, 0); }
|
||||
void AddWrapObserver(bool* observer) { observers.push_back(observer); }
|
||||
inline ID3D11Buffer*& GetBuffer() { return buf; }
|
||||
|
||||
private:
|
||||
ID3D11Buffer* buf = nullptr;
|
||||
unsigned int offset = 0;
|
||||
unsigned int max_size;
|
||||
|
||||
std::list<bool*> observers;
|
||||
};
|
||||
|
||||
static UtilVertexBuffer* util_vbuf = nullptr;
|
||||
static ID3D11SamplerState* linear_copy_sampler = nullptr;
|
||||
static ID3D11SamplerState* point_copy_sampler = nullptr;
|
||||
|
||||
struct STQVertex
|
||||
{
|
||||
float x, y, z, u, v, w;
|
||||
};
|
||||
struct ClearVertex
|
||||
{
|
||||
float x, y, z;
|
||||
u32 col;
|
||||
};
|
||||
struct ColVertex
|
||||
{
|
||||
float x, y, z;
|
||||
u32 col;
|
||||
};
|
||||
|
||||
struct TexQuadData
|
||||
{
|
||||
float u1, v1, u2, v2, S, G;
|
||||
};
|
||||
static TexQuadData tex_quad_data;
|
||||
|
||||
struct DrawQuadData
|
||||
{
|
||||
float x1, y1, x2, y2, z;
|
||||
u32 col;
|
||||
};
|
||||
static DrawQuadData draw_quad_data;
|
||||
|
||||
struct ClearQuadData
|
||||
{
|
||||
u32 col;
|
||||
float z;
|
||||
};
|
||||
static ClearQuadData clear_quad_data;
|
||||
|
||||
// ring buffer offsets
|
||||
static int stq_offset, cq_offset, clearq_offset;
|
||||
|
||||
// observer variables for ring buffer wraps
|
||||
static bool stq_observer, cq_observer, clearq_observer;
|
||||
|
||||
void InitUtils()
|
||||
{
|
||||
util_vbuf = new UtilVertexBuffer(65536); // 64KiB
|
||||
|
||||
float border[4] = {0.f, 0.f, 0.f, 0.f};
|
||||
D3D11_SAMPLER_DESC samDesc = CD3D11_SAMPLER_DESC(
|
||||
D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER,
|
||||
D3D11_TEXTURE_ADDRESS_BORDER, 0.f, 1, D3D11_COMPARISON_ALWAYS, border, 0.f, 0.f);
|
||||
HRESULT hr = D3D::device->CreateSamplerState(&samDesc, &point_copy_sampler);
|
||||
if (FAILED(hr))
|
||||
PanicAlert("Failed to create sampler state at %s %d\n", __FILE__, __LINE__);
|
||||
else
|
||||
SetDebugObjectName(point_copy_sampler, "point copy sampler state");
|
||||
|
||||
samDesc = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_BORDER,
|
||||
D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER, 0.f, 1,
|
||||
D3D11_COMPARISON_ALWAYS, border, 0.f, 0.f);
|
||||
hr = D3D::device->CreateSamplerState(&samDesc, &linear_copy_sampler);
|
||||
if (FAILED(hr))
|
||||
PanicAlert("Failed to create sampler state at %s %d\n", __FILE__, __LINE__);
|
||||
else
|
||||
SetDebugObjectName(linear_copy_sampler, "linear copy sampler state");
|
||||
|
||||
// cached data used to avoid unnecessarily reloading the vertex buffers
|
||||
memset(&tex_quad_data, 0, sizeof(tex_quad_data));
|
||||
memset(&draw_quad_data, 0, sizeof(draw_quad_data));
|
||||
memset(&clear_quad_data, 0, sizeof(clear_quad_data));
|
||||
|
||||
// make sure to properly load the vertex data whenever the corresponding functions get called the
|
||||
// first time
|
||||
stq_observer = cq_observer = clearq_observer = true;
|
||||
util_vbuf->AddWrapObserver(&stq_observer);
|
||||
util_vbuf->AddWrapObserver(&cq_observer);
|
||||
util_vbuf->AddWrapObserver(&clearq_observer);
|
||||
}
|
||||
|
||||
void ShutdownUtils()
|
||||
{
|
||||
SAFE_RELEASE(point_copy_sampler);
|
||||
SAFE_RELEASE(linear_copy_sampler);
|
||||
SAFE_DELETE(util_vbuf);
|
||||
}
|
||||
|
||||
void SetPointCopySampler()
|
||||
{
|
||||
D3D::stateman->SetSampler(0, point_copy_sampler);
|
||||
}
|
||||
|
||||
void SetLinearCopySampler()
|
||||
{
|
||||
D3D::stateman->SetSampler(0, linear_copy_sampler);
|
||||
}
|
||||
|
||||
void drawShadedTexQuad(ID3D11ShaderResourceView* texture, const D3D11_RECT* rSource,
|
||||
int SourceWidth, int SourceHeight, ID3D11PixelShader* PShader,
|
||||
ID3D11VertexShader* VShader, ID3D11InputLayout* layout,
|
||||
ID3D11GeometryShader* GShader, u32 slice)
|
||||
{
|
||||
float sw = 1.0f / (float)SourceWidth;
|
||||
float sh = 1.0f / (float)SourceHeight;
|
||||
float u1 = ((float)rSource->left) * sw;
|
||||
float u2 = ((float)rSource->right) * sw;
|
||||
float v1 = ((float)rSource->top) * sh;
|
||||
float v2 = ((float)rSource->bottom) * sh;
|
||||
float S = (float)slice;
|
||||
|
||||
STQVertex coords[4] = {
|
||||
{-1.0f, 1.0f, 0.0f, u1, v1, S},
|
||||
{1.0f, 1.0f, 0.0f, u2, v1, S},
|
||||
{-1.0f, -1.0f, 0.0f, u1, v2, S},
|
||||
{1.0f, -1.0f, 0.0f, u2, v2, S},
|
||||
};
|
||||
|
||||
// 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.S != S)
|
||||
{
|
||||
stq_offset = util_vbuf->AppendData(coords, sizeof(coords), sizeof(STQVertex));
|
||||
stq_observer = false;
|
||||
|
||||
tex_quad_data.u1 = u1;
|
||||
tex_quad_data.v1 = v1;
|
||||
tex_quad_data.u2 = u2;
|
||||
tex_quad_data.v2 = v2;
|
||||
tex_quad_data.S = S;
|
||||
}
|
||||
UINT stride = sizeof(STQVertex);
|
||||
UINT offset = 0;
|
||||
|
||||
D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
D3D::stateman->SetInputLayout(layout);
|
||||
D3D::stateman->SetVertexBuffer(util_vbuf->GetBuffer(), stride, offset);
|
||||
D3D::stateman->SetPixelShader(PShader);
|
||||
D3D::stateman->SetTexture(0, texture);
|
||||
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);
|
||||
}
|
||||
|
||||
// Fills a certain area of the current render target with the specified color
|
||||
// destination coordinates normalized to (-1;1)
|
||||
void drawColorQuad(u32 Color, float z, float x1, float y1, float x2, float y2)
|
||||
{
|
||||
ColVertex coords[4] = {
|
||||
{x1, y1, z, Color},
|
||||
{x2, y1, z, Color},
|
||||
{x1, y2, z, Color},
|
||||
{x2, y2, z, Color},
|
||||
};
|
||||
|
||||
if (cq_observer || draw_quad_data.x1 != x1 || draw_quad_data.y1 != y1 ||
|
||||
draw_quad_data.x2 != x2 || draw_quad_data.y2 != y2 || draw_quad_data.col != Color ||
|
||||
draw_quad_data.z != z)
|
||||
{
|
||||
cq_offset = util_vbuf->AppendData(coords, sizeof(coords), sizeof(ColVertex));
|
||||
cq_observer = false;
|
||||
|
||||
draw_quad_data.x1 = x1;
|
||||
draw_quad_data.y1 = y1;
|
||||
draw_quad_data.x2 = x2;
|
||||
draw_quad_data.y2 = y2;
|
||||
draw_quad_data.col = Color;
|
||||
draw_quad_data.z = z;
|
||||
}
|
||||
|
||||
stateman->SetVertexShader(VertexShaderCache::GetClearVertexShader());
|
||||
stateman->SetGeometryShader(GeometryShaderCache::GetClearGeometryShader());
|
||||
stateman->SetPixelShader(PixelShaderCache::GetClearProgram());
|
||||
stateman->SetInputLayout(VertexShaderCache::GetClearInputLayout());
|
||||
|
||||
UINT stride = sizeof(ColVertex);
|
||||
UINT offset = 0;
|
||||
stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
stateman->SetVertexBuffer(util_vbuf->GetBuffer(), stride, offset);
|
||||
|
||||
stateman->Apply();
|
||||
context->Draw(4, cq_offset);
|
||||
|
||||
stateman->SetGeometryShader(nullptr);
|
||||
}
|
||||
|
||||
void drawClearQuad(u32 Color, float z)
|
||||
{
|
||||
ClearVertex coords[4] = {
|
||||
{-1.0f, 1.0f, z, Color},
|
||||
{1.0f, 1.0f, z, Color},
|
||||
{-1.0f, -1.0f, z, Color},
|
||||
{1.0f, -1.0f, z, Color},
|
||||
};
|
||||
|
||||
if (clearq_observer || clear_quad_data.col != Color || clear_quad_data.z != z)
|
||||
{
|
||||
clearq_offset = util_vbuf->AppendData(coords, sizeof(coords), sizeof(ClearVertex));
|
||||
clearq_observer = false;
|
||||
|
||||
clear_quad_data.col = Color;
|
||||
clear_quad_data.z = z;
|
||||
}
|
||||
|
||||
stateman->SetVertexShader(VertexShaderCache::GetClearVertexShader());
|
||||
stateman->SetGeometryShader(GeometryShaderCache::GetClearGeometryShader());
|
||||
stateman->SetPixelShader(PixelShaderCache::GetClearProgram());
|
||||
stateman->SetInputLayout(VertexShaderCache::GetClearInputLayout());
|
||||
|
||||
UINT stride = sizeof(ClearVertex);
|
||||
UINT offset = 0;
|
||||
stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
stateman->SetVertexBuffer(util_vbuf->GetBuffer(), stride, offset);
|
||||
|
||||
stateman->Apply();
|
||||
context->Draw(4, clearq_offset);
|
||||
|
||||
stateman->SetGeometryShader(nullptr);
|
||||
}
|
||||
|
||||
static void InitColVertex(ColVertex* vert, float x, float y, float z, u32 col)
|
||||
{
|
||||
vert->x = x;
|
||||
vert->y = y;
|
||||
vert->z = z;
|
||||
vert->col = col;
|
||||
}
|
||||
|
||||
void DrawEFBPokeQuads(EFBAccessType type, const EfbPokeData* points, size_t num_points)
|
||||
{
|
||||
const size_t COL_QUAD_SIZE = sizeof(ColVertex) * 6;
|
||||
|
||||
// Set common state
|
||||
stateman->SetVertexShader(VertexShaderCache::GetClearVertexShader());
|
||||
stateman->SetGeometryShader(GeometryShaderCache::GetClearGeometryShader());
|
||||
stateman->SetPixelShader(PixelShaderCache::GetClearProgram());
|
||||
stateman->SetInputLayout(VertexShaderCache::GetClearInputLayout());
|
||||
stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
stateman->SetVertexBuffer(util_vbuf->GetBuffer(), sizeof(ColVertex), 0);
|
||||
stateman->Apply();
|
||||
|
||||
// if drawing a large number of points at once, this will have to be split into multiple passes.
|
||||
size_t points_per_draw = util_vbuf->GetSize() / COL_QUAD_SIZE;
|
||||
size_t current_point_index = 0;
|
||||
while (current_point_index < num_points)
|
||||
{
|
||||
size_t points_to_draw = std::min(num_points - current_point_index, points_per_draw);
|
||||
size_t required_bytes = COL_QUAD_SIZE * points_to_draw;
|
||||
|
||||
// map and reserve enough buffer space for this draw
|
||||
void* buffer_ptr;
|
||||
int base_vertex_index =
|
||||
util_vbuf->BeginAppendData(&buffer_ptr, (int)required_bytes, sizeof(ColVertex));
|
||||
|
||||
// generate quads for each efb point
|
||||
ColVertex* base_vertex_ptr = reinterpret_cast<ColVertex*>(buffer_ptr);
|
||||
for (size_t i = 0; i < points_to_draw; i++)
|
||||
{
|
||||
// generate quad from the single point (clip-space coordinates)
|
||||
const EfbPokeData* point = &points[current_point_index];
|
||||
float x1 = float(point->x) * 2.0f / EFB_WIDTH - 1.0f;
|
||||
float y1 = -float(point->y) * 2.0f / EFB_HEIGHT + 1.0f;
|
||||
float x2 = float(point->x + 1) * 2.0f / EFB_WIDTH - 1.0f;
|
||||
float y2 = -float(point->y + 1) * 2.0f / EFB_HEIGHT + 1.0f;
|
||||
float z = 0.0f;
|
||||
u32 col = 0;
|
||||
|
||||
if (type == EFBAccessType::PokeZ)
|
||||
{
|
||||
z = 1.0f - static_cast<float>(point->data & 0xFFFFFF) / 16777216.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
col = ((point->data & 0xFF00FF00) | ((point->data >> 16) & 0xFF) |
|
||||
((point->data << 16) & 0xFF0000));
|
||||
}
|
||||
|
||||
current_point_index++;
|
||||
|
||||
// quad -> triangles
|
||||
ColVertex* vertex = &base_vertex_ptr[i * 6];
|
||||
InitColVertex(&vertex[0], x1, y1, z, col);
|
||||
InitColVertex(&vertex[1], x2, y1, z, col);
|
||||
InitColVertex(&vertex[2], x1, y2, z, col);
|
||||
InitColVertex(&vertex[3], x1, y2, z, col);
|
||||
InitColVertex(&vertex[4], x2, y1, z, col);
|
||||
InitColVertex(&vertex[5], x2, y2, z, col);
|
||||
}
|
||||
|
||||
// unmap the util buffer, and issue the draw
|
||||
util_vbuf->EndAppendData();
|
||||
context->Draw(6 * (UINT)points_to_draw, base_vertex_index);
|
||||
}
|
||||
|
||||
stateman->SetGeometryShader(GeometryShaderCache::GetClearGeometryShader());
|
||||
}
|
||||
|
||||
} // namespace D3D
|
||||
|
||||
} // namespace DX11
|
@ -1,32 +0,0 @@
|
||||
// Copyright 2010 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <string>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoCommon/RenderBase.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
namespace D3D
|
||||
{
|
||||
void InitUtils();
|
||||
void ShutdownUtils();
|
||||
|
||||
void SetPointCopySampler();
|
||||
void SetLinearCopySampler();
|
||||
|
||||
void drawShadedTexQuad(ID3D11ShaderResourceView* texture, const D3D11_RECT* rSource,
|
||||
int SourceWidth, int SourceHeight, ID3D11PixelShader* PShader,
|
||||
ID3D11VertexShader* VShader, ID3D11InputLayout* layout,
|
||||
ID3D11GeometryShader* GShader = nullptr, u32 slice = 0);
|
||||
void drawClearQuad(u32 Color, float z);
|
||||
void drawColorQuad(u32 Color, float z, float x1, float y1, float x2, float y2);
|
||||
|
||||
void DrawEFBPokeQuads(EFBAccessType type, const EfbPokeData* points, size_t num_points);
|
||||
}
|
||||
}
|
@ -22,11 +22,11 @@ DXPipeline::DXPipeline(ID3D11InputLayout* input_layout, ID3D11VertexShader* vert
|
||||
ID3D11GeometryShader* geometry_shader, ID3D11PixelShader* pixel_shader,
|
||||
ID3D11RasterizerState* rasterizer_state,
|
||||
ID3D11DepthStencilState* depth_state, ID3D11BlendState* blend_state,
|
||||
D3D11_PRIMITIVE_TOPOLOGY primitive_topology)
|
||||
D3D11_PRIMITIVE_TOPOLOGY primitive_topology, bool use_logic_op)
|
||||
: m_input_layout(input_layout), m_vertex_shader(vertex_shader),
|
||||
m_geometry_shader(geometry_shader), m_pixel_shader(pixel_shader),
|
||||
m_rasterizer_state(rasterizer_state), m_depth_state(depth_state), m_blend_state(blend_state),
|
||||
m_primitive_topology(primitive_topology)
|
||||
m_primitive_topology(primitive_topology), m_use_logic_op(use_logic_op)
|
||||
{
|
||||
if (m_input_layout)
|
||||
m_input_layout->AddRef();
|
||||
@ -84,13 +84,16 @@ std::unique_ptr<DXPipeline> DXPipeline::Create(const AbstractPipelineConfig& con
|
||||
ASSERT(vertex_shader != nullptr && pixel_shader != nullptr);
|
||||
|
||||
ID3D11InputLayout* input_layout =
|
||||
const_cast<D3DVertexFormat*>(static_cast<const D3DVertexFormat*>(config.vertex_format))
|
||||
->GetInputLayout(vertex_shader->GetByteCode());
|
||||
config.vertex_format ?
|
||||
const_cast<D3DVertexFormat*>(static_cast<const D3DVertexFormat*>(config.vertex_format))
|
||||
->GetInputLayout(vertex_shader->GetByteCode().data(),
|
||||
vertex_shader->GetByteCode().size()) :
|
||||
nullptr;
|
||||
|
||||
return std::make_unique<DXPipeline>(input_layout, vertex_shader->GetD3DVertexShader(),
|
||||
geometry_shader ? geometry_shader->GetD3DGeometryShader() :
|
||||
nullptr,
|
||||
pixel_shader->GetD3DPixelShader(), rasterizer_state,
|
||||
depth_state, blend_state, primitive_topology);
|
||||
return std::make_unique<DXPipeline>(
|
||||
input_layout, vertex_shader->GetD3DVertexShader(),
|
||||
geometry_shader ? geometry_shader->GetD3DGeometryShader() : nullptr,
|
||||
pixel_shader->GetD3DPixelShader(), rasterizer_state, depth_state, blend_state,
|
||||
primitive_topology, config.blending_state.logicopenable);
|
||||
}
|
||||
} // namespace DX11
|
||||
|
@ -16,7 +16,8 @@ public:
|
||||
DXPipeline(ID3D11InputLayout* input_layout, ID3D11VertexShader* vertex_shader,
|
||||
ID3D11GeometryShader* geometry_shader, ID3D11PixelShader* pixel_shader,
|
||||
ID3D11RasterizerState* rasterizer_state, ID3D11DepthStencilState* depth_state,
|
||||
ID3D11BlendState* blend_state, D3D11_PRIMITIVE_TOPOLOGY primitive_topology);
|
||||
ID3D11BlendState* blend_state, D3D11_PRIMITIVE_TOPOLOGY primitive_topology,
|
||||
bool use_logic_op);
|
||||
~DXPipeline() override;
|
||||
|
||||
ID3D11InputLayout* GetInputLayout() const { return m_input_layout; }
|
||||
@ -28,6 +29,8 @@ public:
|
||||
ID3D11BlendState* GetBlendState() const { return m_blend_state; }
|
||||
D3D11_PRIMITIVE_TOPOLOGY GetPrimitiveTopology() const { return m_primitive_topology; }
|
||||
bool HasGeometryShader() const { return m_geometry_shader != nullptr; }
|
||||
bool UseLogicOp() const { return m_use_logic_op; }
|
||||
|
||||
static std::unique_ptr<DXPipeline> Create(const AbstractPipelineConfig& config);
|
||||
|
||||
private:
|
||||
@ -39,5 +42,6 @@ private:
|
||||
ID3D11DepthStencilState* m_depth_state;
|
||||
ID3D11BlendState* m_blend_state;
|
||||
D3D11_PRIMITIVE_TOPOLOGY m_primitive_topology;
|
||||
bool m_use_logic_op;
|
||||
};
|
||||
} // namespace DX11
|
||||
|
@ -2,43 +2,28 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DShader.h"
|
||||
#include "VideoBackends/D3D/DXShader.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
DXShader::DXShader(D3DBlob* bytecode, ID3D11VertexShader* vs)
|
||||
: AbstractShader(ShaderStage::Vertex), m_bytecode(bytecode), m_shader(vs)
|
||||
{
|
||||
}
|
||||
|
||||
DXShader::DXShader(D3DBlob* bytecode, ID3D11GeometryShader* gs)
|
||||
: AbstractShader(ShaderStage::Geometry), m_bytecode(bytecode), m_shader(gs)
|
||||
{
|
||||
}
|
||||
|
||||
DXShader::DXShader(D3DBlob* bytecode, ID3D11PixelShader* ps)
|
||||
: AbstractShader(ShaderStage::Pixel), m_bytecode(bytecode), m_shader(ps)
|
||||
{
|
||||
}
|
||||
|
||||
DXShader::DXShader(D3DBlob* bytecode, ID3D11ComputeShader* cs)
|
||||
: AbstractShader(ShaderStage::Compute), m_bytecode(bytecode), m_shader(cs)
|
||||
DXShader::DXShader(ShaderStage stage, BinaryData bytecode, ID3D11DeviceChild* shader)
|
||||
: AbstractShader(stage), m_bytecode(bytecode), m_shader(shader)
|
||||
{
|
||||
}
|
||||
|
||||
DXShader::~DXShader()
|
||||
{
|
||||
m_shader->Release();
|
||||
m_bytecode->Release();
|
||||
}
|
||||
|
||||
D3DBlob* DXShader::GetByteCode() const
|
||||
{
|
||||
return m_bytecode;
|
||||
}
|
||||
|
||||
ID3D11VertexShader* DXShader::GetD3DVertexShader() const
|
||||
@ -67,48 +52,62 @@ ID3D11ComputeShader* DXShader::GetD3DComputeShader() const
|
||||
|
||||
bool DXShader::HasBinary() const
|
||||
{
|
||||
ASSERT(m_bytecode);
|
||||
return true;
|
||||
}
|
||||
|
||||
AbstractShader::BinaryData DXShader::GetBinary() const
|
||||
{
|
||||
return BinaryData(m_bytecode->Data(), m_bytecode->Data() + m_bytecode->Size());
|
||||
return m_bytecode;
|
||||
}
|
||||
|
||||
std::unique_ptr<DXShader> DXShader::CreateFromBlob(ShaderStage stage, D3DBlob* bytecode)
|
||||
std::unique_ptr<DXShader> DXShader::CreateFromBytecode(ShaderStage stage, BinaryData bytecode)
|
||||
{
|
||||
switch (stage)
|
||||
{
|
||||
case ShaderStage::Vertex:
|
||||
{
|
||||
ID3D11VertexShader* vs = D3D::CreateVertexShaderFromByteCode(bytecode);
|
||||
if (vs)
|
||||
return std::make_unique<DXShader>(bytecode, vs);
|
||||
ID3D11VertexShader* vs;
|
||||
HRESULT hr = D3D::device->CreateVertexShader(bytecode.data(), bytecode.size(), nullptr, &vs);
|
||||
CHECK(SUCCEEDED(hr), "Create vertex shader");
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
|
||||
return std::make_unique<DXShader>(ShaderStage::Vertex, std::move(bytecode), vs);
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderStage::Geometry:
|
||||
{
|
||||
ID3D11GeometryShader* gs = D3D::CreateGeometryShaderFromByteCode(bytecode);
|
||||
if (gs)
|
||||
return std::make_unique<DXShader>(bytecode, gs);
|
||||
ID3D11GeometryShader* gs;
|
||||
HRESULT hr = D3D::device->CreateGeometryShader(bytecode.data(), bytecode.size(), nullptr, &gs);
|
||||
CHECK(SUCCEEDED(hr), "Create geometry shader");
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
|
||||
return std::make_unique<DXShader>(ShaderStage::Geometry, std::move(bytecode), gs);
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderStage::Pixel:
|
||||
{
|
||||
ID3D11PixelShader* ps = D3D::CreatePixelShaderFromByteCode(bytecode);
|
||||
if (ps)
|
||||
return std::make_unique<DXShader>(bytecode, ps);
|
||||
ID3D11PixelShader* ps;
|
||||
HRESULT hr = D3D::device->CreatePixelShader(bytecode.data(), bytecode.size(), nullptr, &ps);
|
||||
CHECK(SUCCEEDED(hr), "Create pixel shader");
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
|
||||
return std::make_unique<DXShader>(ShaderStage::Pixel, std::move(bytecode), ps);
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderStage::Compute:
|
||||
{
|
||||
ID3D11ComputeShader* cs = D3D::CreateComputeShaderFromByteCode(bytecode);
|
||||
if (cs)
|
||||
return std::make_unique<DXShader>(bytecode, cs);
|
||||
ID3D11ComputeShader* cs;
|
||||
HRESULT hr = D3D::device->CreateComputeShader(bytecode.data(), bytecode.size(), nullptr, &cs);
|
||||
CHECK(SUCCEEDED(hr), "Create compute shader");
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
|
||||
return std::make_unique<DXShader>(ShaderStage::Compute, std::move(bytecode), cs);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -119,65 +118,85 @@ std::unique_ptr<DXShader> DXShader::CreateFromBlob(ShaderStage stage, D3DBlob* b
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<DXShader> DXShader::CreateFromSource(ShaderStage stage, const char* source,
|
||||
size_t length)
|
||||
static const char* GetCompileTarget(ShaderStage stage)
|
||||
{
|
||||
D3DBlob* bytecode;
|
||||
switch (stage)
|
||||
{
|
||||
case ShaderStage::Vertex:
|
||||
{
|
||||
if (!D3D::CompileVertexShader(std::string(source, length), &bytecode))
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
|
||||
return D3D::VertexShaderVersionString();
|
||||
case ShaderStage::Geometry:
|
||||
{
|
||||
if (!D3D::CompileGeometryShader(std::string(source, length), &bytecode))
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
|
||||
return D3D::GeometryShaderVersionString();
|
||||
case ShaderStage::Pixel:
|
||||
{
|
||||
if (!D3D::CompilePixelShader(std::string(source, length), &bytecode))
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
|
||||
return D3D::PixelShaderVersionString();
|
||||
case ShaderStage::Compute:
|
||||
{
|
||||
if (!D3D::CompileComputeShader(std::string(source, length), &bytecode))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return D3D::ComputeShaderVersionString();
|
||||
default:
|
||||
return nullptr;
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<DXShader> shader = CreateFromBlob(stage, bytecode);
|
||||
if (!shader)
|
||||
bool DXShader::CompileShader(BinaryData* out_bytecode, ShaderStage stage, const char* source,
|
||||
size_t length)
|
||||
{
|
||||
static constexpr D3D_SHADER_MACRO macros[] = {{"API_D3D", "1"}, {nullptr, nullptr}};
|
||||
const UINT flags = g_ActiveConfig.bEnableValidationLayer ?
|
||||
(D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION) :
|
||||
(D3DCOMPILE_OPTIMIZATION_LEVEL3 | D3DCOMPILE_SKIP_VALIDATION);
|
||||
const char* target = GetCompileTarget(stage);
|
||||
|
||||
ID3DBlob* code = nullptr;
|
||||
ID3DBlob* errors = nullptr;
|
||||
HRESULT hr = PD3DCompile(source, length, nullptr, macros, nullptr, "main", target, flags, 0,
|
||||
&code, &errors);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
bytecode->Release();
|
||||
return nullptr;
|
||||
static int num_failures = 0;
|
||||
std::string filename = StringFromFormat(
|
||||
"%sbad_%s_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), target, num_failures++);
|
||||
std::ofstream file;
|
||||
File::OpenFStream(file, filename, std::ios_base::out);
|
||||
file.write(source, length);
|
||||
file << "\n";
|
||||
file.write(static_cast<const char*>(errors->GetBufferPointer()), errors->GetBufferSize());
|
||||
file.close();
|
||||
|
||||
PanicAlert("Failed to compile %s:\nDebug info (%s):\n%s", filename.c_str(), target,
|
||||
static_cast<const char*>(errors->GetBufferPointer()));
|
||||
errors->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
return shader;
|
||||
if (errors && errors->GetBufferSize() > 0)
|
||||
{
|
||||
WARN_LOG(VIDEO, "%s compilation succeeded with warnings:\n%s", target,
|
||||
static_cast<const char*>(errors->GetBufferPointer()));
|
||||
}
|
||||
SAFE_RELEASE(errors);
|
||||
|
||||
out_bytecode->resize(code->GetBufferSize());
|
||||
std::memcpy(out_bytecode->data(), code->GetBufferPointer(), code->GetBufferSize());
|
||||
code->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<DXShader> DXShader::CreateFromSource(ShaderStage stage, const char* source,
|
||||
size_t length)
|
||||
{
|
||||
BinaryData bytecode;
|
||||
if (!CompileShader(&bytecode, stage, source, length))
|
||||
return nullptr;
|
||||
|
||||
return CreateFromBytecode(stage, std::move(bytecode));
|
||||
}
|
||||
|
||||
std::unique_ptr<DXShader> DXShader::CreateFromBinary(ShaderStage stage, const void* data,
|
||||
size_t length)
|
||||
{
|
||||
D3DBlob* bytecode = new D3DBlob(static_cast<unsigned int>(length), static_cast<const u8*>(data));
|
||||
std::unique_ptr<DXShader> shader = CreateFromBlob(stage, bytecode);
|
||||
if (!shader)
|
||||
{
|
||||
bytecode->Release();
|
||||
if (length == 0)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return shader;
|
||||
BinaryData bytecode(length);
|
||||
std::memcpy(bytecode.data(), data, length);
|
||||
return CreateFromBytecode(stage, std::move(bytecode));
|
||||
}
|
||||
|
||||
} // namespace DX11
|
||||
|
@ -3,13 +3,9 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <d3d11.h>
|
||||
#include <memory>
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "VideoBackends/D3D/D3DBlob.h"
|
||||
#include "VideoCommon/AbstractShader.h"
|
||||
|
||||
namespace DX11
|
||||
@ -17,14 +13,11 @@ namespace DX11
|
||||
class DXShader final : public AbstractShader
|
||||
{
|
||||
public:
|
||||
// Note: vs/gs/ps/cs references are transferred.
|
||||
DXShader(D3DBlob* bytecode, ID3D11VertexShader* vs);
|
||||
DXShader(D3DBlob* bytecode, ID3D11GeometryShader* gs);
|
||||
DXShader(D3DBlob* bytecode, ID3D11PixelShader* ps);
|
||||
DXShader(D3DBlob* bytecode, ID3D11ComputeShader* cs);
|
||||
DXShader(ShaderStage stage, BinaryData bytecode, ID3D11DeviceChild* shader);
|
||||
~DXShader() override;
|
||||
|
||||
D3DBlob* GetByteCode() const;
|
||||
const BinaryData& GetByteCode() const { return m_bytecode; }
|
||||
|
||||
ID3D11VertexShader* GetD3DVertexShader() const;
|
||||
ID3D11GeometryShader* GetD3DGeometryShader() const;
|
||||
ID3D11PixelShader* GetD3DPixelShader() const;
|
||||
@ -33,8 +26,11 @@ public:
|
||||
bool HasBinary() const override;
|
||||
BinaryData GetBinary() const override;
|
||||
|
||||
// Creates a new shader object. The reference to bytecode is not transfered upon failure.
|
||||
static std::unique_ptr<DXShader> CreateFromBlob(ShaderStage stage, D3DBlob* bytecode);
|
||||
// Creates a new shader object.
|
||||
static std::unique_ptr<DXShader> CreateFromBytecode(ShaderStage stage, BinaryData bytecode);
|
||||
static bool CompileShader(BinaryData* out_bytecode, ShaderStage stage, const char* source,
|
||||
size_t length);
|
||||
|
||||
static std::unique_ptr<DXShader> CreateFromBinary(ShaderStage stage, const void* data,
|
||||
size_t length);
|
||||
static std::unique_ptr<DXShader> CreateFromSource(ShaderStage stage, const char* source,
|
||||
@ -42,7 +38,7 @@ public:
|
||||
|
||||
private:
|
||||
ID3D11DeviceChild* m_shader;
|
||||
D3DBlob* m_bytecode;
|
||||
BinaryData m_bytecode;
|
||||
};
|
||||
|
||||
} // namespace DX11
|
||||
|
@ -9,25 +9,47 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/D3DTexture.h"
|
||||
#include "VideoBackends/D3D/D3DUtil.h"
|
||||
#include "VideoBackends/D3D/DXTexture.h"
|
||||
#include "VideoBackends/D3D/FramebufferManager.h"
|
||||
#include "VideoBackends/D3D/GeometryShaderCache.h"
|
||||
#include "VideoBackends/D3D/PixelShaderCache.h"
|
||||
#include "VideoBackends/D3D/TextureCache.h"
|
||||
#include "VideoBackends/D3D/VertexShaderCache.h"
|
||||
|
||||
#include "VideoCommon/ImageWrite.h"
|
||||
#include "VideoCommon/TextureConfig.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
namespace
|
||||
{
|
||||
DXGI_FORMAT GetDXGIFormatForHostFormat(AbstractTextureFormat format)
|
||||
DXGI_FORMAT GetDXGIFormatForHostFormat(AbstractTextureFormat format, bool typeless)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case AbstractTextureFormat::DXT1:
|
||||
return DXGI_FORMAT_BC1_UNORM;
|
||||
case AbstractTextureFormat::DXT3:
|
||||
return DXGI_FORMAT_BC2_UNORM;
|
||||
case AbstractTextureFormat::DXT5:
|
||||
return DXGI_FORMAT_BC3_UNORM;
|
||||
case AbstractTextureFormat::BPTC:
|
||||
return DXGI_FORMAT_BC7_UNORM;
|
||||
case AbstractTextureFormat::RGBA8:
|
||||
return typeless ? DXGI_FORMAT_R8G8B8A8_TYPELESS : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case AbstractTextureFormat::BGRA8:
|
||||
return typeless ? DXGI_FORMAT_B8G8R8A8_TYPELESS : DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
case AbstractTextureFormat::R16:
|
||||
return typeless ? DXGI_FORMAT_R16_TYPELESS : DXGI_FORMAT_R16_UNORM;
|
||||
case AbstractTextureFormat::R32F:
|
||||
return typeless ? DXGI_FORMAT_R32_TYPELESS : DXGI_FORMAT_R32_FLOAT;
|
||||
case AbstractTextureFormat::D16:
|
||||
return DXGI_FORMAT_R16_TYPELESS;
|
||||
case AbstractTextureFormat::D24_S8:
|
||||
return DXGI_FORMAT_R24G8_TYPELESS;
|
||||
case AbstractTextureFormat::D32F:
|
||||
return DXGI_FORMAT_R32_TYPELESS;
|
||||
case AbstractTextureFormat::D32F_S8:
|
||||
return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
||||
default:
|
||||
PanicAlert("Unhandled texture format.");
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
DXGI_FORMAT GetSRVFormatForHostFormat(AbstractTextureFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
@ -47,23 +69,6 @@ DXGI_FORMAT GetDXGIFormatForHostFormat(AbstractTextureFormat format)
|
||||
return DXGI_FORMAT_R16_UNORM;
|
||||
case AbstractTextureFormat::R32F:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case AbstractTextureFormat::D16:
|
||||
return DXGI_FORMAT_R16_TYPELESS;
|
||||
case AbstractTextureFormat::D24_S8:
|
||||
return DXGI_FORMAT_R24G8_TYPELESS;
|
||||
case AbstractTextureFormat::D32F:
|
||||
return DXGI_FORMAT_R32_TYPELESS;
|
||||
case AbstractTextureFormat::D32F_S8:
|
||||
return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
||||
default:
|
||||
PanicAlert("Unhandled texture format.");
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
DXGI_FORMAT GetSRVFormatForHostFormat(AbstractTextureFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case AbstractTextureFormat::D16:
|
||||
return DXGI_FORMAT_R16_UNORM;
|
||||
case AbstractTextureFormat::D24_S8:
|
||||
@ -73,7 +78,25 @@ DXGI_FORMAT GetSRVFormatForHostFormat(AbstractTextureFormat format)
|
||||
case AbstractTextureFormat::D32F_S8:
|
||||
return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
||||
default:
|
||||
return GetDXGIFormatForHostFormat(format);
|
||||
PanicAlert("Unhandled SRV format");
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
DXGI_FORMAT GetRTVFormatForHostFormat(AbstractTextureFormat format, bool integer)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case AbstractTextureFormat::RGBA8:
|
||||
return integer ? DXGI_FORMAT_R8G8B8A8_UINT : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case AbstractTextureFormat::BGRA8:
|
||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
case AbstractTextureFormat::R16:
|
||||
return integer ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R16_UNORM;
|
||||
case AbstractTextureFormat::R32F:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
default:
|
||||
PanicAlert("Unhandled RTV format");
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
DXGI_FORMAT GetDSVFormatForHostFormat(AbstractTextureFormat format)
|
||||
@ -89,55 +112,87 @@ DXGI_FORMAT GetDSVFormatForHostFormat(AbstractTextureFormat format)
|
||||
case AbstractTextureFormat::D32F_S8:
|
||||
return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
|
||||
default:
|
||||
return GetDXGIFormatForHostFormat(format);
|
||||
PanicAlert("Unhandled DSV format");
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
DXTexture::DXTexture(const TextureConfig& tex_config) : AbstractTexture(tex_config)
|
||||
DXTexture::DXTexture(const TextureConfig& tex_config, ID3D11Texture2D* d3d_texture,
|
||||
ID3D11ShaderResourceView* d3d_srv, ID3D11UnorderedAccessView* d3d_uav)
|
||||
: AbstractTexture(tex_config), m_d3d_texture(d3d_texture), m_d3d_srv(d3d_srv),
|
||||
m_d3d_uav(d3d_uav)
|
||||
{
|
||||
DXGI_FORMAT tex_format = GetDXGIFormatForHostFormat(m_config.format);
|
||||
DXGI_FORMAT srv_format = GetSRVFormatForHostFormat(m_config.format);
|
||||
DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN;
|
||||
DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN;
|
||||
UINT bind_flags = D3D11_BIND_SHADER_RESOURCE;
|
||||
if (tex_config.rendertarget)
|
||||
{
|
||||
if (IsDepthFormat(tex_config.format))
|
||||
{
|
||||
bind_flags |= D3D11_BIND_DEPTH_STENCIL;
|
||||
dsv_format = GetDSVFormatForHostFormat(m_config.format);
|
||||
}
|
||||
else
|
||||
{
|
||||
bind_flags |= D3D11_BIND_RENDER_TARGET;
|
||||
rtv_format = tex_format;
|
||||
}
|
||||
}
|
||||
|
||||
CD3D11_TEXTURE2D_DESC texdesc(tex_format, tex_config.width, tex_config.height, tex_config.layers,
|
||||
tex_config.levels, bind_flags, D3D11_USAGE_DEFAULT, 0,
|
||||
tex_config.samples, 0, 0);
|
||||
|
||||
ID3D11Texture2D* pTexture;
|
||||
HRESULT hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &pTexture);
|
||||
CHECK(SUCCEEDED(hr), "Create backing DXTexture");
|
||||
|
||||
m_texture = new D3DTexture2D(pTexture, static_cast<D3D11_BIND_FLAG>(bind_flags), srv_format,
|
||||
dsv_format, rtv_format, tex_config.samples > 1);
|
||||
|
||||
SAFE_RELEASE(pTexture);
|
||||
}
|
||||
|
||||
DXTexture::~DXTexture()
|
||||
{
|
||||
g_renderer->UnbindTexture(this);
|
||||
m_texture->Release();
|
||||
if (m_d3d_uav)
|
||||
m_d3d_uav->Release();
|
||||
|
||||
if (m_d3d_srv)
|
||||
{
|
||||
if (D3D::stateman->UnsetTexture(m_d3d_srv) != 0)
|
||||
D3D::stateman->ApplyTextures();
|
||||
|
||||
m_d3d_srv->Release();
|
||||
}
|
||||
m_d3d_texture->Release();
|
||||
}
|
||||
|
||||
D3DTexture2D* DXTexture::GetRawTexIdentifier() const
|
||||
std::unique_ptr<DXTexture> DXTexture::Create(const TextureConfig& config)
|
||||
{
|
||||
return m_texture;
|
||||
// Use typeless to create the texture when it's a render target, so we can alias it with an
|
||||
// integer format (for EFB).
|
||||
const DXGI_FORMAT tex_format = GetDXGIFormatForHostFormat(config.format, config.IsRenderTarget());
|
||||
const DXGI_FORMAT srv_format = GetSRVFormatForHostFormat(config.format);
|
||||
UINT bindflags = D3D11_BIND_SHADER_RESOURCE;
|
||||
if (config.IsRenderTarget())
|
||||
bindflags |= IsDepthFormat(config.format) ? D3D11_BIND_DEPTH_STENCIL : D3D11_BIND_RENDER_TARGET;
|
||||
if (config.IsComputeImage())
|
||||
bindflags |= D3D11_BIND_UNORDERED_ACCESS;
|
||||
|
||||
CD3D11_TEXTURE2D_DESC desc(tex_format, config.width, config.height, config.layers, config.levels,
|
||||
bindflags, D3D11_USAGE_DEFAULT, 0, config.samples, 0, 0);
|
||||
ID3D11Texture2D* d3d_texture;
|
||||
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, &d3d_texture);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("Failed to create %ux%ux%u D3D backing texture", config.width, config.height,
|
||||
config.layers);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ID3D11ShaderResourceView* d3d_srv;
|
||||
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(d3d_texture,
|
||||
config.IsMultisampled() ?
|
||||
D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY :
|
||||
D3D11_SRV_DIMENSION_TEXTURE2DARRAY,
|
||||
srv_format, 0, config.levels, 0, config.layers);
|
||||
hr = D3D::device->CreateShaderResourceView(d3d_texture, &srv_desc, &d3d_srv);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("Failed to create %ux%ux%u D3D SRV", config.width, config.height, config.layers);
|
||||
d3d_texture->Release();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ID3D11UnorderedAccessView* d3d_uav = nullptr;
|
||||
if (config.IsComputeImage())
|
||||
{
|
||||
const CD3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc(
|
||||
d3d_texture, D3D11_UAV_DIMENSION_TEXTURE2DARRAY, srv_format, 0, 0, config.layers);
|
||||
hr = D3D::device->CreateUnorderedAccessView(d3d_texture, &uav_desc, &d3d_uav);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("Failed to create %ux%ux%u D3D UAV", config.width, config.height, config.layers);
|
||||
d3d_uav->Release();
|
||||
d3d_texture->Release();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_unique<DXTexture>(config, d3d_texture, d3d_srv, d3d_uav);
|
||||
}
|
||||
|
||||
void DXTexture::CopyRectangleFromTexture(const AbstractTexture* src,
|
||||
@ -158,42 +213,11 @@ void DXTexture::CopyRectangleFromTexture(const AbstractTexture* src,
|
||||
src_box.back = 1;
|
||||
|
||||
D3D::context->CopySubresourceRegion(
|
||||
m_texture->GetTex(), D3D11CalcSubresource(dst_level, dst_layer, m_config.levels),
|
||||
dst_rect.left, dst_rect.top, 0, srcentry->m_texture->GetTex(),
|
||||
m_d3d_texture, D3D11CalcSubresource(dst_level, dst_layer, m_config.levels), dst_rect.left,
|
||||
dst_rect.top, 0, srcentry->m_d3d_texture,
|
||||
D3D11CalcSubresource(src_level, src_layer, srcentry->m_config.levels), &src_box);
|
||||
}
|
||||
|
||||
void DXTexture::ScaleRectangleFromTexture(const AbstractTexture* source,
|
||||
const MathUtil::Rectangle<int>& srcrect,
|
||||
const MathUtil::Rectangle<int>& dstrect)
|
||||
{
|
||||
const DXTexture* srcentry = static_cast<const DXTexture*>(source);
|
||||
ASSERT(m_config.rendertarget);
|
||||
|
||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||
|
||||
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(float(dstrect.left), float(dstrect.top),
|
||||
float(dstrect.GetWidth()), float(dstrect.GetHeight()));
|
||||
|
||||
D3D::stateman->UnsetTexture(m_texture->GetSRV());
|
||||
D3D::stateman->Apply();
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &m_texture->GetRTV(), nullptr);
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
D3D::SetLinearCopySampler();
|
||||
D3D11_RECT srcRC;
|
||||
srcRC.left = srcrect.left;
|
||||
srcRC.right = srcrect.right;
|
||||
srcRC.top = srcrect.top;
|
||||
srcRC.bottom = srcrect.bottom;
|
||||
D3D::drawShadedTexQuad(
|
||||
srcentry->m_texture->GetSRV(), &srcRC, srcentry->m_config.width, srcentry->m_config.height,
|
||||
PixelShaderCache::GetColorCopyProgram(false), VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader(), 0);
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
void DXTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
|
||||
u32 layer, u32 level)
|
||||
{
|
||||
@ -204,16 +228,16 @@ void DXTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::R
|
||||
rect.top + rect.GetHeight() <= static_cast<int>(srcentry->m_config.height));
|
||||
|
||||
D3D::context->ResolveSubresource(
|
||||
m_texture->GetTex(), D3D11CalcSubresource(level, layer, m_config.levels),
|
||||
srcentry->m_texture->GetTex(), D3D11CalcSubresource(level, layer, srcentry->m_config.levels),
|
||||
GetDXGIFormatForHostFormat(m_config.format));
|
||||
m_d3d_texture, D3D11CalcSubresource(level, layer, m_config.levels), srcentry->m_d3d_texture,
|
||||
D3D11CalcSubresource(level, layer, srcentry->m_config.levels),
|
||||
GetDXGIFormatForHostFormat(m_config.format, false));
|
||||
}
|
||||
|
||||
void DXTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
size_t src_pitch = CalculateStrideForFormat(m_config.format, row_length);
|
||||
D3D::context->UpdateSubresource(m_texture->GetTex(), level, nullptr, buffer,
|
||||
D3D::context->UpdateSubresource(m_d3d_texture, level, nullptr, buffer,
|
||||
static_cast<UINT>(src_pitch), 0);
|
||||
}
|
||||
|
||||
@ -251,8 +275,8 @@ std::unique_ptr<DXStagingTexture> DXStagingTexture::Create(StagingTextureType ty
|
||||
cpu_flags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
|
||||
}
|
||||
|
||||
CD3D11_TEXTURE2D_DESC desc(GetDXGIFormatForHostFormat(config.format), config.width, config.height,
|
||||
1, 1, 0, usage, cpu_flags);
|
||||
CD3D11_TEXTURE2D_DESC desc(GetDXGIFormatForHostFormat(config.format, false), config.width,
|
||||
config.height, 1, 1, 0, usage, cpu_flags);
|
||||
|
||||
ID3D11Texture2D* texture;
|
||||
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, &texture);
|
||||
@ -267,22 +291,33 @@ void DXStagingTexture::CopyFromTexture(const AbstractTexture* src,
|
||||
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
|
||||
u32 src_level, const MathUtil::Rectangle<int>& dst_rect)
|
||||
{
|
||||
ASSERT(m_type == StagingTextureType::Readback);
|
||||
ASSERT(m_type == StagingTextureType::Readback || m_type == StagingTextureType::Mutable);
|
||||
ASSERT(src_rect.GetWidth() == dst_rect.GetWidth() &&
|
||||
src_rect.GetHeight() == dst_rect.GetHeight());
|
||||
ASSERT(src_rect.left >= 0 && static_cast<u32>(src_rect.right) <= src->GetConfig().width &&
|
||||
src_rect.top >= 0 && static_cast<u32>(src_rect.bottom) <= src->GetConfig().height);
|
||||
ASSERT(src_rect.left >= 0 && static_cast<u32>(src_rect.right) <= src->GetWidth() &&
|
||||
src_rect.top >= 0 && static_cast<u32>(src_rect.bottom) <= src->GetHeight());
|
||||
ASSERT(dst_rect.left >= 0 && static_cast<u32>(dst_rect.right) <= m_config.width &&
|
||||
dst_rect.top >= 0 && static_cast<u32>(dst_rect.bottom) <= m_config.height);
|
||||
|
||||
if (IsMapped())
|
||||
DXStagingTexture::Unmap();
|
||||
|
||||
CD3D11_BOX src_box(src_rect.left, src_rect.top, 0, src_rect.right, src_rect.bottom, 1);
|
||||
D3D::context->CopySubresourceRegion(
|
||||
m_tex, 0, static_cast<u32>(dst_rect.left), static_cast<u32>(dst_rect.top), 0,
|
||||
static_cast<const DXTexture*>(src)->GetRawTexIdentifier()->GetTex(),
|
||||
D3D11CalcSubresource(src_level, src_layer, src->GetConfig().levels), &src_box);
|
||||
if (static_cast<u32>(src_rect.GetWidth()) == GetWidth() &&
|
||||
static_cast<u32>(src_rect.GetHeight()) == GetHeight())
|
||||
{
|
||||
// Copy whole resource, needed for depth textures.
|
||||
D3D::context->CopySubresourceRegion(
|
||||
m_tex, 0, 0, 0, 0, static_cast<const DXTexture*>(src)->GetD3DTexture(),
|
||||
D3D11CalcSubresource(src_level, src_layer, src->GetLevels()), nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
CD3D11_BOX src_box(src_rect.left, src_rect.top, 0, src_rect.right, src_rect.bottom, 1);
|
||||
D3D::context->CopySubresourceRegion(
|
||||
m_tex, 0, static_cast<u32>(dst_rect.left), static_cast<u32>(dst_rect.top), 0,
|
||||
static_cast<const DXTexture*>(src)->GetD3DTexture(),
|
||||
D3D11CalcSubresource(src_level, src_layer, src->GetLevels()), &src_box);
|
||||
}
|
||||
|
||||
m_needs_flush = true;
|
||||
}
|
||||
@ -294,19 +329,29 @@ void DXStagingTexture::CopyToTexture(const MathUtil::Rectangle<int>& src_rect, A
|
||||
ASSERT(m_type == StagingTextureType::Upload);
|
||||
ASSERT(src_rect.GetWidth() == dst_rect.GetWidth() &&
|
||||
src_rect.GetHeight() == dst_rect.GetHeight());
|
||||
ASSERT(src_rect.left >= 0 && static_cast<u32>(src_rect.right) <= m_config.width &&
|
||||
src_rect.top >= 0 && static_cast<u32>(src_rect.bottom) <= m_config.height);
|
||||
ASSERT(dst_rect.left >= 0 && static_cast<u32>(dst_rect.right) <= dst->GetConfig().width &&
|
||||
dst_rect.top >= 0 && static_cast<u32>(dst_rect.bottom) <= dst->GetConfig().height);
|
||||
ASSERT(src_rect.left >= 0 && static_cast<u32>(src_rect.right) <= GetWidth() &&
|
||||
src_rect.top >= 0 && static_cast<u32>(src_rect.bottom) <= GetHeight());
|
||||
ASSERT(dst_rect.left >= 0 && static_cast<u32>(dst_rect.right) <= dst->GetWidth() &&
|
||||
dst_rect.top >= 0 && static_cast<u32>(dst_rect.bottom) <= dst->GetHeight());
|
||||
|
||||
if (IsMapped())
|
||||
DXStagingTexture::Unmap();
|
||||
|
||||
CD3D11_BOX src_box(src_rect.left, src_rect.top, 0, src_rect.right, src_rect.bottom, 1);
|
||||
D3D::context->CopySubresourceRegion(
|
||||
static_cast<const DXTexture*>(dst)->GetRawTexIdentifier()->GetTex(),
|
||||
D3D11CalcSubresource(dst_level, dst_layer, dst->GetConfig().levels),
|
||||
static_cast<u32>(dst_rect.left), static_cast<u32>(dst_rect.top), 0, m_tex, 0, &src_box);
|
||||
if (static_cast<u32>(src_rect.GetWidth()) == dst->GetWidth() &&
|
||||
static_cast<u32>(src_rect.GetHeight()) == dst->GetHeight())
|
||||
{
|
||||
D3D::context->CopySubresourceRegion(
|
||||
static_cast<const DXTexture*>(dst)->GetD3DTexture(),
|
||||
D3D11CalcSubresource(dst_level, dst_layer, dst->GetLevels()), 0, 0, 0, m_tex, 0, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
CD3D11_BOX src_box(src_rect.left, src_rect.top, 0, src_rect.right, src_rect.bottom, 1);
|
||||
D3D::context->CopySubresourceRegion(
|
||||
static_cast<const DXTexture*>(dst)->GetD3DTexture(),
|
||||
D3D11CalcSubresource(dst_level, dst_layer, dst->GetLevels()),
|
||||
static_cast<u32>(dst_rect.left), static_cast<u32>(dst_rect.top), 0, m_tex, 0, &src_box);
|
||||
}
|
||||
}
|
||||
|
||||
bool DXStagingTexture::Map()
|
||||
@ -348,11 +393,14 @@ void DXStagingTexture::Flush()
|
||||
m_needs_flush = false;
|
||||
}
|
||||
|
||||
DXFramebuffer::DXFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
|
||||
DXFramebuffer::DXFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
|
||||
AbstractTextureFormat color_format, AbstractTextureFormat depth_format,
|
||||
u32 width, u32 height, u32 layers, u32 samples,
|
||||
ID3D11RenderTargetView* rtv, ID3D11DepthStencilView* dsv)
|
||||
: AbstractFramebuffer(color_format, depth_format, width, height, layers, samples), m_rtv(rtv),
|
||||
m_dsv(dsv)
|
||||
ID3D11RenderTargetView* rtv, ID3D11RenderTargetView* integer_rtv,
|
||||
ID3D11DepthStencilView* dsv)
|
||||
: AbstractFramebuffer(color_attachment, depth_attachment, color_format, depth_format, width,
|
||||
height, layers, samples),
|
||||
m_rtv(rtv), m_integer_rtv(integer_rtv), m_dsv(dsv)
|
||||
{
|
||||
}
|
||||
|
||||
@ -360,12 +408,14 @@ DXFramebuffer::~DXFramebuffer()
|
||||
{
|
||||
if (m_rtv)
|
||||
m_rtv->Release();
|
||||
if (m_integer_rtv)
|
||||
m_integer_rtv->Release();
|
||||
if (m_dsv)
|
||||
m_dsv->Release();
|
||||
}
|
||||
|
||||
std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(const DXTexture* color_attachment,
|
||||
const DXTexture* depth_attachment)
|
||||
std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment,
|
||||
DXTexture* depth_attachment)
|
||||
{
|
||||
if (!ValidateConfig(color_attachment, depth_attachment))
|
||||
return nullptr;
|
||||
@ -381,55 +431,45 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(const DXTexture* color_atta
|
||||
const u32 samples = either_attachment->GetSamples();
|
||||
|
||||
ID3D11RenderTargetView* rtv = nullptr;
|
||||
ID3D11RenderTargetView* integer_rtv = nullptr;
|
||||
if (color_attachment)
|
||||
{
|
||||
D3D11_RENDER_TARGET_VIEW_DESC desc;
|
||||
desc.Format = GetDXGIFormatForHostFormat(color_attachment->GetConfig().format);
|
||||
if (color_attachment->GetConfig().IsMultisampled())
|
||||
{
|
||||
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
desc.Texture2DMSArray.ArraySize = color_attachment->GetConfig().layers;
|
||||
desc.Texture2DMSArray.FirstArraySlice = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
desc.Texture2DArray.ArraySize = color_attachment->GetConfig().layers;
|
||||
desc.Texture2DArray.FirstArraySlice = 0;
|
||||
desc.Texture2DArray.MipSlice = 0;
|
||||
}
|
||||
|
||||
HRESULT hr = D3D::device->CreateRenderTargetView(
|
||||
color_attachment->GetRawTexIdentifier()->GetTex(), &desc, &rtv);
|
||||
CD3D11_RENDER_TARGET_VIEW_DESC desc(
|
||||
color_attachment->IsMultisampled() ? D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY :
|
||||
D3D11_RTV_DIMENSION_TEXTURE2DARRAY,
|
||||
GetRTVFormatForHostFormat(color_attachment->GetFormat(), false), 0, 0,
|
||||
color_attachment->GetLayers());
|
||||
HRESULT hr =
|
||||
D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc, &rtv);
|
||||
CHECK(SUCCEEDED(hr), "Create render target view for framebuffer");
|
||||
|
||||
// Only create the integer RTV on Win8+.
|
||||
DXGI_FORMAT integer_format = GetRTVFormatForHostFormat(color_attachment->GetFormat(), true);
|
||||
if (D3D::device1 && integer_format != desc.Format)
|
||||
{
|
||||
desc.Format = integer_format;
|
||||
hr = D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc,
|
||||
&integer_rtv);
|
||||
CHECK(SUCCEEDED(hr), "Create integer render target view for framebuffer");
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11DepthStencilView* dsv = nullptr;
|
||||
if (depth_attachment)
|
||||
{
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC desc;
|
||||
desc.Format = GetDXGIFormatForHostFormat(depth_attachment->GetConfig().format);
|
||||
if (depth_attachment->GetConfig().IsMultisampled())
|
||||
{
|
||||
desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
desc.Texture2DMSArray.ArraySize = depth_attachment->GetConfig().layers;
|
||||
desc.Texture2DMSArray.FirstArraySlice = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
||||
desc.Texture2DArray.ArraySize = depth_attachment->GetConfig().layers;
|
||||
desc.Texture2DArray.FirstArraySlice = 0;
|
||||
desc.Texture2DArray.MipSlice = 0;
|
||||
}
|
||||
|
||||
HRESULT hr = D3D::device->CreateDepthStencilView(
|
||||
depth_attachment->GetRawTexIdentifier()->GetTex(), &desc, &dsv);
|
||||
const CD3D11_DEPTH_STENCIL_VIEW_DESC desc(
|
||||
depth_attachment->GetConfig().IsMultisampled() ? D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY :
|
||||
D3D11_DSV_DIMENSION_TEXTURE2DARRAY,
|
||||
GetDSVFormatForHostFormat(depth_attachment->GetFormat()), 0, 0,
|
||||
depth_attachment->GetLayers(), 0);
|
||||
HRESULT hr =
|
||||
D3D::device->CreateDepthStencilView(depth_attachment->GetD3DTexture(), &desc, &dsv);
|
||||
CHECK(SUCCEEDED(hr), "Create depth stencil view for framebuffer");
|
||||
}
|
||||
|
||||
return std::make_unique<DXFramebuffer>(color_format, depth_format, width, height, layers, samples,
|
||||
rtv, dsv);
|
||||
return std::make_unique<DXFramebuffer>(color_attachment, depth_attachment, color_format,
|
||||
depth_format, width, height, layers, samples, rtv,
|
||||
integer_rtv, dsv);
|
||||
}
|
||||
|
||||
} // namespace DX11
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <memory>
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
@ -11,32 +12,34 @@
|
||||
#include "VideoCommon/AbstractStagingTexture.h"
|
||||
#include "VideoCommon/AbstractTexture.h"
|
||||
|
||||
class D3DTexture2D;
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
class DXTexture final : public AbstractTexture
|
||||
{
|
||||
public:
|
||||
explicit DXTexture(const TextureConfig& tex_config);
|
||||
explicit DXTexture(const TextureConfig& tex_config, ID3D11Texture2D* d3d_texture,
|
||||
ID3D11ShaderResourceView* d3d_srv, ID3D11UnorderedAccessView* d3d_uav);
|
||||
~DXTexture();
|
||||
|
||||
static std::unique_ptr<DXTexture> Create(const TextureConfig& config);
|
||||
|
||||
void CopyRectangleFromTexture(const AbstractTexture* src,
|
||||
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
|
||||
u32 src_level, const MathUtil::Rectangle<int>& dst_rect,
|
||||
u32 dst_layer, u32 dst_level) override;
|
||||
void ScaleRectangleFromTexture(const AbstractTexture* source,
|
||||
const MathUtil::Rectangle<int>& srcrect,
|
||||
const MathUtil::Rectangle<int>& dstrect) override;
|
||||
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& rect,
|
||||
u32 layer, u32 level) override;
|
||||
void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size) override;
|
||||
|
||||
D3DTexture2D* GetRawTexIdentifier() const;
|
||||
ID3D11Texture2D* GetD3DTexture() const { return m_d3d_texture; }
|
||||
ID3D11ShaderResourceView* GetD3DSRV() const { return m_d3d_srv; }
|
||||
ID3D11UnorderedAccessView* GetD3DUAV() const { return m_d3d_uav; }
|
||||
|
||||
private:
|
||||
D3DTexture2D* m_texture;
|
||||
ID3D11Texture2D* m_d3d_texture;
|
||||
ID3D11ShaderResourceView* m_d3d_srv;
|
||||
ID3D11UnorderedAccessView* m_d3d_uav;
|
||||
};
|
||||
|
||||
class DXStagingTexture final : public AbstractStagingTexture
|
||||
@ -68,19 +71,22 @@ private:
|
||||
class DXFramebuffer final : public AbstractFramebuffer
|
||||
{
|
||||
public:
|
||||
DXFramebuffer(AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width,
|
||||
DXFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
|
||||
AbstractTextureFormat color_format, AbstractTextureFormat depth_format, u32 width,
|
||||
u32 height, u32 layers, u32 samples, ID3D11RenderTargetView* rtv,
|
||||
ID3D11DepthStencilView* dsv);
|
||||
ID3D11RenderTargetView* integer_rtv, ID3D11DepthStencilView* dsv);
|
||||
~DXFramebuffer() override;
|
||||
|
||||
ID3D11RenderTargetView* const* GetRTVArray() const { return &m_rtv; }
|
||||
ID3D11RenderTargetView* const* GetIntegerRTVArray() const { return &m_integer_rtv; }
|
||||
UINT GetNumRTVs() const { return m_rtv ? 1 : 0; }
|
||||
ID3D11DepthStencilView* GetDSV() const { return m_dsv; }
|
||||
static std::unique_ptr<DXFramebuffer> Create(const DXTexture* color_attachment,
|
||||
const DXTexture* depth_attachment);
|
||||
static std::unique_ptr<DXFramebuffer> Create(DXTexture* color_attachment,
|
||||
DXTexture* depth_attachment);
|
||||
|
||||
protected:
|
||||
ID3D11RenderTargetView* m_rtv;
|
||||
ID3D11RenderTargetView* m_integer_rtv;
|
||||
ID3D11DepthStencilView* m_dsv;
|
||||
};
|
||||
|
||||
|
@ -1,303 +0,0 @@
|
||||
// Copyright 2010 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "VideoBackends/D3D/FramebufferManager.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/D3DUtil.h"
|
||||
#include "VideoBackends/D3D/GeometryShaderCache.h"
|
||||
#include "VideoBackends/D3D/PixelShaderCache.h"
|
||||
#include "VideoBackends/D3D/Render.h"
|
||||
#include "VideoBackends/D3D/VertexShaderCache.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
static bool s_integer_efb_render_target = false;
|
||||
|
||||
FramebufferManager::Efb FramebufferManager::m_efb;
|
||||
unsigned int FramebufferManager::m_target_width;
|
||||
unsigned int FramebufferManager::m_target_height;
|
||||
|
||||
D3DTexture2D*& FramebufferManager::GetEFBColorTexture()
|
||||
{
|
||||
return m_efb.color_tex;
|
||||
}
|
||||
|
||||
D3DTexture2D*& FramebufferManager::GetEFBColorReadTexture()
|
||||
{
|
||||
return m_efb.color_read_texture;
|
||||
}
|
||||
ID3D11Texture2D*& FramebufferManager::GetEFBColorStagingBuffer()
|
||||
{
|
||||
return m_efb.color_staging_buf;
|
||||
}
|
||||
|
||||
D3DTexture2D*& FramebufferManager::GetEFBDepthTexture()
|
||||
{
|
||||
return m_efb.depth_tex;
|
||||
}
|
||||
D3DTexture2D*& FramebufferManager::GetEFBDepthReadTexture()
|
||||
{
|
||||
return m_efb.depth_read_texture;
|
||||
}
|
||||
ID3D11Texture2D*& FramebufferManager::GetEFBDepthStagingBuffer()
|
||||
{
|
||||
return m_efb.depth_staging_buf;
|
||||
}
|
||||
|
||||
D3DTexture2D*& FramebufferManager::GetResolvedEFBColorTexture()
|
||||
{
|
||||
if (g_ActiveConfig.iMultisamples > 1)
|
||||
{
|
||||
for (int i = 0; i < m_efb.slices; i++)
|
||||
D3D::context->ResolveSubresource(m_efb.resolved_color_tex->GetTex(),
|
||||
D3D11CalcSubresource(0, i, 1), m_efb.color_tex->GetTex(),
|
||||
D3D11CalcSubresource(0, i, 1), DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
return m_efb.resolved_color_tex;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_efb.color_tex;
|
||||
}
|
||||
}
|
||||
|
||||
D3DTexture2D*& FramebufferManager::GetResolvedEFBDepthTexture()
|
||||
{
|
||||
if (g_ActiveConfig.iMultisamples > 1)
|
||||
{
|
||||
// ResolveSubresource does not work with depth textures.
|
||||
// Instead, we use a shader that selects the minimum depth from all samples.
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
CD3D11_VIEWPORT viewport(0.f, 0.f, (float)m_target_width, (float)m_target_height);
|
||||
D3D::context->RSSetViewports(1, &viewport);
|
||||
D3D::context->OMSetRenderTargets(1, &m_efb.resolved_depth_tex->GetRTV(), nullptr);
|
||||
|
||||
const D3D11_RECT source_rect = CD3D11_RECT(0, 0, m_target_width, m_target_height);
|
||||
D3D::drawShadedTexQuad(
|
||||
m_efb.depth_tex->GetSRV(), &source_rect, m_target_width, m_target_height,
|
||||
PixelShaderCache::GetDepthResolveProgram(), VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader());
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
return m_efb.resolved_depth_tex;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_efb.depth_tex;
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManager::SwapReinterpretTexture()
|
||||
{
|
||||
std::swap(m_efb.color_tex, m_efb.color_temp_tex);
|
||||
std::swap(m_efb.color_int_rtv, m_efb.color_temp_int_rtv);
|
||||
}
|
||||
|
||||
void FramebufferManager::SetIntegerEFBRenderTarget(bool enabled)
|
||||
{
|
||||
if (s_integer_efb_render_target == enabled)
|
||||
return;
|
||||
|
||||
// We only use UINT render targets for logic ops, which is only supported with D3D11.1.
|
||||
if (!D3D::device1)
|
||||
return;
|
||||
|
||||
s_integer_efb_render_target = enabled;
|
||||
BindEFBRenderTarget();
|
||||
}
|
||||
|
||||
void FramebufferManager::BindEFBRenderTarget(bool bind_depth)
|
||||
{
|
||||
ID3D11RenderTargetView* rtv =
|
||||
s_integer_efb_render_target ? m_efb.color_int_rtv : m_efb.color_tex->GetRTV();
|
||||
ID3D11DepthStencilView* dsv = bind_depth ? m_efb.depth_tex->GetDSV() : nullptr;
|
||||
D3D::context->OMSetRenderTargets(1, &rtv, dsv);
|
||||
}
|
||||
|
||||
FramebufferManager::FramebufferManager(int target_width, int target_height)
|
||||
{
|
||||
static constexpr std::array<float, 4> clear_color = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
m_target_width = static_cast<unsigned int>(std::max(target_width, 1));
|
||||
m_target_height = static_cast<unsigned int>(std::max(target_height, 1));
|
||||
DXGI_SAMPLE_DESC sample_desc;
|
||||
sample_desc.Count = g_ActiveConfig.iMultisamples;
|
||||
sample_desc.Quality = 0;
|
||||
|
||||
ID3D11Texture2D* buf;
|
||||
D3D11_TEXTURE2D_DESC texdesc;
|
||||
HRESULT hr;
|
||||
|
||||
m_EFBLayers = m_efb.slices = (g_ActiveConfig.stereo_mode != StereoMode::Off) ? 2 : 1;
|
||||
|
||||
// EFB color texture - primary render target
|
||||
texdesc =
|
||||
CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_TYPELESS, m_target_width, m_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)", m_target_width,
|
||||
m_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));
|
||||
|
||||
SAFE_RELEASE(buf);
|
||||
D3D::SetDebugObjectName(m_efb.color_tex->GetTex(), "EFB color texture");
|
||||
D3D::SetDebugObjectName(m_efb.color_tex->GetSRV(), "EFB color texture shader resource view");
|
||||
D3D::SetDebugObjectName(m_efb.color_tex->GetRTV(), "EFB color texture render target view");
|
||||
D3D::context->ClearRenderTargetView(m_efb.color_tex->GetRTV(), clear_color.data());
|
||||
|
||||
// Temporary EFB color texture - used in ReinterpretPixelData
|
||||
texdesc =
|
||||
CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_TYPELESS, m_target_width, m_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)", m_target_width,
|
||||
m_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));
|
||||
SAFE_RELEASE(buf);
|
||||
D3D::SetDebugObjectName(m_efb.color_temp_tex->GetTex(), "EFB color temp texture");
|
||||
D3D::SetDebugObjectName(m_efb.color_temp_tex->GetSRV(),
|
||||
"EFB color temp texture shader resource view");
|
||||
D3D::SetDebugObjectName(m_efb.color_temp_tex->GetRTV(),
|
||||
"EFB color temp texture render target view");
|
||||
D3D::context->ClearRenderTargetView(m_efb.color_temp_tex->GetRTV(), clear_color.data());
|
||||
|
||||
// Integer render targets for EFB, used for logic op
|
||||
CD3D11_RENDER_TARGET_VIEW_DESC int_rtv_desc(m_efb.color_tex->GetTex(),
|
||||
g_ActiveConfig.iMultisamples > 1 ?
|
||||
D3D11_RTV_DIMENSION_TEXTURE2DMS :
|
||||
D3D11_RTV_DIMENSION_TEXTURE2D,
|
||||
DXGI_FORMAT_R8G8B8A8_UINT);
|
||||
hr = D3D::device->CreateRenderTargetView(m_efb.color_tex->GetTex(), &int_rtv_desc,
|
||||
&m_efb.color_int_rtv);
|
||||
CHECK(hr == S_OK, "create EFB integer RTV(hr=%#x)", hr);
|
||||
hr = D3D::device->CreateRenderTargetView(m_efb.color_temp_tex->GetTex(), &int_rtv_desc,
|
||||
&m_efb.color_temp_int_rtv);
|
||||
CHECK(hr == S_OK, "create EFB integer RTV(hr=%#x)", hr);
|
||||
|
||||
// Render buffer for AccessEFB (color data)
|
||||
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 1, 1, D3D11_BIND_RENDER_TARGET);
|
||||
hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &buf);
|
||||
CHECK(hr == S_OK, "create EFB color read texture (hr=%#x)", hr);
|
||||
m_efb.color_read_texture = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
|
||||
SAFE_RELEASE(buf);
|
||||
D3D::SetDebugObjectName(m_efb.color_read_texture->GetTex(),
|
||||
"EFB color read texture (used in Renderer::AccessEFB)");
|
||||
D3D::SetDebugObjectName(
|
||||
m_efb.color_read_texture->GetRTV(),
|
||||
"EFB color 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_R8G8B8A8_UNORM, 1, 1, 1, 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(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_R32_TYPELESS, m_target_width, m_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)", m_target_width,
|
||||
m_target_height, hr);
|
||||
m_efb.depth_tex = new D3DTexture2D(
|
||||
buf, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE),
|
||||
DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_UNKNOWN, (sample_desc.Count > 1));
|
||||
SAFE_RELEASE(buf);
|
||||
D3D::SetDebugObjectName(m_efb.depth_tex->GetTex(), "EFB depth texture");
|
||||
D3D::SetDebugObjectName(m_efb.depth_tex->GetDSV(), "EFB depth texture depth stencil view");
|
||||
D3D::SetDebugObjectName(m_efb.depth_tex->GetSRV(), "EFB depth texture shader resource view");
|
||||
D3D::context->ClearDepthStencilView(m_efb.depth_tex->GetDSV(), D3D11_CLEAR_DEPTH, 0.0f, 0);
|
||||
|
||||
// Render buffer for AccessEFB (depth data)
|
||||
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 1, 1, 1, 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);
|
||||
SAFE_RELEASE(buf);
|
||||
D3D::SetDebugObjectName(m_efb.depth_read_texture->GetTex(),
|
||||
"EFB depth read texture (used in Renderer::AccessEFB)");
|
||||
D3D::SetDebugObjectName(
|
||||
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);
|
||||
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(m_efb.depth_staging_buf,
|
||||
"EFB depth staging texture (used for Renderer::AccessEFB)");
|
||||
|
||||
if (g_ActiveConfig.iMultisamples > 1)
|
||||
{
|
||||
// Framebuffer resolve textures (color+depth)
|
||||
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, m_target_width, m_target_height,
|
||||
m_efb.slices, 1, D3D11_BIND_SHADER_RESOURCE,
|
||||
D3D11_USAGE_DEFAULT, 0, 1);
|
||||
hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &buf);
|
||||
CHECK(hr == S_OK, "create EFB color resolve texture (size: %dx%d; hr=%#x)", m_target_width,
|
||||
m_target_height, hr);
|
||||
m_efb.resolved_color_tex =
|
||||
new D3DTexture2D(buf, D3D11_BIND_SHADER_RESOURCE, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
SAFE_RELEASE(buf);
|
||||
D3D::SetDebugObjectName(m_efb.resolved_color_tex->GetTex(), "EFB color resolve texture");
|
||||
D3D::SetDebugObjectName(m_efb.resolved_color_tex->GetSRV(),
|
||||
"EFB color resolve texture shader resource view");
|
||||
|
||||
texdesc =
|
||||
CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, m_target_width, m_target_height, m_efb.slices,
|
||||
1, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
|
||||
hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &buf);
|
||||
CHECK(hr == S_OK, "create EFB depth resolve texture (size: %dx%d; hr=%#x)", m_target_width,
|
||||
m_target_height, hr);
|
||||
m_efb.resolved_depth_tex = new D3DTexture2D(
|
||||
buf, (D3D11_BIND_FLAG)(D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET),
|
||||
DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32_FLOAT);
|
||||
SAFE_RELEASE(buf);
|
||||
D3D::SetDebugObjectName(m_efb.resolved_depth_tex->GetTex(), "EFB depth resolve texture");
|
||||
D3D::SetDebugObjectName(m_efb.resolved_depth_tex->GetSRV(),
|
||||
"EFB depth resolve texture shader resource view");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_efb.resolved_color_tex = nullptr;
|
||||
m_efb.resolved_depth_tex = nullptr;
|
||||
}
|
||||
s_integer_efb_render_target = false;
|
||||
}
|
||||
|
||||
FramebufferManager::~FramebufferManager()
|
||||
{
|
||||
SAFE_RELEASE(m_efb.color_tex);
|
||||
SAFE_RELEASE(m_efb.color_int_rtv);
|
||||
SAFE_RELEASE(m_efb.color_temp_tex);
|
||||
SAFE_RELEASE(m_efb.color_temp_int_rtv);
|
||||
SAFE_RELEASE(m_efb.color_staging_buf);
|
||||
SAFE_RELEASE(m_efb.color_read_texture);
|
||||
SAFE_RELEASE(m_efb.resolved_color_tex);
|
||||
SAFE_RELEASE(m_efb.depth_tex);
|
||||
SAFE_RELEASE(m_efb.depth_staging_buf);
|
||||
SAFE_RELEASE(m_efb.depth_read_texture);
|
||||
SAFE_RELEASE(m_efb.resolved_depth_tex);
|
||||
}
|
||||
|
||||
} // namespace DX11
|
@ -1,96 +0,0 @@
|
||||
// Copyright 2009 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoBackends/D3D/D3DTexture.h"
|
||||
#include "VideoCommon/FramebufferManagerBase.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
// On the GameCube, the game sends a request for the graphics processor to
|
||||
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
||||
// called the XFB (External Framebuffer). The size and location of the XFB is
|
||||
// decided at the time of the copy, and the format is always YUYV. The video
|
||||
// interface is given a pointer to the XFB, which will be decoded and
|
||||
// displayed on the TV.
|
||||
//
|
||||
// There are two ways for Dolphin to emulate this:
|
||||
//
|
||||
// Real XFB mode:
|
||||
//
|
||||
// Dolphin will behave like the GameCube and encode the EFB to
|
||||
// a portion of GameCube RAM. The emulated video interface will decode the data
|
||||
// for output to the screen.
|
||||
//
|
||||
// Advantages: Behaves exactly like the GameCube.
|
||||
// Disadvantages: Resolution will be limited.
|
||||
//
|
||||
// Virtual XFB mode:
|
||||
//
|
||||
// When a request is made to copy the EFB to an XFB, Dolphin
|
||||
// will remember the RAM location and size of the XFB in a Virtual XFB list.
|
||||
// The video interface will look up the XFB in the list and use the enhanced
|
||||
// data stored there, if available.
|
||||
//
|
||||
// Advantages: Enables high resolution graphics, better than real hardware.
|
||||
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
|
||||
// possible but uncommon), the Virtual XFB will not capture this information.
|
||||
|
||||
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
||||
// virtualize.
|
||||
|
||||
class FramebufferManager : public FramebufferManagerBase
|
||||
{
|
||||
public:
|
||||
FramebufferManager(int target_width, int target_height);
|
||||
~FramebufferManager();
|
||||
|
||||
static D3DTexture2D*& GetEFBColorTexture();
|
||||
static D3DTexture2D*& GetEFBColorReadTexture();
|
||||
static ID3D11Texture2D*& GetEFBColorStagingBuffer();
|
||||
|
||||
static D3DTexture2D*& GetEFBDepthTexture();
|
||||
static D3DTexture2D*& GetEFBDepthReadTexture();
|
||||
static ID3D11Texture2D*& GetEFBDepthStagingBuffer();
|
||||
|
||||
static D3DTexture2D*& GetResolvedEFBColorTexture();
|
||||
static D3DTexture2D*& GetResolvedEFBDepthTexture();
|
||||
|
||||
static D3DTexture2D*& GetEFBColorTempTexture() { return m_efb.color_temp_tex; }
|
||||
static void SwapReinterpretTexture();
|
||||
static void SetIntegerEFBRenderTarget(bool enabled);
|
||||
static void BindEFBRenderTarget(bool bind_depth = true);
|
||||
|
||||
private:
|
||||
static struct Efb
|
||||
{
|
||||
D3DTexture2D* color_tex;
|
||||
ID3D11RenderTargetView* color_int_rtv;
|
||||
ID3D11Texture2D* color_staging_buf;
|
||||
D3DTexture2D* color_read_texture;
|
||||
|
||||
D3DTexture2D* depth_tex;
|
||||
ID3D11Texture2D* depth_staging_buf;
|
||||
D3DTexture2D* depth_read_texture;
|
||||
|
||||
D3DTexture2D* color_temp_tex;
|
||||
ID3D11RenderTargetView* color_temp_int_rtv;
|
||||
|
||||
D3DTexture2D* resolved_color_tex;
|
||||
D3DTexture2D* resolved_depth_tex;
|
||||
|
||||
int slices;
|
||||
} m_efb;
|
||||
|
||||
static unsigned int m_target_width;
|
||||
static unsigned int m_target_height;
|
||||
};
|
||||
|
||||
} // namespace DX11
|
@ -1,113 +0,0 @@
|
||||
// Copyright 2014 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DShader.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/FramebufferManager.h"
|
||||
#include "VideoBackends/D3D/GeometryShaderCache.h"
|
||||
|
||||
#include "VideoCommon/Debugger.h"
|
||||
#include "VideoCommon/GeometryShaderGen.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
ID3D11GeometryShader* ClearGeometryShader = nullptr;
|
||||
ID3D11GeometryShader* CopyGeometryShader = nullptr;
|
||||
|
||||
ID3D11GeometryShader* GeometryShaderCache::GetClearGeometryShader()
|
||||
{
|
||||
return (g_ActiveConfig.stereo_mode != StereoMode::Off) ? ClearGeometryShader : nullptr;
|
||||
}
|
||||
ID3D11GeometryShader* GeometryShaderCache::GetCopyGeometryShader()
|
||||
{
|
||||
return (g_ActiveConfig.stereo_mode != StereoMode::Off) ? CopyGeometryShader : nullptr;
|
||||
}
|
||||
|
||||
const char clear_shader_code[] = {
|
||||
"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
" float4 vPosition : POSITION;\n"
|
||||
" float4 vColor0 : COLOR0;\n"
|
||||
"};\n"
|
||||
"struct GSOUTPUT\n"
|
||||
"{\n"
|
||||
" float4 vPosition : POSITION;\n"
|
||||
" float4 vColor0 : COLOR0;\n"
|
||||
" uint slice : SV_RenderTargetArrayIndex;\n"
|
||||
"};\n"
|
||||
"[maxvertexcount(6)]\n"
|
||||
"void main(triangle VSOUTPUT o[3], inout TriangleStream<GSOUTPUT> Output)\n"
|
||||
"{\n"
|
||||
"for(int slice = 0; slice < 2; slice++)\n"
|
||||
"{\n"
|
||||
" for(int i = 0; i < 3; i++)\n"
|
||||
" {\n"
|
||||
" GSOUTPUT OUT;\n"
|
||||
" OUT.vPosition = o[i].vPosition;\n"
|
||||
" OUT.vColor0 = o[i].vColor0;\n"
|
||||
" OUT.slice = slice;\n"
|
||||
" Output.Append(OUT);\n"
|
||||
" }\n"
|
||||
" Output.RestartStrip();\n"
|
||||
"}\n"
|
||||
"}\n"};
|
||||
|
||||
const char copy_shader_code[] = {
|
||||
"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
" float4 vPosition : POSITION;\n"
|
||||
" float3 vTexCoord : TEXCOORD0;\n"
|
||||
"};\n"
|
||||
"struct GSOUTPUT\n"
|
||||
"{\n"
|
||||
" float4 vPosition : POSITION;\n"
|
||||
" float3 vTexCoord : TEXCOORD0;\n"
|
||||
" uint slice : SV_RenderTargetArrayIndex;\n"
|
||||
"};\n"
|
||||
"[maxvertexcount(6)]\n"
|
||||
"void main(triangle VSOUTPUT o[3], inout TriangleStream<GSOUTPUT> Output)\n"
|
||||
"{\n"
|
||||
"for(int slice = 0; slice < 2; slice++)\n"
|
||||
"{\n"
|
||||
" for(int i = 0; i < 3; i++)\n"
|
||||
" {\n"
|
||||
" GSOUTPUT OUT;\n"
|
||||
" OUT.vPosition = o[i].vPosition;\n"
|
||||
" OUT.vTexCoord = o[i].vTexCoord;\n"
|
||||
" OUT.vTexCoord.z = float(slice);\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(ClearGeometryShader, "clear geometry shader");
|
||||
|
||||
// used for buffer copy
|
||||
CopyGeometryShader = D3D::CompileAndCreateGeometryShader(copy_shader_code);
|
||||
CHECK(CopyGeometryShader != nullptr, "Create copy geometry shader");
|
||||
D3D::SetDebugObjectName(CopyGeometryShader, "copy geometry shader");
|
||||
}
|
||||
|
||||
void GeometryShaderCache::Shutdown()
|
||||
{
|
||||
SAFE_RELEASE(ClearGeometryShader);
|
||||
SAFE_RELEASE(CopyGeometryShader);
|
||||
}
|
||||
} // DX11
|
@ -1,27 +0,0 @@
|
||||
// Copyright 2014 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <map>
|
||||
|
||||
#include "VideoCommon/GeometryShaderGen.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
class GeometryShaderCache
|
||||
{
|
||||
public:
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
|
||||
static ID3D11GeometryShader* GetClearGeometryShader();
|
||||
static ID3D11GeometryShader* GetCopyGeometryShader();
|
||||
|
||||
static ID3D11Buffer* GetConstantBuffer();
|
||||
static void UpdateConstantBuffer(const void* data, u32 data_size);
|
||||
};
|
||||
|
||||
} // namespace DX11
|
@ -5,10 +5,10 @@
|
||||
#include <array>
|
||||
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DBlob.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/DXShader.h"
|
||||
#include "VideoBackends/D3D/Render.h"
|
||||
#include "VideoBackends/D3D/VertexManager.h"
|
||||
#include "VideoBackends/D3D/VertexShaderCache.h"
|
||||
#include "VideoCommon/NativeVertexFormat.h"
|
||||
|
||||
namespace DX11
|
||||
@ -16,7 +16,7 @@ namespace DX11
|
||||
std::mutex s_input_layout_lock;
|
||||
|
||||
std::unique_ptr<NativeVertexFormat>
|
||||
VertexManager::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl)
|
||||
Renderer::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl)
|
||||
{
|
||||
return std::make_unique<D3DVertexFormat>(vtx_decl);
|
||||
}
|
||||
@ -77,11 +77,11 @@ DXGI_FORMAT VarToD3D(VarType t, int size, bool integer)
|
||||
return retval;
|
||||
}
|
||||
|
||||
D3DVertexFormat::D3DVertexFormat(const PortableVertexDeclaration& _vtx_decl)
|
||||
{
|
||||
this->vtx_decl = _vtx_decl;
|
||||
D3DVertexFormat::D3DVertexFormat(const PortableVertexDeclaration& vtx_decl)
|
||||
: NativeVertexFormat(vtx_decl)
|
||||
|
||||
const AttributeFormat* format = &_vtx_decl.position;
|
||||
{
|
||||
const AttributeFormat* format = &vtx_decl.position;
|
||||
if (format->enable)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "POSITION";
|
||||
@ -93,7 +93,7 @@ D3DVertexFormat::D3DVertexFormat(const PortableVertexDeclaration& _vtx_decl)
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
format = &_vtx_decl.normals[i];
|
||||
format = &vtx_decl.normals[i];
|
||||
if (format->enable)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "NORMAL";
|
||||
@ -107,7 +107,7 @@ D3DVertexFormat::D3DVertexFormat(const PortableVertexDeclaration& _vtx_decl)
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
format = &_vtx_decl.colors[i];
|
||||
format = &vtx_decl.colors[i];
|
||||
if (format->enable)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "COLOR";
|
||||
@ -121,7 +121,7 @@ D3DVertexFormat::D3DVertexFormat(const PortableVertexDeclaration& _vtx_decl)
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
format = &_vtx_decl.texcoords[i];
|
||||
format = &vtx_decl.texcoords[i];
|
||||
if (format->enable)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "TEXCOORD";
|
||||
@ -133,7 +133,7 @@ D3DVertexFormat::D3DVertexFormat(const PortableVertexDeclaration& _vtx_decl)
|
||||
}
|
||||
}
|
||||
|
||||
format = &_vtx_decl.posmtx;
|
||||
format = &vtx_decl.posmtx;
|
||||
if (format->enable)
|
||||
{
|
||||
m_elems[m_num_elems].SemanticName = "BLENDINDICES";
|
||||
@ -150,7 +150,7 @@ D3DVertexFormat::~D3DVertexFormat()
|
||||
SAFE_RELEASE(layout);
|
||||
}
|
||||
|
||||
ID3D11InputLayout* D3DVertexFormat::GetInputLayout(D3DBlob* vs_bytecode)
|
||||
ID3D11InputLayout* D3DVertexFormat::GetInputLayout(const void* vs_bytecode, size_t vs_bytecode_size)
|
||||
{
|
||||
// CreateInputLayout requires a shader input, but it only looks at the signature of the shader,
|
||||
// so we don't need to recompute it if the shader changes.
|
||||
@ -158,8 +158,8 @@ ID3D11InputLayout* D3DVertexFormat::GetInputLayout(D3DBlob* vs_bytecode)
|
||||
if (layout)
|
||||
return layout;
|
||||
|
||||
HRESULT hr = DX11::D3D::device->CreateInputLayout(
|
||||
m_elems.data(), m_num_elems, vs_bytecode->Data(), vs_bytecode->Size(), &layout);
|
||||
HRESULT hr = D3D::device->CreateInputLayout(m_elems.data(), m_num_elems, vs_bytecode,
|
||||
vs_bytecode_size, &layout);
|
||||
if (FAILED(hr))
|
||||
PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__);
|
||||
DX11::D3D::SetDebugObjectName(m_layout, "input layout used to emulate the GX pipeline");
|
||||
|
@ -1,160 +0,0 @@
|
||||
// Copyright 2011 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "VideoBackends/D3D/PSTextureEncoder.h"
|
||||
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DShader.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/D3DUtil.h"
|
||||
#include "VideoBackends/D3D/DXTexture.h"
|
||||
#include "VideoBackends/D3D/FramebufferManager.h"
|
||||
#include "VideoBackends/D3D/Render.h"
|
||||
#include "VideoBackends/D3D/TextureCache.h"
|
||||
#include "VideoBackends/D3D/VertexShaderCache.h"
|
||||
|
||||
#include "VideoCommon/AbstractStagingTexture.h"
|
||||
#include "VideoCommon/AbstractTexture.h"
|
||||
#include "VideoCommon/TextureConversionShader.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
struct EFBEncodeParams
|
||||
{
|
||||
s32 SrcLeft;
|
||||
s32 SrcTop;
|
||||
u32 DestWidth;
|
||||
u32 ScaleFactor;
|
||||
float y_scale;
|
||||
float gamma_rcp;
|
||||
float clamp_top;
|
||||
float clamp_bottom;
|
||||
float filter_coefficients[3];
|
||||
u32 padding;
|
||||
};
|
||||
|
||||
PSTextureEncoder::PSTextureEncoder()
|
||||
{
|
||||
}
|
||||
|
||||
PSTextureEncoder::~PSTextureEncoder() = default;
|
||||
|
||||
void PSTextureEncoder::Init()
|
||||
{
|
||||
m_encoding_render_texture = g_renderer->CreateTexture(TextureCache::GetEncodingTextureConfig());
|
||||
ASSERT(m_encoding_render_texture);
|
||||
|
||||
// Create constant buffer for uploading data to shaders
|
||||
D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(EFBEncodeParams), D3D11_BIND_CONSTANT_BUFFER);
|
||||
HRESULT hr = D3D::device->CreateBuffer(&bd, nullptr, &m_encode_params);
|
||||
CHECK(SUCCEEDED(hr), "create efb encode params buffer");
|
||||
D3D::SetDebugObjectName(m_encode_params, "efb encoder params buffer");
|
||||
}
|
||||
|
||||
void PSTextureEncoder::Shutdown()
|
||||
{
|
||||
for (auto& it : m_encoding_shaders)
|
||||
SAFE_RELEASE(it.second);
|
||||
m_encoding_shaders.clear();
|
||||
|
||||
SAFE_RELEASE(m_encode_params);
|
||||
}
|
||||
|
||||
void PSTextureEncoder::Encode(
|
||||
AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width, u32 bytes_per_row,
|
||||
u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half,
|
||||
float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
|
||||
const TextureCacheBase::CopyFilterCoefficientArray& filter_coefficients)
|
||||
{
|
||||
// Resolve MSAA targets before copying.
|
||||
// FIXME: Instead of resolving EFB, it would be better to pick out a
|
||||
// single sample from each pixel. The game may break if it isn't
|
||||
// expecting the blurred edges around multisampled shapes.
|
||||
ID3D11ShaderResourceView* pEFB = params.depth ?
|
||||
FramebufferManager::GetResolvedEFBDepthTexture()->GetSRV() :
|
||||
FramebufferManager::GetResolvedEFBColorTexture()->GetSRV();
|
||||
|
||||
// Reset API
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
// Set up all the state for EFB encoding
|
||||
{
|
||||
const u32 words_per_row = bytes_per_row / sizeof(u32);
|
||||
|
||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(words_per_row), FLOAT(num_blocks_y));
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
|
||||
constexpr EFBRectangle fullSrcRect(0, 0, EFB_WIDTH, EFB_HEIGHT);
|
||||
TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(fullSrcRect);
|
||||
|
||||
D3D::context->OMSetRenderTargets(
|
||||
1,
|
||||
&static_cast<DXTexture*>(m_encoding_render_texture.get())->GetRawTexIdentifier()->GetRTV(),
|
||||
nullptr);
|
||||
|
||||
EFBEncodeParams encode_params;
|
||||
encode_params.SrcLeft = src_rect.left;
|
||||
encode_params.SrcTop = src_rect.top;
|
||||
encode_params.DestWidth = native_width;
|
||||
encode_params.ScaleFactor = scale_by_half ? 2 : 1;
|
||||
encode_params.y_scale = y_scale;
|
||||
encode_params.gamma_rcp = 1.0f / gamma;
|
||||
encode_params.clamp_top = clamp_top ? src_rect.top / float(EFB_HEIGHT) : 0.0f;
|
||||
encode_params.clamp_bottom = clamp_bottom ? src_rect.bottom / float(EFB_HEIGHT) : 1.0f;
|
||||
for (size_t i = 0; i < filter_coefficients.size(); i++)
|
||||
encode_params.filter_coefficients[i] = filter_coefficients[i];
|
||||
|
||||
D3D::context->UpdateSubresource(m_encode_params, 0, nullptr, &encode_params, 0, 0);
|
||||
D3D::stateman->SetPixelConstants(m_encode_params);
|
||||
|
||||
// We also linear filtering for both box filtering and downsampling higher resolutions to 1x
|
||||
// TODO: This only produces perfect downsampling for 2x IR, other resolutions will need more
|
||||
// complex down filtering to average all pixels and produce the correct result.
|
||||
// Also, box filtering won't be correct for anything other than 1x IR
|
||||
if (scale_by_half || g_renderer->GetEFBScale() != 1 || y_scale > 1.0f)
|
||||
D3D::SetLinearCopySampler();
|
||||
else
|
||||
D3D::SetPointCopySampler();
|
||||
|
||||
D3D::drawShadedTexQuad(pEFB, targetRect.AsRECT(), g_renderer->GetTargetWidth(),
|
||||
g_renderer->GetTargetHeight(), GetEncodingPixelShader(params),
|
||||
VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout());
|
||||
|
||||
// Copy to staging buffer
|
||||
MathUtil::Rectangle<int> copy_rect(0, 0, words_per_row, num_blocks_y);
|
||||
dst->CopyFromTexture(m_encoding_render_texture.get(), copy_rect, 0, 0, copy_rect);
|
||||
}
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PSTextureEncoder::GetEncodingPixelShader(const EFBCopyParams& params)
|
||||
{
|
||||
auto iter = m_encoding_shaders.find(params);
|
||||
if (iter != m_encoding_shaders.end())
|
||||
return iter->second;
|
||||
|
||||
D3DBlob* bytecode = nullptr;
|
||||
const char* shader = TextureConversionShaderTiled::GenerateEncodingShader(params, APIType::D3D);
|
||||
if (!D3D::CompilePixelShader(shader, &bytecode))
|
||||
{
|
||||
PanicAlert("Failed to compile texture encoding shader.");
|
||||
m_encoding_shaders[params] = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ID3D11PixelShader* newShader;
|
||||
HRESULT hr =
|
||||
D3D::device->CreatePixelShader(bytecode->Data(), bytecode->Size(), nullptr, &newShader);
|
||||
CHECK(SUCCEEDED(hr), "create efb encoder pixel shader");
|
||||
|
||||
m_encoding_shaders.emplace(params, newShader);
|
||||
return newShader;
|
||||
}
|
||||
} // namespace DX11
|
@ -1,53 +0,0 @@
|
||||
// Copyright 2011 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoCommon/TextureCacheBase.h"
|
||||
#include "VideoCommon/TextureConversionShader.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
|
||||
class AbstractTexture;
|
||||
class AbstractStagingTexture;
|
||||
|
||||
struct ID3D11Texture2D;
|
||||
struct ID3D11RenderTargetView;
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11InputLayout;
|
||||
struct ID3D11VertexShader;
|
||||
struct ID3D11PixelShader;
|
||||
struct ID3D11ClassLinkage;
|
||||
struct ID3D11ClassInstance;
|
||||
struct ID3D11BlendState;
|
||||
struct ID3D11DepthStencilState;
|
||||
struct ID3D11RasterizerState;
|
||||
struct ID3D11SamplerState;
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
class PSTextureEncoder final
|
||||
{
|
||||
public:
|
||||
PSTextureEncoder();
|
||||
~PSTextureEncoder();
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void Encode(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
|
||||
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
|
||||
bool scale_by_half, float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
|
||||
const TextureCacheBase::CopyFilterCoefficientArray& filter_coefficients);
|
||||
|
||||
private:
|
||||
ID3D11PixelShader* GetEncodingPixelShader(const EFBCopyParams& params);
|
||||
|
||||
ID3D11Buffer* m_encode_params = nullptr;
|
||||
std::unique_ptr<AbstractTexture> m_encoding_render_texture;
|
||||
std::map<EFBCopyParams, ID3D11PixelShader*> m_encoding_shaders;
|
||||
};
|
||||
}
|
@ -1,315 +0,0 @@
|
||||
// Copyright 2010 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Host.h"
|
||||
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DShader.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/PixelShaderCache.h"
|
||||
|
||||
#include "VideoCommon/Debugger.h"
|
||||
#include "VideoCommon/PixelShaderGen.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
ID3D11PixelShader* s_ColorCopyProgram[2] = {nullptr};
|
||||
ID3D11PixelShader* s_ClearProgram = nullptr;
|
||||
ID3D11PixelShader* s_AnaglyphProgram = nullptr;
|
||||
ID3D11PixelShader* s_DepthResolveProgram = nullptr;
|
||||
ID3D11PixelShader* s_rgba6_to_rgb8[2] = {nullptr};
|
||||
ID3D11PixelShader* s_rgb8_to_rgba6[2] = {nullptr};
|
||||
|
||||
const char clear_program_code[] = {"void main(\n"
|
||||
"out float4 ocol0 : SV_Target,\n"
|
||||
"in float4 pos : SV_Position,\n"
|
||||
"in float4 incol0 : COLOR0){\n"
|
||||
"ocol0 = incol0;\n"
|
||||
"}\n"};
|
||||
|
||||
// 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"
|
||||
"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"
|
||||
"ocol0 = Tex0.Sample(samp0,uv0);\n"
|
||||
"}\n"};
|
||||
|
||||
// Anaglyph Red-Cyan shader based on Dubois algorithm
|
||||
// Constants taken from the paper:
|
||||
// "Conversion of a Stereo Pair to Anaglyph with
|
||||
// the Least-Squares Projection Method"
|
||||
// Eric Dubois, March 2009
|
||||
const char anaglyph_program_code[] = {"sampler samp0 : register(s0);\n"
|
||||
"Texture2DArray Tex0 : register(t0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : SV_Target,\n"
|
||||
"in float4 pos : SV_Position,\n"
|
||||
"in float3 uv0 : TEXCOORD0){\n"
|
||||
"float4 c0 = Tex0.Sample(samp0, float3(uv0.xy, 0.0));\n"
|
||||
"float4 c1 = Tex0.Sample(samp0, float3(uv0.xy, 1.0));\n"
|
||||
"float3x3 l = float3x3( 0.437, 0.449, 0.164,\n"
|
||||
" -0.062,-0.062,-0.024,\n"
|
||||
" -0.048,-0.050,-0.017);\n"
|
||||
"float3x3 r = float3x3(-0.011,-0.032,-0.007,\n"
|
||||
" 0.377, 0.761, 0.009,\n"
|
||||
" -0.026,-0.093, 1.234);\n"
|
||||
"ocol0 = float4(mul(l, c0.rgb) + mul(r, c1.rgb), c0.a);\n"
|
||||
"}\n"};
|
||||
|
||||
// TODO: Improve sampling algorithm!
|
||||
const char color_copy_program_code_msaa[] = {
|
||||
"#define SAMPLES %d\n"
|
||||
"sampler samp0 : register(s0);\n"
|
||||
"Texture2DMSArray<float4, SAMPLES> Tex0 : register(t0);\n"
|
||||
"void main(\n"
|
||||
"out float4 ocol0 : SV_Target,\n"
|
||||
"in float4 pos : SV_Position,\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"
|
||||
"ocol0 /= SAMPLES;\n"
|
||||
"}\n"};
|
||||
|
||||
const char depth_resolve_program[] = {
|
||||
"#define SAMPLES %d\n"
|
||||
"Texture2DMSArray<float4, SAMPLES> Tex0 : register(t0);\n"
|
||||
"void main(\n"
|
||||
" out float ocol0 : SV_Target,\n"
|
||||
" in float4 pos : SV_Position,\n"
|
||||
" in float3 uv0 : TEXCOORD0)\n"
|
||||
"{\n"
|
||||
" int width, height, slices, samples;\n"
|
||||
" Tex0.GetDimensions(width, height, slices, samples);\n"
|
||||
" ocol0 = Tex0.Load(int3(uv0.x*(width), uv0.y*(height), uv0.z), 0).x;\n"
|
||||
" for(int i = 1; i < SAMPLES; ++i)\n"
|
||||
" ocol0 = min(ocol0, Tex0.Load(int3(uv0.x*(width), uv0.y*(height), uv0.z), i).x);\n"
|
||||
"}\n"};
|
||||
|
||||
const char reint_rgba6_to_rgb8[] = {"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"
|
||||
"{\n"
|
||||
" int4 src6 = round(Tex0.Sample(samp0,uv0) * 63.f);\n"
|
||||
" int4 dst8;\n"
|
||||
" dst8.r = (src6.r << 2) | (src6.g >> 4);\n"
|
||||
" dst8.g = ((src6.g & 0xF) << 4) | (src6.b >> 2);\n"
|
||||
" dst8.b = ((src6.b & 0x3) << 6) | src6.a;\n"
|
||||
" dst8.a = 255;\n"
|
||||
" ocol0 = (float4)dst8 / 255.f;\n"
|
||||
"}"};
|
||||
|
||||
const char reint_rgba6_to_rgb8_msaa[] = {
|
||||
"#define SAMPLES %d\n"
|
||||
"sampler samp0 : register(s0);\n"
|
||||
"Texture2DMSArray<float4, SAMPLES> Tex0 : register(t0);\n"
|
||||
"void main(\n"
|
||||
" out float4 ocol0 : SV_Target,\n"
|
||||
" in float4 pos : SV_Position,\n"
|
||||
" in float3 uv0 : TEXCOORD0)\n"
|
||||
"{\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(int3(uv0.x*(width), uv0.y*(height), uv0.z), i);\n"
|
||||
" texcol /= SAMPLES;\n"
|
||||
" int4 src6 = round(texcol * 63.f);\n"
|
||||
" int4 dst8;\n"
|
||||
" dst8.r = (src6.r << 2) | (src6.g >> 4);\n"
|
||||
" dst8.g = ((src6.g & 0xF) << 4) | (src6.b >> 2);\n"
|
||||
" dst8.b = ((src6.b & 0x3) << 6) | src6.a;\n"
|
||||
" dst8.a = 255;\n"
|
||||
" ocol0 = (float4)dst8 / 255.f;\n"
|
||||
"}"};
|
||||
|
||||
const char reint_rgb8_to_rgba6[] = {"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"
|
||||
"{\n"
|
||||
" int4 src8 = round(Tex0.Sample(samp0,uv0) * 255.f);\n"
|
||||
" int4 dst6;\n"
|
||||
" dst6.r = src8.r >> 2;\n"
|
||||
" dst6.g = ((src8.r & 0x3) << 4) | (src8.g >> 4);\n"
|
||||
" dst6.b = ((src8.g & 0xF) << 2) | (src8.b >> 6);\n"
|
||||
" dst6.a = src8.b & 0x3F;\n"
|
||||
" ocol0 = (float4)dst6 / 63.f;\n"
|
||||
"}\n"};
|
||||
|
||||
const char reint_rgb8_to_rgba6_msaa[] = {
|
||||
"#define SAMPLES %d\n"
|
||||
"sampler samp0 : register(s0);\n"
|
||||
"Texture2DMSArray<float4, SAMPLES> Tex0 : register(t0);\n"
|
||||
"void main(\n"
|
||||
" out float4 ocol0 : SV_Target,\n"
|
||||
" in float4 pos : SV_Position,\n"
|
||||
" in float3 uv0 : TEXCOORD0)\n"
|
||||
"{\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(int3(uv0.x*(width), uv0.y*(height), uv0.z), i);\n"
|
||||
" texcol /= SAMPLES;\n"
|
||||
" int4 src8 = round(texcol * 255.f);\n"
|
||||
" int4 dst6;\n"
|
||||
" dst6.r = src8.r >> 2;\n"
|
||||
" dst6.g = ((src8.r & 0x3) << 4) | (src8.g >> 4);\n"
|
||||
" dst6.b = ((src8.g & 0xF) << 2) | (src8.b >> 6);\n"
|
||||
" dst6.a = src8.b & 0x3F;\n"
|
||||
" ocol0 = (float4)dst6 / 63.f;\n"
|
||||
"}\n"};
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::ReinterpRGBA6ToRGB8(bool multisampled)
|
||||
{
|
||||
if (!multisampled || g_ActiveConfig.iMultisamples <= 1)
|
||||
{
|
||||
if (!s_rgba6_to_rgb8[0])
|
||||
{
|
||||
s_rgba6_to_rgb8[0] = D3D::CompileAndCreatePixelShader(reint_rgba6_to_rgb8);
|
||||
CHECK(s_rgba6_to_rgb8[0], "Create RGBA6 to RGB8 pixel shader");
|
||||
D3D::SetDebugObjectName(s_rgba6_to_rgb8[0], "RGBA6 to RGB8 pixel shader");
|
||||
}
|
||||
return s_rgba6_to_rgb8[0];
|
||||
}
|
||||
else if (!s_rgba6_to_rgb8[1])
|
||||
{
|
||||
// create MSAA shader for current AA mode
|
||||
std::string buf = StringFromFormat(reint_rgba6_to_rgb8_msaa, g_ActiveConfig.iMultisamples);
|
||||
s_rgba6_to_rgb8[1] = D3D::CompileAndCreatePixelShader(buf);
|
||||
|
||||
CHECK(s_rgba6_to_rgb8[1], "Create RGBA6 to RGB8 MSAA pixel shader");
|
||||
D3D::SetDebugObjectName(s_rgba6_to_rgb8[1], "RGBA6 to RGB8 MSAA pixel shader");
|
||||
}
|
||||
return s_rgba6_to_rgb8[1];
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::ReinterpRGB8ToRGBA6(bool multisampled)
|
||||
{
|
||||
if (!multisampled || g_ActiveConfig.iMultisamples <= 1)
|
||||
{
|
||||
if (!s_rgb8_to_rgba6[0])
|
||||
{
|
||||
s_rgb8_to_rgba6[0] = D3D::CompileAndCreatePixelShader(reint_rgb8_to_rgba6);
|
||||
CHECK(s_rgb8_to_rgba6[0], "Create RGB8 to RGBA6 pixel shader");
|
||||
D3D::SetDebugObjectName(s_rgb8_to_rgba6[0], "RGB8 to RGBA6 pixel shader");
|
||||
}
|
||||
return s_rgb8_to_rgba6[0];
|
||||
}
|
||||
else if (!s_rgb8_to_rgba6[1])
|
||||
{
|
||||
// create MSAA shader for current AA mode
|
||||
std::string buf = StringFromFormat(reint_rgb8_to_rgba6_msaa, g_ActiveConfig.iMultisamples);
|
||||
s_rgb8_to_rgba6[1] = D3D::CompileAndCreatePixelShader(buf);
|
||||
|
||||
CHECK(s_rgb8_to_rgba6[1], "Create RGB8 to RGBA6 MSAA pixel shader");
|
||||
D3D::SetDebugObjectName(s_rgb8_to_rgba6[1], "RGB8 to RGBA6 MSAA pixel shader");
|
||||
}
|
||||
return s_rgb8_to_rgba6[1];
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::GetColorCopyProgram(bool multisampled)
|
||||
{
|
||||
if (!multisampled || g_ActiveConfig.iMultisamples <= 1)
|
||||
{
|
||||
return s_ColorCopyProgram[0];
|
||||
}
|
||||
else if (s_ColorCopyProgram[1])
|
||||
{
|
||||
return s_ColorCopyProgram[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
// create MSAA shader for current AA mode
|
||||
std::string buf = StringFromFormat(color_copy_program_code_msaa, g_ActiveConfig.iMultisamples);
|
||||
s_ColorCopyProgram[1] = D3D::CompileAndCreatePixelShader(buf);
|
||||
CHECK(s_ColorCopyProgram[1] != nullptr, "Create color copy MSAA pixel shader");
|
||||
D3D::SetDebugObjectName(s_ColorCopyProgram[1], "color copy MSAA pixel shader");
|
||||
return s_ColorCopyProgram[1];
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::GetClearProgram()
|
||||
{
|
||||
return s_ClearProgram;
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::GetAnaglyphProgram()
|
||||
{
|
||||
return s_AnaglyphProgram;
|
||||
}
|
||||
|
||||
ID3D11PixelShader* PixelShaderCache::GetDepthResolveProgram()
|
||||
{
|
||||
if (s_DepthResolveProgram != nullptr)
|
||||
return s_DepthResolveProgram;
|
||||
|
||||
// create MSAA shader for current AA mode
|
||||
std::string buf = StringFromFormat(depth_resolve_program, g_ActiveConfig.iMultisamples);
|
||||
s_DepthResolveProgram = D3D::CompileAndCreatePixelShader(buf);
|
||||
CHECK(s_DepthResolveProgram != nullptr, "Create depth matrix MSAA pixel shader");
|
||||
D3D::SetDebugObjectName(s_DepthResolveProgram, "depth resolve pixel shader");
|
||||
return s_DepthResolveProgram;
|
||||
}
|
||||
|
||||
void PixelShaderCache::Init()
|
||||
{
|
||||
// used when drawing clear quads
|
||||
s_ClearProgram = D3D::CompileAndCreatePixelShader(clear_program_code);
|
||||
CHECK(s_ClearProgram != nullptr, "Create clear pixel shader");
|
||||
D3D::SetDebugObjectName(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(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");
|
||||
D3D::SetDebugObjectName(s_ColorCopyProgram[0], "color copy pixel shader");
|
||||
}
|
||||
|
||||
// Used in Swap() when AA mode has changed
|
||||
void PixelShaderCache::InvalidateMSAAShaders()
|
||||
{
|
||||
SAFE_RELEASE(s_ColorCopyProgram[1]);
|
||||
SAFE_RELEASE(s_rgb8_to_rgba6[1]);
|
||||
SAFE_RELEASE(s_rgba6_to_rgb8[1]);
|
||||
SAFE_RELEASE(s_DepthResolveProgram);
|
||||
}
|
||||
|
||||
void PixelShaderCache::Shutdown()
|
||||
{
|
||||
SAFE_RELEASE(s_ClearProgram);
|
||||
SAFE_RELEASE(s_AnaglyphProgram);
|
||||
SAFE_RELEASE(s_DepthResolveProgram);
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
SAFE_RELEASE(s_ColorCopyProgram[i]);
|
||||
SAFE_RELEASE(s_rgba6_to_rgb8[i]);
|
||||
SAFE_RELEASE(s_rgb8_to_rgba6[i]);
|
||||
}
|
||||
}
|
||||
} // DX11
|
@ -1,34 +0,0 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <map>
|
||||
|
||||
#include "VideoCommon/AsyncShaderCompiler.h"
|
||||
#include "VideoCommon/PixelShaderGen.h"
|
||||
#include "VideoCommon/UberShaderPixel.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
class D3DBlob;
|
||||
|
||||
class PixelShaderCache
|
||||
{
|
||||
public:
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
|
||||
static ID3D11PixelShader* GetColorCopyProgram(bool multisampled);
|
||||
static ID3D11PixelShader* GetClearProgram();
|
||||
static ID3D11PixelShader* GetAnaglyphProgram();
|
||||
static ID3D11PixelShader* GetDepthResolveProgram();
|
||||
static ID3D11PixelShader* ReinterpRGBA6ToRGB8(bool multisampled);
|
||||
static ID3D11PixelShader* ReinterpRGB8ToRGBA6(bool multisampled);
|
||||
|
||||
static void InvalidateMSAAShaders();
|
||||
};
|
||||
|
||||
} // namespace DX11
|
@ -23,33 +23,19 @@
|
||||
#include "VideoBackends/D3D/BoundingBox.h"
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/D3DUtil.h"
|
||||
#include "VideoBackends/D3D/DXPipeline.h"
|
||||
#include "VideoBackends/D3D/DXShader.h"
|
||||
#include "VideoBackends/D3D/DXTexture.h"
|
||||
#include "VideoBackends/D3D/FramebufferManager.h"
|
||||
#include "VideoBackends/D3D/GeometryShaderCache.h"
|
||||
#include "VideoBackends/D3D/PixelShaderCache.h"
|
||||
#include "VideoBackends/D3D/TextureCache.h"
|
||||
#include "VideoBackends/D3D/VertexShaderCache.h"
|
||||
|
||||
#include "VideoCommon/BPFunctions.h"
|
||||
#include "VideoCommon/OnScreenDisplay.h"
|
||||
#include "VideoCommon/PixelEngine.h"
|
||||
#include "VideoCommon/FramebufferManager.h"
|
||||
#include "VideoCommon/PostProcessing.h"
|
||||
#include "VideoCommon/RenderState.h"
|
||||
#include "VideoCommon/VideoBackendBase.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
#include "VideoCommon/XFMemory.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
// Reserve 512KB for vertices, and 64KB for uniforms.
|
||||
// This should be sufficient for our usages, and if more is required,
|
||||
// we split it into multiple draws.
|
||||
constexpr u32 UTILITY_VBO_SIZE = 512 * 1024;
|
||||
constexpr u32 UTILITY_UBO_SIZE = 64 * 1024;
|
||||
|
||||
// Nvidia stereo blitting struct defined in "nvstereo.h" from the Nvidia SDK
|
||||
typedef struct _Nv_Stereo_Image_Header
|
||||
{
|
||||
@ -67,118 +53,9 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height, float backbuffer
|
||||
AbstractTextureFormat::RGBA8)
|
||||
{
|
||||
m_last_fullscreen_state = D3D::GetFullscreenState();
|
||||
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
|
||||
SetupDeviceObjects();
|
||||
|
||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)m_target_width, (float)m_target_height);
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
FramebufferManager::BindEFBRenderTarget();
|
||||
m_current_framebuffer_width = m_target_width;
|
||||
m_current_framebuffer_height = m_target_height;
|
||||
}
|
||||
|
||||
Renderer::~Renderer()
|
||||
{
|
||||
TeardownDeviceObjects();
|
||||
}
|
||||
|
||||
void Renderer::SetupDeviceObjects()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D3D11_DEPTH_STENCIL_DESC ddesc;
|
||||
ddesc.DepthEnable = FALSE;
|
||||
ddesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
ddesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
|
||||
ddesc.StencilEnable = FALSE;
|
||||
ddesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
|
||||
ddesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
|
||||
hr = D3D::device->CreateDepthStencilState(&ddesc, &m_clear_depth_states[0]);
|
||||
CHECK(hr == S_OK, "Create depth state for Renderer::ClearScreen");
|
||||
ddesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
||||
ddesc.DepthEnable = TRUE;
|
||||
hr = D3D::device->CreateDepthStencilState(&ddesc, &m_clear_depth_states[1]);
|
||||
CHECK(hr == S_OK, "Create depth state for Renderer::ClearScreen");
|
||||
ddesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
hr = D3D::device->CreateDepthStencilState(&ddesc, &m_clear_depth_states[2]);
|
||||
CHECK(hr == S_OK, "Create depth state for Renderer::ClearScreen");
|
||||
D3D::SetDebugObjectName(m_clear_depth_states[0],
|
||||
"depth state for Renderer::ClearScreen (depth buffer disabled)");
|
||||
D3D::SetDebugObjectName(
|
||||
m_clear_depth_states[1],
|
||||
"depth state for Renderer::ClearScreen (depth buffer enabled, writing enabled)");
|
||||
D3D::SetDebugObjectName(
|
||||
m_clear_depth_states[2],
|
||||
"depth state for Renderer::ClearScreen (depth buffer enabled, writing disabled)");
|
||||
|
||||
D3D11_BLEND_DESC blenddesc;
|
||||
blenddesc.AlphaToCoverageEnable = FALSE;
|
||||
blenddesc.IndependentBlendEnable = FALSE;
|
||||
blenddesc.RenderTarget[0].BlendEnable = FALSE;
|
||||
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
blenddesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
|
||||
blenddesc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
|
||||
blenddesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||
blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
||||
blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
hr = D3D::device->CreateBlendState(&blenddesc, &m_reset_blend_state);
|
||||
CHECK(hr == S_OK, "Create blend state for Renderer::ResetAPIState");
|
||||
D3D::SetDebugObjectName(m_reset_blend_state, "blend state for Renderer::ResetAPIState");
|
||||
|
||||
m_clear_blend_states[0] = m_reset_blend_state;
|
||||
m_reset_blend_state->AddRef();
|
||||
|
||||
blenddesc.RenderTarget[0].RenderTargetWriteMask =
|
||||
D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN | D3D11_COLOR_WRITE_ENABLE_BLUE;
|
||||
hr = D3D::device->CreateBlendState(&blenddesc, &m_clear_blend_states[1]);
|
||||
CHECK(hr == S_OK, "Create blend state for Renderer::ClearScreen");
|
||||
|
||||
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALPHA;
|
||||
hr = D3D::device->CreateBlendState(&blenddesc, &m_clear_blend_states[2]);
|
||||
CHECK(hr == S_OK, "Create blend state for Renderer::ClearScreen");
|
||||
|
||||
blenddesc.RenderTarget[0].RenderTargetWriteMask = 0;
|
||||
hr = D3D::device->CreateBlendState(&blenddesc, &m_clear_blend_states[3]);
|
||||
CHECK(hr == S_OK, "Create blend state for Renderer::ClearScreen");
|
||||
|
||||
ddesc.DepthEnable = FALSE;
|
||||
ddesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
ddesc.DepthFunc = D3D11_COMPARISON_LESS;
|
||||
ddesc.StencilEnable = FALSE;
|
||||
ddesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
|
||||
ddesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
|
||||
hr = D3D::device->CreateDepthStencilState(&ddesc, &m_reset_depth_state);
|
||||
CHECK(hr == S_OK, "Create depth state for Renderer::ResetAPIState");
|
||||
D3D::SetDebugObjectName(m_reset_depth_state, "depth stencil state for Renderer::ResetAPIState");
|
||||
|
||||
D3D11_RASTERIZER_DESC rastdesc = CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID, D3D11_CULL_NONE, false,
|
||||
0, 0.f, 0.f, false, false, false, false);
|
||||
hr = D3D::device->CreateRasterizerState(&rastdesc, &m_reset_rast_state);
|
||||
CHECK(hr == S_OK, "Create rasterizer state for Renderer::ResetAPIState");
|
||||
D3D::SetDebugObjectName(m_reset_rast_state, "rasterizer state for Renderer::ResetAPIState");
|
||||
|
||||
m_screenshot_texture = nullptr;
|
||||
}
|
||||
|
||||
// Kill off all device objects
|
||||
void Renderer::TeardownDeviceObjects()
|
||||
{
|
||||
g_framebuffer_manager.reset();
|
||||
|
||||
SAFE_RELEASE(m_clear_blend_states[0]);
|
||||
SAFE_RELEASE(m_clear_blend_states[1]);
|
||||
SAFE_RELEASE(m_clear_blend_states[2]);
|
||||
SAFE_RELEASE(m_clear_blend_states[3]);
|
||||
SAFE_RELEASE(m_clear_depth_states[0]);
|
||||
SAFE_RELEASE(m_clear_depth_states[1]);
|
||||
SAFE_RELEASE(m_clear_depth_states[2]);
|
||||
SAFE_RELEASE(m_reset_blend_state);
|
||||
SAFE_RELEASE(m_reset_depth_state);
|
||||
SAFE_RELEASE(m_reset_rast_state);
|
||||
SAFE_RELEASE(m_screenshot_texture);
|
||||
SAFE_RELEASE(m_3d_vision_texture);
|
||||
}
|
||||
Renderer::~Renderer() = default;
|
||||
|
||||
void Renderer::Create3DVisionTexture(int width, int height)
|
||||
{
|
||||
@ -200,9 +77,17 @@ void Renderer::Create3DVisionTexture(int width, int height)
|
||||
sys_data.SysMemPitch = pitch;
|
||||
sys_data.pSysMem = memory.get();
|
||||
|
||||
m_3d_vision_texture =
|
||||
D3DTexture2D::Create(width * 2, height + 1, D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, &sys_data);
|
||||
CD3D11_TEXTURE2D_DESC texture_desc(DXGI_FORMAT_R8G8B8A8_UNORM, width * 2, height + 1, 1, 1,
|
||||
D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, 1, 0, 0);
|
||||
ID3D11Texture2D* texture;
|
||||
HRESULT hr = D3D::device->CreateTexture2D(&texture_desc, &sys_data, &texture);
|
||||
CHECK(SUCCEEDED(hr), "Create 3D Vision Texture");
|
||||
m_3d_vision_texture = std::make_unique<DXTexture>(TextureConfig(width * 2, height + 1, 1, 1, 1,
|
||||
AbstractTextureFormat::RGBA8,
|
||||
AbstractTextureFlag_RenderTarget),
|
||||
texture, nullptr, nullptr);
|
||||
m_3d_vision_framebuffer =
|
||||
DXFramebuffer::Create(static_cast<DXTexture*>(m_3d_vision_texture.get()), nullptr);
|
||||
}
|
||||
|
||||
bool Renderer::IsHeadless() const
|
||||
@ -212,7 +97,7 @@ bool Renderer::IsHeadless() const
|
||||
|
||||
std::unique_ptr<AbstractTexture> Renderer::CreateTexture(const TextureConfig& config)
|
||||
{
|
||||
return std::make_unique<DXTexture>(config);
|
||||
return DXTexture::Create(config);
|
||||
}
|
||||
|
||||
std::unique_ptr<AbstractStagingTexture> Renderer::CreateStagingTexture(StagingTextureType type,
|
||||
@ -221,12 +106,11 @@ std::unique_ptr<AbstractStagingTexture> Renderer::CreateStagingTexture(StagingTe
|
||||
return DXStagingTexture::Create(type, config);
|
||||
}
|
||||
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
Renderer::CreateFramebuffer(const AbstractTexture* color_attachment,
|
||||
const AbstractTexture* depth_attachment)
|
||||
std::unique_ptr<AbstractFramebuffer> Renderer::CreateFramebuffer(AbstractTexture* color_attachment,
|
||||
AbstractTexture* depth_attachment)
|
||||
{
|
||||
return DXFramebuffer::Create(static_cast<const DXTexture*>(color_attachment),
|
||||
static_cast<const DXTexture*>(depth_attachment));
|
||||
return DXFramebuffer::Create(static_cast<DXTexture*>(color_attachment),
|
||||
static_cast<DXTexture*>(depth_attachment));
|
||||
}
|
||||
|
||||
std::unique_ptr<AbstractShader> Renderer::CreateShaderFromSource(ShaderStage stage,
|
||||
@ -249,220 +133,44 @@ std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelin
|
||||
void Renderer::SetPipeline(const AbstractPipeline* pipeline)
|
||||
{
|
||||
const DXPipeline* dx_pipeline = static_cast<const DXPipeline*>(pipeline);
|
||||
if (!dx_pipeline)
|
||||
if (m_current_pipeline == dx_pipeline)
|
||||
return;
|
||||
|
||||
D3D::stateman->SetRasterizerState(dx_pipeline->GetRasterizerState());
|
||||
D3D::stateman->SetDepthState(dx_pipeline->GetDepthState());
|
||||
D3D::stateman->SetBlendState(dx_pipeline->GetBlendState());
|
||||
D3D::stateman->SetPrimitiveTopology(dx_pipeline->GetPrimitiveTopology());
|
||||
D3D::stateman->SetInputLayout(dx_pipeline->GetInputLayout());
|
||||
D3D::stateman->SetVertexShader(dx_pipeline->GetVertexShader());
|
||||
D3D::stateman->SetGeometryShader(dx_pipeline->GetGeometryShader());
|
||||
D3D::stateman->SetPixelShader(dx_pipeline->GetPixelShader());
|
||||
}
|
||||
|
||||
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
|
||||
{
|
||||
TargetRectangle result;
|
||||
result.left = EFBToScaledX(rc.left);
|
||||
result.top = EFBToScaledY(rc.top);
|
||||
result.right = EFBToScaledX(rc.right);
|
||||
result.bottom = EFBToScaledY(rc.bottom);
|
||||
return result;
|
||||
if (dx_pipeline)
|
||||
{
|
||||
D3D::stateman->SetRasterizerState(dx_pipeline->GetRasterizerState());
|
||||
D3D::stateman->SetDepthState(dx_pipeline->GetDepthState());
|
||||
D3D::stateman->SetBlendState(dx_pipeline->GetBlendState());
|
||||
D3D::stateman->SetPrimitiveTopology(dx_pipeline->GetPrimitiveTopology());
|
||||
D3D::stateman->SetInputLayout(dx_pipeline->GetInputLayout());
|
||||
D3D::stateman->SetVertexShader(dx_pipeline->GetVertexShader());
|
||||
D3D::stateman->SetGeometryShader(dx_pipeline->GetGeometryShader());
|
||||
D3D::stateman->SetPixelShader(dx_pipeline->GetPixelShader());
|
||||
D3D::stateman->SetIntegerRTV(dx_pipeline->UseLogicOp());
|
||||
}
|
||||
else
|
||||
{
|
||||
// These will be destroyed at pipeline destruction.
|
||||
D3D::stateman->SetInputLayout(nullptr);
|
||||
D3D::stateman->SetVertexShader(nullptr);
|
||||
D3D::stateman->SetGeometryShader(nullptr);
|
||||
D3D::stateman->SetPixelShader(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::SetScissorRect(const MathUtil::Rectangle<int>& rc)
|
||||
{
|
||||
const RECT rect = {rc.left, rc.top, rc.right, rc.bottom};
|
||||
// TODO: Move to stateman
|
||||
const CD3D11_RECT rect(rc.left, rc.top, std::max(rc.right, rc.left + 1),
|
||||
std::max(rc.bottom, rc.top + 1));
|
||||
D3D::context->RSSetScissorRects(1, &rect);
|
||||
}
|
||||
|
||||
// This function allows the CPU to directly access the EFB.
|
||||
// There are EFB peeks (which will read the color or depth of a pixel)
|
||||
// and EFB pokes (which will change the color or depth of a pixel).
|
||||
//
|
||||
// The behavior of EFB peeks can only be modified by:
|
||||
// - GX_PokeAlphaRead
|
||||
// The behavior of EFB pokes can be modified by:
|
||||
// - GX_PokeAlphaMode (TODO)
|
||||
// - GX_PokeAlphaUpdate (TODO)
|
||||
// - GX_PokeBlendMode (TODO)
|
||||
// - GX_PokeColorUpdate (TODO)
|
||||
// - GX_PokeDither (TODO)
|
||||
// - GX_PokeDstAlpha (TODO)
|
||||
// - GX_PokeZMode (TODO)
|
||||
u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||
{
|
||||
// Convert EFB dimensions to the ones of our render target
|
||||
EFBRectangle efbPixelRc;
|
||||
efbPixelRc.left = x;
|
||||
efbPixelRc.top = y;
|
||||
efbPixelRc.right = x + 1;
|
||||
efbPixelRc.bottom = y + 1;
|
||||
TargetRectangle targetPixelRc = Renderer::ConvertEFBRectangle(efbPixelRc);
|
||||
|
||||
// Take the mean of the resulting dimensions; TODO: Don't use the center pixel, compute the
|
||||
// average color instead
|
||||
D3D11_RECT RectToLock;
|
||||
if (type == EFBAccessType::PeekColor || type == EFBAccessType::PeekZ)
|
||||
{
|
||||
RectToLock.left = (targetPixelRc.left + targetPixelRc.right) / 2;
|
||||
RectToLock.top = (targetPixelRc.top + targetPixelRc.bottom) / 2;
|
||||
RectToLock.right = RectToLock.left + 1;
|
||||
RectToLock.bottom = RectToLock.top + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
RectToLock.left = targetPixelRc.left;
|
||||
RectToLock.right = targetPixelRc.right;
|
||||
RectToLock.top = targetPixelRc.top;
|
||||
RectToLock.bottom = targetPixelRc.bottom;
|
||||
}
|
||||
|
||||
// Reset any game specific settings.
|
||||
ResetAPIState();
|
||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, 1.f, 1.f);
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
D3D::SetPointCopySampler();
|
||||
|
||||
// Select copy and read textures depending on if we are doing a color or depth read (since they
|
||||
// are different formats).
|
||||
D3DTexture2D* source_tex;
|
||||
D3DTexture2D* read_tex;
|
||||
ID3D11Texture2D* staging_tex;
|
||||
if (type == EFBAccessType::PeekColor)
|
||||
{
|
||||
source_tex = FramebufferManager::GetEFBColorTexture();
|
||||
read_tex = FramebufferManager::GetEFBColorReadTexture();
|
||||
staging_tex = FramebufferManager::GetEFBColorStagingBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
source_tex = FramebufferManager::GetEFBDepthTexture();
|
||||
read_tex = FramebufferManager::GetEFBDepthReadTexture();
|
||||
staging_tex = FramebufferManager::GetEFBDepthStagingBuffer();
|
||||
}
|
||||
|
||||
// Select pixel shader (we don't want to average depth samples, instead select the minimum).
|
||||
ID3D11PixelShader* copy_pixel_shader;
|
||||
if (type == EFBAccessType::PeekZ && g_ActiveConfig.iMultisamples > 1)
|
||||
copy_pixel_shader = PixelShaderCache::GetDepthResolveProgram();
|
||||
else
|
||||
copy_pixel_shader = PixelShaderCache::GetColorCopyProgram(true);
|
||||
|
||||
// Draw a quad to grab the texel we want to read.
|
||||
D3D::context->OMSetRenderTargets(1, &read_tex->GetRTV(), nullptr);
|
||||
D3D::drawShadedTexQuad(source_tex->GetSRV(), &RectToLock, Renderer::GetTargetWidth(),
|
||||
Renderer::GetTargetHeight(), copy_pixel_shader,
|
||||
VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout());
|
||||
|
||||
// Restore expected game state.
|
||||
RestoreAPIState();
|
||||
|
||||
// Copy the pixel from the renderable to cpu-readable buffer.
|
||||
D3D11_BOX box = CD3D11_BOX(0, 0, 0, 1, 1, 1);
|
||||
D3D::context->CopySubresourceRegion(staging_tex, 0, 0, 0, 0, read_tex->GetTex(), 0, &box);
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
CHECK(D3D::context->Map(staging_tex, 0, D3D11_MAP_READ, 0, &map) == S_OK,
|
||||
"Map staging buffer failed");
|
||||
|
||||
// Convert the framebuffer data to the format the game is expecting to receive.
|
||||
u32 ret;
|
||||
if (type == EFBAccessType::PeekColor)
|
||||
{
|
||||
u32 val;
|
||||
memcpy(&val, map.pData, sizeof(val));
|
||||
|
||||
// our buffers are RGBA, yet a BGRA value is expected
|
||||
val = ((val & 0xFF00FF00) | ((val >> 16) & 0xFF) | ((val << 16) & 0xFF0000));
|
||||
|
||||
// check what to do with the alpha channel (GX_PokeAlphaRead)
|
||||
PixelEngine::UPEAlphaReadReg alpha_read_mode = PixelEngine::GetAlphaReadMode();
|
||||
|
||||
if (bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24)
|
||||
{
|
||||
val = RGBA8ToRGBA6ToRGBA8(val);
|
||||
}
|
||||
else if (bpmem.zcontrol.pixel_format == PEControl::RGB565_Z16)
|
||||
{
|
||||
val = RGBA8ToRGB565ToRGBA8(val);
|
||||
}
|
||||
if (bpmem.zcontrol.pixel_format != PEControl::RGBA6_Z24)
|
||||
{
|
||||
val |= 0xFF000000;
|
||||
}
|
||||
|
||||
if (alpha_read_mode.ReadMode == 2)
|
||||
ret = val; // GX_READ_NONE
|
||||
else if (alpha_read_mode.ReadMode == 1)
|
||||
ret = (val | 0xFF000000); // GX_READ_FF
|
||||
else /*if(alpha_read_mode.ReadMode == 0)*/
|
||||
ret = (val & 0x00FFFFFF); // GX_READ_00
|
||||
}
|
||||
else // type == EFBAccessType::PeekZ
|
||||
{
|
||||
float val;
|
||||
memcpy(&val, map.pData, sizeof(val));
|
||||
|
||||
// depth buffer is inverted in the d3d backend
|
||||
val = 1.0f - val;
|
||||
|
||||
if (bpmem.zcontrol.pixel_format == PEControl::RGB565_Z16)
|
||||
{
|
||||
// if Z is in 16 bit format you must return a 16 bit integer
|
||||
ret = MathUtil::Clamp<u32>(static_cast<u32>(val * 65536.0f), 0, 0xFFFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = MathUtil::Clamp<u32>(static_cast<u32>(val * 16777216.0f), 0, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
D3D::context->Unmap(staging_tex, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points)
|
||||
{
|
||||
ResetAPIState();
|
||||
|
||||
if (type == EFBAccessType::PokeColor)
|
||||
{
|
||||
D3D11_VIEWPORT vp =
|
||||
CD3D11_VIEWPORT(0.0f, 0.0f, (float)GetTargetWidth(), (float)GetTargetHeight());
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
}
|
||||
else // if (type == EFBAccessType::PokeZ)
|
||||
{
|
||||
D3D::stateman->SetBlendState(m_clear_blend_states[3]);
|
||||
D3D::stateman->SetDepthState(m_clear_depth_states[1]);
|
||||
|
||||
D3D11_VIEWPORT vp =
|
||||
CD3D11_VIEWPORT(0.0f, 0.0f, (float)GetTargetWidth(), (float)GetTargetHeight());
|
||||
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
}
|
||||
|
||||
D3D::DrawEFBPokeQuads(type, points, num_points);
|
||||
|
||||
RestoreAPIState();
|
||||
}
|
||||
|
||||
void Renderer::SetViewport(float x, float y, float width, float height, float near_depth,
|
||||
float far_depth)
|
||||
{
|
||||
// In D3D, the viewport rectangle must fit within the render target.
|
||||
D3D11_VIEWPORT vp;
|
||||
vp.TopLeftX = MathUtil::Clamp(x, 0.0f, static_cast<float>(m_current_framebuffer_width - 1));
|
||||
vp.TopLeftY = MathUtil::Clamp(y, 0.0f, static_cast<float>(m_current_framebuffer_height - 1));
|
||||
vp.Width =
|
||||
MathUtil::Clamp(width, 1.0f, static_cast<float>(m_current_framebuffer_width) - vp.TopLeftX);
|
||||
vp.Height =
|
||||
MathUtil::Clamp(height, 1.0f, static_cast<float>(m_current_framebuffer_height) - vp.TopLeftY);
|
||||
vp.MinDepth = near_depth;
|
||||
vp.MaxDepth = far_depth;
|
||||
// TODO: Move to stateman
|
||||
const CD3D11_VIEWPORT vp(x, y, width, height, near_depth, far_depth);
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
}
|
||||
|
||||
@ -478,89 +186,19 @@ void Renderer::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex)
|
||||
D3D::context->DrawIndexed(num_indices, base_index, base_vertex);
|
||||
}
|
||||
|
||||
void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
|
||||
u32 color, u32 z)
|
||||
void Renderer::DispatchComputeShader(const AbstractShader* shader, u32 groups_x, u32 groups_y,
|
||||
u32 groups_z)
|
||||
{
|
||||
ResetAPIState();
|
||||
|
||||
if (colorEnable && alphaEnable)
|
||||
D3D::stateman->SetBlendState(m_clear_blend_states[0]);
|
||||
else if (colorEnable)
|
||||
D3D::stateman->SetBlendState(m_clear_blend_states[1]);
|
||||
else if (alphaEnable)
|
||||
D3D::stateman->SetBlendState(m_clear_blend_states[2]);
|
||||
else
|
||||
D3D::stateman->SetBlendState(m_clear_blend_states[3]);
|
||||
|
||||
// TODO: Should we enable Z testing here?
|
||||
// if (!bpmem.zmode.testenable) D3D::stateman->PushDepthState(s_clear_depth_states[0]);
|
||||
// else
|
||||
if (zEnable)
|
||||
D3D::stateman->SetDepthState(m_clear_depth_states[1]);
|
||||
else /*if (!zEnable)*/
|
||||
D3D::stateman->SetDepthState(m_clear_depth_states[2]);
|
||||
|
||||
// Update the view port for clearing the picture
|
||||
TargetRectangle targetRc = Renderer::ConvertEFBRectangle(rc);
|
||||
D3D11_VIEWPORT vp =
|
||||
CD3D11_VIEWPORT((float)targetRc.left, (float)targetRc.top, (float)targetRc.GetWidth(),
|
||||
(float)targetRc.GetHeight(), 0.f, 1.f);
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
FramebufferManager::SetIntegerEFBRenderTarget(false);
|
||||
|
||||
// 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, 1.0f - (z & 0xFFFFFF) / 16777216.0f);
|
||||
|
||||
RestoreAPIState();
|
||||
}
|
||||
|
||||
void Renderer::ReinterpretPixelData(unsigned int convtype)
|
||||
{
|
||||
// TODO: MSAA support..
|
||||
D3D11_RECT source = CD3D11_RECT(0, 0, GetTargetWidth(), GetTargetHeight());
|
||||
|
||||
ID3D11PixelShader* pixel_shader;
|
||||
if (convtype == 0)
|
||||
pixel_shader = PixelShaderCache::ReinterpRGB8ToRGBA6(true);
|
||||
else if (convtype == 2)
|
||||
pixel_shader = PixelShaderCache::ReinterpRGBA6ToRGB8(true);
|
||||
else
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Trying to reinterpret pixel data with unsupported conversion type %d",
|
||||
convtype);
|
||||
return;
|
||||
}
|
||||
|
||||
// convert data and set the target texture as our new EFB
|
||||
ResetAPIState();
|
||||
|
||||
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, static_cast<float>(GetTargetWidth()),
|
||||
static_cast<float>(GetTargetHeight()));
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTempTexture()->GetRTV(),
|
||||
nullptr);
|
||||
D3D::SetPointCopySampler();
|
||||
D3D::drawShadedTexQuad(
|
||||
FramebufferManager::GetEFBColorTexture()->GetSRV(), &source, GetTargetWidth(),
|
||||
GetTargetHeight(), pixel_shader, VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader());
|
||||
|
||||
FramebufferManager::SwapReinterpretTexture();
|
||||
RestoreAPIState();
|
||||
D3D::stateman->SetComputeShader(static_cast<const DXShader*>(shader)->GetD3DComputeShader());
|
||||
D3D::stateman->SyncComputeBindings();
|
||||
D3D::context->Dispatch(groups_x, groups_y, groups_z);
|
||||
}
|
||||
|
||||
void Renderer::BindBackbuffer(const ClearColor& clear_color)
|
||||
{
|
||||
CheckForSurfaceChange();
|
||||
CheckForSurfaceResize();
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), nullptr);
|
||||
D3D::context->ClearRenderTargetView(D3D::GetBackBuffer()->GetRTV(), clear_color.data());
|
||||
m_current_framebuffer = nullptr;
|
||||
m_current_framebuffer_width = m_backbuffer_width;
|
||||
m_current_framebuffer_height = m_backbuffer_height;
|
||||
SetAndClearFramebuffer(D3D::GetSwapChainFramebuffer(), clear_color);
|
||||
}
|
||||
|
||||
void Renderer::PresentBackbuffer()
|
||||
@ -570,14 +208,6 @@ void Renderer::PresentBackbuffer()
|
||||
|
||||
void Renderer::OnConfigChanged(u32 bits)
|
||||
{
|
||||
// Resize the back buffers NOW to avoid flickering
|
||||
if (bits & (CONFIG_CHANGE_BIT_TARGET_SIZE | CONFIG_CHANGE_BIT_MULTISAMPLES |
|
||||
CONFIG_CHANGE_BIT_STEREO_MODE))
|
||||
{
|
||||
PixelShaderCache::InvalidateMSAAShaders();
|
||||
g_framebuffer_manager.reset();
|
||||
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CheckForSurfaceChange()
|
||||
@ -585,8 +215,8 @@ void Renderer::CheckForSurfaceChange()
|
||||
if (!m_surface_changed.TestAndClear())
|
||||
return;
|
||||
|
||||
SAFE_RELEASE(m_screenshot_texture);
|
||||
SAFE_RELEASE(m_3d_vision_texture);
|
||||
m_3d_vision_framebuffer.reset();
|
||||
m_3d_vision_texture.reset();
|
||||
|
||||
D3D::Reset(reinterpret_cast<HWND>(m_new_surface_handle));
|
||||
m_new_surface_handle = nullptr;
|
||||
@ -601,8 +231,9 @@ void Renderer::CheckForSurfaceResize()
|
||||
if (!m_surface_resized.TestAndClear() && !exclusive_fullscreen_changed)
|
||||
return;
|
||||
|
||||
SAFE_RELEASE(m_screenshot_texture);
|
||||
SAFE_RELEASE(m_3d_vision_texture);
|
||||
m_3d_vision_framebuffer.reset();
|
||||
m_3d_vision_texture.reset();
|
||||
|
||||
m_last_fullscreen_state = fullscreen_state;
|
||||
if (D3D::swapchain)
|
||||
D3D::ResizeSwapChain();
|
||||
@ -625,43 +256,38 @@ void Renderer::UpdateBackbufferSize()
|
||||
}
|
||||
}
|
||||
|
||||
// ALWAYS call RestoreAPIState for each ResetAPIState call you're doing
|
||||
void Renderer::ResetAPIState()
|
||||
void Renderer::SetFramebuffer(AbstractFramebuffer* framebuffer)
|
||||
{
|
||||
D3D::stateman->SetBlendState(m_reset_blend_state);
|
||||
D3D::stateman->SetDepthState(m_reset_depth_state);
|
||||
D3D::stateman->SetRasterizerState(m_reset_rast_state);
|
||||
}
|
||||
if (m_current_framebuffer == framebuffer)
|
||||
return;
|
||||
|
||||
void Renderer::RestoreAPIState()
|
||||
{
|
||||
// Gets us back into a more game-like state.
|
||||
m_current_framebuffer = nullptr;
|
||||
m_current_framebuffer_width = m_target_width;
|
||||
m_current_framebuffer_height = m_target_height;
|
||||
FramebufferManager::BindEFBRenderTarget();
|
||||
BPFunctions::SetViewport();
|
||||
BPFunctions::SetScissor();
|
||||
}
|
||||
// We can't leave the framebuffer bound as a texture and a render target.
|
||||
DXFramebuffer* fb = static_cast<DXFramebuffer*>(framebuffer);
|
||||
if ((fb->GetColorAttachment() &&
|
||||
D3D::stateman->UnsetTexture(
|
||||
static_cast<DXTexture*>(fb->GetColorAttachment())->GetD3DSRV()) != 0) ||
|
||||
(fb->GetDepthAttachment() &&
|
||||
D3D::stateman->UnsetTexture(
|
||||
static_cast<DXTexture*>(fb->GetDepthAttachment())->GetD3DSRV()) != 0))
|
||||
{
|
||||
D3D::stateman->ApplyTextures();
|
||||
}
|
||||
|
||||
void Renderer::SetFramebuffer(const AbstractFramebuffer* framebuffer)
|
||||
{
|
||||
const DXFramebuffer* fb = static_cast<const DXFramebuffer*>(framebuffer);
|
||||
D3D::context->OMSetRenderTargets(fb->GetNumRTVs(), fb->GetRTVArray(), fb->GetDSV());
|
||||
D3D::stateman->SetFramebuffer(fb);
|
||||
m_current_framebuffer = fb;
|
||||
m_current_framebuffer_width = fb->GetWidth();
|
||||
m_current_framebuffer_height = fb->GetHeight();
|
||||
}
|
||||
|
||||
void Renderer::SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer)
|
||||
void Renderer::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer)
|
||||
{
|
||||
SetFramebuffer(framebuffer);
|
||||
}
|
||||
|
||||
void Renderer::SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
|
||||
void Renderer::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer,
|
||||
const ClearColor& color_value, float depth_value)
|
||||
{
|
||||
SetFramebuffer(framebuffer);
|
||||
D3D::stateman->Apply();
|
||||
|
||||
if (framebuffer->GetColorFormat() != AbstractTextureFormat::Undefined)
|
||||
{
|
||||
D3D::context->ClearRenderTargetView(
|
||||
@ -676,9 +302,8 @@ void Renderer::SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
|
||||
|
||||
void Renderer::SetTexture(u32 index, const AbstractTexture* texture)
|
||||
{
|
||||
D3D::stateman->SetTexture(
|
||||
index,
|
||||
texture ? static_cast<const DXTexture*>(texture)->GetRawTexIdentifier()->GetSRV() : nullptr);
|
||||
D3D::stateman->SetTexture(index, texture ? static_cast<const DXTexture*>(texture)->GetD3DSRV() :
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void Renderer::SetSamplerState(u32 index, const SamplerState& state)
|
||||
@ -686,15 +311,15 @@ void Renderer::SetSamplerState(u32 index, const SamplerState& state)
|
||||
D3D::stateman->SetSampler(index, m_state_cache.Get(state));
|
||||
}
|
||||
|
||||
void Renderer::UnbindTexture(const AbstractTexture* texture)
|
||||
void Renderer::SetComputeImageTexture(AbstractTexture* texture, bool read, bool write)
|
||||
{
|
||||
D3D::stateman->UnsetTexture(
|
||||
static_cast<const DXTexture*>(texture)->GetRawTexIdentifier()->GetSRV());
|
||||
D3D::stateman->SetComputeUAV(texture ? static_cast<DXTexture*>(texture)->GetD3DUAV() : nullptr);
|
||||
}
|
||||
|
||||
void Renderer::SetInterlacingMode()
|
||||
void Renderer::UnbindTexture(const AbstractTexture* texture)
|
||||
{
|
||||
// TODO
|
||||
if (D3D::stateman->UnsetTexture(static_cast<const DXTexture*>(texture)->GetD3DSRV()) != 0)
|
||||
D3D::stateman->ApplyTextures();
|
||||
}
|
||||
|
||||
u16 Renderer::BBoxRead(int index)
|
||||
@ -736,93 +361,43 @@ void Renderer::BBoxWrite(int index, u16 _value)
|
||||
BBox::Set(index, value);
|
||||
}
|
||||
|
||||
void Renderer::Flush()
|
||||
{
|
||||
D3D::context->Flush();
|
||||
}
|
||||
|
||||
void Renderer::WaitForGPUIdle()
|
||||
{
|
||||
// There is no glFinish() equivalent in D3D.
|
||||
D3D::context->Flush();
|
||||
}
|
||||
|
||||
void Renderer::RenderXFBToScreen(const AbstractTexture* texture, const EFBRectangle& rc)
|
||||
{
|
||||
const CD3D11_RECT source_rc(rc.left, rc.top, rc.right, rc.bottom);
|
||||
const TargetRectangle target_rc = GetTargetRectangle();
|
||||
if (g_ActiveConfig.stereo_mode != StereoMode::Nvidia3DVision)
|
||||
return ::Renderer::RenderXFBToScreen(texture, rc);
|
||||
|
||||
// activate linear filtering for the buffer copies
|
||||
D3D::SetLinearCopySampler();
|
||||
if (!m_3d_vision_texture)
|
||||
Create3DVisionTexture(m_backbuffer_width, m_backbuffer_height);
|
||||
|
||||
if (g_ActiveConfig.stereo_mode == StereoMode::SBS ||
|
||||
g_ActiveConfig.stereo_mode == StereoMode::TAB)
|
||||
{
|
||||
TargetRectangle left_rc, right_rc;
|
||||
std::tie(left_rc, right_rc) = ConvertStereoRectangle(target_rc);
|
||||
// Render to staging texture which is double the width of the backbuffer
|
||||
SetAndClearFramebuffer(m_3d_vision_framebuffer.get());
|
||||
|
||||
SetViewport(static_cast<float>(left_rc.left), static_cast<float>(left_rc.top),
|
||||
static_cast<float>(left_rc.GetWidth()), static_cast<float>(right_rc.GetHeight()),
|
||||
0.0f, 1.0f);
|
||||
D3D::drawShadedTexQuad(static_cast<const DXTexture*>(texture)->GetRawTexIdentifier()->GetSRV(),
|
||||
&source_rc, texture->GetWidth(), texture->GetHeight(),
|
||||
PixelShaderCache::GetColorCopyProgram(false),
|
||||
VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout(), nullptr, 0);
|
||||
const auto target_rc = GetTargetRectangle();
|
||||
m_post_processor->BlitFromTexture(target_rc, rc, texture, 0);
|
||||
m_post_processor->BlitFromTexture(
|
||||
MathUtil::Rectangle<int>(target_rc.left + m_backbuffer_width, target_rc.top,
|
||||
target_rc.right + m_backbuffer_width, target_rc.bottom),
|
||||
rc, texture, 1);
|
||||
|
||||
SetViewport(static_cast<float>(right_rc.left), static_cast<float>(right_rc.top),
|
||||
static_cast<float>(right_rc.GetWidth()), static_cast<float>(right_rc.GetHeight()),
|
||||
0.0f, 1.0f);
|
||||
D3D::drawShadedTexQuad(static_cast<const DXTexture*>(texture)->GetRawTexIdentifier()->GetSRV(),
|
||||
&source_rc, texture->GetWidth(), texture->GetHeight(),
|
||||
PixelShaderCache::GetColorCopyProgram(false),
|
||||
VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout(), nullptr, 1);
|
||||
}
|
||||
else if (g_ActiveConfig.stereo_mode == StereoMode::Nvidia3DVision)
|
||||
{
|
||||
if (!m_3d_vision_texture)
|
||||
Create3DVisionTexture(m_backbuffer_width, m_backbuffer_height);
|
||||
// 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.
|
||||
const CD3D11_BOX box(0, 0, 0, m_backbuffer_width, m_backbuffer_height, 1);
|
||||
D3D::context->CopySubresourceRegion(D3D::GetSwapChainTexture()->GetD3DTexture(), 0, 0, 0, 0,
|
||||
m_3d_vision_texture->GetD3DTexture(), 0, &box);
|
||||
|
||||
const CD3D11_VIEWPORT left_vp(
|
||||
static_cast<float>(target_rc.left), static_cast<float>(target_rc.top),
|
||||
static_cast<float>(target_rc.GetWidth()), static_cast<float>(target_rc.GetHeight()));
|
||||
const CD3D11_VIEWPORT right_vp(
|
||||
static_cast<float>(target_rc.left + m_backbuffer_width), static_cast<float>(target_rc.top),
|
||||
static_cast<float>(target_rc.GetWidth()), static_cast<float>(target_rc.GetHeight()));
|
||||
|
||||
// Render to staging texture which is double the width of the backbuffer
|
||||
D3D::context->OMSetRenderTargets(1, &m_3d_vision_texture->GetRTV(), nullptr);
|
||||
|
||||
D3D::context->RSSetViewports(1, &left_vp);
|
||||
D3D::drawShadedTexQuad(static_cast<const DXTexture*>(texture)->GetRawTexIdentifier()->GetSRV(),
|
||||
&source_rc, texture->GetWidth(), texture->GetHeight(),
|
||||
PixelShaderCache::GetColorCopyProgram(false),
|
||||
VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout(), nullptr, 0);
|
||||
|
||||
D3D::context->RSSetViewports(1, &right_vp);
|
||||
D3D::drawShadedTexQuad(static_cast<const DXTexture*>(texture)->GetRawTexIdentifier()->GetSRV(),
|
||||
&source_rc, texture->GetWidth(), texture->GetHeight(),
|
||||
PixelShaderCache::GetColorCopyProgram(false),
|
||||
VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout(), nullptr, 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.
|
||||
const CD3D11_BOX box(0, 0, 0, m_backbuffer_width, m_backbuffer_height, 1);
|
||||
D3D::context->CopySubresourceRegion(D3D::GetBackBuffer()->GetTex(), 0, 0, 0, 0,
|
||||
m_3d_vision_texture->GetTex(), 0, &box);
|
||||
|
||||
// Restore render target to backbuffer
|
||||
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetViewport(static_cast<float>(target_rc.left), static_cast<float>(target_rc.top),
|
||||
static_cast<float>(target_rc.GetWidth()), static_cast<float>(target_rc.GetHeight()),
|
||||
0.0f, 1.0f);
|
||||
|
||||
ID3D11PixelShader* pixelShader = (g_Config.stereo_mode == StereoMode::Anaglyph) ?
|
||||
PixelShaderCache::GetAnaglyphProgram() :
|
||||
PixelShaderCache::GetColorCopyProgram(false);
|
||||
ID3D11GeometryShader* geomShader = (g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer) ?
|
||||
GeometryShaderCache::GetCopyGeometryShader() :
|
||||
nullptr;
|
||||
D3D::drawShadedTexQuad(static_cast<const DXTexture*>(texture)->GetRawTexIdentifier()->GetSRV(),
|
||||
&source_rc, texture->GetWidth(), texture->GetHeight(), pixelShader,
|
||||
VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout(), geomShader);
|
||||
}
|
||||
// Restore render target to backbuffer
|
||||
SetFramebuffer(D3D::GetSwapChainFramebuffer());
|
||||
}
|
||||
|
||||
void Renderer::SetFullscreen(bool enable_fullscreen)
|
||||
|
@ -9,11 +9,10 @@
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoCommon/RenderBase.h"
|
||||
|
||||
enum class EFBAccessType;
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
class D3DTexture2D;
|
||||
class DXTexture;
|
||||
class DXFramebuffer;
|
||||
|
||||
class Renderer : public ::Renderer
|
||||
{
|
||||
@ -32,53 +31,43 @@ public:
|
||||
size_t length) override;
|
||||
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
|
||||
size_t length) override;
|
||||
std::unique_ptr<NativeVertexFormat>
|
||||
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
|
||||
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
|
||||
std::unique_ptr<AbstractFramebuffer>
|
||||
CreateFramebuffer(const AbstractTexture* color_attachment,
|
||||
const AbstractTexture* depth_attachment) override;
|
||||
CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment) override;
|
||||
|
||||
void SetPipeline(const AbstractPipeline* pipeline) override;
|
||||
void SetFramebuffer(const AbstractFramebuffer* framebuffer) override;
|
||||
void SetAndDiscardFramebuffer(const AbstractFramebuffer* framebuffer) override;
|
||||
void SetAndClearFramebuffer(const AbstractFramebuffer* framebuffer,
|
||||
const ClearColor& color_value = {},
|
||||
void SetFramebuffer(AbstractFramebuffer* framebuffer) override;
|
||||
void SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer) override;
|
||||
void SetAndClearFramebuffer(AbstractFramebuffer* framebuffer, const ClearColor& color_value = {},
|
||||
float depth_value = 0.0f) override;
|
||||
void SetScissorRect(const MathUtil::Rectangle<int>& rc) override;
|
||||
void SetTexture(u32 index, const AbstractTexture* texture) override;
|
||||
void SetSamplerState(u32 index, const SamplerState& state) override;
|
||||
void SetComputeImageTexture(AbstractTexture* texture, bool read, bool write) override;
|
||||
void UnbindTexture(const AbstractTexture* texture) override;
|
||||
void SetInterlacingMode() override;
|
||||
void SetViewport(float x, float y, float width, float height, float near_depth,
|
||||
float far_depth) override;
|
||||
void Draw(u32 base_vertex, u32 num_vertices) override;
|
||||
void DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex) override;
|
||||
void DispatchComputeShader(const AbstractShader* shader, u32 groups_x, u32 groups_y,
|
||||
u32 groups_z) override;
|
||||
void BindBackbuffer(const ClearColor& clear_color = {}) override;
|
||||
void PresentBackbuffer() override;
|
||||
void SetFullscreen(bool enable_fullscreen) override;
|
||||
bool IsFullscreen() const override;
|
||||
|
||||
u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override;
|
||||
void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override;
|
||||
|
||||
u16 BBoxRead(int index) override;
|
||||
void BBoxWrite(int index, u16 value) override;
|
||||
|
||||
void ResetAPIState() override;
|
||||
void RestoreAPIState() override;
|
||||
|
||||
TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
|
||||
void Flush() override;
|
||||
void WaitForGPUIdle() override;
|
||||
|
||||
void RenderXFBToScreen(const AbstractTexture* texture, const EFBRectangle& rc) override;
|
||||
void OnConfigChanged(u32 bits) override;
|
||||
|
||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
|
||||
u32 color, u32 z) override;
|
||||
|
||||
void ReinterpretPixelData(unsigned int convtype) override;
|
||||
|
||||
private:
|
||||
void SetupDeviceObjects();
|
||||
void TeardownDeviceObjects();
|
||||
void Create3DVisionTexture(int width, int height);
|
||||
void CheckForSurfaceChange();
|
||||
void CheckForSurfaceResize();
|
||||
@ -86,15 +75,9 @@ private:
|
||||
|
||||
StateCache m_state_cache;
|
||||
|
||||
std::array<ID3D11BlendState*, 4> m_clear_blend_states{};
|
||||
std::array<ID3D11DepthStencilState*, 3> m_clear_depth_states{};
|
||||
ID3D11BlendState* m_reset_blend_state = nullptr;
|
||||
ID3D11DepthStencilState* m_reset_depth_state = nullptr;
|
||||
ID3D11RasterizerState* m_reset_rast_state = nullptr;
|
||||
|
||||
ID3D11Texture2D* m_screenshot_texture = nullptr;
|
||||
D3DTexture2D* m_3d_vision_texture = nullptr;
|
||||
std::unique_ptr<DXTexture> m_3d_vision_texture;
|
||||
std::unique_ptr<DXFramebuffer> m_3d_vision_framebuffer;
|
||||
|
||||
bool m_last_fullscreen_state = false;
|
||||
};
|
||||
}
|
||||
} // namespace DX11
|
||||
|
@ -1,318 +0,0 @@
|
||||
// Copyright 2010 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "VideoBackends/D3D/TextureCache.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DShader.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/D3DTexture.h"
|
||||
#include "VideoBackends/D3D/D3DUtil.h"
|
||||
#include "VideoBackends/D3D/DXTexture.h"
|
||||
#include "VideoBackends/D3D/FramebufferManager.h"
|
||||
#include "VideoBackends/D3D/GeometryShaderCache.h"
|
||||
#include "VideoBackends/D3D/PSTextureEncoder.h"
|
||||
#include "VideoBackends/D3D/PixelShaderCache.h"
|
||||
#include "VideoBackends/D3D/VertexShaderCache.h"
|
||||
|
||||
#include "VideoCommon/ImageWrite.h"
|
||||
#include "VideoCommon/RenderBase.h"
|
||||
#include "VideoCommon/TextureConfig.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
static std::unique_ptr<PSTextureEncoder> g_encoder;
|
||||
|
||||
void TextureCache::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params,
|
||||
u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
|
||||
const EFBRectangle& src_rect, bool scale_by_half, float y_scale,
|
||||
float gamma, bool clamp_top, bool clamp_bottom,
|
||||
const CopyFilterCoefficientArray& filter_coefficients)
|
||||
{
|
||||
g_encoder->Encode(dst, params, native_width, bytes_per_row, num_blocks_y, memory_stride, src_rect,
|
||||
scale_by_half, y_scale, gamma, clamp_top, clamp_bottom, filter_coefficients);
|
||||
}
|
||||
|
||||
const char palette_shader[] =
|
||||
R"HLSL(
|
||||
sampler samp0 : register(s0);
|
||||
Texture2DArray Tex0 : register(t0);
|
||||
Buffer<uint> Tex1 : register(t1);
|
||||
uniform float Multiply;
|
||||
|
||||
uint Convert3To8(uint v)
|
||||
{
|
||||
// Swizzle bits: 00000123 -> 12312312
|
||||
return (v << 5) | (v << 2) | (v >> 1);
|
||||
}
|
||||
|
||||
uint Convert4To8(uint v)
|
||||
{
|
||||
// Swizzle bits: 00001234 -> 12341234
|
||||
return (v << 4) | v;
|
||||
}
|
||||
|
||||
uint Convert5To8(uint v)
|
||||
{
|
||||
// Swizzle bits: 00012345 -> 12345123
|
||||
return (v << 3) | (v >> 2);
|
||||
}
|
||||
|
||||
uint Convert6To8(uint v)
|
||||
{
|
||||
// Swizzle bits: 00123456 -> 12345612
|
||||
return (v << 2) | (v >> 4);
|
||||
}
|
||||
|
||||
float4 DecodePixel_RGB5A3(uint val)
|
||||
{
|
||||
int r,g,b,a;
|
||||
if ((val&0x8000))
|
||||
{
|
||||
r=Convert5To8((val>>10) & 0x1f);
|
||||
g=Convert5To8((val>>5 ) & 0x1f);
|
||||
b=Convert5To8((val ) & 0x1f);
|
||||
a=0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
a=Convert3To8((val>>12) & 0x7);
|
||||
r=Convert4To8((val>>8 ) & 0xf);
|
||||
g=Convert4To8((val>>4 ) & 0xf);
|
||||
b=Convert4To8((val ) & 0xf);
|
||||
}
|
||||
return float4(r, g, b, a) / 255;
|
||||
}
|
||||
|
||||
float4 DecodePixel_RGB565(uint val)
|
||||
{
|
||||
int r, g, b, a;
|
||||
r = Convert5To8((val >> 11) & 0x1f);
|
||||
g = Convert6To8((val >> 5) & 0x3f);
|
||||
b = Convert5To8((val) & 0x1f);
|
||||
a = 0xFF;
|
||||
return float4(r, g, b, a) / 255;
|
||||
}
|
||||
|
||||
float4 DecodePixel_IA8(uint val)
|
||||
{
|
||||
int i = val & 0xFF;
|
||||
int a = val >> 8;
|
||||
return float4(i, i, i, a) / 255;
|
||||
}
|
||||
|
||||
void main(
|
||||
out float4 ocol0 : SV_Target,
|
||||
in float4 pos : SV_Position,
|
||||
in float3 uv0 : TEXCOORD0)
|
||||
{
|
||||
uint src = round(Tex0.Sample(samp0,uv0) * Multiply).r;
|
||||
src = Tex1.Load(src);
|
||||
src = ((src << 8) & 0xFF00) | (src >> 8);
|
||||
ocol0 = DECODE(src);
|
||||
}
|
||||
)HLSL";
|
||||
|
||||
void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source,
|
||||
const void* palette, TLUTFormat format)
|
||||
{
|
||||
DXTexture* source_texture = static_cast<DXTexture*>(source->texture.get());
|
||||
DXTexture* destination_texture = static_cast<DXTexture*>(destination->texture.get());
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
// stretch picture with increased internal resolution
|
||||
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, static_cast<float>(source->GetWidth()),
|
||||
static_cast<float>(source->GetHeight()));
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
|
||||
D3D11_BOX box{0, 0, 0, 512, 1, 1};
|
||||
D3D::context->UpdateSubresource(palette_buf, 0, &box, palette, 0, 0);
|
||||
|
||||
D3D::stateman->SetTexture(1, palette_buf_srv);
|
||||
|
||||
// TODO: Add support for C14X2 format. (Different multiplier, more palette entries.)
|
||||
float params[8] = {source->format == TextureFormat::I4 ? 15.f : 255.f};
|
||||
D3D::context->UpdateSubresource(uniform_buffer, 0, nullptr, ¶ms, 0, 0);
|
||||
D3D::stateman->SetPixelConstants(uniform_buffer);
|
||||
|
||||
const D3D11_RECT sourcerect = CD3D11_RECT(0, 0, source->GetWidth(), source->GetHeight());
|
||||
|
||||
D3D::SetPointCopySampler();
|
||||
|
||||
// Make sure we don't draw with the texture set as both a source and target.
|
||||
// (This can happen because we don't unbind textures when we free them.)
|
||||
D3D::stateman->UnsetTexture(destination_texture->GetRawTexIdentifier()->GetSRV());
|
||||
D3D::stateman->Apply();
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &destination_texture->GetRawTexIdentifier()->GetRTV(),
|
||||
nullptr);
|
||||
|
||||
// Create texture copy
|
||||
D3D::drawShadedTexQuad(
|
||||
source_texture->GetRawTexIdentifier()->GetSRV(), &sourcerect, source->GetWidth(),
|
||||
source->GetHeight(), palette_pixel_shader[static_cast<int>(format)],
|
||||
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout(),
|
||||
GeometryShaderCache::GetCopyGeometryShader());
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
ID3D11PixelShader* GetConvertShader(const char* Type)
|
||||
{
|
||||
std::string shader = "#define DECODE DecodePixel_";
|
||||
shader.append(Type);
|
||||
shader.append("\n");
|
||||
shader.append(palette_shader);
|
||||
return D3D::CompileAndCreatePixelShader(shader);
|
||||
}
|
||||
|
||||
TextureCache::TextureCache()
|
||||
{
|
||||
// FIXME: Is it safe here?
|
||||
g_encoder = std::make_unique<PSTextureEncoder>();
|
||||
g_encoder->Init();
|
||||
|
||||
palette_buf = nullptr;
|
||||
palette_buf_srv = nullptr;
|
||||
uniform_buffer = nullptr;
|
||||
palette_pixel_shader[static_cast<int>(TLUTFormat::IA8)] = GetConvertShader("IA8");
|
||||
palette_pixel_shader[static_cast<int>(TLUTFormat::RGB565)] = GetConvertShader("RGB565");
|
||||
palette_pixel_shader[static_cast<int>(TLUTFormat::RGB5A3)] = GetConvertShader("RGB5A3");
|
||||
auto lutBd = CD3D11_BUFFER_DESC(sizeof(u16) * 256, D3D11_BIND_SHADER_RESOURCE);
|
||||
HRESULT hr = D3D::device->CreateBuffer(&lutBd, nullptr, &palette_buf);
|
||||
CHECK(SUCCEEDED(hr), "create palette decoder lut buffer");
|
||||
D3D::SetDebugObjectName(palette_buf, "texture decoder lut buffer");
|
||||
// TODO: C14X2 format.
|
||||
auto outlutUavDesc =
|
||||
CD3D11_SHADER_RESOURCE_VIEW_DESC(palette_buf, DXGI_FORMAT_R16_UINT, 0, 256, 0);
|
||||
hr = D3D::device->CreateShaderResourceView(palette_buf, &outlutUavDesc, &palette_buf_srv);
|
||||
CHECK(SUCCEEDED(hr), "create palette decoder lut srv");
|
||||
D3D::SetDebugObjectName(palette_buf_srv, "texture decoder lut srv");
|
||||
const D3D11_BUFFER_DESC cbdesc =
|
||||
CD3D11_BUFFER_DESC(sizeof(float) * 8, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT);
|
||||
hr = D3D::device->CreateBuffer(&cbdesc, nullptr, &uniform_buffer);
|
||||
CHECK(SUCCEEDED(hr), "Create palette decoder constant buffer");
|
||||
D3D::SetDebugObjectName(uniform_buffer,
|
||||
"a constant buffer used in TextureCache::CopyRenderTargetToTexture");
|
||||
}
|
||||
|
||||
TextureCache::~TextureCache()
|
||||
{
|
||||
g_encoder->Shutdown();
|
||||
g_encoder.reset();
|
||||
|
||||
SAFE_RELEASE(palette_buf);
|
||||
SAFE_RELEASE(palette_buf_srv);
|
||||
SAFE_RELEASE(uniform_buffer);
|
||||
for (auto*& shader : palette_pixel_shader)
|
||||
SAFE_RELEASE(shader);
|
||||
for (auto& iter : m_efb_to_tex_pixel_shaders)
|
||||
SAFE_RELEASE(iter.second);
|
||||
}
|
||||
|
||||
void TextureCache::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy,
|
||||
const EFBRectangle& src_rect, bool scale_by_half,
|
||||
EFBCopyFormat dst_format, bool is_intensity, float gamma,
|
||||
bool clamp_top, bool clamp_bottom,
|
||||
const CopyFilterCoefficientArray& filter_coefficients)
|
||||
{
|
||||
auto* destination_texture = static_cast<DXTexture*>(entry->texture.get());
|
||||
|
||||
bool multisampled = g_ActiveConfig.iMultisamples > 1;
|
||||
ID3D11ShaderResourceView* efb_tex_srv;
|
||||
if (multisampled)
|
||||
{
|
||||
efb_tex_srv = is_depth_copy ? FramebufferManager::GetResolvedEFBDepthTexture()->GetSRV() :
|
||||
FramebufferManager::GetResolvedEFBColorTexture()->GetSRV();
|
||||
}
|
||||
else
|
||||
{
|
||||
efb_tex_srv = is_depth_copy ? FramebufferManager::GetEFBDepthTexture()->GetSRV() :
|
||||
FramebufferManager::GetEFBColorTexture()->GetSRV();
|
||||
}
|
||||
|
||||
auto uid = TextureConversionShaderGen::GetShaderUid(dst_format, is_depth_copy, is_intensity,
|
||||
scale_by_half,
|
||||
NeedsCopyFilterInShader(filter_coefficients));
|
||||
ID3D11PixelShader* pixel_shader = GetEFBToTexPixelShader(uid);
|
||||
if (!pixel_shader)
|
||||
return;
|
||||
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
// stretch picture with increased internal resolution
|
||||
const D3D11_VIEWPORT vp =
|
||||
CD3D11_VIEWPORT(0.f, 0.f, static_cast<float>(destination_texture->GetConfig().width),
|
||||
static_cast<float>(destination_texture->GetConfig().height));
|
||||
D3D::context->RSSetViewports(1, &vp);
|
||||
|
||||
const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(src_rect);
|
||||
// TODO: try targetSource.asRECT();
|
||||
const D3D11_RECT sourcerect =
|
||||
CD3D11_RECT(targetSource.left, targetSource.top, targetSource.right, targetSource.bottom);
|
||||
|
||||
// Use linear filtering if (bScaleByHalf), use point filtering otherwise
|
||||
if (scale_by_half)
|
||||
D3D::SetLinearCopySampler();
|
||||
else
|
||||
D3D::SetPointCopySampler();
|
||||
|
||||
struct PixelConstants
|
||||
{
|
||||
float filter_coefficients[3];
|
||||
float gamma_rcp;
|
||||
float clamp_top;
|
||||
float clamp_bottom;
|
||||
float pixel_height;
|
||||
u32 padding;
|
||||
};
|
||||
PixelConstants constants;
|
||||
for (size_t i = 0; i < filter_coefficients.size(); i++)
|
||||
constants.filter_coefficients[i] = filter_coefficients[i];
|
||||
constants.gamma_rcp = 1.0f / gamma;
|
||||
constants.clamp_top = clamp_top ? src_rect.top / float(EFB_HEIGHT) : 0.0f;
|
||||
constants.clamp_bottom = clamp_bottom ? src_rect.bottom / float(EFB_HEIGHT) : 1.0f;
|
||||
constants.pixel_height =
|
||||
g_ActiveConfig.bCopyEFBScaled ? 1.0f / g_renderer->GetTargetHeight() : 1.0f / EFB_HEIGHT;
|
||||
constants.padding = 0;
|
||||
D3D::context->UpdateSubresource(uniform_buffer, 0, nullptr, &constants, 0, 0);
|
||||
D3D::stateman->SetPixelConstants(uniform_buffer);
|
||||
|
||||
// Make sure we don't draw with the texture set as both a source and target.
|
||||
// (This can happen because we don't unbind textures when we free them.)
|
||||
D3D::stateman->UnsetTexture(destination_texture->GetRawTexIdentifier()->GetSRV());
|
||||
D3D::stateman->Apply();
|
||||
|
||||
D3D::context->OMSetRenderTargets(1, &destination_texture->GetRawTexIdentifier()->GetRTV(),
|
||||
nullptr);
|
||||
|
||||
// Create texture copy
|
||||
D3D::drawShadedTexQuad(
|
||||
efb_tex_srv, &sourcerect, g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(),
|
||||
pixel_shader, VertexShaderCache::GetSimpleVertexShader(),
|
||||
VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader());
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
ID3D11PixelShader*
|
||||
TextureCache::GetEFBToTexPixelShader(const TextureConversionShaderGen::TCShaderUid& uid)
|
||||
{
|
||||
auto iter = m_efb_to_tex_pixel_shaders.find(uid);
|
||||
if (iter != m_efb_to_tex_pixel_shaders.end())
|
||||
return iter->second;
|
||||
|
||||
ShaderCode code = TextureConversionShaderGen::GenerateShader(APIType::D3D, uid.GetUidData());
|
||||
ID3D11PixelShader* shader = D3D::CompileAndCreatePixelShader(code.GetBuffer());
|
||||
m_efb_to_tex_pixel_shaders.emplace(uid, shader);
|
||||
return shader;
|
||||
}
|
||||
} // namespace DX11
|
@ -1,49 +0,0 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "VideoBackends/D3D/D3DTexture.h"
|
||||
#include "VideoCommon/TextureCacheBase.h"
|
||||
#include "VideoCommon/TextureConverterShaderGen.h"
|
||||
|
||||
class AbstractTexture;
|
||||
struct TextureConfig;
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
class TextureCache : public TextureCacheBase
|
||||
{
|
||||
public:
|
||||
TextureCache();
|
||||
~TextureCache();
|
||||
|
||||
private:
|
||||
void ConvertTexture(TCacheEntry* destination, TCacheEntry* source, const void* palette,
|
||||
TLUTFormat format) override;
|
||||
|
||||
void CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
|
||||
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
|
||||
bool scale_by_half, float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
|
||||
const CopyFilterCoefficientArray& filter_coefficients) override;
|
||||
|
||||
void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect,
|
||||
bool scale_by_half, EFBCopyFormat dst_format, bool is_intensity,
|
||||
float gamma, bool clamp_top, bool clamp_bottom,
|
||||
const CopyFilterCoefficientArray& filter_coefficients) override;
|
||||
|
||||
bool CompileShaders() override { return true; }
|
||||
void DeleteShaders() override {}
|
||||
ID3D11PixelShader* GetEFBToTexPixelShader(const TextureConversionShaderGen::TCShaderUid& uid);
|
||||
|
||||
ID3D11Buffer* palette_buf;
|
||||
ID3D11ShaderResourceView* palette_buf_srv;
|
||||
ID3D11Buffer* uniform_buffer;
|
||||
ID3D11PixelShader* palette_pixel_shader[3];
|
||||
|
||||
std::map<TextureConversionShaderGen::TCShaderUid, ID3D11PixelShader*> m_efb_to_tex_pixel_shaders;
|
||||
};
|
||||
}
|
@ -7,24 +7,19 @@
|
||||
#include <d3d11.h>
|
||||
|
||||
#include "Common/Align.h"
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "VideoBackends/D3D/BoundingBox.h"
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/FramebufferManager.h"
|
||||
#include "VideoBackends/D3D/GeometryShaderCache.h"
|
||||
#include "VideoBackends/D3D/PixelShaderCache.h"
|
||||
#include "VideoBackends/D3D/Render.h"
|
||||
#include "VideoBackends/D3D/VertexShaderCache.h"
|
||||
|
||||
#include "VideoCommon/BoundingBox.h"
|
||||
#include "VideoCommon/Debugger.h"
|
||||
#include "VideoCommon/GeometryShaderManager.h"
|
||||
#include "VideoCommon/IndexGenerator.h"
|
||||
#include "VideoCommon/NativeVertexFormat.h"
|
||||
#include "VideoCommon/PixelShaderManager.h"
|
||||
#include "VideoCommon/RenderBase.h"
|
||||
#include "VideoCommon/Statistics.h"
|
||||
#include "VideoCommon/VertexLoaderManager.h"
|
||||
#include "VideoCommon/VertexShaderManager.h"
|
||||
@ -32,11 +27,6 @@
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
// TODO: Find sensible values for these two
|
||||
const u32 MAX_IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE * sizeof(u16) * 8;
|
||||
const u32 MAX_VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE;
|
||||
const u32 MAX_BUFFER_SIZE = MAX_IBUFFER_SIZE + MAX_VBUFFER_SIZE;
|
||||
|
||||
static ID3D11Buffer* AllocateConstantBuffer(u32 size)
|
||||
{
|
||||
const u32 cbsize = Common::AlignUp(size, 16u); // must be a multiple of 16
|
||||
@ -59,71 +49,172 @@ static void UpdateConstantBuffer(ID3D11Buffer* const buffer, const void* data, u
|
||||
ADDSTAT(stats.thisFrame.bytesUniformStreamed, data_size);
|
||||
}
|
||||
|
||||
void VertexManager::CreateDeviceObjects()
|
||||
static ID3D11ShaderResourceView*
|
||||
CreateTexelBufferView(ID3D11Buffer* buffer, TexelBufferFormat format, DXGI_FORMAT srv_format)
|
||||
{
|
||||
D3D11_BUFFER_DESC bufdesc =
|
||||
CD3D11_BUFFER_DESC(MAX_BUFFER_SIZE, D3D11_BIND_INDEX_BUFFER | D3D11_BIND_VERTEX_BUFFER,
|
||||
D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
ID3D11ShaderResourceView* srv;
|
||||
CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(buffer, srv_format, 0,
|
||||
VertexManager::TEXEL_STREAM_BUFFER_SIZE /
|
||||
VertexManager::GetTexelBufferElementSize(format));
|
||||
CHECK(SUCCEEDED(D3D::device->CreateShaderResourceView(buffer, &srv_desc, &srv)),
|
||||
"Create SRV for texel buffer");
|
||||
return srv;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_BUFFER_COUNT; i++)
|
||||
VertexManager::VertexManager() = default;
|
||||
|
||||
VertexManager::~VertexManager()
|
||||
{
|
||||
for (auto& srv_ptr : m_texel_buffer_views)
|
||||
SAFE_RELEASE(srv_ptr);
|
||||
SAFE_RELEASE(m_texel_buffer);
|
||||
SAFE_RELEASE(m_pixel_constant_buffer);
|
||||
SAFE_RELEASE(m_geometry_constant_buffer);
|
||||
SAFE_RELEASE(m_vertex_constant_buffer);
|
||||
for (auto& buffer : m_buffers)
|
||||
SAFE_RELEASE(buffer);
|
||||
}
|
||||
|
||||
bool VertexManager::Initialize()
|
||||
{
|
||||
if (!VertexManagerBase::Initialize())
|
||||
return false;
|
||||
|
||||
CD3D11_BUFFER_DESC bufdesc((VERTEX_STREAM_BUFFER_SIZE + INDEX_STREAM_BUFFER_SIZE) / BUFFER_COUNT,
|
||||
D3D11_BIND_INDEX_BUFFER | D3D11_BIND_VERTEX_BUFFER,
|
||||
D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
|
||||
for (int i = 0; i < BUFFER_COUNT; i++)
|
||||
{
|
||||
m_buffers[i] = nullptr;
|
||||
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, nullptr, &m_buffers[i])),
|
||||
"Failed to create buffer.");
|
||||
D3D::SetDebugObjectName(m_buffers[i], "Buffer of VertexManager");
|
||||
}
|
||||
|
||||
m_buffer_cursor = MAX_BUFFER_SIZE;
|
||||
|
||||
m_vertex_constant_buffer = AllocateConstantBuffer(sizeof(VertexShaderConstants));
|
||||
m_geometry_constant_buffer = AllocateConstantBuffer(sizeof(GeometryShaderConstants));
|
||||
m_pixel_constant_buffer = AllocateConstantBuffer(sizeof(PixelShaderConstants));
|
||||
}
|
||||
if (!m_vertex_constant_buffer || !m_geometry_constant_buffer || !m_pixel_constant_buffer)
|
||||
return false;
|
||||
|
||||
void VertexManager::DestroyDeviceObjects()
|
||||
{
|
||||
SAFE_RELEASE(m_pixel_constant_buffer);
|
||||
SAFE_RELEASE(m_geometry_constant_buffer);
|
||||
SAFE_RELEASE(m_vertex_constant_buffer);
|
||||
for (int i = 0; i < MAX_BUFFER_COUNT; i++)
|
||||
CD3D11_BUFFER_DESC texel_buf_desc(TEXEL_STREAM_BUFFER_SIZE, D3D11_BIND_SHADER_RESOURCE,
|
||||
D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&texel_buf_desc, nullptr, &m_texel_buffer)),
|
||||
"Creating texel buffer failed");
|
||||
if (!m_texel_buffer)
|
||||
return false;
|
||||
|
||||
static constexpr std::array<std::pair<TexelBufferFormat, DXGI_FORMAT>, NUM_TEXEL_BUFFER_FORMATS>
|
||||
format_mapping = {{
|
||||
{TEXEL_BUFFER_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT},
|
||||
{TEXEL_BUFFER_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT},
|
||||
{TEXEL_BUFFER_FORMAT_RGBA8_UINT, DXGI_FORMAT_R8G8B8A8_UNORM},
|
||||
{TEXEL_BUFFER_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT},
|
||||
}};
|
||||
for (const auto& it : format_mapping)
|
||||
{
|
||||
SAFE_RELEASE(m_buffers[i]);
|
||||
m_texel_buffer_views[it.first] = CreateTexelBufferView(m_texel_buffer, it.first, it.second);
|
||||
if (!m_texel_buffer_views[it.first])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
VertexManager::VertexManager()
|
||||
{
|
||||
m_staging_vertex_buffer.resize(MAXVBUFFERSIZE);
|
||||
|
||||
m_cur_buffer_pointer = m_base_buffer_pointer = &m_staging_vertex_buffer[0];
|
||||
m_end_buffer_pointer = m_base_buffer_pointer + m_staging_vertex_buffer.size();
|
||||
|
||||
m_staging_index_buffer.resize(MAXIBUFFERSIZE);
|
||||
|
||||
CreateDeviceObjects();
|
||||
}
|
||||
|
||||
VertexManager::~VertexManager()
|
||||
{
|
||||
DestroyDeviceObjects();
|
||||
return true;
|
||||
}
|
||||
|
||||
void VertexManager::UploadUtilityUniforms(const void* uniforms, u32 uniforms_size)
|
||||
{
|
||||
// Just use the one buffer for all three.
|
||||
InvalidateConstants();
|
||||
UpdateConstantBuffer(m_vertex_constant_buffer, uniforms, uniforms_size);
|
||||
D3D::stateman->SetVertexConstants(m_vertex_constant_buffer);
|
||||
D3D::stateman->SetGeometryConstants(m_vertex_constant_buffer);
|
||||
D3D::stateman->SetPixelConstants(m_vertex_constant_buffer);
|
||||
VertexShaderManager::dirty = true;
|
||||
GeometryShaderManager::dirty = true;
|
||||
PixelShaderManager::dirty = true;
|
||||
}
|
||||
|
||||
void VertexManager::ResetBuffer(u32 vertex_stride, bool cull_all)
|
||||
bool VertexManager::MapTexelBuffer(u32 required_size, D3D11_MAPPED_SUBRESOURCE& sr)
|
||||
{
|
||||
if ((m_texel_buffer_offset + required_size) > TEXEL_STREAM_BUFFER_SIZE)
|
||||
{
|
||||
// Restart buffer.
|
||||
HRESULT hr = D3D::context->Map(m_texel_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &sr);
|
||||
CHECK(SUCCEEDED(hr), "Map texel buffer");
|
||||
if (FAILED(hr))
|
||||
return false;
|
||||
|
||||
m_texel_buffer_offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't overwrite the earlier-used space.
|
||||
HRESULT hr = D3D::context->Map(m_texel_buffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &sr);
|
||||
CHECK(SUCCEEDED(hr), "Map texel buffer");
|
||||
if (FAILED(hr))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VertexManager::UploadTexelBuffer(const void* data, u32 data_size, TexelBufferFormat format,
|
||||
u32* out_offset)
|
||||
{
|
||||
if (data_size > TEXEL_STREAM_BUFFER_SIZE)
|
||||
return false;
|
||||
|
||||
const u32 elem_size = GetTexelBufferElementSize(format);
|
||||
m_texel_buffer_offset = Common::AlignUp(m_texel_buffer_offset, elem_size);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE sr;
|
||||
if (!MapTexelBuffer(data_size, sr))
|
||||
return false;
|
||||
|
||||
*out_offset = m_texel_buffer_offset / elem_size;
|
||||
std::memcpy(static_cast<u8*>(sr.pData) + m_texel_buffer_offset, data, data_size);
|
||||
ADDSTAT(stats.thisFrame.bytesUniformStreamed, data_size);
|
||||
m_texel_buffer_offset += data_size;
|
||||
|
||||
D3D::context->Unmap(m_texel_buffer, 0);
|
||||
D3D::stateman->SetTexture(0, m_texel_buffer_views[static_cast<size_t>(format)]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VertexManager::UploadTexelBuffer(const void* data, u32 data_size, TexelBufferFormat format,
|
||||
u32* out_offset, const void* palette_data, u32 palette_size,
|
||||
TexelBufferFormat palette_format, u32* out_palette_offset)
|
||||
{
|
||||
const u32 elem_size = GetTexelBufferElementSize(format);
|
||||
const u32 palette_elem_size = GetTexelBufferElementSize(palette_format);
|
||||
const u32 reserve_size = data_size + palette_size + palette_elem_size;
|
||||
if (reserve_size > TEXEL_STREAM_BUFFER_SIZE)
|
||||
return false;
|
||||
|
||||
m_texel_buffer_offset = Common::AlignUp(m_texel_buffer_offset, elem_size);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE sr;
|
||||
if (!MapTexelBuffer(reserve_size, sr))
|
||||
return false;
|
||||
|
||||
const u32 palette_byte_offset = Common::AlignUp(data_size, palette_elem_size);
|
||||
std::memcpy(static_cast<u8*>(sr.pData) + m_texel_buffer_offset, data, data_size);
|
||||
std::memcpy(static_cast<u8*>(sr.pData) + m_texel_buffer_offset + palette_byte_offset,
|
||||
palette_data, palette_size);
|
||||
ADDSTAT(stats.thisFrame.bytesUniformStreamed, palette_byte_offset + palette_size);
|
||||
*out_offset = m_texel_buffer_offset / elem_size;
|
||||
*out_palette_offset = (m_texel_buffer_offset + palette_byte_offset) / palette_elem_size;
|
||||
m_texel_buffer_offset += palette_byte_offset + palette_size;
|
||||
|
||||
D3D::context->Unmap(m_texel_buffer, 0);
|
||||
D3D::stateman->SetTexture(0, m_texel_buffer_views[static_cast<size_t>(format)]);
|
||||
D3D::stateman->SetTexture(1, m_texel_buffer_views[static_cast<size_t>(palette_format)]);
|
||||
return true;
|
||||
}
|
||||
|
||||
void VertexManager::ResetBuffer(u32 vertex_stride)
|
||||
{
|
||||
m_base_buffer_pointer = m_cpu_vertex_buffer.data();
|
||||
m_cur_buffer_pointer = m_base_buffer_pointer;
|
||||
IndexGenerator::Start(m_staging_index_buffer.data());
|
||||
m_end_buffer_pointer = m_base_buffer_pointer + m_cpu_vertex_buffer.size();
|
||||
IndexGenerator::Start(m_cpu_index_buffer.data());
|
||||
}
|
||||
|
||||
void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices,
|
||||
@ -143,10 +234,10 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in
|
||||
}
|
||||
|
||||
D3D11_MAP MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
|
||||
if (cursor + totalBufferSize >= MAX_BUFFER_SIZE)
|
||||
if (cursor + totalBufferSize >= BUFFER_SIZE)
|
||||
{
|
||||
// Wrap around
|
||||
m_current_buffer = (m_current_buffer + 1) % MAX_BUFFER_COUNT;
|
||||
m_current_buffer = (m_current_buffer + 1) % BUFFER_COUNT;
|
||||
cursor = 0;
|
||||
MapType = D3D11_MAP_WRITE_DISCARD;
|
||||
}
|
||||
@ -159,8 +250,7 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in
|
||||
if (vertexBufferSize > 0)
|
||||
std::memcpy(mappedData + cursor, m_base_buffer_pointer, vertexBufferSize);
|
||||
if (indexBufferSize > 0)
|
||||
std::memcpy(mappedData + cursor + vertexBufferSize, m_staging_index_buffer.data(),
|
||||
indexBufferSize);
|
||||
std::memcpy(mappedData + cursor + vertexBufferSize, m_cpu_index_buffer.data(), indexBufferSize);
|
||||
D3D::context->Unmap(m_buffers[m_current_buffer], 0);
|
||||
|
||||
m_buffer_cursor = cursor + totalBufferSize;
|
||||
@ -172,7 +262,7 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in
|
||||
D3D::stateman->SetIndexBuffer(m_buffers[m_current_buffer]);
|
||||
}
|
||||
|
||||
void VertexManager::UploadConstants()
|
||||
void VertexManager::UploadUniforms()
|
||||
{
|
||||
if (VertexShaderManager::dirty)
|
||||
{
|
||||
@ -199,20 +289,4 @@ void VertexManager::UploadConstants()
|
||||
D3D::stateman->SetVertexConstants(m_vertex_constant_buffer);
|
||||
D3D::stateman->SetGeometryConstants(m_geometry_constant_buffer);
|
||||
}
|
||||
|
||||
void VertexManager::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex)
|
||||
{
|
||||
FramebufferManager::SetIntegerEFBRenderTarget(
|
||||
m_current_pipeline_config.blending_state.logicopenable);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
D3D::stateman->Apply();
|
||||
D3D::context->DrawIndexed(num_indices, base_index, base_vertex);
|
||||
}
|
||||
} // namespace DX11
|
||||
|
@ -18,13 +18,12 @@ struct ID3D11Buffer;
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
class D3DBlob;
|
||||
class D3DVertexFormat : public NativeVertexFormat
|
||||
{
|
||||
public:
|
||||
D3DVertexFormat(const PortableVertexDeclaration& vtx_decl);
|
||||
~D3DVertexFormat();
|
||||
ID3D11InputLayout* GetInputLayout(D3DBlob* vs_bytecode);
|
||||
ID3D11InputLayout* GetInputLayout(const void* vs_bytecode, size_t vs_bytecode_size);
|
||||
|
||||
private:
|
||||
std::array<D3D11_INPUT_ELEMENT_DESC, 32> m_elems{};
|
||||
@ -39,35 +38,39 @@ public:
|
||||
VertexManager();
|
||||
~VertexManager();
|
||||
|
||||
std::unique_ptr<NativeVertexFormat>
|
||||
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
|
||||
bool Initialize();
|
||||
|
||||
void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size) override;
|
||||
bool UploadTexelBuffer(const void* data, u32 data_size, TexelBufferFormat format,
|
||||
u32* out_offset) override;
|
||||
bool UploadTexelBuffer(const void* data, u32 data_size, TexelBufferFormat format, u32* out_offset,
|
||||
const void* palette_data, u32 palette_size,
|
||||
TexelBufferFormat palette_format, u32* out_palette_offset) override;
|
||||
|
||||
protected:
|
||||
void CreateDeviceObjects() override;
|
||||
void DestroyDeviceObjects() override;
|
||||
void ResetBuffer(u32 vertex_stride, bool cull_all) override;
|
||||
void ResetBuffer(u32 vertex_stride) override;
|
||||
void CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_indices, u32* out_base_vertex,
|
||||
u32* out_base_index) override;
|
||||
void UploadConstants() override;
|
||||
void DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex) override;
|
||||
void UploadUniforms() override;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
MAX_BUFFER_COUNT = 2
|
||||
};
|
||||
ID3D11Buffer* m_buffers[MAX_BUFFER_COUNT] = {};
|
||||
static constexpr u32 BUFFER_COUNT = 2;
|
||||
static constexpr u32 BUFFER_SIZE =
|
||||
(VERTEX_STREAM_BUFFER_SIZE + INDEX_STREAM_BUFFER_SIZE) / BUFFER_COUNT;
|
||||
|
||||
bool MapTexelBuffer(u32 required_size, D3D11_MAPPED_SUBRESOURCE& sr);
|
||||
|
||||
ID3D11Buffer* m_buffers[BUFFER_COUNT] = {};
|
||||
u32 m_current_buffer = 0;
|
||||
u32 m_buffer_cursor = 0;
|
||||
|
||||
std::vector<u8> m_staging_vertex_buffer;
|
||||
std::vector<u16> m_staging_index_buffer;
|
||||
|
||||
ID3D11Buffer* m_vertex_constant_buffer = nullptr;
|
||||
ID3D11Buffer* m_geometry_constant_buffer = nullptr;
|
||||
ID3D11Buffer* m_pixel_constant_buffer = nullptr;
|
||||
|
||||
ID3D11Buffer* m_texel_buffer = nullptr;
|
||||
std::array<ID3D11ShaderResourceView*, NUM_TEXEL_BUFFER_FORMATS> m_texel_buffer_views;
|
||||
u32 m_texel_buffer_offset = 0;
|
||||
};
|
||||
|
||||
} // namespace DX11
|
||||
|
@ -1,136 +0,0 @@
|
||||
// Copyright 2010 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Host.h"
|
||||
|
||||
#include "VideoBackends/D3D/D3DShader.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/VertexManager.h"
|
||||
#include "VideoBackends/D3D/VertexShaderCache.h"
|
||||
|
||||
#include "VideoCommon/Debugger.h"
|
||||
#include "VideoCommon/Statistics.h"
|
||||
#include "VideoCommon/UberShaderVertex.h"
|
||||
#include "VideoCommon/VertexLoaderManager.h"
|
||||
#include "VideoCommon/VertexShaderGen.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
static ID3D11VertexShader* SimpleVertexShader = nullptr;
|
||||
static ID3D11VertexShader* ClearVertexShader = nullptr;
|
||||
static ID3D11InputLayout* SimpleLayout = nullptr;
|
||||
static ID3D11InputLayout* ClearLayout = nullptr;
|
||||
|
||||
ID3D11VertexShader* VertexShaderCache::GetSimpleVertexShader()
|
||||
{
|
||||
return SimpleVertexShader;
|
||||
}
|
||||
ID3D11VertexShader* VertexShaderCache::GetClearVertexShader()
|
||||
{
|
||||
return ClearVertexShader;
|
||||
}
|
||||
ID3D11InputLayout* VertexShaderCache::GetSimpleInputLayout()
|
||||
{
|
||||
return SimpleLayout;
|
||||
}
|
||||
ID3D11InputLayout* VertexShaderCache::GetClearInputLayout()
|
||||
{
|
||||
return ClearLayout;
|
||||
}
|
||||
|
||||
// this class will load the precompiled shaders into our cache
|
||||
template <typename UidType>
|
||||
class VertexShaderCacheInserter : public LinearDiskCacheReader<UidType, u8>
|
||||
{
|
||||
public:
|
||||
void Read(const UidType& key, const u8* value, u32 value_size)
|
||||
{
|
||||
D3DBlob* blob = new D3DBlob(value_size, value);
|
||||
VertexShaderCache::InsertByteCode(key, blob);
|
||||
blob->Release();
|
||||
}
|
||||
};
|
||||
|
||||
const char simple_shader_code[] = {
|
||||
"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float3 vTexCoord : TEXCOORD0;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float3 inTEX0 : TEXCOORD0)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;\n"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vTexCoord = inTEX0;\n"
|
||||
"return OUT;\n"
|
||||
"}\n"};
|
||||
|
||||
const char clear_shader_code[] = {
|
||||
"struct VSOUTPUT\n"
|
||||
"{\n"
|
||||
"float4 vPosition : POSITION;\n"
|
||||
"float4 vColor0 : COLOR0;\n"
|
||||
"};\n"
|
||||
"VSOUTPUT main(float4 inPosition : POSITION,float4 inColor0: COLOR0)\n"
|
||||
"{\n"
|
||||
"VSOUTPUT OUT;\n"
|
||||
"OUT.vPosition = inPosition;\n"
|
||||
"OUT.vColor0 = inColor0;\n"
|
||||
"return OUT;\n"
|
||||
"}\n"};
|
||||
|
||||
void VertexShaderCache::Init()
|
||||
{
|
||||
const D3D11_INPUT_ELEMENT_DESC simpleelems[2] = {
|
||||
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
|
||||
};
|
||||
const D3D11_INPUT_ELEMENT_DESC clearelems[2] = {
|
||||
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{"COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
};
|
||||
|
||||
D3DBlob* blob;
|
||||
D3D::CompileVertexShader(simple_shader_code, &blob);
|
||||
D3D::device->CreateInputLayout(simpleelems, 2, blob->Data(), blob->Size(), &SimpleLayout);
|
||||
SimpleVertexShader = D3D::CreateVertexShaderFromByteCode(blob);
|
||||
if (SimpleLayout == nullptr || SimpleVertexShader == nullptr)
|
||||
PanicAlert("Failed to create simple vertex shader or input layout at %s %d\n", __FILE__,
|
||||
__LINE__);
|
||||
blob->Release();
|
||||
D3D::SetDebugObjectName(SimpleVertexShader, "simple vertex shader");
|
||||
D3D::SetDebugObjectName(SimpleLayout, "simple input layout");
|
||||
|
||||
D3D::CompileVertexShader(clear_shader_code, &blob);
|
||||
D3D::device->CreateInputLayout(clearelems, 2, blob->Data(), blob->Size(), &ClearLayout);
|
||||
ClearVertexShader = D3D::CreateVertexShaderFromByteCode(blob);
|
||||
if (ClearLayout == nullptr || ClearVertexShader == nullptr)
|
||||
PanicAlert("Failed to create clear vertex shader or input layout at %s %d\n", __FILE__,
|
||||
__LINE__);
|
||||
blob->Release();
|
||||
D3D::SetDebugObjectName(ClearVertexShader, "clear vertex shader");
|
||||
D3D::SetDebugObjectName(ClearLayout, "clear input layout");
|
||||
|
||||
SETSTAT(stats.numVertexShadersCreated, 0);
|
||||
SETSTAT(stats.numVertexShadersAlive, 0);
|
||||
}
|
||||
|
||||
void VertexShaderCache::Shutdown()
|
||||
{
|
||||
SAFE_RELEASE(SimpleVertexShader);
|
||||
SAFE_RELEASE(ClearVertexShader);
|
||||
|
||||
SAFE_RELEASE(SimpleLayout);
|
||||
SAFE_RELEASE(ClearLayout);
|
||||
}
|
||||
} // namespace DX11
|
@ -1,32 +0,0 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DBlob.h"
|
||||
|
||||
#include "VideoCommon/AsyncShaderCompiler.h"
|
||||
#include "VideoCommon/UberShaderVertex.h"
|
||||
#include "VideoCommon/VertexShaderGen.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
class D3DVertexFormat;
|
||||
|
||||
class VertexShaderCache
|
||||
{
|
||||
public:
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
|
||||
static ID3D11VertexShader* GetSimpleVertexShader();
|
||||
static ID3D11VertexShader* GetClearVertexShader();
|
||||
static ID3D11InputLayout* GetSimpleInputLayout();
|
||||
static ID3D11InputLayout* GetClearInputLayout();
|
||||
};
|
||||
|
||||
} // namespace DX11
|
@ -12,17 +12,14 @@
|
||||
|
||||
#include "VideoBackends/D3D/BoundingBox.h"
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DUtil.h"
|
||||
#include "VideoBackends/D3D/GeometryShaderCache.h"
|
||||
#include "VideoBackends/D3D/PerfQuery.h"
|
||||
#include "VideoBackends/D3D/PixelShaderCache.h"
|
||||
#include "VideoBackends/D3D/Render.h"
|
||||
#include "VideoBackends/D3D/TextureCache.h"
|
||||
#include "VideoBackends/D3D/VertexManager.h"
|
||||
#include "VideoBackends/D3D/VertexShaderCache.h"
|
||||
#include "VideoBackends/D3D/VideoBackend.h"
|
||||
|
||||
#include "VideoCommon/FramebufferManager.h"
|
||||
#include "VideoCommon/ShaderCache.h"
|
||||
#include "VideoCommon/TextureCacheBase.h"
|
||||
#include "VideoCommon/VideoCommon.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
@ -51,6 +48,7 @@ void VideoBackend::InitBackendInfo()
|
||||
|
||||
g_Config.backend_info.api_type = APIType::D3D;
|
||||
g_Config.backend_info.MaxTextureSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
g_Config.backend_info.bUsesLowerLeftOrigin = false;
|
||||
g_Config.backend_info.bSupportsExclusiveFullscreen = true;
|
||||
g_Config.backend_info.bSupportsDualSourceBlend = true;
|
||||
g_Config.backend_info.bSupportsPrimitiveRestart = true;
|
||||
@ -58,16 +56,17 @@ void VideoBackend::InitBackendInfo()
|
||||
g_Config.backend_info.bSupportsGeometryShaders = true;
|
||||
g_Config.backend_info.bSupportsComputeShaders = false;
|
||||
g_Config.backend_info.bSupports3DVision = true;
|
||||
g_Config.backend_info.bSupportsPostProcessing = false;
|
||||
g_Config.backend_info.bSupportsPostProcessing = true;
|
||||
g_Config.backend_info.bSupportsPaletteConversion = true;
|
||||
g_Config.backend_info.bSupportsClipControl = true;
|
||||
g_Config.backend_info.bSupportsDepthClamp = true;
|
||||
g_Config.backend_info.bSupportsReversedDepthRange = false;
|
||||
g_Config.backend_info.bSupportsLogicOp = true;
|
||||
g_Config.backend_info.bSupportsMultithreading = false;
|
||||
g_Config.backend_info.bSupportsGPUTextureDecoding = false;
|
||||
g_Config.backend_info.bSupportsGPUTextureDecoding = true;
|
||||
g_Config.backend_info.bSupportsST3CTextures = false;
|
||||
g_Config.backend_info.bSupportsCopyToVram = true;
|
||||
g_Config.backend_info.bSupportsLargePoints = false;
|
||||
g_Config.backend_info.bSupportsBitfield = false;
|
||||
g_Config.backend_info.bSupportsDynamicSamplerIndexing = false;
|
||||
g_Config.backend_info.bSupportsBPTCTextures = false;
|
||||
@ -149,21 +148,20 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi)
|
||||
// internal interfaces
|
||||
g_renderer =
|
||||
std::make_unique<Renderer>(backbuffer_width, backbuffer_height, wsi.render_surface_scale);
|
||||
g_shader_cache = std::make_unique<VideoCommon::ShaderCache>();
|
||||
g_texture_cache = std::make_unique<TextureCache>();
|
||||
g_vertex_manager = std::make_unique<VertexManager>();
|
||||
g_shader_cache = std::make_unique<VideoCommon::ShaderCache>();
|
||||
g_framebuffer_manager = std::make_unique<FramebufferManager>();
|
||||
g_texture_cache = std::make_unique<TextureCacheBase>();
|
||||
g_perf_query = std::make_unique<PerfQuery>();
|
||||
|
||||
VertexShaderCache::Init();
|
||||
PixelShaderCache::Init();
|
||||
GeometryShaderCache::Init();
|
||||
|
||||
if (!g_renderer->Initialize() || !g_shader_cache->Initialize())
|
||||
if (!g_renderer->Initialize() || !g_vertex_manager->Initialize() ||
|
||||
!g_shader_cache->Initialize() || !g_framebuffer_manager->Initialize() ||
|
||||
!g_texture_cache->Initialize())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D::InitUtils();
|
||||
BBox::Init();
|
||||
|
||||
g_shader_cache->InitializeShaderCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -172,16 +170,13 @@ void VideoBackend::Shutdown()
|
||||
g_shader_cache->Shutdown();
|
||||
g_renderer->Shutdown();
|
||||
|
||||
D3D::ShutdownUtils();
|
||||
PixelShaderCache::Shutdown();
|
||||
VertexShaderCache::Shutdown();
|
||||
GeometryShaderCache::Shutdown();
|
||||
BBox::Shutdown();
|
||||
|
||||
g_perf_query.reset();
|
||||
g_vertex_manager.reset();
|
||||
g_texture_cache.reset();
|
||||
g_framebuffer_manager.reset();
|
||||
g_shader_cache.reset();
|
||||
g_vertex_manager.reset();
|
||||
g_renderer.reset();
|
||||
|
||||
ShutdownShared();
|
||||
|
Reference in New Issue
Block a user