I think clean up DX11 code a bit. Used "smart" pointers to avoid need to manually AddRef/Release in many places. Eliminated the D3DBlob class (replaced with just D3D10CreateBlob). Eliminated some Init/Shutdown functions (moved stuff into ctors/dtors). This should not affect behavior at all, only code maintainability.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7421 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Jordan Woyak 2011-03-30 07:17:23 +00:00
parent c316417a34
commit 3d5d205c73
40 changed files with 1384 additions and 1611 deletions

View file

@ -191,7 +191,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Src\D3DBase.cpp" /> <ClCompile Include="Src\D3DBase.cpp" />
<ClCompile Include="Src\D3DBlob.cpp" />
<ClCompile Include="Src\D3DShader.cpp" /> <ClCompile Include="Src\D3DShader.cpp" />
<ClCompile Include="Src\D3DTexture.cpp" /> <ClCompile Include="Src\D3DTexture.cpp" />
<ClCompile Include="Src\D3DUtil.cpp" /> <ClCompile Include="Src\D3DUtil.cpp" />
@ -220,7 +219,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Src\D3DBase.h" /> <ClInclude Include="Src\D3DBase.h" />
<ClInclude Include="Src\D3DBlob.h" />
<ClInclude Include="Src\D3DShader.h" /> <ClInclude Include="Src\D3DShader.h" />
<ClInclude Include="Src\D3DTexture.h" /> <ClInclude Include="Src\D3DTexture.h" />
<ClInclude Include="Src\D3DUtil.h" /> <ClInclude Include="Src\D3DUtil.h" />

View file

@ -6,9 +6,6 @@
<ClCompile Include="Src\D3DBase.cpp"> <ClCompile Include="Src\D3DBase.cpp">
<Filter>D3D</Filter> <Filter>D3D</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Src\D3DBlob.cpp">
<Filter>D3D</Filter>
</ClCompile>
<ClCompile Include="Src\D3DShader.cpp"> <ClCompile Include="Src\D3DShader.cpp">
<Filter>D3D</Filter> <Filter>D3D</Filter>
</ClCompile> </ClCompile>
@ -69,9 +66,6 @@
<ClInclude Include="Src\D3DBase.h"> <ClInclude Include="Src\D3DBase.h">
<Filter>D3D</Filter> <Filter>D3D</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Src\D3DBlob.h">
<Filter>D3D</Filter>
</ClInclude>
<ClInclude Include="Src\D3DShader.h"> <ClInclude Include="Src\D3DShader.h">
<Filter>D3D</Filter> <Filter>D3D</Filter>
</ClInclude> </ClInclude>

View file

@ -43,20 +43,120 @@ int dxgi_dll_ref = 0;
typedef HRESULT (WINAPI* D3D11CREATEDEVICEANDSWAPCHAIN)(IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL*, UINT, UINT, CONST DXGI_SWAP_CHAIN_DESC*, IDXGISwapChain**, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext**); typedef HRESULT (WINAPI* D3D11CREATEDEVICEANDSWAPCHAIN)(IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL*, UINT, UINT, CONST DXGI_SWAP_CHAIN_DESC*, IDXGISwapChain**, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext**);
D3D11CREATEDEVICE PD3D11CreateDevice = NULL; D3D11CREATEDEVICE PD3D11CreateDevice = NULL;
D3D11CREATEDEVICEANDSWAPCHAIN PD3D11CreateDeviceAndSwapChain = NULL; D3D11CREATEDEVICEANDSWAPCHAIN PD3D11CreateDeviceAndSwapChain = NULL;
HINSTANCE hD3DDll = NULL; D3D10CREATEBLOB PD3D10CreateBlob = NULL;
HINSTANCE hD3DDll_10 = NULL;
HINSTANCE hD3DDll_11 = NULL;
int d3d_dll_ref = 0; int d3d_dll_ref = 0;
// SharedPtr funcs
HRESULT D3D11CreateDeviceShared(IDXGIAdapter *pAdapter, D3D_DRIVER_TYPE DriverType,
HMODULE Software, UINT Flags, const D3D_FEATURE_LEVEL *pFeatureLevels,
UINT FeatureLevels, UINT SDKVersion, SharedPtr<ID3D11Device>* _Device,
D3D_FEATURE_LEVEL *pFeatureLevel, SharedPtr<ID3D11DeviceContext>* _ImmediateContext)
{
ID3D11Device* device = nullptr;
ID3D11DeviceContext* context = nullptr;
const HRESULT hr = PD3D11CreateDevice(pAdapter, DriverType, Software, Flags, pFeatureLevels,
FeatureLevels, SDKVersion, &device, pFeatureLevel, &context);
if (_Device)
*_Device = SharedPtr<ID3D11Device>::FromPtr(device);
if (_ImmediateContext)
*_ImmediateContext = SharedPtr<ID3D11DeviceContext>::FromPtr(context);
return hr;
}
HRESULT D3D11CreateDeviceAndSwapChainShared(IDXGIAdapter *pAdapter,
D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, const D3D_FEATURE_LEVEL *pFeatureLevels,
UINT FeatureLevels, UINT SDKVersion, const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc,
SharedPtr<IDXGISwapChain>* _SwapChain, SharedPtr<ID3D11Device>* _Device,
D3D_FEATURE_LEVEL *pFeatureLevel, SharedPtr<ID3D11DeviceContext>* _ImmediateContext)
{
ID3D11Device* device = nullptr;
IDXGISwapChain* chain = nullptr;
ID3D11DeviceContext* context = nullptr;
const HRESULT hr = PD3D11CreateDeviceAndSwapChain(pAdapter, DriverType, Software, Flags,
pFeatureLevels, FeatureLevels, SDKVersion, pSwapChainDesc, &chain, &device, pFeatureLevel, &context);
if (_Device)
*_Device = SharedPtr<ID3D11Device>::FromPtr(device);
if (_SwapChain)
*_SwapChain = SharedPtr<IDXGISwapChain>::FromPtr(chain);
if (_ImmediateContext)
*_ImmediateContext = SharedPtr<ID3D11DeviceContext>::FromPtr(context);
return hr;
}
SharedPtr<ID3D11Texture2D> CreateTexture2DShared(
const D3D11_TEXTURE2D_DESC* pDesc, const D3D11_SUBRESOURCE_DATA* pInitialData)
{
ID3D11Texture2D* texture = nullptr;
D3D::g_device->CreateTexture2D(pDesc, pInitialData, &texture);
return SharedPtr<ID3D11Texture2D>::FromPtr(texture);
}
SharedPtr<ID3D11Texture2D> SwapChainGetBufferTexture2DShared(IDXGISwapChain* swapchain, UINT buffer)
{
ID3D11Texture2D* buf = nullptr;
swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf);
return SharedPtr<ID3D11Texture2D>::FromPtr(buf);
}
SharedPtr<ID3D11BlendState> CreateBlendStateShared(const D3D11_BLEND_DESC *pBlendStateDesc)
{
ID3D11BlendState* state = nullptr;
D3D::g_device->CreateBlendState(pBlendStateDesc, &state);
return SharedPtr<ID3D11BlendState>::FromPtr(state);
}
SharedPtr<ID3D11InputLayout> CreateInputLayoutShared(const D3D11_INPUT_ELEMENT_DESC *pInputElementDescs,
UINT NumElements, const void *pShaderBytecodeWithInputSignature, SIZE_T BytecodeLength)
{
ID3D11InputLayout* layout = nullptr;
D3D::g_device->CreateInputLayout(pInputElementDescs, NumElements,
pShaderBytecodeWithInputSignature, BytecodeLength, &layout);
return SharedPtr<ID3D11InputLayout>::FromPtr(layout);
}
SharedPtr<ID3D11Buffer> CreateBufferShared(const D3D11_BUFFER_DESC *pDesc,
const D3D11_SUBRESOURCE_DATA *pInitialData)
{
ID3D11Buffer* buffer = nullptr;
D3D::g_device->CreateBuffer(pDesc, pInitialData, &buffer);
return SharedPtr<ID3D11Buffer>::FromPtr(buffer);
}
namespace D3D namespace D3D
{ {
ID3D11Device* device = NULL; SharedPtr<ID3D11Device> g_device;
ID3D11DeviceContext* context = NULL; SharedPtr<ID3D11DeviceContext> g_context;
IDXGISwapChain* swapchain = NULL; SharedPtr<IDXGISwapChain> g_swapchain;
D3D_FEATURE_LEVEL featlevel; D3D_FEATURE_LEVEL featlevel;
D3DTexture2D* backbuf = NULL; std::unique_ptr<D3DTexture2D> backbuf;
HWND hWnd; HWND hWnd;
std::vector<DXGI_SAMPLE_DESC> aa_modes; // supported AA modes of the current adapter std::vector<DXGI_SAMPLE_DESC> g_aa_modes; // supported AA modes of the current adapter
bool bgra_textures_supported; bool bgra_textures_supported;
@ -91,21 +191,36 @@ HRESULT LoadDXGI()
HRESULT LoadD3D() HRESULT LoadD3D()
{ {
if (d3d_dll_ref++ > 0) return S_OK; if (d3d_dll_ref++ > 0)
return S_OK;
if (hD3DDll) return S_OK; hD3DDll_10 = LoadLibraryA("d3d10.dll");
hD3DDll = LoadLibraryA("d3d11.dll"); if (!hD3DDll_10)
if (!hD3DDll) {
MessageBoxA(NULL, "Failed to load d3d10.dll", "Critical error", MB_OK | MB_ICONERROR);
--d3d_dll_ref;
return E_FAIL;
}
hD3DDll_11 = LoadLibraryA("d3d11.dll");
if (!hD3DDll_11)
{ {
MessageBoxA(NULL, "Failed to load d3d11.dll", "Critical error", MB_OK | MB_ICONERROR); MessageBoxA(NULL, "Failed to load d3d11.dll", "Critical error", MB_OK | MB_ICONERROR);
--d3d_dll_ref; --d3d_dll_ref;
return E_FAIL; return E_FAIL;
} }
PD3D11CreateDevice = (D3D11CREATEDEVICE)GetProcAddress(hD3DDll, "D3D11CreateDevice");
if (PD3D11CreateDevice == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3D11CreateDevice!", "Critical error", MB_OK | MB_ICONERROR);
PD3D11CreateDeviceAndSwapChain = (D3D11CREATEDEVICEANDSWAPCHAIN)GetProcAddress(hD3DDll, "D3D11CreateDeviceAndSwapChain"); PD3D11CreateDevice = (D3D11CREATEDEVICE)GetProcAddress(hD3DDll_11, "D3D11CreateDevice");
if (PD3D11CreateDeviceAndSwapChain == NULL) MessageBoxA(NULL, "GetProcAddress failed for D3D11CreateDeviceAndSwapChain!", "Critical error", MB_OK | MB_ICONERROR); if (PD3D11CreateDevice == NULL)
MessageBoxA(NULL, "GetProcAddress failed for D3D11CreateDevice!", "Critical error", MB_OK | MB_ICONERROR);
PD3D11CreateDeviceAndSwapChain = (D3D11CREATEDEVICEANDSWAPCHAIN)GetProcAddress(hD3DDll_11, "D3D11CreateDeviceAndSwapChain");
if (PD3D11CreateDeviceAndSwapChain == NULL)
MessageBoxA(NULL, "GetProcAddress failed for D3D11CreateDeviceAndSwapChain!", "Critical error", MB_OK | MB_ICONERROR);
PD3D10CreateBlob = (D3D10CREATEBLOB)GetProcAddress(hD3DDll_10, "D3D10CreateBlob");
if (PD3D10CreateBlob == NULL)
MessageBoxA(NULL, "GetProcAddress failed for D3D10CreateBlob!", "Critical error", MB_OK | MB_ICONERROR);
return S_OK; return S_OK;
} }
@ -201,13 +316,17 @@ void UnloadD3DX()
void UnloadD3D() void UnloadD3D()
{ {
if (!d3d_dll_ref) return; if (!d3d_dll_ref || --d3d_dll_ref != 0)
if (--d3d_dll_ref != 0) return; return;
FreeLibrary(hD3DDll_10);
FreeLibrary(hD3DDll_11);
hD3DDll_10 = hD3DDll_11 = NULL;
if(hD3DDll) FreeLibrary(hD3DDll);
hD3DDll = NULL;
PD3D11CreateDevice = NULL; PD3D11CreateDevice = NULL;
PD3D11CreateDeviceAndSwapChain = NULL; PD3D11CreateDeviceAndSwapChain = NULL;
PD3D10CreateBlob = NULL;
} }
void UnloadD3DCompiler() void UnloadD3DCompiler()
@ -220,46 +339,50 @@ void UnloadD3DCompiler()
PD3DReflect = NULL; PD3DReflect = NULL;
} }
void EnumAAModes(IDXGIAdapter* adapter, std::vector<DXGI_SAMPLE_DESC>& aa_modes) std::vector<DXGI_SAMPLE_DESC> EnumAAModes(IDXGIAdapter* adapter)
{ {
aa_modes.clear();
// NOTE: D3D 10.0 doesn't support multisampled resources which are bound as depth buffers AND shader resources. // NOTE: D3D 10.0 doesn't support multisampled resources which are bound as depth buffers AND shader resources.
// Thus, we can't have MSAA with 10.0 level hardware. // Thus, we can't have MSAA with 10.0 level hardware.
ID3D11Device* device;
ID3D11DeviceContext* context;
D3D_FEATURE_LEVEL feat_level; D3D_FEATURE_LEVEL feat_level;
HRESULT hr = PD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, D3D11_CREATE_DEVICE_SINGLETHREADED, supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION, &device, &feat_level, &context);
SharedPtr<ID3D11Device> device;
SharedPtr<ID3D11DeviceContext> context;
const HRESULT hr = D3D11CreateDeviceShared(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL,
D3D11_CREATE_DEVICE_SINGLETHREADED, supported_feature_levels,
NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION, std::addressof(device), &feat_level, std::addressof(context));
std::vector<DXGI_SAMPLE_DESC> aa_modes;
if (FAILED(hr) || feat_level == D3D_FEATURE_LEVEL_10_0) if (FAILED(hr) || feat_level == D3D_FEATURE_LEVEL_10_0)
{ {
DXGI_SAMPLE_DESC desc; DXGI_SAMPLE_DESC desc;
desc.Count = 1; desc.Count = 1;
desc.Quality = 0; desc.Quality = 0;
aa_modes.push_back(desc); aa_modes.push_back(desc);
SAFE_RELEASE(context);
SAFE_RELEASE(device);
return;
} }
else
for (int samples = 0; samples < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; ++samples)
{ {
UINT quality_levels = 0; for (UINT samples = 0; samples != D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; ++samples)
device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, samples, &quality_levels); {
if (quality_levels > 0) { UINT quality_levels = 0;
DXGI_SAMPLE_DESC desc; device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, samples, &quality_levels);
desc.Count = samples; if (quality_levels > 0)
for (desc.Quality = 0; desc.Quality < quality_levels; ++desc.Quality) {
aa_modes.push_back(desc); DXGI_SAMPLE_DESC desc;
desc.Count = samples;
for (desc.Quality = 0; desc.Quality != quality_levels; ++desc.Quality)
aa_modes.push_back(desc);
}
} }
} }
context->Release(); return aa_modes;
device->Release();
} }
DXGI_SAMPLE_DESC GetAAMode(int index) DXGI_SAMPLE_DESC GetAAMode(int index)
{ {
return aa_modes[index]; return g_aa_modes[index];
} }
HRESULT Create(HWND wnd) HRESULT Create(HWND wnd)
@ -286,32 +409,37 @@ HRESULT Create(HWND wnd)
} }
IDXGIFactory* factory; IDXGIFactory* factory;
IDXGIAdapter* adapter;
IDXGIOutput* output;
hr = PCreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory); hr = PCreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
if (FAILED(hr)) MessageBox(wnd, _T("Failed to create IDXGIFactory object"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR); if (FAILED(hr))
MessageBox(wnd, _T("Failed to create IDXGIFactory object"),
_T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
IDXGIAdapter* adapter;
hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter); hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter);
if (FAILED(hr)) if (FAILED(hr))
{ {
// try using the first one // try using the first one
hr = factory->EnumAdapters(0, &adapter); hr = factory->EnumAdapters(0, &adapter);
if (FAILED(hr)) MessageBox(wnd, _T("Failed to enumerate adapters"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR); if (FAILED(hr))
MessageBox(wnd, _T("Failed to enumerate adapters"),
_T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
} }
// TODO: Make this configurable // TODO: Make this configurable
IDXGIOutput* output;
hr = adapter->EnumOutputs(0, &output); hr = adapter->EnumOutputs(0, &output);
if (FAILED(hr)) if (FAILED(hr))
{ {
// try using the first one // try using the first one
hr = adapter->EnumOutputs(0, &output); hr = adapter->EnumOutputs(0, &output);
if (FAILED(hr)) MessageBox(wnd, _T("Failed to enumerate outputs"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR); if (FAILED(hr))
MessageBox(wnd, _T("Failed to enumerate outputs"),
_T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
} }
// get supported AA modes // get supported AA modes
aa_modes.clear(); g_aa_modes = EnumAAModes(adapter);
EnumAAModes(adapter, aa_modes); if (g_Config.iMultisampleMode >= (int)g_aa_modes.size())
if (g_Config.iMultisampleMode >= (int)aa_modes.size())
{ {
g_Config.iMultisampleMode = 0; g_Config.iMultisampleMode = 0;
UpdateActiveConfig(); UpdateActiveConfig();
@ -333,49 +461,58 @@ HRESULT Create(HWND wnd)
mode_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; mode_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
mode_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; mode_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
hr = output->FindClosestMatchingMode(&mode_desc, &swap_chain_desc.BufferDesc, NULL); hr = output->FindClosestMatchingMode(&mode_desc, &swap_chain_desc.BufferDesc, NULL);
if (FAILED(hr)) MessageBox(wnd, _T("Failed to find a supported video mode"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR); if (FAILED(hr))
MessageBox(wnd, _T("Failed to find a supported video mode"),
_T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
// forcing buffer resolution to xres and yres.. TODO: The new video mode might not actually be supported! // forcing buffer resolution to xres and yres.. TODO: The new video mode might not actually be supported!
swap_chain_desc.BufferDesc.Width = xres; swap_chain_desc.BufferDesc.Width = xres;
swap_chain_desc.BufferDesc.Height = yres; swap_chain_desc.BufferDesc.Height = yres;
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
D3D11_CREATE_DEVICE_FLAG device_flags = (D3D11_CREATE_DEVICE_FLAG)(D3D11_CREATE_DEVICE_DEBUG|D3D11_CREATE_DEVICE_SINGLETHREADED); const D3D11_CREATE_DEVICE_FLAG device_flags = (D3D11_CREATE_DEVICE_FLAG)(D3D11_CREATE_DEVICE_DEBUG
| D3D11_CREATE_DEVICE_SINGLETHREADED);
#else #else
D3D11_CREATE_DEVICE_FLAG device_flags = D3D11_CREATE_DEVICE_SINGLETHREADED; const D3D11_CREATE_DEVICE_FLAG device_flags = D3D11_CREATE_DEVICE_SINGLETHREADED;
#endif #endif
hr = PD3D11CreateDeviceAndSwapChain(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, device_flags,
supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS, SharedPtr<ID3D11Device> device;
D3D11_SDK_VERSION, &swap_chain_desc, &swapchain, &device, SharedPtr<IDXGISwapChain> swapchain;
&featlevel, &context); SharedPtr<ID3D11DeviceContext> context;
if (FAILED(hr) || !device || !context || !swapchain)
hr = D3D11CreateDeviceAndSwapChainShared(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, device_flags,
supported_feature_levels, NUM_SUPPORTED_FEATURE_LEVELS, D3D11_SDK_VERSION,
&swap_chain_desc, std::addressof(swapchain), std::addressof(device), &featlevel, std::addressof(context));
if (FAILED(hr) || !device || !swapchain || !context)
{ {
MessageBox(wnd, _T("Failed to initialize Direct3D.\nMake sure your video card supports at least D3D 10.0"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR); MessageBox(wnd, _T("Failed to initialize Direct3D.\nMake sure your video card supports at least D3D 10.0"),
SAFE_RELEASE(device); _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
SAFE_RELEASE(context);
SAFE_RELEASE(swapchain);
return E_FAIL; return E_FAIL;
} }
SetDebugObjectName((ID3D11DeviceChild*)context, "device context");
SetDebugObjectName(context, "device context");
SAFE_RELEASE(factory); SAFE_RELEASE(factory);
SAFE_RELEASE(output); SAFE_RELEASE(output);
SAFE_RELEASE(adapter); SAFE_RELEASE(adapter);
ID3D11Texture2D* buf; auto const buf = SwapChainGetBufferTexture2DShared(swapchain, 0);
hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf); if (!buf)
if (FAILED(hr))
{ {
MessageBox(wnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR); MessageBox(wnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
SAFE_RELEASE(device);
SAFE_RELEASE(context);
SAFE_RELEASE(swapchain);
return E_FAIL; return E_FAIL;
} }
backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
SAFE_RELEASE(buf); g_device = device;
g_context = context;
g_swapchain = swapchain;
backbuf.reset(new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET));
CHECK(backbuf!=NULL, "Create back buffer texture"); CHECK(backbuf!=NULL, "Create back buffer texture");
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetTex(), "backbuffer texture"); SetDebugObjectName(backbuf->GetTex(), "backbuffer texture");
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetRTV(), "backbuffer render target view"); SetDebugObjectName(backbuf->GetRTV(), "backbuffer render target view");
context->OMSetRenderTargets(1, &backbuf->GetRTV(), NULL); context->OMSetRenderTargets(1, &backbuf->GetRTV(), NULL);
@ -384,30 +521,22 @@ HRESULT Create(HWND wnd)
device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &format_support); device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &format_support);
bgra_textures_supported = (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0; bgra_textures_supported = (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
stateman = new StateManager; stateman.reset(new StateManager);
return S_OK; return S_OK;
} }
void Close() void Close()
{ {
// release all bound resources // release all bound resources
context->ClearState(); g_context->ClearState();
SAFE_RELEASE(backbuf); backbuf.reset();
SAFE_RELEASE(swapchain); g_swapchain.reset();
SAFE_DELETE(stateman); stateman.reset();
context->Flush(); // immediately destroy device objects g_context->Flush(); // immediately destroy device objects
SAFE_RELEASE(context); g_context.reset();
ULONG references = device->Release(); g_device.reset();
if (references)
{
ERROR_LOG(VIDEO, "Unreleased references: %i.", references);
}
else
{
NOTICE_LOG(VIDEO, "Successfully released all device references!");
}
device = NULL;
// unload DLLs // unload DLLs
UnloadD3DX(); UnloadD3DX();
@ -436,7 +565,7 @@ const char* PixelShaderVersionString()
else /*if(featlevel == D3D_FEATURE_LEVEL_10_0)*/ return "ps_4_0"; else /*if(featlevel == D3D_FEATURE_LEVEL_10_0)*/ return "ps_4_0";
} }
D3DTexture2D* &GetBackBuffer() { return backbuf; } D3DTexture2D* GetBackBuffer() { return backbuf.get(); }
unsigned int GetBackBufferWidth() { return xres; } unsigned int GetBackBufferWidth() { return xres; }
unsigned int GetBackBufferHeight() { return yres; } unsigned int GetBackBufferHeight() { return yres; }
@ -469,31 +598,27 @@ unsigned int GetMaxTextureSize()
void Reset() void Reset()
{ {
// release all back buffer references // release all back buffer references
SAFE_RELEASE(backbuf); backbuf.reset();
// resize swapchain buffers // resize swapchain buffers
RECT client; RECT client;
GetClientRect(hWnd, &client); GetClientRect(hWnd, &client);
xres = client.right - client.left; xres = client.right - client.left;
yres = client.bottom - client.top; yres = client.bottom - client.top;
D3D::swapchain->ResizeBuffers(1, xres, yres, DXGI_FORMAT_R8G8B8A8_UNORM, 0); D3D::g_swapchain->ResizeBuffers(1, xres, yres, DXGI_FORMAT_R8G8B8A8_UNORM, 0);
// recreate back buffer texture // recreate back buffer texture
ID3D11Texture2D* buf; auto const buf = SwapChainGetBufferTexture2DShared(g_swapchain, 0);
HRESULT hr = swapchain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&buf); if (!buf)
if (FAILED(hr))
{ {
MessageBox(hWnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR); MessageBox(hWnd, _T("Failed to get swapchain buffer"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR);
SAFE_RELEASE(device);
SAFE_RELEASE(context);
SAFE_RELEASE(swapchain);
return; return;
} }
backbuf = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
SAFE_RELEASE(buf); backbuf.reset(new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET));
CHECK(backbuf!=NULL, "Create back buffer texture"); CHECK(backbuf!=NULL, "Create back buffer texture");
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetTex(), "backbuffer texture"); SetDebugObjectName(backbuf->GetTex(), "backbuffer texture");
SetDebugObjectName((ID3D11DeviceChild*)backbuf->GetRTV(), "backbuffer render target view"); SetDebugObjectName(backbuf->GetRTV(), "backbuffer render target view");
} }
bool BeginFrame() bool BeginFrame()
@ -503,8 +628,9 @@ bool BeginFrame()
PanicAlert("BeginFrame called although a frame is already in progress"); PanicAlert("BeginFrame called although a frame is already in progress");
return false; return false;
} }
bFrameInProgress = true; bFrameInProgress = true;
return (device != NULL); return (g_device != NULL);
} }
void EndFrame() void EndFrame()
@ -520,7 +646,7 @@ void EndFrame()
void Present() void Present()
{ {
// TODO: Is 1 the correct value for vsyncing? // TODO: Is 1 the correct value for vsyncing?
swapchain->Present((UINT)g_ActiveConfig.bVSync, 0); g_swapchain->Present((UINT)g_ActiveConfig.bVSync, 0);
} }
} // namespace D3D } // namespace D3D

View file

@ -17,21 +17,35 @@
#pragma once #pragma once
#include <vector>
#include <D3DX11.h> #include <D3DX11.h>
#include <D3Dcompiler.h> #include <D3Dcompiler.h>
#include "D3DUtil.h"
#include "Common.h" #include "Common.h"
#include <vector>
namespace DX11 namespace DX11
{ {
#define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; } #define SAFE_RELEASE(x) { if (x) (x)->Release(); (x) = NULL; }
#define SAFE_DELETE(x) { delete (x); (x) = NULL; }
#define SAFE_DELETE_ARRAY(x) { delete[] (x); (x) = NULL; } #define CHECK(cond, Message, ...) if (!(cond)) { \
#define CHECK(cond, Message, ...) if (!(cond)) { PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); } PanicAlert(__FUNCTION__ "Failed in %s at line %d: " Message, __FILE__, __LINE__, __VA_ARGS__); }
class D3DTexture2D; class D3DTexture2D;
SharedPtr<ID3D11Texture2D> CreateTexture2DShared(
const D3D11_TEXTURE2D_DESC* pDesc, const D3D11_SUBRESOURCE_DATA* pInitialData);
SharedPtr<ID3D11BlendState> CreateBlendStateShared(const D3D11_BLEND_DESC *pBlendStateDesc);
SharedPtr<ID3D11InputLayout> CreateInputLayoutShared(const D3D11_INPUT_ELEMENT_DESC *pInputElementDescs,
UINT NumElements, const void *pShaderBytecodeWithInputSignature, SIZE_T BytecodeLength);
SharedPtr<ID3D11Buffer> CreateBufferShared(const D3D11_BUFFER_DESC *pDesc,
const D3D11_SUBRESOURCE_DATA *pInitialData);
namespace D3D namespace D3D
{ {
@ -44,15 +58,16 @@ void UnloadD3D();
void UnloadD3DX(); void UnloadD3DX();
void UnloadD3DCompiler(); void UnloadD3DCompiler();
void EnumAAModes(IDXGIAdapter* adapter, std::vector<DXGI_SAMPLE_DESC>& aa_modes); std::vector<DXGI_SAMPLE_DESC> EnumAAModes(IDXGIAdapter* adapter);
DXGI_SAMPLE_DESC GetAAMode(int index); DXGI_SAMPLE_DESC GetAAMode(int index);
HRESULT Create(HWND wnd); HRESULT Create(HWND wnd);
void Close(); void Close();
extern ID3D11Device* device; extern SharedPtr<ID3D11Device> g_device;
extern ID3D11DeviceContext* context; extern SharedPtr<ID3D11DeviceContext> g_context;
extern IDXGISwapChain* swapchain; extern SharedPtr<IDXGISwapChain> g_swapchain;
extern bool bFrameInProgress; extern bool bFrameInProgress;
void Reset(); void Reset();
@ -62,7 +77,7 @@ void Present();
unsigned int GetBackBufferWidth(); unsigned int GetBackBufferWidth();
unsigned int GetBackBufferHeight(); unsigned int GetBackBufferHeight();
D3DTexture2D* &GetBackBuffer(); D3DTexture2D* GetBackBuffer();
const char* PixelShaderVersionString(); const char* PixelShaderVersionString();
const char* GeometryShaderVersionString(); const char* GeometryShaderVersionString();
const char* VertexShaderVersionString(); const char* VertexShaderVersionString();
@ -73,10 +88,14 @@ unsigned int GetMaxTextureSize();
// Ihis function will assign a name to the given resource. // Ihis function will assign a name to the given resource.
// The DirectX debug layer will make it easier to identify resources that way, // The DirectX debug layer will make it easier to identify resources that way,
// e.g. when listing up all resources who have unreleased references. // e.g. when listing up all resources who have unreleased references.
inline void SetDebugObjectName(ID3D11DeviceChild* resource, const char* name) template <typename T>
void SetDebugObjectName(T resource, const char* name)
{ {
static_assert(std::is_convertible<T, ID3D11DeviceChild*>::value,
"resource must be convertible to ID3D11DeviceChild*");
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
resource->SetPrivateData( WKPDID_D3DDebugObjectName, (UINT)strlen(name), name); resource->SetPrivateData(WKPDID_D3DDebugObjectName, (UINT)strlen(name), name);
#endif #endif
} }
@ -108,6 +127,8 @@ typedef HRESULT (WINAPI* CREATEDXGIFACTORY)(REFIID, void**);
extern CREATEDXGIFACTORY PCreateDXGIFactory; extern CREATEDXGIFACTORY PCreateDXGIFactory;
typedef HRESULT (WINAPI* D3D11CREATEDEVICE)(IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL*, UINT, UINT, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext**); typedef HRESULT (WINAPI* D3D11CREATEDEVICE)(IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL*, UINT, UINT, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext**);
extern D3D11CREATEDEVICE PD3D11CreateDevice; extern D3D11CREATEDEVICE PD3D11CreateDevice;
typedef HRESULT (WINAPI* D3D10CREATEBLOB)(SIZE_T NumBytes, LPD3D10BLOB *ppBuffer);
extern D3D10CREATEBLOB PD3D10CreateBlob;
typedef HRESULT (WINAPI *D3DREFLECT)(LPCVOID, SIZE_T, REFIID, void**); typedef HRESULT (WINAPI *D3DREFLECT)(LPCVOID, SIZE_T, REFIID, void**);
extern D3DREFLECT PD3DReflect; extern D3DREFLECT PD3DReflect;

View file

@ -1,69 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <d3d11.h>
#include "D3DBlob.h"
namespace DX11
{
D3DBlob::D3DBlob(unsigned int blob_size, const u8* init_data) : ref(1), size(blob_size), blob(NULL)
{
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()
{
return size;
}
u8* D3DBlob::Data()
{
return data;
}
} // namespace DX11

View file

@ -1,53 +0,0 @@
// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#pragma once
#include "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 = NULL);
// d3dblob will be AddRef'd
D3DBlob(ID3D10Blob* d3dblob);
void AddRef();
unsigned int Release();
unsigned int Size();
u8* Data();
private:
~D3DBlob();
unsigned int ref;
unsigned int size;
u8* data;
ID3D10Blob* blob;
};
} // namespace

View file

@ -19,7 +19,6 @@
#include "VideoConfig.h" #include "VideoConfig.h"
#include "D3DBase.h"
#include "D3DShader.h" #include "D3DShader.h"
namespace DX11 namespace DX11
@ -29,211 +28,149 @@ namespace D3D
{ {
// bytecode->shader // bytecode->shader
ID3D11VertexShader* CreateVertexShaderFromByteCode(const void* bytecode, unsigned int len) SharedPtr<ID3D11VertexShader> CreateVertexShaderFromByteCode(const void* bytecode, unsigned int len)
{ {
ID3D11VertexShader* v_shader; ID3D11VertexShader* v_shader = nullptr;
HRESULT hr = D3D::device->CreateVertexShader(bytecode, len, NULL, &v_shader); HRESULT hr = D3D::g_device->CreateVertexShader(bytecode, len, NULL, &v_shader);
if (FAILED(hr)) if (FAILED(hr))
{ PanicAlert("CreateVertexShaderFromByteCode failed from %p (size %d) at %s %d\n",
PanicAlert("CreateVertexShaderFromByteCode failed from %p (size %d) at %s %d\n", bytecode, len, __FILE__, __LINE__); bytecode, len, __FILE__, __LINE__);
v_shader = NULL;
}
return v_shader;
}
// code->bytecode return SharedPtr<ID3D11VertexShader>::FromPtr(v_shader);
bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob)
{
ID3D10Blob* shaderBuffer = NULL;
ID3D10Blob* errorBuffer = NULL;
#if defined(_DEBUG) || defined(DEBUGFAST)
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS;
#else
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_OPTIMIZATION_LEVEL3|D3D10_SHADER_SKIP_VALIDATION;
#endif
HRESULT hr = PD3DX11CompileFromMemory(code, len, NULL, NULL, NULL, "main", D3D::VertexShaderVersionString(),
flags, 0, NULL, &shaderBuffer, &errorBuffer, NULL);
if (errorBuffer)
{
INFO_LOG(VIDEO, "Vertex shader compiler messages:\n%s\n",
(const char*)errorBuffer->GetBufferPointer());
}
if (FAILED(hr))
{
if (g_ActiveConfig.bShowShaderErrors)
{
std::string msg = (char*)errorBuffer->GetBufferPointer();
msg += "\n\n";
msg += code;
MessageBoxA(0, msg.c_str(), "Error compiling vertex shader", MB_ICONERROR);
}
*blob = NULL;
errorBuffer->Release();
}
else
{
*blob = new D3DBlob(shaderBuffer);
shaderBuffer->Release();
}
return SUCCEEDED(hr);
} }
// bytecode->shader // bytecode->shader
ID3D11GeometryShader* CreateGeometryShaderFromByteCode(const void* bytecode, unsigned int len) SharedPtr<ID3D11GeometryShader> CreateGeometryShaderFromByteCode(const void* bytecode, unsigned int len)
{ {
ID3D11GeometryShader* g_shader; ID3D11GeometryShader* g_shader = nullptr;
HRESULT hr = D3D::device->CreateGeometryShader(bytecode, len, NULL, &g_shader); HRESULT hr = D3D::g_device->CreateGeometryShader(bytecode, len, NULL, &g_shader);
if (FAILED(hr)) if (FAILED(hr))
{ PanicAlert("CreateGeometryShaderFromByteCode failed from %p (size %d) at %s %d\n",
PanicAlert("CreateGeometryShaderFromByteCode failed from %p (size %d) at %s %d\n", bytecode, len, __FILE__, __LINE__); bytecode, len, __FILE__, __LINE__);
g_shader = NULL;
}
return g_shader;
}
// code->bytecode return SharedPtr<ID3D11GeometryShader>::FromPtr(g_shader);
bool CompileGeometryShader(const char* code, unsigned int len, D3DBlob** blob,
const D3D_SHADER_MACRO* pDefines)
{
ID3D10Blob* shaderBuffer = NULL;
ID3D10Blob* errorBuffer = NULL;
#if defined(_DEBUG) || defined(DEBUGFAST)
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS;
#else
UINT flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY|D3D10_SHADER_OPTIMIZATION_LEVEL3|D3D10_SHADER_SKIP_VALIDATION;
#endif
HRESULT hr = PD3DX11CompileFromMemory(code, len, NULL, pDefines, NULL, "main", D3D::GeometryShaderVersionString(),
flags, 0, NULL, &shaderBuffer, &errorBuffer, NULL);
if (errorBuffer)
{
INFO_LOG(VIDEO, "Geometry shader compiler messages:\n%s\n",
(const char*)errorBuffer->GetBufferPointer());
}
if (FAILED(hr))
{
if (g_ActiveConfig.bShowShaderErrors)
{
std::string msg = (char*)errorBuffer->GetBufferPointer();
msg += "\n\n";
msg += code;
MessageBoxA(0, msg.c_str(), "Error compiling geometry shader", MB_ICONERROR);
}
*blob = NULL;
errorBuffer->Release();
}
else
{
*blob = new D3DBlob(shaderBuffer);
shaderBuffer->Release();
}
return SUCCEEDED(hr);
} }
// bytecode->shader // bytecode->shader
ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, unsigned int len) SharedPtr<ID3D11PixelShader> CreatePixelShaderFromByteCode(const void* bytecode, unsigned int len)
{ {
ID3D11PixelShader* p_shader; ID3D11PixelShader* p_shader = nullptr;
HRESULT hr = D3D::device->CreatePixelShader(bytecode, len, NULL, &p_shader); HRESULT hr = D3D::g_device->CreatePixelShader(bytecode, len, NULL, &p_shader);
if (FAILED(hr)) if (FAILED(hr))
{
PanicAlert("CreatePixelShaderFromByteCode failed at %s %d\n", __FILE__, __LINE__); PanicAlert("CreatePixelShaderFromByteCode failed at %s %d\n", __FILE__, __LINE__);
p_shader = NULL;
return SharedPtr<ID3D11PixelShader>::FromPtr(p_shader);
}
static SharedPtr<ID3D10Blob> CompileShader(const char* code, unsigned int len,
const char* ver_str, const D3D_SHADER_MACRO* pDefines = NULL)
{
static const UINT shader_compilation_flags = D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY
#if defined(_DEBUG) || defined(DEBUGFAST)
| D3D10_SHADER_DEBUG | D3D10_SHADER_WARNINGS_ARE_ERRORS;
#else
| D3D10_SHADER_OPTIMIZATION_LEVEL3 | D3D10_SHADER_SKIP_VALIDATION;
#endif
ID3D10Blob* shaderBuffer = nullptr;
ID3D10Blob* errorBuffer = nullptr;
HRESULT hr = PD3DX11CompileFromMemory(code, len, NULL, pDefines, NULL, "main", ver_str,
shader_compilation_flags, 0, NULL, &shaderBuffer, &errorBuffer, NULL);
if (FAILED(hr) && g_ActiveConfig.bShowShaderErrors)
{
std::string msg = (const char*)errorBuffer->GetBufferPointer();
msg += "\n\n";
msg += ver_str;
msg += "\n\n";
msg += code;
MessageBoxA(0, msg.c_str(), "Error compiling shader", MB_ICONERROR);
} }
return p_shader;
if (errorBuffer)
{
INFO_LOG(VIDEO, "Shader %s compiler messages:\n%s\n", ver_str,
(const char*)errorBuffer->GetBufferPointer());
errorBuffer->Release();
}
return SharedPtr<ID3D10Blob>::FromPtr(shaderBuffer);
} }
// code->bytecode // code->bytecode
bool CompilePixelShader(const char* code, unsigned int len, D3DBlob** blob, SharedPtr<ID3D10Blob> CompileVertexShader(const char* code, unsigned int len)
{
return CompileShader(code, len, D3D::VertexShaderVersionString());
}
// code->bytecode
SharedPtr<ID3D10Blob> CompileGeometryShader(const char* code, unsigned int len,
const D3D_SHADER_MACRO* pDefines) const D3D_SHADER_MACRO* pDefines)
{ {
ID3D10Blob* shaderBuffer = NULL; return CompileShader(code, len, D3D::GeometryShaderVersionString());
ID3D10Blob* errorBuffer = NULL;
#if defined(_DEBUG) || defined(DEBUGFAST)
UINT flags = D3D10_SHADER_DEBUG|D3D10_SHADER_WARNINGS_ARE_ERRORS;
#else
UINT flags = D3D10_SHADER_OPTIMIZATION_LEVEL3;
#endif
HRESULT hr = PD3DX11CompileFromMemory(code, len, NULL, pDefines, NULL, "main", D3D::PixelShaderVersionString(),
flags, 0, NULL, &shaderBuffer, &errorBuffer, NULL);
if (errorBuffer)
{
INFO_LOG(VIDEO, "Pixel shader compiler messages:\n%s",
(const char*)errorBuffer->GetBufferPointer());
}
if (FAILED(hr))
{
if (g_ActiveConfig.bShowShaderErrors)
{
std::string msg = (char*)errorBuffer->GetBufferPointer();
msg += "\n\n";
msg += code;
MessageBoxA(0, msg.c_str(), "Error compiling pixel shader", MB_ICONERROR);
}
*blob = NULL;
errorBuffer->Release();
}
else
{
*blob = new D3DBlob(shaderBuffer);
shaderBuffer->Release();
}
return SUCCEEDED(hr);
} }
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, // code->bytecode
unsigned int len) SharedPtr<ID3D10Blob> CompilePixelShader(const char* code, unsigned int len,
const D3D_SHADER_MACRO* pDefines)
{ {
D3DBlob* blob = NULL; return CompileShader(code, len, D3D::PixelShaderVersionString(), pDefines);
if (CompileVertexShader(code, len, &blob))
{
ID3D11VertexShader* v_shader = CreateVertexShaderFromByteCode(blob);
blob->Release();
return v_shader;
}
PanicAlert("Failed to compile and create vertex shader from %p (size %d) at %s %d\n", code, len, __FILE__, __LINE__);
return NULL;
} }
ID3D11GeometryShader* CompileAndCreateGeometryShader(const char* code, SharedPtr<ID3D11VertexShader> CompileAndCreateVertexShader(const char* code, unsigned int len,
unsigned int len, const D3D_SHADER_MACRO* pDefines) SharedPtr<ID3D10Blob>* bytecode)
{ {
D3DBlob* blob = NULL; auto const blob = CompileVertexShader(code, len);
if (CompileGeometryShader(code, len, &blob, pDefines))
{
ID3D11GeometryShader* g_shader = CreateGeometryShaderFromByteCode(blob);
blob->Release();
return g_shader;
}
PanicAlert("Failed to compile and create geometry shader from %p (size %d) at %s %d\n", code, len, __FILE__, __LINE__);
return NULL;
}
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code,
unsigned int len)
{
D3DBlob* blob = NULL;
CompilePixelShader(code, len, &blob);
if (blob) if (blob)
{ {
ID3D11PixelShader* p_shader = CreatePixelShaderFromByteCode(blob); if (bytecode)
blob->Release(); *bytecode = blob;
return p_shader; return CreateVertexShaderFromByteCode(blob->GetBufferPointer(), (unsigned int)blob->GetBufferSize());
}
else
{
PanicAlert("Failed to compile and create vertex shader from %p (size %d) at %s %d\n",
code, len, __FILE__, __LINE__);
return SharedPtr<ID3D11VertexShader>::FromPtr(nullptr);
}
}
SharedPtr<ID3D11GeometryShader> CompileAndCreateGeometryShader(const char* code, unsigned int len,
const D3D_SHADER_MACRO* pDefines, SharedPtr<ID3D10Blob>* bytecode)
{
auto const blob = CompileGeometryShader(code, len, pDefines);
if (blob)
{
if (bytecode)
*bytecode = blob;
return CreateGeometryShaderFromByteCode(blob->GetBufferPointer(), (unsigned int)blob->GetBufferSize());
}
else
{
PanicAlert("Failed to compile and create geometry shader from %p (size %d) at %s %d\n",
code, len, __FILE__, __LINE__);
return SharedPtr<ID3D11GeometryShader>::FromPtr(nullptr);
}
}
SharedPtr<ID3D11PixelShader> CompileAndCreatePixelShader(const char* code, unsigned int len,
const D3D_SHADER_MACRO* pDefines, SharedPtr<ID3D10Blob>* bytecode)
{
auto const blob = CompilePixelShader(code, len, pDefines);
if (blob)
{
if (bytecode)
*bytecode = blob;
return CreatePixelShaderFromByteCode(blob->GetBufferPointer(), (unsigned int)blob->GetBufferSize());
}
else
{
PanicAlert("Failed to compile and create pixel shader, %s %d\n", __FILE__, __LINE__);
return SharedPtr<ID3D11PixelShader>::FromPtr(nullptr);
} }
PanicAlert("Failed to compile and create pixel shader, %s %d\n", __FILE__, __LINE__);
return NULL;
} }
} // namespace } // namespace

View file

@ -18,49 +18,47 @@
#pragma once #pragma once
#include "D3DBase.h" #include "D3DBase.h"
#include "D3DBlob.h"
struct ID3D11PixelShader;
struct ID3D11VertexShader;
namespace DX11 namespace DX11
{ {
namespace D3D namespace D3D
{ {
ID3D11VertexShader* CreateVertexShaderFromByteCode(const void* bytecode, unsigned int len);
ID3D11GeometryShader* CreateGeometryShaderFromByteCode(const void* bytecode, unsigned int len);
ID3D11PixelShader* CreatePixelShaderFromByteCode(const void* bytecode, unsigned int len);
// The returned bytecode buffers should be Release()d. // returns bytecode
bool CompileVertexShader(const char* code, unsigned int len, SharedPtr<ID3D10Blob> CompileVertexShader(const char* code, unsigned int len);
D3DBlob** blob); SharedPtr<ID3D10Blob> CompileGeometryShader(const char* code, unsigned int len,
bool CompileGeometryShader(const char* code, unsigned int len, const D3D_SHADER_MACRO* pDefines = NULL);
D3DBlob** blob, const D3D_SHADER_MACRO* pDefines = NULL); SharedPtr<ID3D10Blob> CompilePixelShader(const char* code, unsigned int len,
bool CompilePixelShader(const char* code, unsigned int len, const D3D_SHADER_MACRO* pDefines = NULL);
D3DBlob** blob, const D3D_SHADER_MACRO* pDefines = NULL);
// Utility functions SharedPtr<ID3D11VertexShader> CreateVertexShaderFromByteCode(const void* bytecode, unsigned int len);
ID3D11VertexShader* CompileAndCreateVertexShader(const char* code, SharedPtr<ID3D11GeometryShader> CreateGeometryShaderFromByteCode(const void* bytecode, unsigned int len);
unsigned int len); SharedPtr<ID3D11PixelShader> CreatePixelShaderFromByteCode(const void* bytecode, unsigned int len);
ID3D11GeometryShader* CompileAndCreateGeometryShader(const char* code,
unsigned int len, const D3D_SHADER_MACRO* pDefines = NULL);
ID3D11PixelShader* CompileAndCreatePixelShader(const char* code,
unsigned int len);
inline ID3D11VertexShader* CreateVertexShaderFromByteCode(D3DBlob* bytecode) inline SharedPtr<ID3D11VertexShader> CreateVertexShaderFromByteCode(SharedPtr<ID3D10Blob> bytecode)
{ return CreateVertexShaderFromByteCode(bytecode->Data(), bytecode->Size()); } {
inline ID3D11GeometryShader* CreateGeometryShaderFromByteCode(D3DBlob* bytecode) return CreateVertexShaderFromByteCode(bytecode->GetBufferPointer(), (unsigned int)bytecode->GetBufferSize());
{ return CreateGeometryShaderFromByteCode(bytecode->Data(), bytecode->Size()); } }
inline ID3D11PixelShader* CreatePixelShaderFromByteCode(D3DBlob* bytecode)
{ return CreatePixelShaderFromByteCode(bytecode->Data(), bytecode->Size()); } inline SharedPtr<ID3D11GeometryShader> CreateGeometryShaderFromByteCode(SharedPtr<ID3D10Blob> bytecode)
{
return CreateGeometryShaderFromByteCode(bytecode->GetBufferPointer(), (unsigned int)bytecode->GetBufferSize());
}
inline SharedPtr<ID3D11PixelShader> CreatePixelShaderFromByteCode(SharedPtr<ID3D10Blob> bytecode)
{
return CreatePixelShaderFromByteCode(bytecode->GetBufferPointer(), (unsigned int)bytecode->GetBufferSize());
}
// Utility functions, optionally return the bytecode if "bytecode" is non-null
SharedPtr<ID3D11VertexShader> CompileAndCreateVertexShader(const char* code, unsigned int len,
SharedPtr<ID3D10Blob>* bytecode = nullptr);
SharedPtr<ID3D11GeometryShader> CompileAndCreateGeometryShader(const char* code, unsigned int len,
const D3D_SHADER_MACRO* pDefines = nullptr, SharedPtr<ID3D10Blob>* bytecode = nullptr);
SharedPtr<ID3D11PixelShader> CompileAndCreatePixelShader(const char* code, unsigned int len,
const D3D_SHADER_MACRO* pDefines = nullptr, SharedPtr<ID3D10Blob>* bytecode = nullptr);
inline ID3D11VertexShader* CompileAndCreateVertexShader(D3DBlob* code)
{ return CompileAndCreateVertexShader((const char*)code->Data(), code->Size()); }
inline ID3D11GeometryShader* CompileAndCreateGeometryShader(D3DBlob* code, const D3D_SHADER_MACRO* pDefines = NULL)
{ return CompileAndCreateGeometryShader((const char*)code->Data(), code->Size(), pDefines); }
inline ID3D11PixelShader* CompileAndCreatePixelShader(D3DBlob* code)
{ return CompileAndCreatePixelShader((const char*)code->Data(), code->Size()); }
} }
} // namespace DX11 } // namespace DX11

View file

@ -29,7 +29,7 @@ void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned
if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING) if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING)
{ {
D3D11_MAPPED_SUBRESOURCE map; D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(pTexture, level, D3D11_MAP_WRITE_DISCARD, 0, &map); D3D::g_context->Map(pTexture, level, D3D11_MAP_WRITE_DISCARD, 0, &map);
if (4 * pitch == map.RowPitch) if (4 * pitch == map.RowPitch)
{ {
memcpy(map.pData, buffer, map.RowPitch * height); memcpy(map.pData, buffer, map.RowPitch * height);
@ -39,63 +39,43 @@ void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned
for (unsigned int y = 0; y < height; ++y) for (unsigned int y = 0; y < height; ++y)
memcpy((u8*)map.pData + y * map.RowPitch, (u32*)buffer + y * pitch, 4 * pitch); memcpy((u8*)map.pData + y * map.RowPitch, (u32*)buffer + y * pitch, 4 * pitch);
} }
D3D::context->Unmap(pTexture, level); D3D::g_context->Unmap(pTexture, level);
} }
else else
{ {
D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1); D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1);
D3D::context->UpdateSubresource(pTexture, level, &dest_region, buffer, 4*pitch, 4*pitch*height); D3D::g_context->UpdateSubresource(pTexture, level, &dest_region, buffer, 4*pitch, 4*pitch*height);
} }
} }
} // namespace } // namespace
D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels) std::unique_ptr<D3DTexture2D> D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind,
D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels)
{ {
ID3D11Texture2D* pTexture = NULL;
HRESULT hr;
D3D11_CPU_ACCESS_FLAG cpuflags; 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); if (usage == D3D11_USAGE_STAGING)
else if (usage == D3D11_USAGE_DYNAMIC) cpuflags = D3D11_CPU_ACCESS_WRITE; cpuflags = (D3D11_CPU_ACCESS_FLAG)(D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ);
else cpuflags = (D3D11_CPU_ACCESS_FLAG)0; else if (usage == D3D11_USAGE_DYNAMIC)
D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(fmt, width, height, 1, levels, bind, usage, cpuflags); cpuflags = D3D11_CPU_ACCESS_WRITE;
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &pTexture); else
if (FAILED(hr)) cpuflags = (D3D11_CPU_ACCESS_FLAG)0;
const D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(fmt, width, height, 1, levels, bind, usage, cpuflags);
auto texture = CreateTexture2DShared(&texdesc, NULL);
if (!texture)
{ {
PanicAlert("Failed to create texture at %s, line %d: hr=%#x\n", __FILE__, __LINE__, hr); PanicAlert("Failed to create texture at %s, line %d\n", __FILE__, __LINE__);
return NULL; return NULL;
} }
D3DTexture2D* ret = new D3DTexture2D(pTexture, bind); return std::unique_ptr<D3DTexture2D>(new D3DTexture2D(texture, bind));
SAFE_RELEASE(pTexture);
return ret;
} }
void D3DTexture2D::AddRef() D3DTexture2D::D3DTexture2D(SharedPtr<ID3D11Texture2D> texptr, D3D11_BIND_FLAG bind,
{ DXGI_FORMAT srv_format, DXGI_FORMAT dsv_format, DXGI_FORMAT rtv_format, bool multisampled)
++ref; : ref(1), tex(texptr), srv(NULL), rtv(NULL), dsv(NULL)
}
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)
: ref(1), tex(texptr), srv(NULL), rtv(NULL), dsv(NULL)
{ {
D3D11_SRV_DIMENSION srv_dim = multisampled ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D; D3D11_SRV_DIMENSION srv_dim = multisampled ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
D3D11_DSV_DIMENSION dsv_dim = multisampled ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D; D3D11_DSV_DIMENSION dsv_dim = multisampled ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
@ -103,10 +83,12 @@ D3DTexture2D::D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind,
D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = CD3D11_SHADER_RESOURCE_VIEW_DESC(srv_dim, srv_format); 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_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); 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_SHADER_RESOURCE)
if (bind & D3D11_BIND_RENDER_TARGET) D3D::device->CreateRenderTargetView(tex, &rtv_desc, &rtv); D3D::g_device->CreateShaderResourceView(tex, &srv_desc, &srv);
if (bind & D3D11_BIND_DEPTH_STENCIL) D3D::device->CreateDepthStencilView(tex, &dsv_desc, &dsv); if (bind & D3D11_BIND_RENDER_TARGET)
tex->AddRef(); D3D::g_device->CreateRenderTargetView(tex, &rtv_desc, &rtv);
if (bind & D3D11_BIND_DEPTH_STENCIL)
D3D::g_device->CreateDepthStencilView(tex, &dsv_desc, &dsv);
} }
D3DTexture2D::~D3DTexture2D() D3DTexture2D::~D3DTexture2D()
@ -114,7 +96,6 @@ D3DTexture2D::~D3DTexture2D()
SAFE_RELEASE(srv); SAFE_RELEASE(srv);
SAFE_RELEASE(rtv); SAFE_RELEASE(rtv);
SAFE_RELEASE(dsv); SAFE_RELEASE(dsv);
SAFE_RELEASE(tex);
} }
} // namespace DX11 } // namespace DX11

View file

@ -34,22 +34,22 @@ public:
// either create an ID3D11Texture2D object, pass it to the constructor and specify what views to create // 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 // 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); D3DTexture2D(SharedPtr<ID3D11Texture2D> texptr, D3D11_BIND_FLAG bind,
static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1); DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN, bool multisampled = false);
// reference counting, use AddRef() when creating a new reference and Release() it when you don't need it anymore static std::unique_ptr<D3DTexture2D> Create(unsigned int width, unsigned int height,
void AddRef(); D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1);
UINT Release();
ID3D11Texture2D* &GetTex(); ID3D11Texture2D* GetTex() { return tex; }
ID3D11ShaderResourceView* &GetSRV(); ID3D11ShaderResourceView*const& GetSRV() { return srv; }
ID3D11RenderTargetView* &GetRTV(); ID3D11RenderTargetView*const& GetRTV() { return rtv; }
ID3D11DepthStencilView* &GetDSV(); ID3D11DepthStencilView*const& GetDSV() { return dsv; }
private:
~D3DTexture2D(); ~D3DTexture2D();
ID3D11Texture2D* tex; private:
SharedPtr<ID3D11Texture2D> tex;
ID3D11ShaderResourceView* srv; ID3D11ShaderResourceView* srv;
ID3D11RenderTargetView* rtv; ID3D11RenderTargetView* rtv;
ID3D11DepthStencilView* dsv; ID3D11DepthStencilView* dsv;

View file

@ -34,36 +34,35 @@ namespace D3D
class UtilVertexBuffer class UtilVertexBuffer
{ {
public: public:
UtilVertexBuffer(int size) : buf(NULL), offset(0), max_size(size) UtilVertexBuffer(UINT size)
: offset(0), max_size(size)
{ {
D3D11_BUFFER_DESC desc = CD3D11_BUFFER_DESC(max_size, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D11_BUFFER_DESC desc = CD3D11_BUFFER_DESC(max_size, D3D11_BIND_VERTEX_BUFFER,
device->CreateBuffer(&desc, NULL, &buf); D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
} m_buf = CreateBufferShared(&desc, NULL);
~UtilVertexBuffer()
{
buf->Release();
} }
// returns vertex offset to the new data // returns vertex offset to the new data
int AppendData(void* data, int size, int vertex_size) int AppendData(void* data, UINT size, UINT vertex_size)
{ {
D3D11_MAPPED_SUBRESOURCE map; D3D11_MAPPED_SUBRESOURCE map;
if(offset + size >= max_size) if (offset + size >= max_size)
{ {
// wrap buffer around and notify observers // wrap buffer around and notify observers
offset = 0; offset = 0;
context->Map(buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); g_context->Map(m_buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
for(std::list<bool*>::iterator it = observers.begin(); it != observers.end(); ++it) for each (auto obs in observers)
**it = true; *obs = true;
} }
else else
{ {
context->Map(buf, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map); g_context->Map(m_buf, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map);
} }
offset = ((offset+vertex_size-1)/vertex_size)*vertex_size; // align offset to vertex_size bytes
offset = ((offset+vertex_size - 1) / vertex_size) * vertex_size; // align offset to vertex_size bytes
memcpy((u8*)map.pData + offset, data, size); memcpy((u8*)map.pData + offset, data, size);
context->Unmap(buf, 0); g_context->Unmap(m_buf, 0);
offset += size; offset += size;
return (offset - size) / vertex_size; return (offset - size) / vertex_size;
@ -74,18 +73,18 @@ public:
observers.push_back(observer); observers.push_back(observer);
} }
inline ID3D11Buffer* &GetBuffer() { return buf; } ID3D11Buffer*const& GetBuffer() { return m_buf; }
private: private:
ID3D11Buffer* buf; SharedPtr<ID3D11Buffer> m_buf;
int offset; UINT offset;
int max_size; UINT max_size;
std::list<bool*> observers; std::list<bool*> observers;
}; };
CD3DFont font; CD3DFont font;
UtilVertexBuffer* util_vbuf = NULL; std::unique_ptr<UtilVertexBuffer> util_vbuf;
#define MAX_NUM_VERTICES 50*6 #define MAX_NUM_VERTICES 50*6
struct FONT2DVERTEX { struct FONT2DVERTEX {
@ -104,13 +103,10 @@ inline FONT2DVERTEX InitFont2DVertex(float x, float y, u32 color, float tu, floa
return v; return v;
} }
CD3DFont::CD3DFont() : m_dwTexWidth(512), m_dwTexHeight(512) CD3DFont::CD3DFont()
: m_dwTexWidth(512), m_dwTexHeight(512)
{ {
m_pTexture = NULL; m_pTexture = NULL;
m_pVB = NULL;
m_InputLayout = NULL;
m_pshader = NULL;
m_vshader = NULL;
} }
const char fontpixshader[] = { const char fontpixshader[] = {
@ -224,21 +220,20 @@ int CD3DFont::Init()
// Create a new texture for the font // Create a new texture for the font
// possible optimization: store the converted data in a buffer and fill the texture on creation. // possible optimization: store the converted data in a buffer and fill the texture on creation.
// That way, we can use a static texture // That way, we can use a static texture
ID3D11Texture2D* buftex;
D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, m_dwTexWidth, m_dwTexHeight, D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, m_dwTexWidth, m_dwTexHeight,
1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DYNAMIC, 1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
D3D11_CPU_ACCESS_WRITE);
hr = device->CreateTexture2D(&texdesc, NULL, &buftex); auto buftex = CreateTexture2DShared(&texdesc, NULL);
if (FAILED(hr)) if (!buftex)
{ {
PanicAlert("Failed to create font texture"); PanicAlert("Failed to create font texture");
return hr; return S_FALSE;
} }
D3D::SetDebugObjectName((ID3D11DeviceChild*)buftex, "texture of a CD3DFont object"); D3D::SetDebugObjectName(buftex, "texture of a CD3DFont object");
// Lock the surface and write the alpha values for the set pixels // Lock the surface and write the alpha values for the set pixels
D3D11_MAPPED_SUBRESOURCE texmap; D3D11_MAPPED_SUBRESOURCE texmap;
hr = context->Map(buftex, 0, D3D11_MAP_WRITE_DISCARD, 0, &texmap); hr = g_context->Map(buftex, 0, D3D11_MAP_WRITE_DISCARD, 0, &texmap);
if (FAILED(hr)) PanicAlert("Failed to map a texture at %s %d\n", __FILE__, __LINE__); if (FAILED(hr)) PanicAlert("Failed to map a texture at %s %d\n", __FILE__, __LINE__);
for (y = 0; y < m_dwTexHeight; y++) for (y = 0; y < m_dwTexHeight; y++)
@ -252,10 +247,12 @@ int CD3DFont::Init()
} }
// Done updating texture, so clean up used objects // Done updating texture, so clean up used objects
context->Unmap(buftex, 0); g_context->Unmap(buftex, 0);
hr = D3D::device->CreateShaderResourceView(buftex, NULL, &m_pTexture); hr = D3D::g_device->CreateShaderResourceView(buftex, NULL, &m_pTexture);
if (FAILED(hr)) PanicAlert("Failed to create shader resource view at %s %d\n", __FILE__, __LINE__); if (FAILED(hr))
SAFE_RELEASE(buftex); PanicAlert("Failed to create shader resource view at %s %d\n", __FILE__, __LINE__);
buftex.reset();
SelectObject(hDC, hOldbmBitmap); SelectObject(hDC, hOldbmBitmap);
DeleteObject(hbmBitmap); DeleteObject(hbmBitmap);
@ -265,15 +262,16 @@ int CD3DFont::Init()
// setup device objects for drawing // setup device objects for drawing
m_pshader = D3D::CompileAndCreatePixelShader(fontpixshader, sizeof(fontpixshader)); m_pshader = D3D::CompileAndCreatePixelShader(fontpixshader, sizeof(fontpixshader));
if (m_pshader == NULL) PanicAlert("Failed to create pixel shader, %s %d\n", __FILE__, __LINE__); if (!m_pshader)
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_pshader, "pixel shader of a CD3DFont object"); PanicAlert("Failed to create pixel shader, %s %d\n", __FILE__, __LINE__);
D3D::SetDebugObjectName(m_pshader, "pixel shader of a CD3DFont object");
D3DBlob* vsbytecode; SharedPtr<ID3D10Blob> vsbytecode;
D3D::CompileVertexShader(fontvertshader, sizeof(fontvertshader), &vsbytecode); m_vshader = D3D::CompileAndCreateVertexShader(fontvertshader, sizeof(fontvertshader), std::addressof(vsbytecode));
if (vsbytecode == NULL) PanicAlert("Failed to compile vertex shader, %s %d\n", __FILE__, __LINE__);
m_vshader = D3D::CreateVertexShaderFromByteCode(vsbytecode); if (!m_vshader)
if (m_vshader == NULL) PanicAlert("Failed to create vertex shader, %s %d\n", __FILE__, __LINE__); PanicAlert("Failed to compile/create vertex shader, %s %d\n", __FILE__, __LINE__);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_vshader, "vertex shader of a CD3DFont object"); D3D::SetDebugObjectName(m_vshader, "vertex shader of a CD3DFont object");
const D3D11_INPUT_ELEMENT_DESC desc[] = const D3D11_INPUT_ELEMENT_DESC desc[] =
{ {
@ -281,9 +279,11 @@ int CD3DFont::Init()
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 },
}; };
hr = D3D::device->CreateInputLayout(desc, 3, vsbytecode->Data(), vsbytecode->Size(), &m_InputLayout);
if (FAILED(hr)) PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__); m_InputLayout = CreateInputLayoutShared(desc, 3, vsbytecode->GetBufferPointer(),
SAFE_RELEASE(vsbytecode); vsbytecode->GetBufferSize());
if (!m_InputLayout)
PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__);
D3D11_BLEND_DESC blenddesc; D3D11_BLEND_DESC blenddesc;
blenddesc.AlphaToCoverageEnable = FALSE; blenddesc.AlphaToCoverageEnable = FALSE;
@ -296,34 +296,37 @@ int CD3DFont::Init()
blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
hr = D3D::device->CreateBlendState(&blenddesc, &m_blendstate); m_blendstate = CreateBlendStateShared(&blenddesc);
CHECK(hr==S_OK, "Create font blend state"); CHECK(m_blendstate, "Create font blend state");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_blendstate, "blend state of a CD3DFont object"); D3D::SetDebugObjectName(m_blendstate, "blend state of a CD3DFont object");
D3D11_RASTERIZER_DESC rastdesc = CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID, D3D11_CULL_NONE, false, 0, 0.f, 0.f, false, false, false, false); D3D11_RASTERIZER_DESC rastdesc = CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID, D3D11_CULL_NONE,
hr = D3D::device->CreateRasterizerState(&rastdesc, &m_raststate); false, 0, 0.f, 0.f, false, false, false, false);
hr = D3D::g_device->CreateRasterizerState(&rastdesc, &m_raststate);
CHECK(hr==S_OK, "Create font rasterizer state"); CHECK(hr==S_OK, "Create font rasterizer state");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_raststate, "rasterizer state of a CD3DFont object"); D3D::SetDebugObjectName(m_raststate, "rasterizer state of a CD3DFont object");
D3D11_BUFFER_DESC vbdesc = CD3D11_BUFFER_DESC(MAX_NUM_VERTICES*sizeof(FONT2DVERTEX), D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D11_BUFFER_DESC vbdesc = CD3D11_BUFFER_DESC(MAX_NUM_VERTICES * sizeof(FONT2DVERTEX),
if (FAILED(hr = device->CreateBuffer(&vbdesc, NULL, &m_pVB))) D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
m_pVB = CreateBufferShared(&vbdesc, NULL);
if (!m_pVB)
{ {
PanicAlert("Failed to create font vertex buffer at %s, line %d\n", __FILE__, __LINE__); PanicAlert("Failed to create font vertex buffer at %s, line %d\n", __FILE__, __LINE__);
return hr; return hr;
} }
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_pVB, "vertex buffer of a CD3DFont object"); D3D::SetDebugObjectName(m_pVB, "vertex buffer of a CD3DFont object");
return S_OK; return S_OK;
} }
int CD3DFont::Shutdown() int CD3DFont::Shutdown()
{ {
SAFE_RELEASE(m_pVB); m_pVB.reset();
SAFE_RELEASE(m_pTexture); SAFE_RELEASE(m_pTexture);
SAFE_RELEASE(m_InputLayout); m_InputLayout.reset();
SAFE_RELEASE(m_pshader); m_pshader.reset();
SAFE_RELEASE(m_vshader); m_vshader.reset();
SAFE_RELEASE(m_blendstate); m_blendstate.reset();
SAFE_RELEASE(m_raststate); SAFE_RELEASE(m_raststate);
return S_OK; return S_OK;
@ -351,7 +354,7 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw
int dwNumTriangles = 0L; int dwNumTriangles = 0L;
D3D11_MAPPED_SUBRESOURCE vbmap; D3D11_MAPPED_SUBRESOURCE vbmap;
HRESULT hr = context->Map(m_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vbmap); HRESULT hr = g_context->Map(m_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vbmap);
if (FAILED(hr)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__, __LINE__); if (FAILED(hr)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__, __LINE__);
pVertices = (D3D::FONT2DVERTEX*)vbmap.pData; pVertices = (D3D::FONT2DVERTEX*)vbmap.pData;
@ -360,12 +363,12 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw
D3D::stateman->PushRasterizerState(m_raststate); D3D::stateman->PushRasterizerState(m_raststate);
D3D::stateman->Apply(); D3D::stateman->Apply();
D3D::context->PSSetShader(m_pshader, NULL, 0); D3D::g_context->PSSetShader(m_pshader, NULL, 0);
D3D::context->VSSetShader(m_vshader, NULL, 0); D3D::g_context->VSSetShader(m_vshader, NULL, 0);
D3D::context->IASetInputLayout(m_InputLayout); D3D::g_context->IASetInputLayout(m_InputLayout);
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D::g_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
D3D::context->PSSetShaderResources(0, 1, &m_pTexture); D3D::g_context->PSSetShaderResources(0, 1, &m_pTexture);
float fStartX = sx; float fStartX = sx;
while (c = *strText++) while (c = *strText++)
@ -402,14 +405,14 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw
if (dwNumTriangles * 3 > (MAX_NUM_VERTICES - 6)) if (dwNumTriangles * 3 > (MAX_NUM_VERTICES - 6))
{ {
context->Unmap(m_pVB, 0); g_context->Unmap(m_pVB, 0);
D3D::context->IASetVertexBuffers(0, 1, &m_pVB, &stride, &bufoffset); D3D::g_context->IASetVertexBuffers(0, 1, &m_pVB, &stride, &bufoffset);
D3D::context->Draw(3 * dwNumTriangles, 0); D3D::g_context->Draw(3 * dwNumTriangles, 0);
dwNumTriangles = 0; dwNumTriangles = 0;
D3D11_MAPPED_SUBRESOURCE vbmap; D3D11_MAPPED_SUBRESOURCE vbmap;
hr = context->Map(m_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vbmap); hr = g_context->Map(m_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vbmap);
if (FAILED(hr)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__, __LINE__); if (FAILED(hr)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__, __LINE__);
pVertices = (D3D::FONT2DVERTEX*)vbmap.pData; pVertices = (D3D::FONT2DVERTEX*)vbmap.pData;
} }
@ -417,11 +420,11 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw
} }
// Unlock and render the vertex buffer // Unlock and render the vertex buffer
context->Unmap(m_pVB, 0); g_context->Unmap(m_pVB, 0);
if (dwNumTriangles > 0) if (dwNumTriangles > 0)
{ {
D3D::context->IASetVertexBuffers(0, 1, &m_pVB, &stride, &bufoffset); D3D::g_context->IASetVertexBuffers(0, 1, &m_pVB, &stride, &bufoffset);
D3D::context->Draw(3 * dwNumTriangles, 0); D3D::g_context->Draw(3 * dwNumTriangles, 0);
} }
D3D::stateman->PopBlendState(); D3D::stateman->PopBlendState();
D3D::stateman->PopRasterizerState(); D3D::stateman->PopRasterizerState();
@ -467,18 +470,25 @@ bool stq_observer, stsq_observer, cq_observer, clearq_observer;
void InitUtils() void InitUtils()
{ {
util_vbuf = new UtilVertexBuffer(0x4000); util_vbuf.reset(new UtilVertexBuffer(0x4000));
float border[4] = { 0.f, 0.f, 0.f, 0.f }; const 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); D3D11_SAMPLER_DESC samDesc = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_POINT,
HRESULT hr = D3D::device->CreateSamplerState(&samDesc, &point_copy_sampler); D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER,
if (FAILED(hr)) PanicAlert("Failed to create sampler state at %s %d\n", __FILE__, __LINE__); 0.f, 1, D3D11_COMPARISON_ALWAYS, border, 0.f, 0.f);
else SetDebugObjectName((ID3D11DeviceChild*)point_copy_sampler, "point copy sampler state"); HRESULT hr = D3D::g_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); samDesc = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_BORDER,
hr = D3D::device->CreateSamplerState(&samDesc, &linear_copy_sampler); D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER, 0.f, 1, D3D11_COMPARISON_ALWAYS, border, 0.f, 0.f);
if (FAILED(hr)) PanicAlert("Failed to create sampler state at %s %d\n", __FILE__, __LINE__); hr = D3D::g_device->CreateSamplerState(&samDesc, &linear_copy_sampler);
else SetDebugObjectName((ID3D11DeviceChild*)linear_copy_sampler, "linear copy sampler state"); 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 // cached data used to avoid unnecessarily reloading the vertex buffers
memset(&tex_quad_data, 0, sizeof(tex_quad_data)); memset(&tex_quad_data, 0, sizeof(tex_quad_data));
@ -501,17 +511,17 @@ void ShutdownUtils()
font.Shutdown(); font.Shutdown();
SAFE_RELEASE(point_copy_sampler); SAFE_RELEASE(point_copy_sampler);
SAFE_RELEASE(linear_copy_sampler); SAFE_RELEASE(linear_copy_sampler);
SAFE_DELETE(util_vbuf); util_vbuf.reset();
} }
void SetPointCopySampler() void SetPointCopySampler()
{ {
D3D::context->PSSetSamplers(0, 1, &point_copy_sampler); D3D::g_context->PSSetSamplers(0, 1, &point_copy_sampler);
} }
void SetLinearCopySampler() void SetLinearCopySampler()
{ {
D3D::context->PSSetSamplers(0, 1, &linear_copy_sampler); D3D::g_context->PSSetSamplers(0, 1, &linear_copy_sampler);
} }
void drawShadedTexQuad(ID3D11ShaderResourceView* texture, void drawShadedTexQuad(ID3D11ShaderResourceView* texture,
@ -555,17 +565,17 @@ void drawShadedTexQuad(ID3D11ShaderResourceView* texture,
UINT stride = sizeof(STQVertex); UINT stride = sizeof(STQVertex);
UINT offset = 0; UINT offset = 0;
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); D3D::g_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
D3D::context->IASetInputLayout(layout); D3D::g_context->IASetInputLayout(layout);
D3D::context->IASetVertexBuffers(0, 1, &util_vbuf->GetBuffer(), &stride, &offset); D3D::g_context->IASetVertexBuffers(0, 1, &util_vbuf->GetBuffer(), &stride, &offset);
D3D::context->PSSetShader(PShader, NULL, 0); D3D::g_context->PSSetShader(PShader, NULL, 0);
D3D::context->PSSetShaderResources(0, 1, &texture); D3D::g_context->PSSetShaderResources(0, 1, &texture);
D3D::context->VSSetShader(Vshader, NULL, 0); D3D::g_context->VSSetShader(Vshader, NULL, 0);
D3D::stateman->Apply(); D3D::stateman->Apply();
D3D::context->Draw(4, stq_offset); D3D::g_context->Draw(4, stq_offset);
ID3D11ShaderResourceView* texres = NULL; ID3D11ShaderResourceView* texres = NULL;
context->PSSetShaderResources(0, 1, &texres); // immediately unbind the texture g_context->PSSetShaderResources(0, 1, &texres); // immediately unbind the texture
} }
void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture, void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
@ -612,17 +622,17 @@ void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
UINT stride = sizeof(STSQVertex); UINT stride = sizeof(STSQVertex);
UINT offset = 0; UINT offset = 0;
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); g_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
context->IASetVertexBuffers(0, 1, &util_vbuf->GetBuffer(), &stride, &offset); g_context->IASetVertexBuffers(0, 1, &util_vbuf->GetBuffer(), &stride, &offset);
context->IASetInputLayout(layout); g_context->IASetInputLayout(layout);
context->PSSetShaderResources(0, 1, &texture); g_context->PSSetShaderResources(0, 1, &texture);
context->PSSetShader(PShader, NULL, 0); g_context->PSSetShader(PShader, NULL, 0);
context->VSSetShader(Vshader, NULL, 0); g_context->VSSetShader(Vshader, NULL, 0);
stateman->Apply(); stateman->Apply();
context->Draw(4, stsq_offset); g_context->Draw(4, stsq_offset);
ID3D11ShaderResourceView* texres = NULL; ID3D11ShaderResourceView* texres = NULL;
context->PSSetShaderResources(0, 1, &texres); // immediately unbind the texture g_context->PSSetShaderResources(0, 1, &texres); // immediately unbind the texture
} }
// Fills a certain area of the current render target with the specified color // Fills a certain area of the current render target with the specified color
@ -651,17 +661,17 @@ void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2)
draw_quad_data.col = Color; draw_quad_data.col = Color;
} }
context->VSSetShader(VertexShaderCache::GetClearVertexShader(), NULL, 0); g_context->VSSetShader(VertexShaderCache::GetClearVertexShader(), NULL, 0);
context->PSSetShader(PixelShaderCache::GetClearProgram(), NULL, 0); g_context->PSSetShader(PixelShaderCache::GetClearProgram(), NULL, 0);
context->IASetInputLayout(VertexShaderCache::GetClearInputLayout()); g_context->IASetInputLayout(VertexShaderCache::GetClearInputLayout());
UINT stride = sizeof(ColVertex); UINT stride = sizeof(ColVertex);
UINT offset = 0; UINT offset = 0;
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); g_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
context->IASetVertexBuffers(0, 1, &util_vbuf->GetBuffer(), &stride, &offset); g_context->IASetVertexBuffers(0, 1, &util_vbuf->GetBuffer(), &stride, &offset);
stateman->Apply(); stateman->Apply();
context->Draw(4, cq_offset); g_context->Draw(4, cq_offset);
} }
void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout) void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout)
@ -681,16 +691,16 @@ void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexS
clear_quad_data.col = Color; clear_quad_data.col = Color;
clear_quad_data.z = z; clear_quad_data.z = z;
} }
context->VSSetShader(Vshader, NULL, 0); g_context->VSSetShader(Vshader, NULL, 0);
context->PSSetShader(PShader, NULL, 0); g_context->PSSetShader(PShader, NULL, 0);
context->IASetInputLayout(layout); g_context->IASetInputLayout(layout);
UINT stride = sizeof(ClearVertex); UINT stride = sizeof(ClearVertex);
UINT offset = 0; UINT offset = 0;
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); g_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
context->IASetVertexBuffers(0, 1, &util_vbuf->GetBuffer(), &stride, &offset); g_context->IASetVertexBuffers(0, 1, &util_vbuf->GetBuffer(), &stride, &offset);
stateman->Apply(); stateman->Apply();
context->Draw(4, clearq_offset); g_context->Draw(4, clearq_offset);
} }
} // namespace D3D } // namespace D3D

View file

@ -23,68 +23,150 @@
namespace DX11 namespace DX11
{ {
// simple "smart" pointer which calls AddRef/Release as needed
template <typename T>
class SharedPtr
{
public:
typedef T* pointer;
static SharedPtr FromPtr(pointer ptr)
{
return SharedPtr(ptr);
}
SharedPtr()
: data(nullptr)
{}
SharedPtr(const SharedPtr& other)
: data(NULL)
{
*this = other;
}
SharedPtr& operator=(const SharedPtr& other)
{
if (other.data)
other.data->AddRef();
reset();
data = other.data;
return *this;
}
~SharedPtr()
{
reset();
}
void reset()
{
if (data)
data->Release();
data = nullptr;
}
// returning reference for dx functions needing pointer to pointer
operator pointer const&() const
{
return data;
}
T& operator*() const
{
return *data;
}
// overloading operator& for dx functions needing pointer to pointer
T*const* operator&() const
{
return &data;
}
pointer operator->() const
{
return data;
}
bool operator==(const SharedPtr& other) const
{
return data == other.data;
}
bool operator!=(const SharedPtr& other) const
{
return !(*this == other);
}
private:
explicit SharedPtr(pointer ptr)
: data(ptr)
{}
pointer data;
};
namespace D3D namespace D3D
{ {
// Font creation flags
#define D3DFONT_BOLD 0x0001
#define D3DFONT_ITALIC 0x0002
// Font rendering flags // Font creation flags
#define D3DFONT_CENTERED 0x0001 static const u32 D3DFONT_BOLD = 0x0001;
static const u32 D3DFONT_ITALIC = 0x0002;
class CD3DFont // Font rendering flags
{ static const u32 D3DFONT_CENTERED = 0x0001;
ID3D11ShaderResourceView* m_pTexture;
ID3D11Buffer* m_pVB;
ID3D11InputLayout* m_InputLayout;
ID3D11PixelShader* m_pshader;
ID3D11VertexShader* m_vshader;
ID3D11BlendState* m_blendstate;
ID3D11RasterizerState* m_raststate;
const int m_dwTexWidth;
const int m_dwTexHeight;
unsigned int m_LineHeight;
float m_fTexCoords[128-32][4];
public: class CD3DFont
CD3DFont(); {
// 2D text drawing function ID3D11ShaderResourceView* m_pTexture;
// Initializing and destroying device-dependent objects SharedPtr<ID3D11Buffer> m_pVB;
int Init(); SharedPtr<ID3D11InputLayout> m_InputLayout;
int Shutdown(); SharedPtr<ID3D11PixelShader> m_pshader;
int DrawTextScaled(float x, float y, SharedPtr<ID3D11VertexShader> m_vshader;
float size, SharedPtr<ID3D11BlendState> m_blendstate;
float spacing, u32 dwColor, ID3D11RasterizerState* m_raststate;
const char* strText); const int m_dwTexWidth;
}; const int m_dwTexHeight;
unsigned int m_LineHeight;
float m_fTexCoords[128-32][4];
extern CD3DFont font; public:
CD3DFont();
// 2D text drawing function
// Initializing and destroying device-dependent objects
int Init();
int Shutdown();
int DrawTextScaled(float x, float y, float size,
float spacing, u32 dwColor, const char* strText);
};
void InitUtils(); extern CD3DFont font;
void ShutdownUtils();
void SetPointCopySampler(); void InitUtils();
void SetLinearCopySampler(); void ShutdownUtils();
void SetPointCopySampler();
void SetLinearCopySampler();
void drawShadedTexQuad(ID3D11ShaderResourceView* texture,
const D3D11_RECT* rSource,
int SourceWidth, int SourceHeight,
ID3D11PixelShader* PShader, ID3D11VertexShader* VShader,
ID3D11InputLayout* layout, float Gamma = 1.0f);
void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
const MathUtil::Rectangle<float>* rSource,
int SourceWidth, int SourceHeight,
const MathUtil::Rectangle<float>* rDest,
ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader,
ID3D11InputLayout* layout, float Gamma = 1.0f);
void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout);
void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2);
void drawShadedTexQuad(ID3D11ShaderResourceView* texture,
const D3D11_RECT* rSource,
int SourceWidth,
int SourceHeight,
ID3D11PixelShader* PShader,
ID3D11VertexShader* VShader,
ID3D11InputLayout* layout,
float Gamma = 1.0f);
void drawShadedTexSubQuad(ID3D11ShaderResourceView* texture,
const MathUtil::Rectangle<float>* rSource,
int SourceWidth,
int SourceHeight,
const MathUtil::Rectangle<float>* rDest,
ID3D11PixelShader* PShader,
ID3D11VertexShader* Vshader,
ID3D11InputLayout* layout,
float Gamma = 1.0f);
void drawClearQuad(u32 Color, float z, ID3D11PixelShader* PShader, ID3D11VertexShader* Vshader, ID3D11InputLayout* layout);
void drawColorQuad(u32 Color, float x1, float y1, float x2, float y2);
} }
} }

View file

@ -23,153 +23,155 @@
#include "PixelShaderCache.h" #include "PixelShaderCache.h"
#include "Render.h" #include "Render.h"
#include "VertexShaderCache.h" #include "VertexShaderCache.h"
#include "XFBEncoder.h"
#include "HW/Memmap.h" #include "HW/Memmap.h"
namespace DX11 { namespace DX11
{
static XFBEncoder s_xfbEncoder;
FramebufferManager::Efb FramebufferManager::m_efb; FramebufferManager::Efb FramebufferManager::m_efb;
D3DTexture2D* &FramebufferManager::GetEFBColorTexture() { return m_efb.color_tex; } D3DTexture2D* FramebufferManager::GetResolvedEFBColorTexture()
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.iMultisampleMode) if (g_ActiveConfig.iMultisampleMode)
{ {
D3D::context->ResolveSubresource(m_efb.resolved_color_tex->GetTex(), 0, m_efb.color_tex->GetTex(), 0, DXGI_FORMAT_R8G8B8A8_UNORM); D3D::g_context->ResolveSubresource(m_efb.resolved_color_tex->GetTex(), 0, m_efb.color_tex->GetTex(), 0, DXGI_FORMAT_R8G8B8A8_UNORM);
return m_efb.resolved_color_tex; return m_efb.resolved_color_tex.get();
} }
else else
return m_efb.color_tex; return m_efb.color_tex.get();
} }
D3DTexture2D* &FramebufferManager::GetResolvedEFBDepthTexture() D3DTexture2D* FramebufferManager::GetResolvedEFBDepthTexture()
{ {
if (g_ActiveConfig.iMultisampleMode) if (g_ActiveConfig.iMultisampleMode)
{ {
D3D::context->ResolveSubresource(m_efb.resolved_color_tex->GetTex(), 0, m_efb.color_tex->GetTex(), 0, DXGI_FORMAT_R8G8B8A8_UNORM); D3D::g_context->ResolveSubresource(m_efb.resolved_color_tex->GetTex(), 0, m_efb.color_tex->GetTex(), 0, DXGI_FORMAT_R8G8B8A8_UNORM);
return m_efb.resolved_color_tex; return m_efb.resolved_color_tex.get();
} }
else else
return m_efb.depth_tex; return m_efb.depth_tex.get();
} }
FramebufferManager::FramebufferManager() FramebufferManager::FramebufferManager()
{ {
unsigned int target_width = Renderer::GetFullTargetWidth(); const unsigned int target_width = Renderer::GetFullTargetWidth();
unsigned int target_height = Renderer::GetFullTargetHeight(); const unsigned int target_height = Renderer::GetFullTargetHeight();
DXGI_SAMPLE_DESC sample_desc = D3D::GetAAMode(g_ActiveConfig.iMultisampleMode); DXGI_SAMPLE_DESC sample_desc = D3D::GetAAMode(g_ActiveConfig.iMultisampleMode);
ID3D11Texture2D* buf;
D3D11_TEXTURE2D_DESC texdesc;
HRESULT hr;
// EFB color texture - primary render target // EFB color texture - primary render target
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, 1, 1, D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality); {
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf); auto texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height,
CHECK(hr==S_OK, "create EFB color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); 1, 1, D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality);
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)); auto const buf = CreateTexture2DShared(&texdesc, NULL);
CHECK(buf, "create EFB color texture (size: %dx%d)", target_width, target_height);
m_efb.color_tex.reset(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)));
CHECK(m_efb.color_tex!=NULL, "create EFB color texture (size: %dx%d)", target_width, target_height); CHECK(m_efb.color_tex!=NULL, "create EFB color texture (size: %dx%d)", target_width, target_height);
SAFE_RELEASE(buf); D3D::SetDebugObjectName(m_efb.color_tex->GetTex(), "EFB color texture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetTex(), "EFB color texture"); D3D::SetDebugObjectName(m_efb.color_tex->GetSRV(), "EFB color texture shader resource view");
D3D::SetDebugObjectName((ID3D11DeviceChild*)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::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetRTV(), "EFB color texture render target view"); }
// Temporary EFB color texture - used in ReinterpretPixelData // Temporary EFB color texture - used in ReinterpretPixelData
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, 1, 1, D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, 1, 0); {
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf); auto texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height,
CHECK(hr==S_OK, "create EFB color temp texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); 1, 1, D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, 1, 0);
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); auto const buf = CreateTexture2DShared(&texdesc, NULL);
CHECK(buf, "create EFB color temp texture (size: %dx%d)", target_width, target_height);
m_efb.color_temp_tex.reset(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));
CHECK(m_efb.color_temp_tex!=NULL, "create EFB color temp texture (size: %dx%d)", target_width, target_height); CHECK(m_efb.color_temp_tex!=NULL, "create EFB color temp texture (size: %dx%d)", target_width, target_height);
SAFE_RELEASE(buf); D3D::SetDebugObjectName(m_efb.color_temp_tex->GetTex(), "EFB color temp texture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)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((ID3D11DeviceChild*)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::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_temp_tex->GetRTV(), "EFB color temp texture render target view"); }
// AccessEFB - Sysmem buffer used to retrieve the pixel data from color_tex // AccessEFB - Sysmem buffer used to retrieve the pixel data from color_tex
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ); {
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.color_staging_buf); auto texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ);
CHECK(hr==S_OK, "create EFB color staging buffer (hr=%#x)", hr); m_efb.color_staging_buf = CreateTexture2DShared(&texdesc, NULL);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_staging_buf, "EFB color staging texture (used for Renderer::AccessEFB)"); CHECK(m_efb.color_staging_buf, "create EFB color staging buffer");
D3D::SetDebugObjectName(m_efb.color_staging_buf, "EFB color staging texture (used for Renderer::AccessEFB)");
}
// EFB depth buffer - primary depth buffer // EFB depth buffer - primary depth buffer
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width, target_height, 1, 1, D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality); {
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf); auto texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width, target_height, 1, 1, D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, sample_desc.Count, sample_desc.Quality);
CHECK(hr==S_OK, "create EFB depth texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); auto const buf = CreateTexture2DShared(&texdesc, NULL);
m_efb.depth_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE), DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, (sample_desc.Count > 1)); CHECK(buf, "create EFB depth texture (size: %dx%d)", target_width, target_height);
SAFE_RELEASE(buf); m_efb.depth_tex.reset(new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE),
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetTex(), "EFB depth texture"); DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, (sample_desc.Count > 1)));
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetDSV(), "EFB depth texture depth stencil view"); D3D::SetDebugObjectName(m_efb.depth_tex->GetTex(), "EFB depth texture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_tex->GetSRV(), "EFB depth texture shader resource view"); 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");
}
// Render buffer for AccessEFB (depth data) // 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, NULL, &buf); auto texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 1, 1, 1, 1, D3D11_BIND_RENDER_TARGET);
CHECK(hr==S_OK, "create EFB depth read texture (hr=%#x)", hr); auto const buf = CreateTexture2DShared(&texdesc, NULL);
m_efb.depth_read_texture = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET); CHECK(buf, "create EFB depth read texture");
SAFE_RELEASE(buf); m_efb.depth_read_texture.reset(new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET));
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_read_texture->GetTex(), "EFB depth read texture (used in Renderer::AccessEFB)"); D3D::SetDebugObjectName(m_efb.depth_read_texture->GetTex(), "EFB depth read texture (used in Renderer::AccessEFB)");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_read_texture->GetRTV(), "EFB depth read texture render target view (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 // 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, NULL, &m_efb.depth_staging_buf); auto texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, 1, 1, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ);
CHECK(hr==S_OK, "create EFB depth staging buffer (hr=%#x)", hr); m_efb.depth_staging_buf = CreateTexture2DShared(&texdesc, NULL);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_staging_buf, "EFB depth staging texture (used for Renderer::AccessEFB)"); CHECK(m_efb.depth_staging_buf, "create EFB depth staging buffer");
D3D::SetDebugObjectName(m_efb.depth_staging_buf, "EFB depth staging texture (used for Renderer::AccessEFB)");
}
if (g_ActiveConfig.iMultisampleMode) if (g_ActiveConfig.iMultisampleMode)
{ {
// Framebuffer resolve textures (color+depth) // Framebuffer resolve textures (color+depth)
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, 1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, 1); {
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf); auto texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height,
m_efb.resolved_color_tex = new D3DTexture2D(buf, D3D11_BIND_SHADER_RESOURCE, DXGI_FORMAT_R8G8B8A8_UNORM); 1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, 1);
auto const buf = CreateTexture2DShared(&texdesc, NULL);
m_efb.resolved_color_tex.reset(new D3DTexture2D(buf, D3D11_BIND_SHADER_RESOURCE, DXGI_FORMAT_R8G8B8A8_UNORM));
CHECK(m_efb.resolved_color_tex!=NULL, "create EFB color resolve texture (size: %dx%d)", target_width, target_height); CHECK(m_efb.resolved_color_tex!=NULL, "create EFB color resolve texture (size: %dx%d)", target_width, target_height);
SAFE_RELEASE(buf); D3D::SetDebugObjectName(m_efb.resolved_color_tex->GetTex(), "EFB color resolve texture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)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");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.resolved_color_tex->GetSRV(), "EFB color resolve texture shader resource view"); }
texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width, target_height, 1, 1, D3D11_BIND_SHADER_RESOURCE); {
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf); auto texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, target_width, target_height, 1, 1, D3D11_BIND_SHADER_RESOURCE);
CHECK(hr==S_OK, "create EFB depth resolve texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); auto const buf = CreateTexture2DShared(&texdesc, NULL);
m_efb.resolved_depth_tex = new D3DTexture2D(buf, D3D11_BIND_SHADER_RESOURCE, DXGI_FORMAT_R24_UNORM_X8_TYPELESS); CHECK(buf, "create EFB depth resolve texture (size: %dx%d)", target_width, target_height);
SAFE_RELEASE(buf); m_efb.resolved_depth_tex.reset(new D3DTexture2D(buf, D3D11_BIND_SHADER_RESOURCE, DXGI_FORMAT_R24_UNORM_X8_TYPELESS));
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.resolved_depth_tex->GetTex(), "EFB depth resolve texture"); D3D::SetDebugObjectName(m_efb.resolved_depth_tex->GetTex(), "EFB depth resolve texture");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.resolved_depth_tex->GetSRV(), "EFB depth resolve texture shader resource view"); D3D::SetDebugObjectName(m_efb.resolved_depth_tex->GetSRV(), "EFB depth resolve texture shader resource view");
}
} }
else else
{ {
m_efb.resolved_color_tex = NULL; m_efb.resolved_color_tex = NULL;
m_efb.resolved_depth_tex = NULL; m_efb.resolved_depth_tex = NULL;
} }
s_xfbEncoder.Init();
} }
FramebufferManager::~FramebufferManager() FramebufferManager::~FramebufferManager()
{ {
s_xfbEncoder.Shutdown(); m_efb.color_tex.reset();
m_efb.color_staging_buf.reset();
SAFE_RELEASE(m_efb.color_tex); m_efb.depth_tex.reset();
SAFE_RELEASE(m_efb.color_temp_tex); m_efb.depth_staging_buf.reset();
SAFE_RELEASE(m_efb.color_staging_buf); m_efb.depth_read_texture.reset();
SAFE_RELEASE(m_efb.resolved_color_tex);
SAFE_RELEASE(m_efb.depth_tex); m_efb.color_temp_tex.reset();
SAFE_RELEASE(m_efb.depth_staging_buf);
SAFE_RELEASE(m_efb.depth_read_texture); m_efb.resolved_color_tex.reset();
SAFE_RELEASE(m_efb.resolved_depth_tex); m_efb.resolved_depth_tex.reset();
} }
void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma) void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc,float Gamma)
{ {
u8* dst = Memory::GetPointer(xfbAddr); u8* dst = Memory::GetPointer(xfbAddr);
s_xfbEncoder.Encode(dst, fbWidth, fbHeight, sourceRc, Gamma); m_xfbEncoder.Encode(dst, fbWidth, fbHeight, sourceRc, Gamma);
} }
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height) XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
@ -214,8 +216,8 @@ void XFBSource::CopyEFB(float Gamma)
// Copy EFB data to XFB and restore render target again // Copy EFB data to XFB and restore render target again
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)texWidth, (float)texHeight); const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)texWidth, (float)texHeight);
D3D::context->RSSetViewports(1, &vp); D3D::g_context->RSSetViewports(1, &vp);
D3D::context->OMSetRenderTargets(1, &tex->GetRTV(), NULL); D3D::g_context->OMSetRenderTargets(1, &tex->GetRTV(), NULL);
D3D::SetLinearCopySampler(); D3D::SetLinearCopySampler();
D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), sourceRc.AsRECT(), D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), sourceRc.AsRECT(),
@ -223,7 +225,7 @@ void XFBSource::CopyEFB(float Gamma)
PixelShaderCache::GetColorCopyProgram(true), VertexShaderCache::GetSimpleVertexShader(), PixelShaderCache::GetColorCopyProgram(true), VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout(),Gamma); VertexShaderCache::GetSimpleInputLayout(),Gamma);
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(),
FramebufferManager::GetEFBDepthTexture()->GetDSV()); FramebufferManager::GetEFBDepthTexture()->GetDSV());
} }

View file

@ -23,6 +23,7 @@
#include "FramebufferManagerBase.h" #include "FramebufferManagerBase.h"
#include "D3DTexture.h" #include "D3DTexture.h"
#include "XFBEncoder.h"
namespace DX11 { namespace DX11 {
@ -60,15 +61,16 @@ namespace DX11 {
struct XFBSource : public XFBSourceBase struct XFBSource : public XFBSourceBase
{ {
XFBSource(D3DTexture2D *_tex) : tex(_tex) {} XFBSource(std::unique_ptr<D3DTexture2D>&& _tex)
~XFBSource() { tex->Release(); } : tex(std::move(_tex))
{}
void Draw(const MathUtil::Rectangle<float> &sourcerc, void Draw(const MathUtil::Rectangle<float> &sourcerc,
const MathUtil::Rectangle<float> &drawrc, int width, int height) const; const MathUtil::Rectangle<float> &drawrc, int width, int height) const;
void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight); void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
void CopyEFB(float Gamma); void CopyEFB(float Gamma);
D3DTexture2D* const tex; std::unique_ptr<D3DTexture2D> const tex;
}; };
class FramebufferManager : public FramebufferManagerBase class FramebufferManager : public FramebufferManagerBase
@ -77,22 +79,21 @@ public:
FramebufferManager(); FramebufferManager();
~FramebufferManager(); ~FramebufferManager();
static D3DTexture2D* &GetEFBColorTexture(); static D3DTexture2D* GetEFBColorTexture() { return m_efb.color_tex.get(); }
static ID3D11Texture2D* &GetEFBColorStagingBuffer(); static ID3D11Texture2D* GetEFBColorStagingBuffer() { return m_efb.color_staging_buf; }
static D3DTexture2D* &GetEFBDepthTexture(); static D3DTexture2D* GetEFBDepthTexture() { return m_efb.depth_tex.get(); }
static D3DTexture2D* &GetEFBDepthReadTexture(); static D3DTexture2D* GetEFBDepthReadTexture() { return m_efb.depth_read_texture.get(); }
static ID3D11Texture2D* &GetEFBDepthStagingBuffer(); static ID3D11Texture2D* GetEFBDepthStagingBuffer() { return m_efb.depth_staging_buf; }
static D3DTexture2D* &GetResolvedEFBColorTexture(); static D3DTexture2D* GetResolvedEFBColorTexture();
static D3DTexture2D* &GetResolvedEFBDepthTexture(); static D3DTexture2D* GetResolvedEFBDepthTexture();
static D3DTexture2D* &GetEFBColorTempTexture() { return m_efb.color_temp_tex; } static D3DTexture2D* GetEFBColorTempTexture() { return m_efb.color_temp_tex.get(); }
static void SwapReinterpretTexture() static void SwapReinterpretTexture()
{ {
D3DTexture2D* swaptex = GetEFBColorTempTexture(); std::swap(m_efb.color_temp_tex, m_efb.color_tex);
m_efb.color_temp_tex = GetEFBColorTexture();
m_efb.color_tex = swaptex;
} }
private: private:
@ -103,18 +104,20 @@ private:
static struct Efb static struct Efb
{ {
D3DTexture2D* color_tex; std::unique_ptr<D3DTexture2D> color_tex;
ID3D11Texture2D* color_staging_buf; SharedPtr<ID3D11Texture2D> color_staging_buf;
D3DTexture2D* depth_tex; std::unique_ptr<D3DTexture2D> depth_tex;
ID3D11Texture2D* depth_staging_buf; SharedPtr<ID3D11Texture2D> depth_staging_buf;
D3DTexture2D* depth_read_texture; std::unique_ptr<D3DTexture2D> depth_read_texture;
D3DTexture2D* color_temp_tex; std::unique_ptr<D3DTexture2D> color_temp_tex;
D3DTexture2D* resolved_color_tex; std::unique_ptr<D3DTexture2D> resolved_color_tex;
D3DTexture2D* resolved_depth_tex; std::unique_ptr<D3DTexture2D> resolved_depth_tex;
} m_efb; } m_efb;
XFBEncoder m_xfbEncoder;
}; };
} // namespace DX11 } // namespace DX11

View file

@ -26,66 +26,19 @@ namespace DX11
namespace D3D namespace D3D
{ {
StateManager* stateman; std::unique_ptr<StateManager> stateman;
template<typename T> AutoState<T>::AutoState(const T* object) : state(object)
{
((IUnknown*)state)->AddRef();
}
template<typename T> AutoState<T>::AutoState(const AutoState<T> &source)
{
state = source.GetPtr();
((T*)state)->AddRef();
}
template<typename T> AutoState<T>::~AutoState()
{
if(state) ((T*)state)->Release();
state = NULL;
}
StateManager::StateManager() : cur_blendstate(NULL), cur_depthstate(NULL), cur_raststate(NULL) {}
void StateManager::PushBlendState(const ID3D11BlendState* state) { blendstates.push(AutoBlendState(state)); }
void StateManager::PushDepthState(const ID3D11DepthStencilState* state) { depthstates.push(AutoDepthStencilState(state)); }
void StateManager::PushRasterizerState(const ID3D11RasterizerState* state) { raststates.push(AutoRasterizerState(state)); }
void StateManager::PopBlendState() { blendstates.pop(); }
void StateManager::PopDepthState() { depthstates.pop(); }
void StateManager::PopRasterizerState() { raststates.pop(); }
void StateManager::Apply() void StateManager::Apply()
{ {
if (!blendstates.empty()) if (blendstates.empty() || depthstates.empty() || raststates.empty())
{ {
if (cur_blendstate != blendstates.top().GetPtr()) ERROR_LOG(VIDEO, "Tried to apply without complete state!");
{ return;
cur_blendstate = (ID3D11BlendState*)blendstates.top().GetPtr();
D3D::context->OMSetBlendState(cur_blendstate, NULL, 0xFFFFFFFF);
}
} }
else ERROR_LOG(VIDEO, "Tried to apply without blend state!");
if (!depthstates.empty()) D3D::g_context->OMSetBlendState(blendstates.top(), NULL, 0xFFFFFFFF);
{ D3D::g_context->OMSetDepthStencilState(depthstates.top(), 0);
if (cur_depthstate != depthstates.top().GetPtr()) D3D::g_context->RSSetState(raststates.top());
{
cur_depthstate = (ID3D11DepthStencilState*)depthstates.top().GetPtr();
D3D::context->OMSetDepthStencilState(cur_depthstate, 0);
}
}
else ERROR_LOG(VIDEO, "Tried to apply without depth state!");
if (!raststates.empty())
{
if (cur_raststate != raststates.top().GetPtr())
{
cur_raststate = (ID3D11RasterizerState*)raststates.top().GetPtr();
D3D::context->RSSetState(cur_raststate);
}
}
else ERROR_LOG(VIDEO, "Tried to apply without rasterizer state!");
} }
} // namespace } // namespace

View file

@ -19,9 +19,7 @@
#include <stack> #include <stack>
struct ID3D11BlendState; #include "D3DUtil.h"
struct ID3D11DepthStencilState;
struct ID3D11RasterizerState;
namespace DX11 namespace DX11
{ {
@ -29,37 +27,35 @@ namespace DX11
namespace D3D namespace D3D
{ {
template<typename T> class AutoState typedef SharedPtr<ID3D11BlendState> AutoBlendState;
{ typedef SharedPtr<ID3D11DepthStencilState> AutoDepthStencilState;
public: typedef SharedPtr<ID3D11RasterizerState> AutoRasterizerState;
AutoState(const T* object);
AutoState(const AutoState<T> &source);
~AutoState();
const inline T* GetPtr() const { return state; }
private:
const T* state;
};
typedef AutoState<ID3D11BlendState> AutoBlendState;
typedef AutoState<ID3D11DepthStencilState> AutoDepthStencilState;
typedef AutoState<ID3D11RasterizerState> AutoRasterizerState;
class StateManager class StateManager
{ {
public: public:
StateManager();
// call any of these to change the affected states // call any of these to change the affected states
void PushBlendState(const ID3D11BlendState* state); void PushBlendState(const AutoBlendState& state)
void PushDepthState(const ID3D11DepthStencilState* state); {
void PushRasterizerState(const ID3D11RasterizerState* state); blendstates.push(state);
}
void PushDepthState(ID3D11DepthStencilState* state)
{
state->AddRef();
depthstates.push(AutoDepthStencilState::FromPtr(state));
}
void PushRasterizerState(ID3D11RasterizerState* state)
{
state->AddRef();
raststates.push(AutoRasterizerState::FromPtr(state));
}
// call these after drawing // call these after drawing
void PopBlendState(); void PopBlendState() { blendstates.pop(); }
void PopDepthState(); void PopDepthState() { depthstates.pop(); }
void PopRasterizerState(); void PopRasterizerState() { raststates.pop(); }
// call this before any drawing operation if states could have changed meanwhile // call this before any drawing operation if states could have changed meanwhile
void Apply(); void Apply();
@ -68,12 +64,9 @@ private:
std::stack<AutoBlendState> blendstates; std::stack<AutoBlendState> blendstates;
std::stack<AutoDepthStencilState> depthstates; std::stack<AutoDepthStencilState> depthstates;
std::stack<AutoRasterizerState> raststates; std::stack<AutoRasterizerState> raststates;
ID3D11BlendState* cur_blendstate;
ID3D11DepthStencilState* cur_depthstate;
ID3D11RasterizerState* cur_raststate;
}; };
extern StateManager* stateman; extern std::unique_ptr<StateManager> stateman;
} // namespace } // namespace

View file

@ -135,39 +135,19 @@ static const char LINE_GS_COMMON[] =
; ;
LineGeometryShader::LineGeometryShader() LineGeometryShader::LineGeometryShader()
: m_ready(false), m_paramsBuffer(NULL) : m_ready(false)
{ }
void LineGeometryShader::Init()
{ {
m_ready = false;
HRESULT hr;
// Create constant buffer for uploading data to geometry shader // Create constant buffer for uploading data to geometry shader
D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(LineGSParams), D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(LineGSParams),
D3D11_BIND_CONSTANT_BUFFER); D3D11_BIND_CONSTANT_BUFFER);
hr = D3D::device->CreateBuffer(&bd, NULL, &m_paramsBuffer); m_paramsBuffer = CreateBufferShared(&bd, NULL);
CHECK(SUCCEEDED(hr), "create line geometry shader params buffer"); CHECK(m_paramsBuffer, "create line geometry shader params buffer");
D3D::SetDebugObjectName(m_paramsBuffer, "line geometry shader params buffer"); D3D::SetDebugObjectName(m_paramsBuffer, "line geometry shader params buffer");
m_ready = true; m_ready = true;
} }
void LineGeometryShader::Shutdown()
{
m_ready = false;
for (ComboMap::iterator it = m_shaders.begin(); it != m_shaders.end(); ++it)
{
SAFE_RELEASE(it->second);
}
m_shaders.clear();
SAFE_RELEASE(m_paramsBuffer);
}
bool LineGeometryShader::SetShader(u32 components, float lineWidth, bool LineGeometryShader::SetShader(u32 components, float lineWidth,
float texOffset, float vpWidth, float vpHeight) float texOffset, float vpWidth, float vpHeight)
{ {
@ -194,12 +174,13 @@ bool LineGeometryShader::SetShader(u32 components, float lineWidth,
{ "NUM_TEXCOORDS", numTexCoordsStr.str().c_str() }, { "NUM_TEXCOORDS", numTexCoordsStr.str().c_str() },
{ NULL, NULL } { NULL, NULL }
}; };
ID3D11GeometryShader* newShader = D3D::CompileAndCreateGeometryShader(code, unsigned int(strlen(code)), macros);
auto const newShader = D3D::CompileAndCreateGeometryShader(code, unsigned int(strlen(code)), macros);
if (!newShader) if (!newShader)
{ {
WARN_LOG(VIDEO, "Line geometry shader for components 0x%.08X failed to compile", components); WARN_LOG(VIDEO, "Line geometry shader for components 0x%.08X failed to compile", components);
// Add dummy shader to prevent trying to compile again // Add dummy shader to prevent trying to compile again
m_shaders[components] = NULL; m_shaders[components].reset();
return false; return false;
} }
@ -210,18 +191,18 @@ bool LineGeometryShader::SetShader(u32 components, float lineWidth,
{ {
if (shaderIt->second) if (shaderIt->second)
{ {
LineGSParams params = { 0 }; LineGSParams params = {};
params.LineWidth = lineWidth; params.LineWidth = lineWidth;
params.TexOffset = texOffset; params.TexOffset = texOffset;
params.VpWidth = vpWidth; params.VpWidth = vpWidth;
params.VpHeight = vpHeight; params.VpHeight = vpHeight;
D3D::context->UpdateSubresource(m_paramsBuffer, 0, NULL, &params, 0, 0); D3D::g_context->UpdateSubresource(m_paramsBuffer, 0, NULL, &params, 0, 0);
DEBUG_LOG(VIDEO, "Line params: width %f, texOffset %f, vpWidth %f, vpHeight %f", DEBUG_LOG(VIDEO, "Line params: width %f, texOffset %f, vpWidth %f, vpHeight %f",
lineWidth, texOffset, vpWidth, vpHeight); lineWidth, texOffset, vpWidth, vpHeight);
D3D::context->GSSetShader(shaderIt->second, NULL, 0); D3D::g_context->GSSetShader(shaderIt->second, NULL, 0);
D3D::context->GSSetConstantBuffers(0, 1, &m_paramsBuffer); D3D::g_context->GSSetConstantBuffers(0, 1, &m_paramsBuffer);
return true; return true;
} }

View file

@ -19,9 +19,7 @@
#define _LINEGEOMETRYSHADER_H #define _LINEGEOMETRYSHADER_H
#include "VideoCommon.h" #include "VideoCommon.h"
#include "D3DUtil.h"
struct ID3D11Buffer;
struct ID3D11GeometryShader;
namespace DX11 namespace DX11
{ {
@ -30,27 +28,21 @@ namespace DX11
// vertex format. // vertex format.
class LineGeometryShader class LineGeometryShader
{ {
public: public:
LineGeometryShader(); LineGeometryShader();
void Init();
void Shutdown();
// Returns true on success, false on failure // Returns true on success, false on failure
bool SetShader(u32 components, float lineWidth, float texOffset, bool SetShader(u32 components, float lineWidth, float texOffset,
float vpWidth, float vpHeight); float vpWidth, float vpHeight);
private: private:
bool m_ready; bool m_ready;
ID3D11Buffer* m_paramsBuffer; SharedPtr<ID3D11Buffer> m_paramsBuffer;
typedef std::map<u32, ID3D11GeometryShader*> ComboMap; typedef std::map<u32, SharedPtr<ID3D11GeometryShader>> ComboMap;
ComboMap m_shaders; ComboMap m_shaders;
}; };
} }

View file

@ -17,7 +17,6 @@
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "D3DBase.h" #include "D3DBase.h"
#include "D3DBlob.h"
#include "NativeVertexFormat.h" #include "NativeVertexFormat.h"
#include "VertexManager.h" #include "VertexManager.h"
#include "VertexShaderCache.h" #include "VertexShaderCache.h"
@ -30,12 +29,11 @@ class D3DVertexFormat : public NativeVertexFormat
D3D11_INPUT_ELEMENT_DESC m_elems[32]; D3D11_INPUT_ELEMENT_DESC m_elems[32];
UINT m_num_elems; UINT m_num_elems;
DX11::D3DBlob* m_vs_bytecode; SharedPtr<ID3D10Blob> m_vs_bytecode;
ID3D11InputLayout* m_layout; SharedPtr<ID3D11InputLayout> m_layout;
public: public:
D3DVertexFormat() : m_num_elems(0), m_vs_bytecode(NULL), m_layout(NULL) {} D3DVertexFormat() : m_num_elems(0) {}
~D3DVertexFormat() { SAFE_RELEASE(m_vs_bytecode); SAFE_RELEASE(m_layout); }
void Initialize(const PortableVertexDeclaration &_vtx_decl); void Initialize(const PortableVertexDeclaration &_vtx_decl);
void SetupVertexPointers(); void SetupVertexPointers();
@ -141,17 +139,15 @@ void D3DVertexFormat::SetupVertexPointers()
{ {
if (m_vs_bytecode != DX11::VertexShaderCache::GetActiveShaderBytecode()) if (m_vs_bytecode != DX11::VertexShaderCache::GetActiveShaderBytecode())
{ {
SAFE_RELEASE(m_vs_bytecode);
SAFE_RELEASE(m_layout);
m_vs_bytecode = DX11::VertexShaderCache::GetActiveShaderBytecode(); m_vs_bytecode = DX11::VertexShaderCache::GetActiveShaderBytecode();
m_vs_bytecode->AddRef();
HRESULT hr = DX11::D3D::device->CreateInputLayout(m_elems, m_num_elems, m_vs_bytecode->Data(), m_vs_bytecode->Size(), &m_layout); m_layout = CreateInputLayoutShared(m_elems, m_num_elems,
if (FAILED(hr)) PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__); m_vs_bytecode->GetBufferPointer(), m_vs_bytecode->GetBufferSize());
DX11::D3D::SetDebugObjectName((ID3D11DeviceChild*)m_layout, "input layout used to emulate the GX pipeline"); if (!m_layout)
PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__);
DX11::D3D::SetDebugObjectName(m_layout, "input layout used to emulate the GX pipeline");
} }
DX11::D3D::context->IASetInputLayout(m_layout); DX11::D3D::g_context->IASetInputLayout(m_layout);
} }
} // namespace DX11 } // namespace DX11

View file

@ -846,24 +846,6 @@ static const char EFB_ENCODE_PS[] =
"}\n" "}\n"
; ;
PSTextureEncoder::PSTextureEncoder()
: m_ready(false), m_out(NULL), m_outRTV(NULL), m_outStage(NULL),
m_encodeParams(NULL),
m_quad(NULL), m_vShader(NULL), m_quadLayout(NULL),
m_efbEncodeBlendState(NULL), m_efbEncodeDepthState(NULL),
m_efbEncodeRastState(NULL), m_efbSampler(NULL),
m_dynamicShader(NULL), m_classLinkage(NULL)
{
for (size_t i = 0; i < 4; ++i)
m_fetchClass[i] = NULL;
for (size_t i = 0; i < 2; ++i)
m_scaledFetchClass[i] = NULL;
for (size_t i = 0; i < 2; ++i)
m_intensityClass[i] = NULL;
for (size_t i = 0; i < 16; ++i)
m_generatorClass[i] = NULL;
}
static const D3D11_INPUT_ELEMENT_DESC QUAD_LAYOUT_DESC[] = { static const D3D11_INPUT_ELEMENT_DESC QUAD_LAYOUT_DESC[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 } { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }
}; };
@ -874,11 +856,22 @@ static const struct QuadVertex
float posY; float posY;
} QUAD_VERTS[4] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } }; } QUAD_VERTS[4] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } };
void PSTextureEncoder::Init() PSTextureEncoder::PSTextureEncoder()
: m_ready(false), m_outRTV(NULL),
m_efbEncodeDepthState(NULL),
m_efbEncodeRastState(NULL), m_efbSampler(NULL),
m_classLinkage(NULL)
{ {
m_ready = false; m_ready = false;
HRESULT hr; for (size_t i = 0; i < 4; ++i)
m_fetchClass[i] = NULL;
for (size_t i = 0; i < 2; ++i)
m_scaledFetchClass[i] = NULL;
for (size_t i = 0; i < 2; ++i)
m_intensityClass[i] = NULL;
for (size_t i = 0; i < 16; ++i)
m_generatorClass[i] = NULL;
// Create output texture RGBA format // Create output texture RGBA format
@ -886,15 +879,15 @@ void PSTextureEncoder::Init()
D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC( D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC(
DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT,
EFB_WIDTH, EFB_HEIGHT/4, 1, 1, D3D11_BIND_RENDER_TARGET); EFB_WIDTH, EFB_HEIGHT/4, 1, 1, D3D11_BIND_RENDER_TARGET);
hr = D3D::device->CreateTexture2D(&t2dd, NULL, &m_out); m_out = CreateTexture2DShared(&t2dd, NULL);
CHECK(SUCCEEDED(hr), "create efb encode output texture"); CHECK(m_out, "create efb encode output texture");
D3D::SetDebugObjectName(m_out, "efb encoder output texture"); D3D::SetDebugObjectName(m_out, "efb encoder output texture");
// Create output render target view // Create output render target view
D3D11_RENDER_TARGET_VIEW_DESC rtvd = CD3D11_RENDER_TARGET_VIEW_DESC(m_out, D3D11_RENDER_TARGET_VIEW_DESC rtvd = CD3D11_RENDER_TARGET_VIEW_DESC(m_out,
D3D11_RTV_DIMENSION_TEXTURE2D, DXGI_FORMAT_R32G32B32A32_UINT); D3D11_RTV_DIMENSION_TEXTURE2D, DXGI_FORMAT_R32G32B32A32_UINT);
hr = D3D::device->CreateRenderTargetView(m_out, &rtvd, &m_outRTV); HRESULT hr = D3D::g_device->CreateRenderTargetView(m_out, &rtvd, &m_outRTV);
CHECK(SUCCEEDED(hr), "create efb encode output render target view"); CHECK(SUCCEEDED(hr), "create efb encode output render target view");
D3D::SetDebugObjectName(m_outRTV, "efb encoder output rtv"); D3D::SetDebugObjectName(m_outRTV, "efb encoder output rtv");
@ -903,16 +896,16 @@ void PSTextureEncoder::Init()
t2dd.Usage = D3D11_USAGE_STAGING; t2dd.Usage = D3D11_USAGE_STAGING;
t2dd.BindFlags = 0; t2dd.BindFlags = 0;
t2dd.CPUAccessFlags = D3D11_CPU_ACCESS_READ; t2dd.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
hr = D3D::device->CreateTexture2D(&t2dd, NULL, &m_outStage); m_outStage = CreateTexture2DShared(&t2dd, NULL);
CHECK(SUCCEEDED(hr), "create efb encode output staging buffer"); CHECK(m_outStage, "create efb encode output staging buffer");
D3D::SetDebugObjectName(m_outStage, "efb encoder output staging buffer"); D3D::SetDebugObjectName(m_outStage, "efb encoder output staging buffer");
// Create constant buffer for uploading data to shaders // Create constant buffer for uploading data to shaders
D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(EFBEncodeParams), D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(EFBEncodeParams),
D3D11_BIND_CONSTANT_BUFFER); D3D11_BIND_CONSTANT_BUFFER);
hr = D3D::device->CreateBuffer(&bd, NULL, &m_encodeParams); m_encodeParams = CreateBufferShared(&bd, NULL);
CHECK(SUCCEEDED(hr), "create efb encode params buffer"); CHECK(m_encodeParams, "create efb encode params buffer");
D3D::SetDebugObjectName(m_encodeParams, "efb encoder params buffer"); D3D::SetDebugObjectName(m_encodeParams, "efb encoder params buffer");
// Create vertex quad // Create vertex quad
@ -921,33 +914,23 @@ void PSTextureEncoder::Init()
D3D11_USAGE_IMMUTABLE); D3D11_USAGE_IMMUTABLE);
D3D11_SUBRESOURCE_DATA srd = { QUAD_VERTS, 0, 0 }; D3D11_SUBRESOURCE_DATA srd = { QUAD_VERTS, 0, 0 };
hr = D3D::device->CreateBuffer(&bd, &srd, &m_quad); m_quad = CreateBufferShared(&bd, &srd);
CHECK(SUCCEEDED(hr), "create efb encode quad vertex buffer"); CHECK(m_quad, "create efb encode quad vertex buffer");
D3D::SetDebugObjectName(m_quad, "efb encoder quad vertex buffer"); D3D::SetDebugObjectName(m_quad, "efb encoder quad vertex buffer");
// Create vertex shader // Create vertex shader
SharedPtr<ID3D10Blob> bytecode;
D3DBlob* bytecode = NULL; m_vShader = D3D::CompileAndCreateVertexShader(EFB_ENCODE_VS, sizeof(EFB_ENCODE_VS), std::addressof(bytecode));
if (!D3D::CompileVertexShader(EFB_ENCODE_VS, sizeof(EFB_ENCODE_VS), &bytecode)) CHECK(m_vShader, "compile/create efb encode vertex shader");
{
ERROR_LOG(VIDEO, "EFB encode vertex shader failed to compile");
return;
}
hr = D3D::device->CreateVertexShader(bytecode->Data(), bytecode->Size(), NULL, &m_vShader);
CHECK(SUCCEEDED(hr), "create efb encode vertex shader");
D3D::SetDebugObjectName(m_vShader, "efb encoder vertex shader"); D3D::SetDebugObjectName(m_vShader, "efb encoder vertex shader");
// Create input layout for vertex quad using bytecode from vertex shader // Create input layout for vertex quad using bytecode from vertex shader
m_quadLayout = CreateInputLayoutShared(QUAD_LAYOUT_DESC,
hr = D3D::device->CreateInputLayout(QUAD_LAYOUT_DESC, sizeof(QUAD_LAYOUT_DESC) / sizeof(D3D11_INPUT_ELEMENT_DESC),
sizeof(QUAD_LAYOUT_DESC)/sizeof(D3D11_INPUT_ELEMENT_DESC), bytecode->GetBufferPointer(), bytecode->GetBufferSize());
bytecode->Data(), bytecode->Size(), &m_quadLayout); CHECK(m_quadLayout, "create efb encode quad vertex layout");
CHECK(SUCCEEDED(hr), "create efb encode quad vertex layout");
D3D::SetDebugObjectName(m_quadLayout, "efb encoder quad layout"); D3D::SetDebugObjectName(m_quadLayout, "efb encoder quad layout");
bytecode->Release();
// Create pixel shader // Create pixel shader
#ifdef USE_DYNAMIC_MODE #ifdef USE_DYNAMIC_MODE
@ -958,44 +941,46 @@ void PSTextureEncoder::Init()
return; return;
// Create blend state // Create blend state
{
D3D11_BLEND_DESC bld = CD3D11_BLEND_DESC(CD3D11_DEFAULT()); auto const bld = CD3D11_BLEND_DESC(CD3D11_DEFAULT());
hr = D3D::device->CreateBlendState(&bld, &m_efbEncodeBlendState); m_efbEncodeBlendState = CreateBlendStateShared(&bld);
CHECK(SUCCEEDED(hr), "create efb encode blend state"); CHECK(SUCCEEDED(hr), "create efb encode blend state");
D3D::SetDebugObjectName(m_efbEncodeBlendState, "efb encoder blend state"); D3D::SetDebugObjectName(m_efbEncodeBlendState, "efb encoder blend state");
}
// Create depth state // Create depth state
{
D3D11_DEPTH_STENCIL_DESC dsd = CD3D11_DEPTH_STENCIL_DESC(CD3D11_DEFAULT()); auto dsd = CD3D11_DEPTH_STENCIL_DESC(CD3D11_DEFAULT());
dsd.DepthEnable = FALSE; dsd.DepthEnable = FALSE;
hr = D3D::device->CreateDepthStencilState(&dsd, &m_efbEncodeDepthState); hr = D3D::g_device->CreateDepthStencilState(&dsd, &m_efbEncodeDepthState);
CHECK(SUCCEEDED(hr), "create efb encode depth state"); CHECK(SUCCEEDED(hr), "create efb encode depth state");
D3D::SetDebugObjectName(m_efbEncodeDepthState, "efb encoder depth state"); D3D::SetDebugObjectName(m_efbEncodeDepthState, "efb encoder depth state");
}
// Create rasterizer state // Create rasterizer state
{
D3D11_RASTERIZER_DESC rd = CD3D11_RASTERIZER_DESC(CD3D11_DEFAULT()); auto rd = CD3D11_RASTERIZER_DESC(CD3D11_DEFAULT());
rd.CullMode = D3D11_CULL_NONE; rd.CullMode = D3D11_CULL_NONE;
rd.DepthClipEnable = FALSE; rd.DepthClipEnable = FALSE;
hr = D3D::device->CreateRasterizerState(&rd, &m_efbEncodeRastState); hr = D3D::g_device->CreateRasterizerState(&rd, &m_efbEncodeRastState);
CHECK(SUCCEEDED(hr), "create efb encode rast state"); CHECK(SUCCEEDED(hr), "create efb encode rast state");
D3D::SetDebugObjectName(m_efbEncodeRastState, "efb encoder rast state"); D3D::SetDebugObjectName(m_efbEncodeRastState, "efb encoder rast state");
}
// Create efb texture sampler // Create efb texture sampler
{
D3D11_SAMPLER_DESC sd = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT()); auto sd = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT());
sd.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sd.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
hr = D3D::device->CreateSamplerState(&sd, &m_efbSampler); hr = D3D::g_device->CreateSamplerState(&sd, &m_efbSampler);
CHECK(SUCCEEDED(hr), "create efb encode texture sampler"); CHECK(SUCCEEDED(hr), "create efb encode texture sampler");
D3D::SetDebugObjectName(m_efbSampler, "efb encoder texture sampler"); D3D::SetDebugObjectName(m_efbSampler, "efb encoder texture sampler");
}
m_ready = true; m_ready = true;
} }
void PSTextureEncoder::Shutdown() PSTextureEncoder::~PSTextureEncoder()
{ {
m_ready = false;
for (size_t i = 0; i < 4; ++i) for (size_t i = 0; i < 4; ++i)
SAFE_RELEASE(m_fetchClass[i]); SAFE_RELEASE(m_fetchClass[i]);
for (size_t i = 0; i < 2; ++i) for (size_t i = 0; i < 2; ++i)
@ -1004,29 +989,13 @@ void PSTextureEncoder::Shutdown()
SAFE_RELEASE(m_intensityClass[i]); SAFE_RELEASE(m_intensityClass[i]);
for (size_t i = 0; i < 16; ++i) for (size_t i = 0; i < 16; ++i)
SAFE_RELEASE(m_generatorClass[i]); SAFE_RELEASE(m_generatorClass[i]);
m_linkageArray.clear();
SAFE_RELEASE(m_classLinkage); SAFE_RELEASE(m_classLinkage);
SAFE_RELEASE(m_dynamicShader);
for (ComboMap::iterator it = m_staticShaders.begin();
it != m_staticShaders.end(); ++it)
{
SAFE_RELEASE(it->second);
}
m_staticShaders.clear();
SAFE_RELEASE(m_efbSampler); SAFE_RELEASE(m_efbSampler);
SAFE_RELEASE(m_efbEncodeRastState); SAFE_RELEASE(m_efbEncodeRastState);
SAFE_RELEASE(m_efbEncodeDepthState); SAFE_RELEASE(m_efbEncodeDepthState);
SAFE_RELEASE(m_efbEncodeBlendState);
SAFE_RELEASE(m_quadLayout);
SAFE_RELEASE(m_vShader);
SAFE_RELEASE(m_quad);
SAFE_RELEASE(m_encodeParams);
SAFE_RELEASE(m_outStage);
SAFE_RELEASE(m_outRTV); SAFE_RELEASE(m_outRTV);
SAFE_RELEASE(m_out);
} }
size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat,
@ -1083,7 +1052,7 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat,
if (SetStaticShader(dstFormat, srcFormat, isIntensity, scaleByHalf)) if (SetStaticShader(dstFormat, srcFormat, isIntensity, scaleByHalf))
#endif #endif
{ {
D3D::context->VSSetShader(m_vShader, NULL, 0); D3D::g_context->VSSetShader(m_vShader, NULL, 0);
D3D::stateman->PushBlendState(m_efbEncodeBlendState); D3D::stateman->PushBlendState(m_efbEncodeBlendState);
D3D::stateman->PushDepthState(m_efbEncodeDepthState); D3D::stateman->PushDepthState(m_efbEncodeDepthState);
@ -1091,13 +1060,13 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat,
D3D::stateman->Apply(); D3D::stateman->Apply();
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(cacheLinesPerRow*2), FLOAT(numBlocksY)); D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(cacheLinesPerRow*2), FLOAT(numBlocksY));
D3D::context->RSSetViewports(1, &vp); D3D::g_context->RSSetViewports(1, &vp);
D3D::context->IASetInputLayout(m_quadLayout); D3D::g_context->IASetInputLayout(m_quadLayout);
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); D3D::g_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
UINT stride = sizeof(QuadVertex); UINT stride = sizeof(QuadVertex);
UINT offset = 0; UINT offset = 0;
D3D::context->IASetVertexBuffers(0, 1, &m_quad, &stride, &offset); D3D::g_context->IASetVertexBuffers(0, 1, &m_quad, &stride, &offset);
EFBRectangle fullSrcRect; EFBRectangle fullSrcRect;
fullSrcRect.left = 0; fullSrcRect.left = 0;
@ -1115,52 +1084,52 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat,
params.TexTop = float(targetRect.top) / g_renderer->GetFullTargetHeight(); params.TexTop = float(targetRect.top) / g_renderer->GetFullTargetHeight();
params.TexRight = float(targetRect.right) / g_renderer->GetFullTargetWidth(); params.TexRight = float(targetRect.right) / g_renderer->GetFullTargetWidth();
params.TexBottom = float(targetRect.bottom) / g_renderer->GetFullTargetHeight(); params.TexBottom = float(targetRect.bottom) / g_renderer->GetFullTargetHeight();
D3D::context->UpdateSubresource(m_encodeParams, 0, NULL, &params, 0, 0); D3D::g_context->UpdateSubresource(m_encodeParams, 0, NULL, &params, 0, 0);
D3D::context->VSSetConstantBuffers(0, 1, &m_encodeParams); D3D::g_context->VSSetConstantBuffers(0, 1, &m_encodeParams);
D3D::context->OMSetRenderTargets(1, &m_outRTV, NULL); D3D::g_context->OMSetRenderTargets(1, &m_outRTV, NULL);
ID3D11ShaderResourceView* pEFB = (srcFormat == PIXELFMT_Z24) ? ID3D11ShaderResourceView* pEFB = (srcFormat == PIXELFMT_Z24) ?
FramebufferManager::GetEFBDepthTexture()->GetSRV() : FramebufferManager::GetEFBDepthTexture()->GetSRV() :
FramebufferManager::GetEFBColorTexture()->GetSRV(); FramebufferManager::GetEFBColorTexture()->GetSRV();
D3D::context->PSSetConstantBuffers(0, 1, &m_encodeParams); D3D::g_context->PSSetConstantBuffers(0, 1, &m_encodeParams);
D3D::context->PSSetShaderResources(0, 1, &pEFB); D3D::g_context->PSSetShaderResources(0, 1, &pEFB);
D3D::context->PSSetSamplers(0, 1, &m_efbSampler); D3D::g_context->PSSetSamplers(0, 1, &m_efbSampler);
// Encode! // Encode!
D3D::context->Draw(4, 0); D3D::g_context->Draw(4, 0);
// Copy to staging buffer // Copy to staging buffer
D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, cacheLinesPerRow*2, numBlocksY, 1); D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, cacheLinesPerRow*2, numBlocksY, 1);
D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox); D3D::g_context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox);
// Clean up state // Clean up state
IUnknown* nullDummy = NULL; IUnknown* nullDummy = NULL;
D3D::context->PSSetSamplers(0, 1, (ID3D11SamplerState**)&nullDummy); D3D::g_context->PSSetSamplers(0, 1, (ID3D11SamplerState**)&nullDummy);
D3D::context->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&nullDummy); D3D::g_context->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&nullDummy);
D3D::context->PSSetConstantBuffers(0, 1, (ID3D11Buffer**)&nullDummy); D3D::g_context->PSSetConstantBuffers(0, 1, (ID3D11Buffer**)&nullDummy);
D3D::context->OMSetRenderTargets(0, NULL, NULL); D3D::g_context->OMSetRenderTargets(0, NULL, NULL);
D3D::context->VSSetConstantBuffers(0, 1, (ID3D11Buffer**)&nullDummy); D3D::g_context->VSSetConstantBuffers(0, 1, (ID3D11Buffer**)&nullDummy);
D3D::stateman->PopRasterizerState(); D3D::stateman->PopRasterizerState();
D3D::stateman->PopDepthState(); D3D::stateman->PopDepthState();
D3D::stateman->PopBlendState(); D3D::stateman->PopBlendState();
D3D::context->PSSetShader(NULL, NULL, 0); D3D::g_context->PSSetShader(NULL, NULL, 0);
D3D::context->VSSetShader(NULL, NULL, 0); D3D::g_context->VSSetShader(NULL, NULL, 0);
// Transfer staging buffer to GameCube/Wii RAM // Transfer staging buffer to GameCube/Wii RAM
D3D11_MAPPED_SUBRESOURCE map = { 0 }; D3D11_MAPPED_SUBRESOURCE map = { 0 };
hr = D3D::context->Map(m_outStage, 0, D3D11_MAP_READ, 0, &map); hr = D3D::g_context->Map(m_outStage, 0, D3D11_MAP_READ, 0, &map);
CHECK(SUCCEEDED(hr), "map staging buffer"); CHECK(SUCCEEDED(hr), "map staging buffer");
u8* src = (u8*)map.pData; u8* src = (u8*)map.pData;
@ -1171,7 +1140,7 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat,
src += map.RowPitch; src += map.RowPitch;
} }
D3D::context->Unmap(m_outStage, 0); D3D::g_context->Unmap(m_outStage, 0);
encodeSize = bpmem.copyMipMapStrideChannels*32 * numBlocksY; encodeSize = bpmem.copyMipMapStrideChannels*32 * numBlocksY;
} }
@ -1179,8 +1148,7 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat,
// Restore API // Restore API
g_renderer->RestoreAPIState(); g_renderer->RestoreAPIState();
D3D::context->OMSetRenderTargets(1, D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(),
&FramebufferManager::GetEFBColorTexture()->GetRTV(),
FramebufferManager::GetEFBDepthTexture()->GetDSV()); FramebufferManager::GetEFBDepthTexture()->GetDSV());
return encodeSize; return encodeSize;
@ -1235,15 +1203,15 @@ bool PSTextureEncoder::SetStaticShader(unsigned int dstFormat, unsigned int srcF
case 0xC: generatorFuncName = "Generate_C"; break; case 0xC: generatorFuncName = "Generate_C"; break;
default: default:
WARN_LOG(VIDEO, "No generator available for dst format 0x%X; aborting", generatorNum); WARN_LOG(VIDEO, "No generator available for dst format 0x%X; aborting", generatorNum);
m_staticShaders[key] = NULL; m_staticShaders[key].reset();
return false; return false;
break;
} }
INFO_LOG(VIDEO, "Compiling efb encoding shader for dstFormat 0x%X, srcFormat %d, isIntensity %d, scaleByHalf %d", INFO_LOG(VIDEO, "Compiling efb encoding shader for dstFormat 0x%X, srcFormat %d, isIntensity %d, scaleByHalf %d",
dstFormat, srcFormat, isIntensity ? 1 : 0, scaleByHalf ? 1 : 0); dstFormat, srcFormat, isIntensity ? 1 : 0, scaleByHalf ? 1 : 0);
// Shader permutation not found, so compile it // Shader permutation not found, so compile it
D3DBlob* bytecode = NULL;
D3D_SHADER_MACRO macros[] = { D3D_SHADER_MACRO macros[] = {
{ "IMP_FETCH", FETCH_FUNC_NAMES[fetchNum] }, { "IMP_FETCH", FETCH_FUNC_NAMES[fetchNum] },
{ "IMP_SCALEDFETCH", SCALEDFETCH_FUNC_NAMES[scaledFetchNum] }, { "IMP_SCALEDFETCH", SCALEDFETCH_FUNC_NAMES[scaledFetchNum] },
@ -1251,29 +1219,30 @@ bool PSTextureEncoder::SetStaticShader(unsigned int dstFormat, unsigned int srcF
{ "IMP_GENERATOR", generatorFuncName }, { "IMP_GENERATOR", generatorFuncName },
{ NULL, NULL } { NULL, NULL }
}; };
if (!D3D::CompilePixelShader(EFB_ENCODE_PS, sizeof(EFB_ENCODE_PS), &bytecode, macros))
auto const bytecode = D3D::CompilePixelShader(EFB_ENCODE_PS, sizeof(EFB_ENCODE_PS), macros);
if (!bytecode)
{ {
WARN_LOG(VIDEO, "EFB encoder shader for dstFormat 0x%X, srcFormat %d, isIntensity %d, scaleByHalf %d failed to compile", WARN_LOG(VIDEO, "EFB encoder shader for dstFormat 0x%X, srcFormat %d, isIntensity %d, scaleByHalf %d failed to compile",
dstFormat, srcFormat, isIntensity ? 1 : 0, scaleByHalf ? 1 : 0); dstFormat, srcFormat, isIntensity ? 1 : 0, scaleByHalf ? 1 : 0);
// Add dummy shader to map to prevent trying to compile over and // Add dummy shader to map to prevent trying to compile over and
// over again // over again
m_staticShaders[key] = NULL; m_staticShaders[key].reset();
return false; return false;
} }
ID3D11PixelShader* newShader; ID3D11PixelShader* newShader = nullptr;
HRESULT hr = D3D::device->CreatePixelShader(bytecode->Data(), bytecode->Size(), NULL, &newShader); HRESULT hr = D3D::g_device->CreatePixelShader(bytecode->GetBufferPointer(), bytecode->GetBufferSize(), NULL, &newShader);
CHECK(SUCCEEDED(hr), "create efb encoder pixel shader"); CHECK(SUCCEEDED(hr), "create efb encoder pixel shader");
it = m_staticShaders.insert(std::make_pair(key, newShader)).first; it = m_staticShaders.insert(std::make_pair(key, SharedPtr<ID3D11PixelShader>::FromPtr(newShader))).first;
bytecode->Release();
} }
if (it != m_staticShaders.end()) if (it != m_staticShaders.end())
{ {
if (it->second) if (it->second)
{ {
D3D::context->PSSetShader(it->second, NULL, 0); D3D::g_context->PSSetShader(it->second, NULL, 0);
return true; return true;
} }
else else
@ -1285,32 +1254,24 @@ bool PSTextureEncoder::SetStaticShader(unsigned int dstFormat, unsigned int srcF
bool PSTextureEncoder::InitDynamicMode() bool PSTextureEncoder::InitDynamicMode()
{ {
HRESULT hr; const D3D_SHADER_MACRO macros[] = {
D3D_SHADER_MACRO macros[] = {
{ "DYNAMIC_MODE", NULL }, { "DYNAMIC_MODE", NULL },
{ NULL, NULL } { NULL, NULL }
}; };
D3DBlob* bytecode = NULL; HRESULT hr = D3D::g_device->CreateClassLinkage(&m_classLinkage);
if (!D3D::CompilePixelShader(EFB_ENCODE_PS, sizeof(EFB_ENCODE_PS), &bytecode, macros))
{
ERROR_LOG(VIDEO, "EFB encode pixel shader failed to compile");
return false;
}
hr = D3D::device->CreateClassLinkage(&m_classLinkage);
CHECK(SUCCEEDED(hr), "create efb encode class linkage"); CHECK(SUCCEEDED(hr), "create efb encode class linkage");
D3D::SetDebugObjectName(m_classLinkage, "efb encoder class linkage"); D3D::SetDebugObjectName(m_classLinkage, "efb encoder class linkage");
hr = D3D::device->CreatePixelShader(bytecode->Data(), bytecode->Size(), m_classLinkage, &m_dynamicShader); SharedPtr<ID3D10Blob> bytecode;
CHECK(SUCCEEDED(hr), "create efb encode pixel shader"); m_dynamicShader = D3D::CompileAndCreatePixelShader(EFB_ENCODE_PS, sizeof(EFB_ENCODE_PS), macros, std::addressof(bytecode));
CHECK(m_dynamicShader, "compile/create efb encode pixel shader");
D3D::SetDebugObjectName(m_dynamicShader, "efb encoder pixel shader"); D3D::SetDebugObjectName(m_dynamicShader, "efb encoder pixel shader");
// Use D3DReflect // Use D3DReflect
ID3D11ShaderReflection* reflect = NULL; ID3D11ShaderReflection* reflect = NULL;
hr = PD3DReflect(bytecode->Data(), bytecode->Size(), IID_ID3D11ShaderReflection, (void**)&reflect); hr = PD3DReflect(bytecode->GetBufferPointer(), bytecode->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&reflect);
CHECK(SUCCEEDED(hr), "reflect on efb encoder shader"); CHECK(SUCCEEDED(hr), "reflect on efb encoder shader");
// Get number of slots and create dynamic linkage array // Get number of slots and create dynamic linkage array
@ -1347,7 +1308,6 @@ bool PSTextureEncoder::InitDynamicMode()
m_generatorClass[i] = NULL; m_generatorClass[i] = NULL;
reflect->Release(); reflect->Release();
bytecode->Release();
return true; return true;
} }
@ -1385,6 +1345,7 @@ bool PSTextureEncoder::SetDynamicShader(unsigned int dstFormat,
default: default:
WARN_LOG(VIDEO, "No generator available for dst format 0x%X; aborting", generatorNum); WARN_LOG(VIDEO, "No generator available for dst format 0x%X; aborting", generatorNum);
return false; return false;
break;
} }
// Make sure class instances are available // Make sure class instances are available
@ -1433,7 +1394,7 @@ bool PSTextureEncoder::SetDynamicShader(unsigned int dstFormat,
if (m_generatorSlot != UINT(-1)) if (m_generatorSlot != UINT(-1))
m_linkageArray[m_generatorSlot] = m_generatorClass[generatorNum]; m_linkageArray[m_generatorSlot] = m_generatorClass[generatorNum];
D3D::context->PSSetShader(m_dynamicShader, D3D::g_context->PSSetShader(m_dynamicShader,
m_linkageArray.empty() ? NULL : &m_linkageArray[0], m_linkageArray.empty() ? NULL : &m_linkageArray[0],
(UINT)m_linkageArray.size()); (UINT)m_linkageArray.size());

View file

@ -19,48 +19,32 @@
#define _PSTEXTUREENCODER_H #define _PSTEXTUREENCODER_H
#include "TextureEncoder.h" #include "TextureEncoder.h"
#include "D3DUtil.h"
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 namespace DX11
{ {
class PSTextureEncoder : public TextureEncoder class PSTextureEncoder : public TextureEncoder
{ {
public: public:
PSTextureEncoder(); PSTextureEncoder();
~PSTextureEncoder();
void Init();
void Shutdown();
size_t Encode(u8* dst, unsigned int dstFormat, size_t Encode(u8* dst, unsigned int dstFormat,
unsigned int srcFormat, const EFBRectangle& srcRect, bool isIntensity, unsigned int srcFormat, const EFBRectangle& srcRect, bool isIntensity,
bool scaleByHalf); bool scaleByHalf);
private: private:
bool m_ready; bool m_ready;
ID3D11Texture2D* m_out; SharedPtr<ID3D11Texture2D> m_out;
ID3D11RenderTargetView* m_outRTV; ID3D11RenderTargetView* m_outRTV;
ID3D11Texture2D* m_outStage; SharedPtr<ID3D11Texture2D> m_outStage;
ID3D11Buffer* m_encodeParams; SharedPtr<ID3D11Buffer> m_encodeParams;
ID3D11Buffer* m_quad; SharedPtr<ID3D11Buffer> m_quad;
ID3D11VertexShader* m_vShader; SharedPtr<ID3D11VertexShader> m_vShader;
ID3D11InputLayout* m_quadLayout; SharedPtr<ID3D11InputLayout> m_quadLayout;
ID3D11BlendState* m_efbEncodeBlendState; SharedPtr<ID3D11BlendState> m_efbEncodeBlendState;
ID3D11DepthStencilState* m_efbEncodeDepthState; ID3D11DepthStencilState* m_efbEncodeDepthState;
ID3D11RasterizerState* m_efbEncodeRastState; ID3D11RasterizerState* m_efbEncodeRastState;
ID3D11SamplerState* m_efbSampler; ID3D11SamplerState* m_efbSampler;
@ -80,7 +64,7 @@ private:
| (scaleByHalf ? (1<<0) : 0); | (scaleByHalf ? (1<<0) : 0);
} }
typedef std::map<ComboKey, ID3D11PixelShader*> ComboMap; typedef std::map<ComboKey, SharedPtr<ID3D11PixelShader>> ComboMap;
ComboMap m_staticShaders; ComboMap m_staticShaders;
@ -91,7 +75,7 @@ private:
bool SetDynamicShader(unsigned int dstFormat, unsigned int srcFormat, bool SetDynamicShader(unsigned int dstFormat, unsigned int srcFormat,
bool isIntensity, bool scaleByHalf); bool isIntensity, bool scaleByHalf);
ID3D11PixelShader* m_dynamicShader; SharedPtr<ID3D11PixelShader> m_dynamicShader;
ID3D11ClassLinkage* m_classLinkage; ID3D11ClassLinkage* m_classLinkage;
// Interface slots // Interface slots
@ -111,7 +95,6 @@ private:
ID3D11ClassInstance* m_generatorClass[16]; ID3D11ClassInstance* m_generatorClass[16];
std::vector<ID3D11ClassInstance*> m_linkageArray; std::vector<ID3D11ClassInstance*> m_linkageArray;
}; };
} }

View file

@ -44,13 +44,14 @@ const PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry;
LinearDiskCache<PIXELSHADERUID, u8> g_ps_disk_cache; LinearDiskCache<PIXELSHADERUID, u8> g_ps_disk_cache;
ID3D11PixelShader* s_ColorMatrixProgram[2] = {NULL}; SharedPtr<ID3D11PixelShader> s_ColorMatrixProgram[2];
ID3D11PixelShader* s_ColorCopyProgram[2] = {NULL}; SharedPtr<ID3D11PixelShader> s_ColorCopyProgram[2];
ID3D11PixelShader* s_DepthMatrixProgram[2] = {NULL}; SharedPtr<ID3D11PixelShader> s_DepthMatrixProgram[2];
ID3D11PixelShader* s_ClearProgram = NULL; SharedPtr<ID3D11PixelShader> s_ClearProgram;
ID3D11PixelShader* s_rgba6_to_rgb8 = NULL; SharedPtr<ID3D11PixelShader> s_rgba6_to_rgb8;
ID3D11PixelShader* s_rgb8_to_rgba6 = NULL; SharedPtr<ID3D11PixelShader> s_rgb8_to_rgba6;
ID3D11Buffer* pscbuf = NULL;
SharedPtr<ID3D11Buffer> pscbuf;
const char clear_program_code[] = { const char clear_program_code[] = {
"void main(\n" "void main(\n"
@ -178,11 +179,13 @@ ID3D11PixelShader* PixelShaderCache::ReinterpRGBA6ToRGB8()
"}" "}"
}; };
if(s_rgba6_to_rgb8) return s_rgba6_to_rgb8; if (!s_rgba6_to_rgb8)
{
s_rgba6_to_rgb8 = D3D::CompileAndCreatePixelShader(code, sizeof(code)); s_rgba6_to_rgb8 = D3D::CompileAndCreatePixelShader(code, sizeof(code));
CHECK(s_rgba6_to_rgb8!=NULL, "Create RGBA6 to RGB8 pixel shader"); CHECK(s_rgba6_to_rgb8, "Create RGBA6 to RGB8 pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_rgba6_to_rgb8, "RGBA6 to RGB8 pixel shader"); D3D::SetDebugObjectName(s_rgba6_to_rgb8, "RGBA6 to RGB8 pixel shader");
}
return s_rgba6_to_rgb8; return s_rgba6_to_rgb8;
} }
@ -207,63 +210,80 @@ ID3D11PixelShader* PixelShaderCache::ReinterpRGB8ToRGBA6()
"}\n" "}\n"
}; };
if(s_rgb8_to_rgba6) return s_rgb8_to_rgba6; if (!s_rgb8_to_rgba6)
{
s_rgb8_to_rgba6 = D3D::CompileAndCreatePixelShader(code, sizeof(code));
CHECK(s_rgb8_to_rgba6, "Create RGB8 to RGBA6 pixel shader");
D3D::SetDebugObjectName(s_rgb8_to_rgba6, "RGB8 to RGBA6 pixel shader");
}
s_rgb8_to_rgba6 = D3D::CompileAndCreatePixelShader(code, sizeof(code));
CHECK(s_rgb8_to_rgba6!=NULL, "Create RGB8 to RGBA6 pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_rgb8_to_rgba6, "RGB8 to RGBA6 pixel shader");
return s_rgb8_to_rgba6; return s_rgb8_to_rgba6;
} }
ID3D11PixelShader* PixelShaderCache::GetColorCopyProgram(bool multisampled) ID3D11PixelShader* PixelShaderCache::GetColorCopyProgram(bool multisampled)
{ {
if (!multisampled || D3D::GetAAMode(g_ActiveConfig.iMultisampleMode).Count == 1) return s_ColorCopyProgram[0]; if (!multisampled || D3D::GetAAMode(g_ActiveConfig.iMultisampleMode).Count == 1)
else if (s_ColorCopyProgram[1]) return s_ColorCopyProgram[1]; {
else return s_ColorCopyProgram[0];
}
else if (!s_ColorCopyProgram[1])
{ {
// TODO: recreate shader on AA mode change! // TODO: recreate shader on AA mode change!
// create MSAA shader for current AA mode // create MSAA shader for current AA mode
char buf[1024]; char buf[1024];
int l = sprintf_s(buf, 1024, color_copy_program_code_msaa, D3D::GetAAMode(g_ActiveConfig.iMultisampleMode)); const int l = sprintf_s(buf, 1024, color_copy_program_code_msaa, D3D::GetAAMode(g_ActiveConfig.iMultisampleMode));
s_ColorCopyProgram[1] = D3D::CompileAndCreatePixelShader(buf, l); s_ColorCopyProgram[1] = D3D::CompileAndCreatePixelShader(buf, l);
CHECK(s_ColorCopyProgram[1]!=NULL, "Create color copy MSAA pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ColorCopyProgram[1], "color copy MSAA pixel shader"); CHECK(s_ColorCopyProgram[1], "Create color copy MSAA pixel shader");
return s_ColorCopyProgram[1]; D3D::SetDebugObjectName(s_ColorCopyProgram[1], "color copy MSAA pixel shader");
} }
return s_ColorCopyProgram[1];
} }
ID3D11PixelShader* PixelShaderCache::GetColorMatrixProgram(bool multisampled) ID3D11PixelShader* PixelShaderCache::GetColorMatrixProgram(bool multisampled)
{ {
if (!multisampled || D3D::GetAAMode(g_ActiveConfig.iMultisampleMode).Count == 1) return s_ColorMatrixProgram[0]; if (!multisampled || D3D::GetAAMode(g_ActiveConfig.iMultisampleMode).Count == 1)
else if (s_ColorMatrixProgram[1]) return s_ColorMatrixProgram[1]; {
else return s_ColorMatrixProgram[0];
}
else if (!s_ColorMatrixProgram[1])
{ {
// TODO: recreate shader on AA mode change! // TODO: recreate shader on AA mode change!
// create MSAA shader for current AA mode // create MSAA shader for current AA mode
char buf[1024]; char buf[1024];
int l = sprintf_s(buf, 1024, color_matrix_program_code_msaa, D3D::GetAAMode(g_ActiveConfig.iMultisampleMode)); const int l = sprintf_s(buf, 1024, color_matrix_program_code_msaa, D3D::GetAAMode(g_ActiveConfig.iMultisampleMode));
s_ColorMatrixProgram[1] = D3D::CompileAndCreatePixelShader(buf, l); s_ColorMatrixProgram[1] = D3D::CompileAndCreatePixelShader(buf, l);
CHECK(s_ColorMatrixProgram[1]!=NULL, "Create color matrix MSAA pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ColorMatrixProgram[1], "color matrix MSAA pixel shader"); CHECK(s_ColorMatrixProgram[1], "Create color matrix MSAA pixel shader");
return s_ColorMatrixProgram[1]; D3D::SetDebugObjectName(s_ColorMatrixProgram[1], "color matrix MSAA pixel shader");
} }
return s_ColorMatrixProgram[1];
} }
ID3D11PixelShader* PixelShaderCache::GetDepthMatrixProgram(bool multisampled) ID3D11PixelShader* PixelShaderCache::GetDepthMatrixProgram(bool multisampled)
{ {
if (!multisampled || D3D::GetAAMode(g_ActiveConfig.iMultisampleMode).Count == 1) return s_DepthMatrixProgram[0]; if (!multisampled || D3D::GetAAMode(g_ActiveConfig.iMultisampleMode).Count == 1)
else if (s_DepthMatrixProgram[1]) return s_DepthMatrixProgram[1]; {
else return s_DepthMatrixProgram[0];
}
else if (!s_DepthMatrixProgram[1])
{ {
// TODO: recreate shader on AA mode change! // TODO: recreate shader on AA mode change!
// create MSAA shader for current AA mode // create MSAA shader for current AA mode
char buf[1024]; char buf[1024];
int l = sprintf_s(buf, 1024, depth_matrix_program_msaa, D3D::GetAAMode(g_ActiveConfig.iMultisampleMode)); const int l = sprintf_s(buf, 1024, depth_matrix_program_msaa, D3D::GetAAMode(g_ActiveConfig.iMultisampleMode));
s_DepthMatrixProgram[1] = D3D::CompileAndCreatePixelShader(buf, l); s_DepthMatrixProgram[1] = D3D::CompileAndCreatePixelShader(buf, l);
CHECK(s_DepthMatrixProgram[1]!=NULL, "Create depth matrix MSAA pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_DepthMatrixProgram[1], "depth matrix MSAA pixel shader"); CHECK(s_DepthMatrixProgram[1], "Create depth matrix MSAA pixel shader");
return s_DepthMatrixProgram[1]; D3D::SetDebugObjectName(s_DepthMatrixProgram[1], "depth matrix MSAA pixel shader");
} }
return s_DepthMatrixProgram[1];
} }
ID3D11PixelShader* PixelShaderCache::GetClearProgram() ID3D11PixelShader* PixelShaderCache::GetClearProgram()
@ -271,15 +291,15 @@ ID3D11PixelShader* PixelShaderCache::GetClearProgram()
return s_ClearProgram; return s_ClearProgram;
} }
ID3D11Buffer* &PixelShaderCache::GetConstantBuffer() ID3D11Buffer*const& PixelShaderCache::GetConstantBuffer()
{ {
// TODO: divide the global variables of the generated shaders into about 5 constant buffers to speed this up // TODO: divide the global variables of the generated shaders into about 5 constant buffers to speed this up
if (pscbufchanged) if (pscbufchanged)
{ {
D3D11_MAPPED_SUBRESOURCE map; D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(pscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); D3D::g_context->Map(pscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, psconstants, sizeof(psconstants)); memcpy(map.pData, psconstants, sizeof(psconstants));
D3D::context->Unmap(pscbuf, 0); D3D::g_context->Unmap(pscbuf, 0);
pscbufchanged = false; pscbufchanged = false;
} }
return pscbuf; return pscbuf;
@ -299,29 +319,29 @@ void PixelShaderCache::Init()
{ {
unsigned int cbsize = ((sizeof(psconstants))&(~0xf))+0x10; // must be a multiple of 16 unsigned int cbsize = ((sizeof(psconstants))&(~0xf))+0x10; // must be a multiple of 16
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
D3D::device->CreateBuffer(&cbdesc, NULL, &pscbuf); pscbuf = CreateBufferShared(&cbdesc, NULL);
CHECK(pscbuf!=NULL, "Create pixel shader constant buffer"); CHECK(pscbuf, "Create pixel shader constant buffer");
D3D::SetDebugObjectName((ID3D11DeviceChild*)pscbuf, "pixel shader constant buffer used to emulate the GX pipeline"); D3D::SetDebugObjectName(pscbuf, "pixel shader constant buffer used to emulate the GX pipeline");
// used when drawing clear quads // used when drawing clear quads
s_ClearProgram = D3D::CompileAndCreatePixelShader(clear_program_code, sizeof(clear_program_code)); s_ClearProgram = D3D::CompileAndCreatePixelShader(clear_program_code, sizeof(clear_program_code));
CHECK(s_ClearProgram!=NULL, "Create clear pixel shader"); CHECK(s_ClearProgram, "Create clear pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ClearProgram, "clear pixel shader"); D3D::SetDebugObjectName(s_ClearProgram, "clear pixel shader");
// used when copying/resolving the color buffer // used when copying/resolving the color buffer
s_ColorCopyProgram[0] = D3D::CompileAndCreatePixelShader(color_copy_program_code, sizeof(color_copy_program_code)); s_ColorCopyProgram[0] = D3D::CompileAndCreatePixelShader(color_copy_program_code, sizeof(color_copy_program_code));
CHECK(s_ColorCopyProgram[0]!=NULL, "Create color copy pixel shader"); CHECK(s_ColorCopyProgram[0], "Create color copy pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ColorCopyProgram[0], "color copy pixel shader"); D3D::SetDebugObjectName(s_ColorCopyProgram[0], "color copy pixel shader");
// used for color conversion // used for color conversion
s_ColorMatrixProgram[0] = D3D::CompileAndCreatePixelShader(color_matrix_program_code, sizeof(color_matrix_program_code)); s_ColorMatrixProgram[0] = D3D::CompileAndCreatePixelShader(color_matrix_program_code, sizeof(color_matrix_program_code));
CHECK(s_ColorMatrixProgram[0]!=NULL, "Create color matrix pixel shader"); CHECK(s_ColorMatrixProgram[0], "Create color matrix pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_ColorMatrixProgram[0], "color matrix pixel shader"); D3D::SetDebugObjectName(s_ColorMatrixProgram[0], "color matrix pixel shader");
// used for depth copy // used for depth copy
s_DepthMatrixProgram[0] = D3D::CompileAndCreatePixelShader(depth_matrix_program, sizeof(depth_matrix_program)); s_DepthMatrixProgram[0] = D3D::CompileAndCreatePixelShader(depth_matrix_program, sizeof(depth_matrix_program));
CHECK(s_DepthMatrixProgram[0]!=NULL, "Create depth matrix pixel shader"); CHECK(s_DepthMatrixProgram[0], "Create depth matrix pixel shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)s_DepthMatrixProgram[0], "depth matrix pixel shader"); D3D::SetDebugObjectName(s_DepthMatrixProgram[0], "depth matrix pixel shader");
Clear(); Clear();
@ -341,31 +361,29 @@ void PixelShaderCache::Init()
// ONLY to be used during shutdown. // ONLY to be used during shutdown.
void PixelShaderCache::Clear() void PixelShaderCache::Clear()
{ {
for (PSCache::iterator iter = PixelShaders.begin(); iter != PixelShaders.end(); iter++)
iter->second.Destroy();
PixelShaders.clear(); PixelShaders.clear();
} }
// Used in Swap() when AA mode has changed // Used in Swap() when AA mode has changed
void PixelShaderCache::InvalidateMSAAShaders() void PixelShaderCache::InvalidateMSAAShaders()
{ {
SAFE_RELEASE(s_ColorCopyProgram[1]); s_ColorCopyProgram[1].reset();
SAFE_RELEASE(s_ColorMatrixProgram[1]); s_ColorMatrixProgram[1].reset();
SAFE_RELEASE(s_DepthMatrixProgram[1]); s_DepthMatrixProgram[1].reset();
} }
void PixelShaderCache::Shutdown() void PixelShaderCache::Shutdown()
{ {
SAFE_RELEASE(pscbuf); pscbuf.reset();
SAFE_RELEASE(s_rgba6_to_rgb8); s_rgba6_to_rgb8.reset();
SAFE_RELEASE(s_rgb8_to_rgba6); s_rgb8_to_rgba6.reset();
SAFE_RELEASE(s_ClearProgram); s_ClearProgram.reset();
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
{ {
SAFE_RELEASE(s_ColorCopyProgram[i]); s_ColorCopyProgram[i].reset();
SAFE_RELEASE(s_ColorMatrixProgram[i]); s_ColorMatrixProgram[i].reset();
SAFE_RELEASE(s_DepthMatrixProgram[i]); s_DepthMatrixProgram[i].reset();
} }
Clear(); Clear();
@ -373,7 +391,7 @@ void PixelShaderCache::Shutdown()
g_ps_disk_cache.Close(); g_ps_disk_cache.Close();
} }
bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components) bool PixelShaderCache::LoadShader(DSTALPHA_MODE dstAlphaMode, u32 components)
{ {
PIXELSHADERUID uid; PIXELSHADERUID uid;
GetPixelShaderId(&uid, dstAlphaMode); GetPixelShaderId(&uid, dstAlphaMode);
@ -398,14 +416,14 @@ bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
last_entry = &entry; last_entry = &entry;
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true); GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true);
return (entry.shader != NULL); return (!!entry.shader);
} }
// Need to compile a new shader // Need to compile a new shader
const char* code = GeneratePixelShaderCode(dstAlphaMode, API_D3D11, components); const char* code = GeneratePixelShaderCode(dstAlphaMode, API_D3D11, components);
D3DBlob* pbytecode; auto const pbytecode = D3D::CompilePixelShader(code, (unsigned int)strlen(code));
if (!D3D::CompilePixelShader(code, (unsigned int)strlen(code), &pbytecode)) if (!pbytecode)
{ {
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code); PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
@ -413,25 +431,25 @@ bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
} }
// Insert the bytecode into the caches // Insert the bytecode into the caches
g_ps_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size()); g_ps_disk_cache.Append(uid, (u8*)pbytecode->GetBufferPointer(), (u32)pbytecode->GetBufferSize());
g_ps_disk_cache.Sync(); g_ps_disk_cache.Sync();
bool result = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size()); bool result = InsertByteCode(uid, pbytecode->GetBufferPointer(), (u32)pbytecode->GetBufferSize());
pbytecode->Release();
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
return result; return result;
} }
bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const void* bytecode, unsigned int bytecodelen) bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const void* bytecode, unsigned int bytecodelen)
{ {
ID3D11PixelShader* shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen); auto const shader = D3D::CreatePixelShaderFromByteCode(bytecode, bytecodelen);
if (shader == NULL) if (!shader)
{ {
PanicAlert("Failed to create pixel shader at %s %d\n", __FILE__, __LINE__); PanicAlert("Failed to create pixel shader at %s %d\n", __FILE__, __LINE__);
// INCSTAT(stats.numPixelShadersFailed);
return false; return false;
} }
// TODO: Somehow make the debug name a bit more specific // TODO: Somehow make the debug name a bit more specific
D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a pixel shader of PixelShaderCache"); D3D::SetDebugObjectName(shader, "a pixel shader of PixelShaderCache");
// Make an entry in the table // Make an entry in the table
PSCacheEntry newentry; PSCacheEntry newentry;
@ -440,11 +458,6 @@ bool PixelShaderCache::InsertByteCode(const PIXELSHADERUID &uid, const void* byt
PixelShaders[uid] = newentry; PixelShaders[uid] = newentry;
last_entry = &PixelShaders[uid]; last_entry = &PixelShaders[uid];
if (!shader) {
// INCSTAT(stats.numPixelShadersFailed);
return false;
}
INCSTAT(stats.numPixelShadersCreated); INCSTAT(stats.numPixelShadersCreated);
SETSTAT(stats.numPixelShadersAlive, PixelShaders.size()); SETSTAT(stats.numPixelShadersAlive, PixelShaders.size());
return true; return true;

View file

@ -33,11 +33,12 @@ public:
static void Init(); static void Init();
static void Clear(); static void Clear();
static void Shutdown(); static void Shutdown();
static bool SetShader(DSTALPHA_MODE dstAlphaMode, u32 components); // TODO: Should be renamed to LoadShader
static bool LoadShader(DSTALPHA_MODE dstAlphaMode, u32 components);
static bool InsertByteCode(const PIXELSHADERUID &uid, const void* bytecode, unsigned int bytecodelen); static bool InsertByteCode(const PIXELSHADERUID &uid, const void* bytecode, unsigned int bytecodelen);
static ID3D11PixelShader* GetActiveShader() { return last_entry->shader; } static SharedPtr<ID3D11PixelShader> GetActiveShader() { return last_entry->shader; }
static ID3D11Buffer* &GetConstantBuffer(); static ID3D11Buffer*const& GetConstantBuffer();
static ID3D11PixelShader* GetColorMatrixProgram(bool multisampled); static ID3D11PixelShader* GetColorMatrixProgram(bool multisampled);
static ID3D11PixelShader* GetColorCopyProgram(bool multisampled); static ID3D11PixelShader* GetColorCopyProgram(bool multisampled);
@ -51,11 +52,10 @@ public:
private: private:
struct PSCacheEntry struct PSCacheEntry
{ {
ID3D11PixelShader* shader; SharedPtr<ID3D11PixelShader> shader;
int frameCount; int frameCount;
PSCacheEntry() : shader(NULL), frameCount(0) {} PSCacheEntry() : frameCount(0) {}
void Destroy() { SAFE_RELEASE(shader); }
}; };
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache; typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;

View file

@ -128,39 +128,19 @@ static const char POINT_GS_COMMON[] =
; ;
PointGeometryShader::PointGeometryShader() PointGeometryShader::PointGeometryShader()
: m_ready(false), m_paramsBuffer(NULL) : m_ready(false)
{ }
void PointGeometryShader::Init()
{ {
m_ready = false;
HRESULT hr;
// Create constant buffer for uploading data to geometry shader // Create constant buffer for uploading data to geometry shader
D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(PointGSParams), D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(PointGSParams),
D3D11_BIND_CONSTANT_BUFFER); D3D11_BIND_CONSTANT_BUFFER);
hr = D3D::device->CreateBuffer(&bd, NULL, &m_paramsBuffer); m_paramsBuffer = CreateBufferShared(&bd, NULL);
CHECK(SUCCEEDED(hr), "create point geometry shader params buffer"); CHECK(m_paramsBuffer, "create point geometry shader params buffer");
D3D::SetDebugObjectName(m_paramsBuffer, "point geometry shader params buffer"); D3D::SetDebugObjectName(m_paramsBuffer, "point geometry shader params buffer");
m_ready = true; m_ready = true;
} }
void PointGeometryShader::Shutdown()
{
m_ready = false;
for (ComboMap::iterator it = m_shaders.begin(); it != m_shaders.end(); ++it)
{
SAFE_RELEASE(it->second);
}
m_shaders.clear();
SAFE_RELEASE(m_paramsBuffer);
}
bool PointGeometryShader::SetShader(u32 components, float pointSize, bool PointGeometryShader::SetShader(u32 components, float pointSize,
float texOffset, float vpWidth, float vpHeight) float texOffset, float vpWidth, float vpHeight)
{ {
@ -187,12 +167,13 @@ bool PointGeometryShader::SetShader(u32 components, float pointSize,
{ "NUM_TEXCOORDS", numTexCoordsStr.str().c_str() }, { "NUM_TEXCOORDS", numTexCoordsStr.str().c_str() },
{ NULL, NULL } { NULL, NULL }
}; };
ID3D11GeometryShader* newShader = D3D::CompileAndCreateGeometryShader(code, unsigned int(strlen(code)), macros);
auto const newShader = D3D::CompileAndCreateGeometryShader(code, unsigned int(strlen(code)), macros);
if (!newShader) if (!newShader)
{ {
WARN_LOG(VIDEO, "Point geometry shader for components 0x%.08X failed to compile", components); WARN_LOG(VIDEO, "Point geometry shader for components 0x%.08X failed to compile", components);
// Add dummy shader to prevent trying to compile again // Add dummy shader to prevent trying to compile again
m_shaders[components] = NULL; m_shaders[components].reset();
return false; return false;
} }
@ -203,18 +184,18 @@ bool PointGeometryShader::SetShader(u32 components, float pointSize,
{ {
if (shaderIt->second) if (shaderIt->second)
{ {
PointGSParams params = { 0 }; PointGSParams params = {};
params.PointSize = pointSize; params.PointSize = pointSize;
params.TexOffset = texOffset; params.TexOffset = texOffset;
params.VpWidth = vpWidth; params.VpWidth = vpWidth;
params.VpHeight = vpHeight; params.VpHeight = vpHeight;
D3D::context->UpdateSubresource(m_paramsBuffer, 0, NULL, &params, 0, 0); D3D::g_context->UpdateSubresource(m_paramsBuffer, 0, NULL, &params, 0, 0);
DEBUG_LOG(VIDEO, "Point params: size %f, texOffset %f, vpWidth %f, vpHeight %f", DEBUG_LOG(VIDEO, "Point params: size %f, texOffset %f, vpWidth %f, vpHeight %f",
pointSize, texOffset, vpWidth, vpHeight); pointSize, texOffset, vpWidth, vpHeight);
D3D::context->GSSetShader(shaderIt->second, NULL, 0); D3D::g_context->GSSetShader(shaderIt->second, NULL, 0);
D3D::context->GSSetConstantBuffers(0, 1, &m_paramsBuffer); D3D::g_context->GSSetConstantBuffers(0, 1, &m_paramsBuffer);
return true; return true;
} }

View file

@ -19,9 +19,7 @@
#define _POINTGEOMETRYSHADER_H #define _POINTGEOMETRYSHADER_H
#include "VideoCommon.h" #include "VideoCommon.h"
#include "D3DUtil.h"
struct ID3D11Buffer;
struct ID3D11GeometryShader;
namespace DX11 namespace DX11
{ {
@ -30,27 +28,21 @@ namespace DX11
// vertex format. // vertex format.
class PointGeometryShader class PointGeometryShader
{ {
public: public:
PointGeometryShader(); PointGeometryShader();
void Init();
void Shutdown();
// Returns true on success, false on failure // Returns true on success, false on failure
bool SetShader(u32 components, float pointSize, float texOffset, bool SetShader(u32 components, float pointSize, float texOffset,
float vpWidth, float vpHeight); float vpWidth, float vpHeight);
private: private:
bool m_ready; bool m_ready;
ID3D11Buffer* m_paramsBuffer; SharedPtr<ID3D11Buffer> m_paramsBuffer;
typedef std::map<u32, ID3D11GeometryShader*> ComboMap; typedef std::map<u32, SharedPtr<ID3D11GeometryShader>> ComboMap;
ComboMap m_shaders; ComboMap m_shaders;
}; };
} }

View file

@ -40,7 +40,6 @@
#include "VertexShaderCache.h" #include "VertexShaderCache.h"
#include "Core.h" #include "Core.h"
#include "OnFrame.h" #include "OnFrame.h"
#include "Television.h"
#include "Host.h" #include "Host.h"
namespace DX11 namespace DX11
@ -52,12 +51,10 @@ static u32 s_LastAA = 0;
static u32 s_blendMode; static u32 s_blendMode;
static Television s_television; SharedPtr<ID3D11Buffer> access_efb_cbuf;
SharedPtr<ID3D11BlendState> clearblendstates[4];
ID3D11Buffer* access_efb_cbuf = NULL;
ID3D11BlendState* clearblendstates[4] = {NULL};
ID3D11DepthStencilState* cleardepthstates[3] = {NULL}; ID3D11DepthStencilState* cleardepthstates[3] = {NULL};
ID3D11BlendState* resetblendstate = NULL; SharedPtr<ID3D11BlendState> resetblendstate;
ID3D11DepthStencilState* resetdepthstate = NULL; ID3D11DepthStencilState* resetdepthstate = NULL;
ID3D11RasterizerState* resetraststate = NULL; ID3D11RasterizerState* resetraststate = NULL;
@ -217,8 +214,6 @@ static const D3D11_TEXTURE_ADDRESS_MODE d3dClamps[4] =
void SetupDeviceObjects() void SetupDeviceObjects()
{ {
s_television.Init();
g_framebuffer_manager = new FramebufferManager; g_framebuffer_manager = new FramebufferManager;
HRESULT hr; HRESULT hr;
@ -227,9 +222,9 @@ void SetupDeviceObjects()
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(20*sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT); D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(20*sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT);
D3D11_SUBRESOURCE_DATA data; D3D11_SUBRESOURCE_DATA data;
data.pSysMem = colmat; data.pSysMem = colmat;
hr = D3D::device->CreateBuffer(&cbdesc, &data, &access_efb_cbuf); access_efb_cbuf = CreateBufferShared(&cbdesc, &data);
CHECK(hr==S_OK, "Create constant buffer for Renderer::AccessEFB"); CHECK(access_efb_cbuf, "Create constant buffer for Renderer::AccessEFB");
D3D::SetDebugObjectName((ID3D11DeviceChild*)access_efb_cbuf, "constant buffer for Renderer::AccessEFB"); D3D::SetDebugObjectName(access_efb_cbuf, "constant buffer for Renderer::AccessEFB");
D3D11_DEPTH_STENCIL_DESC ddesc; D3D11_DEPTH_STENCIL_DESC ddesc;
ddesc.DepthEnable = FALSE; ddesc.DepthEnable = FALSE;
@ -238,18 +233,18 @@ void SetupDeviceObjects()
ddesc.StencilEnable = FALSE; ddesc.StencilEnable = FALSE;
ddesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; ddesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
ddesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; ddesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
hr = D3D::device->CreateDepthStencilState(&ddesc, &cleardepthstates[0]); hr = D3D::g_device->CreateDepthStencilState(&ddesc, &cleardepthstates[0]);
CHECK(hr==S_OK, "Create depth state for Renderer::ClearScreen"); CHECK(hr==S_OK, "Create depth state for Renderer::ClearScreen");
ddesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; ddesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
ddesc.DepthEnable = TRUE; ddesc.DepthEnable = TRUE;
hr = D3D::device->CreateDepthStencilState(&ddesc, &cleardepthstates[1]); hr = D3D::g_device->CreateDepthStencilState(&ddesc, &cleardepthstates[1]);
CHECK(hr==S_OK, "Create depth state for Renderer::ClearScreen"); CHECK(hr==S_OK, "Create depth state for Renderer::ClearScreen");
ddesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; ddesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
hr = D3D::device->CreateDepthStencilState(&ddesc, &cleardepthstates[2]); hr = D3D::g_device->CreateDepthStencilState(&ddesc, &cleardepthstates[2]);
CHECK(hr==S_OK, "Create depth state for Renderer::ClearScreen"); CHECK(hr==S_OK, "Create depth state for Renderer::ClearScreen");
D3D::SetDebugObjectName((ID3D11DeviceChild*)cleardepthstates[0], "depth state for Renderer::ClearScreen (depth buffer disabled)"); D3D::SetDebugObjectName(cleardepthstates[0], "depth state for Renderer::ClearScreen (depth buffer disabled)");
D3D::SetDebugObjectName((ID3D11DeviceChild*)cleardepthstates[1], "depth state for Renderer::ClearScreen (depth buffer enabled, writing enabled)"); D3D::SetDebugObjectName(cleardepthstates[1], "depth state for Renderer::ClearScreen (depth buffer enabled, writing enabled)");
D3D::SetDebugObjectName((ID3D11DeviceChild*)cleardepthstates[2], "depth state for Renderer::ClearScreen (depth buffer enabled, writing disabled)"); D3D::SetDebugObjectName(cleardepthstates[2], "depth state for Renderer::ClearScreen (depth buffer enabled, writing disabled)");
D3D11_BLEND_DESC blenddesc; D3D11_BLEND_DESC blenddesc;
blenddesc.AlphaToCoverageEnable = FALSE; blenddesc.AlphaToCoverageEnable = FALSE;
@ -262,24 +257,23 @@ void SetupDeviceObjects()
blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
hr = D3D::device->CreateBlendState(&blenddesc, &resetblendstate); resetblendstate = CreateBlendStateShared(&blenddesc);
CHECK(hr==S_OK, "Create blend state for Renderer::ResetAPIState"); CHECK(resetblendstate, "Create blend state for Renderer::ResetAPIState");
D3D::SetDebugObjectName((ID3D11DeviceChild*)resetblendstate, "blend state for Renderer::ResetAPIState"); D3D::SetDebugObjectName(resetblendstate, "blend state for Renderer::ResetAPIState");
clearblendstates[0] = resetblendstate; clearblendstates[0] = resetblendstate;
resetblendstate->AddRef();
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED|D3D11_COLOR_WRITE_ENABLE_GREEN|D3D11_COLOR_WRITE_ENABLE_BLUE; blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED
hr = D3D::device->CreateBlendState(&blenddesc, &clearblendstates[1]); | D3D11_COLOR_WRITE_ENABLE_GREEN | D3D11_COLOR_WRITE_ENABLE_BLUE;
CHECK(hr==S_OK, "Create blend state for Renderer::ClearScreen"); clearblendstates[1] = CreateBlendStateShared(&blenddesc);
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALPHA; blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALPHA;
hr = D3D::device->CreateBlendState(&blenddesc, &clearblendstates[2]); clearblendstates[2] = CreateBlendStateShared(&blenddesc);
CHECK(hr==S_OK, "Create blend state for Renderer::ClearScreen");
blenddesc.RenderTarget[0].RenderTargetWriteMask = 0; blenddesc.RenderTarget[0].RenderTargetWriteMask = 0;
hr = D3D::device->CreateBlendState(&blenddesc, &clearblendstates[3]); clearblendstates[3] = CreateBlendStateShared(&blenddesc);
CHECK(hr==S_OK, "Create blend state for Renderer::ClearScreen");
CHECK(clearblendstates[1] && clearblendstates[2] && clearblendstates[3], "Create blend state for Renderer::ClearScreen");
ddesc.DepthEnable = FALSE; ddesc.DepthEnable = FALSE;
ddesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; ddesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
@ -287,14 +281,14 @@ void SetupDeviceObjects()
ddesc.StencilEnable = FALSE; ddesc.StencilEnable = FALSE;
ddesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; ddesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
ddesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; ddesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
hr = D3D::device->CreateDepthStencilState(&ddesc, &resetdepthstate); hr = D3D::g_device->CreateDepthStencilState(&ddesc, &resetdepthstate);
CHECK(hr==S_OK, "Create depth state for Renderer::ResetAPIState"); CHECK(hr==S_OK, "Create depth state for Renderer::ResetAPIState");
D3D::SetDebugObjectName((ID3D11DeviceChild*)resetdepthstate, "depth stencil state for Renderer::ResetAPIState"); D3D::SetDebugObjectName(resetdepthstate, "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); 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, &resetraststate); hr = D3D::g_device->CreateRasterizerState(&rastdesc, &resetraststate);
CHECK(hr==S_OK, "Create rasterizer state for Renderer::ResetAPIState"); CHECK(hr==S_OK, "Create rasterizer state for Renderer::ResetAPIState");
D3D::SetDebugObjectName((ID3D11DeviceChild*)resetraststate, "rasterizer state for Renderer::ResetAPIState"); D3D::SetDebugObjectName(resetraststate, "rasterizer state for Renderer::ResetAPIState");
} }
// Kill off all POOL_DEFAULT device objects. // Kill off all POOL_DEFAULT device objects.
@ -302,19 +296,17 @@ void TeardownDeviceObjects()
{ {
delete g_framebuffer_manager; delete g_framebuffer_manager;
SAFE_RELEASE(access_efb_cbuf); access_efb_cbuf.reset();
SAFE_RELEASE(clearblendstates[0]);
SAFE_RELEASE(clearblendstates[1]); for (int i = 0; i != 4; ++i)
SAFE_RELEASE(clearblendstates[2]); clearblendstates[i].reset();
SAFE_RELEASE(clearblendstates[3]);
SAFE_RELEASE(cleardepthstates[0]); SAFE_RELEASE(cleardepthstates[0]);
SAFE_RELEASE(cleardepthstates[1]); SAFE_RELEASE(cleardepthstates[1]);
SAFE_RELEASE(cleardepthstates[2]); SAFE_RELEASE(cleardepthstates[2]);
SAFE_RELEASE(resetblendstate); resetblendstate.reset();
SAFE_RELEASE(resetdepthstate); SAFE_RELEASE(resetdepthstate);
SAFE_RELEASE(resetraststate); SAFE_RELEASE(resetraststate);
s_television.Shutdown();
} }
Renderer::Renderer() Renderer::Renderer()
@ -326,6 +318,8 @@ Renderer::Renderer()
D3D::Create(EmuWindow::GetWnd()); D3D::Create(EmuWindow::GetWnd());
m_television.reset(new Television);
s_backbuffer_width = D3D::GetBackBufferWidth(); s_backbuffer_width = D3D::GetBackBufferWidth();
s_backbuffer_height = D3D::GetBackBufferHeight(); s_backbuffer_height = D3D::GetBackBufferHeight();
@ -379,19 +373,21 @@ Renderer::Renderer()
// Clear EFB textures // Clear EFB textures
float ClearColor[4] = { 0.f, 0.f, 0.f, 1.f }; float ClearColor[4] = { 0.f, 0.f, 0.f, 1.f };
D3D::context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), ClearColor); D3D::g_context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), ClearColor);
D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0); D3D::g_context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0);
D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)(s_Fulltarget_width - s_target_width) / 2.f, D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)(s_Fulltarget_width - s_target_width) / 2.f,
(float)(s_Fulltarget_height - s_target_height) / 2.f, (float)(s_Fulltarget_height - s_target_height) / 2.f,
(float)s_target_width, (float)s_target_height); (float)s_target_width, (float)s_target_height);
D3D::context->RSSetViewports(1, &vp); D3D::g_context->RSSetViewports(1, &vp);
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
D3D::BeginFrame(); D3D::BeginFrame();
} }
Renderer::~Renderer() Renderer::~Renderer()
{ {
m_television.reset();
TeardownDeviceObjects(); TeardownDeviceObjects();
D3D::EndFrame(); D3D::EndFrame();
D3D::Present(); D3D::Present();
@ -481,7 +477,7 @@ bool Renderer::SetScissorRect()
if (rc.right >= rc.left && rc.bottom >= rc.top) if (rc.right >= rc.left && rc.bottom >= rc.top)
{ {
D3D::context->RSSetScissorRects(1, rc.AsRECT()); D3D::g_context->RSSetScissorRects(1, rc.AsRECT());
return true; return true;
} }
else else
@ -489,7 +485,7 @@ bool Renderer::SetScissorRect()
//WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom); //WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom);
*rc.AsRECT() = CD3D11_RECT(TargetStrideX(), TargetStrideY(), *rc.AsRECT() = CD3D11_RECT(TargetStrideX(), TargetStrideY(),
TargetStrideX() + s_target_width, TargetStrideY() + s_target_height); TargetStrideX() + s_target_width, TargetStrideY() + s_target_height);
D3D::context->RSSetScissorRects(1, rc.AsRECT()); D3D::g_context->RSSetScissorRects(1, rc.AsRECT());
return false; return false;
} }
} }
@ -568,9 +564,9 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
// depth buffers can only be completely CopySubresourceRegion'ed, so we're using drawShadedTexQuad instead // depth buffers can only be completely CopySubresourceRegion'ed, so we're using drawShadedTexQuad instead
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, 1.f, 1.f); D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, 1.f, 1.f);
D3D::context->RSSetViewports(1, &vp); D3D::g_context->RSSetViewports(1, &vp);
D3D::context->PSSetConstantBuffers(0, 1, &access_efb_cbuf); D3D::g_context->PSSetConstantBuffers(0, 1, &access_efb_cbuf);
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBDepthReadTexture()->GetRTV(), NULL); D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBDepthReadTexture()->GetRTV(), NULL);
D3D::SetPointCopySampler(); D3D::SetPointCopySampler();
D3D::drawShadedTexQuad(FramebufferManager::GetEFBDepthTexture()->GetSRV(), D3D::drawShadedTexQuad(FramebufferManager::GetEFBDepthTexture()->GetSRV(),
&RectToLock, &RectToLock,
@ -580,17 +576,17 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout()); VertexShaderCache::GetSimpleInputLayout());
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
// copy to system memory // copy to system memory
D3D11_BOX box = CD3D11_BOX(0, 0, 0, 1, 1, 1); D3D11_BOX box = CD3D11_BOX(0, 0, 0, 1, 1, 1);
read_tex = FramebufferManager::GetEFBDepthStagingBuffer(); read_tex = FramebufferManager::GetEFBDepthStagingBuffer();
D3D::context->CopySubresourceRegion(read_tex, 0, 0, 0, 0, FramebufferManager::GetEFBDepthReadTexture()->GetTex(), 0, &box); D3D::g_context->CopySubresourceRegion(read_tex, 0, 0, 0, 0, FramebufferManager::GetEFBDepthReadTexture()->GetTex(), 0, &box);
RestoreAPIState(); // restore game state RestoreAPIState(); // restore game state
// read the data from system memory // read the data from system memory
D3D::context->Map(read_tex, 0, D3D11_MAP_READ, 0, &map); D3D::g_context->Map(read_tex, 0, D3D11_MAP_READ, 0, &map);
float val = *(float*)map.pData; float val = *(float*)map.pData;
u32 ret = 0; u32 ret = 0;
@ -603,7 +599,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
{ {
ret = ((u32)(val * 0xffffff)); ret = ((u32)(val * 0xffffff));
} }
D3D::context->Unmap(read_tex, 0); D3D::g_context->Unmap(read_tex, 0);
// TODO: in RE0 this value is often off by one in Video_DX9 (where this code is derived from), which causes lighting to disappear // TODO: in RE0 this value is often off by one in Video_DX9 (where this code is derived from), which causes lighting to disappear
return ret; return ret;
@ -613,14 +609,14 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
// we can directly copy to system memory here // we can directly copy to system memory here
read_tex = FramebufferManager::GetEFBColorStagingBuffer(); read_tex = FramebufferManager::GetEFBColorStagingBuffer();
D3D11_BOX box = CD3D11_BOX(RectToLock.left, RectToLock.top, 0, RectToLock.right, RectToLock.bottom, 1); D3D11_BOX box = CD3D11_BOX(RectToLock.left, RectToLock.top, 0, RectToLock.right, RectToLock.bottom, 1);
D3D::context->CopySubresourceRegion(read_tex, 0, 0, 0, 0, FramebufferManager::GetEFBColorTexture()->GetTex(), 0, &box); D3D::g_context->CopySubresourceRegion(read_tex, 0, 0, 0, 0, FramebufferManager::GetEFBColorTexture()->GetTex(), 0, &box);
// read the data from system memory // read the data from system memory
D3D::context->Map(read_tex, 0, D3D11_MAP_READ, 0, &map); D3D::g_context->Map(read_tex, 0, D3D11_MAP_READ, 0, &map);
u32 ret = 0; u32 ret = 0;
if(map.pData) if(map.pData)
ret = *(u32*)map.pData; ret = *(u32*)map.pData;
D3D::context->Unmap(read_tex, 0); D3D::g_context->Unmap(read_tex, 0);
// check what to do with the alpha channel (GX_PokeAlphaRead) // check what to do with the alpha channel (GX_PokeAlphaRead)
PixelEngine::UPEAlphaReadReg alpha_read_mode; PixelEngine::UPEAlphaReadReg alpha_read_mode;
@ -650,7 +646,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
// TODO: The first five PE registers may change behavior of EFB pokes, this isn't implemented, yet. // TODO: The first five PE registers may change behavior of EFB pokes, this isn't implemented, yet.
ResetAPIState(); ResetAPIState();
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), NULL); D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), NULL);
D3D::drawColorQuad(rgbaColor, (float)RectToLock.left * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f, D3D::drawColorQuad(rgbaColor, (float)RectToLock.left * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
- (float)RectToLock.top * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f, - (float)RectToLock.top * 2.f / (float)Renderer::GetFullTargetHeight() + 1.f,
(float)RectToLock.right * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f, (float)RectToLock.right * 2.f / (float)Renderer::GetFullTargetWidth() - 1.f,
@ -730,15 +726,15 @@ void Renderer::UpdateViewport()
} }
else else
{ {
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL); D3D::g_context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL);
delete g_framebuffer_manager; delete g_framebuffer_manager;
g_framebuffer_manager = new FramebufferManager; g_framebuffer_manager = new FramebufferManager;
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
float clear_col[4] = { 0.f, 0.f, 0.f, 1.f }; float clear_col[4] = { 0.f, 0.f, 0.f, 1.f };
D3D::context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), clear_col); D3D::g_context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), clear_col);
D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0); D3D::g_context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0);
} }
} }
@ -746,7 +742,7 @@ void Renderer::UpdateViewport()
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(newx, newy, newwidth, newheight, D3D11_VIEWPORT vp = CD3D11_VIEWPORT(newx, newy, newwidth, newheight,
0.f, // (xfregs.rawViewport[5] - xfregs.rawViewport[2]) / 16777216.0f; 0.f, // (xfregs.rawViewport[5] - xfregs.rawViewport[2]) / 16777216.0f;
1.f); // xfregs.rawViewport[5] / 16777216.0f; 1.f); // xfregs.rawViewport[5] / 16777216.0f;
D3D::context->RSSetViewports(1, &vp); D3D::g_context->RSSetViewports(1, &vp);
} }
void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z)
@ -766,7 +762,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE
// Update the view port for clearing the picture // Update the view port for clearing the picture
TargetRectangle targetRc = Renderer::ConvertEFBRectangle(rc); 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); 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); D3D::g_context->RSSetViewports(1, &vp);
// Color is passed in bgra mode so we need to convert it to rgba // Color is passed in bgra mode so we need to convert it to rgba
u32 rgbaColor = (color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000); u32 rgbaColor = (color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000);
@ -796,16 +792,16 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
g_renderer->ResetAPIState(); g_renderer->ResetAPIState();
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)g_renderer->GetFullTargetWidth(), (float)g_renderer->GetFullTargetHeight()); D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)g_renderer->GetFullTargetWidth(), (float)g_renderer->GetFullTargetHeight());
D3D::context->RSSetViewports(1, &vp); D3D::g_context->RSSetViewports(1, &vp);
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTempTexture()->GetRTV(), NULL); D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTempTexture()->GetRTV(), NULL);
D3D::SetPointCopySampler(); D3D::SetPointCopySampler();
D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), &source, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight(), pixel_shader, VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout()); D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), &source, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight(), pixel_shader, VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
g_renderer->RestoreAPIState(); g_renderer->RestoreAPIState();
FramebufferManager::SwapReinterpretTexture(); FramebufferManager::SwapReinterpretTexture();
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
} }
void SetSrcBlend(D3D11_BLEND val) void SetSrcBlend(D3D11_BLEND val)
@ -885,15 +881,15 @@ void Renderer::SetBlendMode(bool forceUpdate)
bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle &rc) bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle &rc)
{ {
// copy back buffer to system memory // copy back buffer to system memory
ID3D11Texture2D* buftex;
D3D11_TEXTURE2D_DESC tex_desc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, D3D::GetBackBufferWidth(), D3D::GetBackBufferHeight(), 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE); D3D11_TEXTURE2D_DESC tex_desc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, D3D::GetBackBufferWidth(), D3D::GetBackBufferHeight(), 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ|D3D11_CPU_ACCESS_WRITE);
HRESULT hr = D3D::device->CreateTexture2D(&tex_desc, NULL, &buftex); auto const buftex = CreateTexture2DShared(&tex_desc, NULL);
if (FAILED(hr)) PanicAlert("Failed to create screenshot buffer texture"); if (!buftex)
D3D::context->CopyResource(buftex, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex()); PanicAlert("Failed to create screenshot buffer texture");
D3D::g_context->CopyResource(buftex, D3D::GetBackBuffer()->GetTex());
// D3DX11SaveTextureToFileA doesn't allow us to ignore the alpha channel, so we need to strip it out ourselves // D3DX11SaveTextureToFileA doesn't allow us to ignore the alpha channel, so we need to strip it out ourselves
D3D11_MAPPED_SUBRESOURCE map; D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(buftex, 0, D3D11_MAP_READ_WRITE, 0, &map); D3D::g_context->Map(buftex, 0, D3D11_MAP_READ_WRITE, 0, &map);
for (unsigned int y = 0; y < D3D::GetBackBufferHeight(); ++y) for (unsigned int y = 0; y < D3D::GetBackBufferHeight(); ++y)
{ {
u8* ptr = (u8*)map.pData + y * map.RowPitch + 3; u8* ptr = (u8*)map.pData + y * map.RowPitch + 3;
@ -903,12 +899,10 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle
ptr += 4; ptr += 4;
} }
} }
D3D::context->Unmap(buftex, 0); D3D::g_context->Unmap(buftex, 0);
// ready to be saved // ready to be saved
hr = PD3DX11SaveTextureToFileA(D3D::context, buftex, D3DX11_IFF_PNG, filename.c_str()); HRESULT hr = PD3DX11SaveTextureToFileA(D3D::g_context, buftex, D3DX11_IFF_PNG, filename.c_str());
buftex->Release();
return SUCCEEDED(hr); return SUCCEEDED(hr);
} }
@ -939,9 +933,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
TargetRectangle dst_rect; TargetRectangle dst_rect;
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect); ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)s_backbuffer_width, (float)s_backbuffer_height); D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)s_backbuffer_width, (float)s_backbuffer_height);
D3D::context->RSSetViewports(1, &vp); D3D::g_context->RSSetViewports(1, &vp);
float ClearColor[4] = { 0.f, 0.f, 0.f, 1.f }; float ClearColor[4] = { 0.f, 0.f, 0.f, 1.f };
D3D::context->ClearRenderTargetView(D3D::GetBackBuffer()->GetRTV(), ClearColor); D3D::g_context->ClearRenderTargetView(D3D::GetBackBuffer()->GetRTV(), ClearColor);
int X = dst_rect.left; int X = dst_rect.left;
int Y = dst_rect.top; int Y = dst_rect.top;
@ -957,8 +951,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
if (Width > (s_backbuffer_width - X)) Width = s_backbuffer_width - X; if (Width > (s_backbuffer_width - X)) Width = s_backbuffer_width - X;
if (Height > (s_backbuffer_height - Y)) Height = s_backbuffer_height - Y; if (Height > (s_backbuffer_height - Y)) Height = s_backbuffer_height - Y;
vp = CD3D11_VIEWPORT((float)X, (float)Y, (float)Width, (float)Height); vp = CD3D11_VIEWPORT((float)X, (float)Y, (float)Width, (float)Height);
D3D::context->RSSetViewports(1, &vp); D3D::g_context->RSSetViewports(1, &vp);
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL); D3D::g_context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL);
// activate linear filtering for the buffer copies // activate linear filtering for the buffer copies
D3D::SetLinearCopySampler(); D3D::SetLinearCopySampler();
@ -966,10 +960,10 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
if (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB) if (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)
{ {
// TODO: Television should be used to render Virtual XFB mode as well. // TODO: Television should be used to render Virtual XFB mode as well.
s_television.Submit(xfbAddr, fbWidth, fbHeight); m_television->Submit(xfbAddr, fbWidth, fbHeight);
s_television.Render(); m_television->Render();
} }
else if(g_ActiveConfig.bUseXFB) else if (g_ActiveConfig.bUseXFB)
{ {
const XFBSourceBase* xfbSource; const XFBSourceBase* xfbSource;
@ -1138,19 +1132,19 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
s_LastEFBScale = g_ActiveConfig.iEFBScale; s_LastEFBScale = g_ActiveConfig.iEFBScale;
CalculateTargetSize(); CalculateTargetSize();
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL); D3D::g_context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL);
delete g_framebuffer_manager; delete g_framebuffer_manager;
g_framebuffer_manager = new FramebufferManager; g_framebuffer_manager = new FramebufferManager;
float clear_col[4] = { 0.f, 0.f, 0.f, 1.f }; float clear_col[4] = { 0.f, 0.f, 0.f, 1.f };
D3D::context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), clear_col); D3D::g_context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), clear_col);
D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0); D3D::g_context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0);
} }
// begin next frame // begin next frame
Renderer::RestoreAPIState(); Renderer::RestoreAPIState();
D3D::BeginFrame(); D3D::BeginFrame();
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
UpdateViewport(); UpdateViewport();
VertexShaderManager::SetViewportChanged(); VertexShaderManager::SetViewportChanged();
@ -1199,25 +1193,26 @@ void Renderer::ApplyState(bool bUseDstAlpha)
gx_state.blenddc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; gx_state.blenddc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
} }
ID3D11BlendState* blstate; {
hr = D3D::device->CreateBlendState(&gx_state.blenddc, &blstate); auto const blstate = CreateBlendStateShared(&gx_state.blenddc);
if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__); if (!blstate)
PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
D3D::stateman->PushBlendState(blstate); D3D::stateman->PushBlendState(blstate);
D3D::SetDebugObjectName((ID3D11DeviceChild*)blstate, "blend state used to emulate the GX pipeline"); D3D::SetDebugObjectName(blstate, "blend state used to emulate the GX pipeline");
SAFE_RELEASE(blstate); }
ID3D11DepthStencilState* depth_state; ID3D11DepthStencilState* depth_state;
hr = D3D::device->CreateDepthStencilState(&gx_state.depthdc, &depth_state); hr = D3D::g_device->CreateDepthStencilState(&gx_state.depthdc, &depth_state);
if (SUCCEEDED(hr)) D3D::SetDebugObjectName((ID3D11DeviceChild*)depth_state, "depth-stencil state used to emulate the GX pipeline"); if (SUCCEEDED(hr)) D3D::SetDebugObjectName(depth_state, "depth-stencil state used to emulate the GX pipeline");
else PanicAlert("Failed to create depth state at %s %d\n", __FILE__, __LINE__); else PanicAlert("Failed to create depth state at %s %d\n", __FILE__, __LINE__);
D3D::stateman->PushDepthState(depth_state); D3D::stateman->PushDepthState(depth_state);
SAFE_RELEASE(depth_state); SAFE_RELEASE(depth_state);
gx_state.rastdc.FillMode = (g_ActiveConfig.bWireFrame) ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID; gx_state.rastdc.FillMode = (g_ActiveConfig.bWireFrame) ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID;
ID3D11RasterizerState* raststate; ID3D11RasterizerState* raststate;
hr = D3D::device->CreateRasterizerState(&gx_state.rastdc, &raststate); hr = D3D::g_device->CreateRasterizerState(&gx_state.rastdc, &raststate);
if (FAILED(hr)) PanicAlert("Failed to create rasterizer state at %s %d\n", __FILE__, __LINE__); if (FAILED(hr)) PanicAlert("Failed to create rasterizer state at %s %d\n", __FILE__, __LINE__);
D3D::SetDebugObjectName((ID3D11DeviceChild*)raststate, "rasterizer state used to emulate the GX pipeline"); D3D::SetDebugObjectName(raststate, "rasterizer state used to emulate the GX pipeline");
D3D::stateman->PushRasterizerState(raststate); D3D::stateman->PushRasterizerState(raststate);
SAFE_RELEASE(raststate); SAFE_RELEASE(raststate);
@ -1228,13 +1223,13 @@ void Renderer::ApplyState(bool bUseDstAlpha)
//if (shader_resources[stage]) //if (shader_resources[stage])
{ {
if(g_ActiveConfig.iMaxAnisotropy > 0) gx_state.sampdc[stage].Filter = D3D11_FILTER_ANISOTROPIC; if(g_ActiveConfig.iMaxAnisotropy > 0) gx_state.sampdc[stage].Filter = D3D11_FILTER_ANISOTROPIC;
hr = D3D::device->CreateSamplerState(&gx_state.sampdc[stage], &samplerstate[stage]); hr = D3D::g_device->CreateSamplerState(&gx_state.sampdc[stage], &samplerstate[stage]);
if (FAILED(hr)) PanicAlert("Fail %s %d, stage=%d\n", __FILE__, __LINE__, stage); if (FAILED(hr)) PanicAlert("Fail %s %d, stage=%d\n", __FILE__, __LINE__, stage);
else D3D::SetDebugObjectName((ID3D11DeviceChild*)samplerstate[stage], "sampler state used to emulate the GX pipeline"); else D3D::SetDebugObjectName(samplerstate[stage], "sampler state used to emulate the GX pipeline");
} }
// else samplerstate[stage] = NULL; // else samplerstate[stage] = NULL;
} }
D3D::context->PSSetSamplers(0, 8, samplerstate); D3D::g_context->PSSetSamplers(0, 8, samplerstate);
for (unsigned int stage = 0; stage < 8; stage++) for (unsigned int stage = 0; stage < 8; stage++)
SAFE_RELEASE(samplerstate[stage]); SAFE_RELEASE(samplerstate[stage]);
@ -1247,17 +1242,17 @@ void Renderer::ApplyState(bool bUseDstAlpha)
SetLogicOpMode(); SetLogicOpMode();
} }
D3D::context->PSSetConstantBuffers(0, 1, &PixelShaderCache::GetConstantBuffer()); D3D::g_context->PSSetConstantBuffers(0, 1, &PixelShaderCache::GetConstantBuffer());
D3D::context->VSSetConstantBuffers(0, 1, &VertexShaderCache::GetConstantBuffer()); D3D::g_context->VSSetConstantBuffers(0, 1, &VertexShaderCache::GetConstantBuffer());
D3D::context->PSSetShader(PixelShaderCache::GetActiveShader(), NULL, 0); D3D::g_context->PSSetShader(PixelShaderCache::GetActiveShader(), NULL, 0);
D3D::context->VSSetShader(VertexShaderCache::GetActiveShader(), NULL, 0); D3D::g_context->VSSetShader(VertexShaderCache::GetActiveShader(), NULL, 0);
} }
void Renderer::RestoreState() void Renderer::RestoreState()
{ {
ID3D11ShaderResourceView* shader_resources[8] = { NULL }; ID3D11ShaderResourceView* shader_resources[8] = { NULL };
D3D::context->PSSetShaderResources(0, 8, shader_resources); D3D::g_context->PSSetShaderResources(0, 8, shader_resources);
D3D::stateman->PopBlendState(); D3D::stateman->PopBlendState();
D3D::stateman->PopDepthState(); D3D::stateman->PopDepthState();
@ -1270,9 +1265,9 @@ void Renderer::ApplyCullDisable()
rastDesc.CullMode = D3D11_CULL_NONE; rastDesc.CullMode = D3D11_CULL_NONE;
ID3D11RasterizerState* raststate; ID3D11RasterizerState* raststate;
HRESULT hr = D3D::device->CreateRasterizerState(&rastDesc, &raststate); HRESULT hr = D3D::g_device->CreateRasterizerState(&rastDesc, &raststate);
if (FAILED(hr)) PanicAlert("Failed to create culling-disabled rasterizer state at %s %d\n", __FILE__, __LINE__); if (FAILED(hr)) PanicAlert("Failed to create culling-disabled rasterizer state at %s %d\n", __FILE__, __LINE__);
D3D::SetDebugObjectName((ID3D11DeviceChild*)raststate, "rasterizer state (culling disabled) used to emulate the GX pipeline"); D3D::SetDebugObjectName(raststate, "rasterizer state (culling disabled) used to emulate the GX pipeline");
D3D::stateman->PushRasterizerState(raststate); D3D::stateman->PushRasterizerState(raststate);
SAFE_RELEASE(raststate); SAFE_RELEASE(raststate);

View file

@ -3,6 +3,7 @@
#define _RENDER_H_ #define _RENDER_H_
#include "RenderBase.h" #include "RenderBase.h"
#include "Television.h"
namespace DX11 namespace DX11
{ {
@ -60,6 +61,9 @@ public:
void SetVSConstant4fv(unsigned int const_number, const float *f); void SetVSConstant4fv(unsigned int const_number, const float *f);
void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f); void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f);
void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f); void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
private:
std::unique_ptr<Television> m_television;
}; };
} }

View file

@ -71,43 +71,35 @@ static const char YUYV_DECODER_PS[] =
; ;
Television::Television() Television::Television()
: m_yuyvTexture(NULL), m_yuyvTextureSRV(NULL), m_pShader(NULL) : m_yuyvTextureSRV(NULL)
{ }
void Television::Init()
{ {
HRESULT hr;
// Create YUYV texture for real XFB mode // Create YUYV texture for real XFB mode
// This texture format is designed for YUYV data. // This texture format is designed for YUYV data.
D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC( D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC(
DXGI_FORMAT_G8R8_G8B8_UNORM, MAX_XFB_WIDTH, MAX_XFB_HEIGHT, 1, 1); DXGI_FORMAT_G8R8_G8B8_UNORM, MAX_XFB_WIDTH, MAX_XFB_HEIGHT, 1, 1);
hr = D3D::device->CreateTexture2D(&t2dd, NULL, &m_yuyvTexture); m_yuyvTexture = CreateTexture2DShared(&t2dd, NULL);
CHECK(SUCCEEDED(hr), "create tv yuyv texture"); CHECK(m_yuyvTexture, "create tv yuyv texture");
D3D::SetDebugObjectName(m_yuyvTexture, "tv yuyv texture"); D3D::SetDebugObjectName(m_yuyvTexture, "tv yuyv texture");
// Create shader resource view for YUYV texture // Create shader resource view for YUYV texture
D3D11_SHADER_RESOURCE_VIEW_DESC srvd = CD3D11_SHADER_RESOURCE_VIEW_DESC( D3D11_SHADER_RESOURCE_VIEW_DESC srvd = CD3D11_SHADER_RESOURCE_VIEW_DESC(
m_yuyvTexture, D3D11_SRV_DIMENSION_TEXTURE2D, m_yuyvTexture, D3D11_SRV_DIMENSION_TEXTURE2D, DXGI_FORMAT_G8R8_G8B8_UNORM);
DXGI_FORMAT_G8R8_G8B8_UNORM); HRESULT hr = D3D::g_device->CreateShaderResourceView(m_yuyvTexture, &srvd, &m_yuyvTextureSRV);
hr = D3D::device->CreateShaderResourceView(m_yuyvTexture, &srvd, &m_yuyvTextureSRV);
CHECK(SUCCEEDED(hr), "create tv yuyv texture srv"); CHECK(SUCCEEDED(hr), "create tv yuyv texture srv");
D3D::SetDebugObjectName(m_yuyvTextureSRV, "tv yuyv texture srv"); D3D::SetDebugObjectName(m_yuyvTextureSRV, "tv yuyv texture srv");
// Create YUYV-decoding pixel shader // Create YUYV-decoding pixel shader
m_pShader = D3D::CompileAndCreatePixelShader(YUYV_DECODER_PS, sizeof(YUYV_DECODER_PS)); m_pShader = D3D::CompileAndCreatePixelShader(YUYV_DECODER_PS, sizeof(YUYV_DECODER_PS));
CHECK(m_pShader != NULL, "compile and create yuyv decoder pixel shader"); CHECK(m_pShader, "compile and create yuyv decoder pixel shader");
D3D::SetDebugObjectName(m_pShader, "yuyv decoder pixel shader"); D3D::SetDebugObjectName(m_pShader, "yuyv decoder pixel shader");
} }
void Television::Shutdown() Television::~Television()
{ {
SAFE_RELEASE(m_pShader);
SAFE_RELEASE(m_yuyvTextureSRV); SAFE_RELEASE(m_yuyvTextureSRV);
SAFE_RELEASE(m_yuyvTexture);
} }
void Television::Submit(u32 xfbAddr, u32 width, u32 height) void Television::Submit(u32 xfbAddr, u32 width, u32 height)
@ -119,7 +111,7 @@ void Television::Submit(u32 xfbAddr, u32 width, u32 height)
// Load data from GameCube RAM to YUYV texture // Load data from GameCube RAM to YUYV texture
u8* yuyvSrc = Memory::GetPointer(xfbAddr); u8* yuyvSrc = Memory::GetPointer(xfbAddr);
D3D11_BOX box = CD3D11_BOX(0, 0, 0, width, height, 1); D3D11_BOX box = CD3D11_BOX(0, 0, 0, width, height, 1);
D3D::context->UpdateSubresource(m_yuyvTexture, 0, &box, yuyvSrc, 2*width, 2*width*height); D3D::g_context->UpdateSubresource(m_yuyvTexture, 0, &box, yuyvSrc, 2*width, 2*width*height);
} }
void Television::Render() void Television::Render()

View file

@ -20,22 +20,16 @@
#include "VideoCommon.h" #include "VideoCommon.h"
struct ID3D11Texture2D; #include "D3DUtil.h"
struct ID3D11ShaderResourceView;
struct ID3D11PixelShader;
namespace DX11 namespace DX11
{ {
class Television class Television
{ {
public: public:
Television(); Television();
~Television();
void Init();
void Shutdown();
// Submit video data to be drawn. This will change the current state of the // Submit video data to be drawn. This will change the current state of the
// TV. xfbAddr points to YUYV data stored in GameCube/Wii RAM, but the XFB // TV. xfbAddr points to YUYV data stored in GameCube/Wii RAM, but the XFB
@ -54,10 +48,9 @@ private:
// Used for real XFB mode // Used for real XFB mode
ID3D11Texture2D* m_yuyvTexture; SharedPtr<ID3D11Texture2D> m_yuyvTexture;
ID3D11ShaderResourceView* m_yuyvTextureSRV; ID3D11ShaderResourceView* m_yuyvTextureSRV;
ID3D11PixelShader* m_pShader; SharedPtr<ID3D11PixelShader> m_pShader;
}; };
} }

View file

@ -31,23 +31,18 @@
namespace DX11 namespace DX11
{ {
static TextureEncoder* g_encoder = NULL; static std::unique_ptr<TextureEncoder> g_encoder;
const size_t MAX_COPY_BUFFERS = 25; const size_t MAX_COPY_BUFFERS = 25;
ID3D11Buffer* efbcopycbuf[MAX_COPY_BUFFERS] = { 0 }; static SharedPtr<ID3D11Buffer> efbcopycbuf[MAX_COPY_BUFFERS];
TextureCache::TCacheEntry::~TCacheEntry()
{
texture->Release();
}
void TextureCache::TCacheEntry::Bind(unsigned int stage) void TextureCache::TCacheEntry::Bind(unsigned int stage)
{ {
D3D::context->PSSetShaderResources(stage, 1, &texture->GetSRV()); D3D::g_context->PSSetShaderResources(stage, 1, &texture->GetSRV());
} }
bool TextureCache::TCacheEntry::Save(const char filename[]) bool TextureCache::TCacheEntry::Save(const char filename[])
{ {
return SUCCEEDED(PD3DX11SaveTextureToFileA(D3D::context, texture->GetTex(), D3DX11_IFF_PNG, filename)); return SUCCEEDED(PD3DX11SaveTextureToFileA(D3D::g_context, texture->GetTex(), D3DX11_IFF_PNG, filename));
} }
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
@ -56,7 +51,7 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, expanded_width, level, usage); D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, expanded_width, level, usage);
if (autogen_mips) if (autogen_mips)
PD3DX11FilterTexture(D3D::context, texture->GetTex(), 0, D3DX11_DEFAULT); PD3DX11FilterTexture(D3D::g_context, texture->GetTex(), 0, D3DX11_DEFAULT);
} }
TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
@ -81,18 +76,16 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
const D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, const D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM,
width, height, 1, tex_levels, D3D11_BIND_SHADER_RESOURCE, usage, cpu_access); width, height, 1, tex_levels, D3D11_BIND_SHADER_RESOURCE, usage, cpu_access);
ID3D11Texture2D *pTexture; auto const pTexture = CreateTexture2DShared(&texdesc, data);
const HRESULT hr = D3D::device->CreateTexture2D(&texdesc, data, &pTexture); CHECK(pTexture, "Create texture of the TextureCache");
CHECK(SUCCEEDED(hr), "Create texture of the TextureCache");
TCacheEntry* const entry = new TCacheEntry(new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE)); std::unique_ptr<D3DTexture2D> tx(new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE));
auto const entry = new TCacheEntry(std::move(tx));
entry->usage = usage; entry->usage = usage;
// TODO: better debug names // TODO: better debug names
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry->texture->GetTex(), "a texture of the TextureCache"); D3D::SetDebugObjectName(entry->texture->GetTex(), "a texture of the TextureCache");
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry->texture->GetSRV(), "shader resource view of a texture of the TextureCache"); D3D::SetDebugObjectName(entry->texture->GetSRV(), "shader resource view of a texture of the TextureCache");
SAFE_RELEASE(pTexture);
return entry; return entry;
} }
@ -108,7 +101,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
// stretch picture with increased internal resolution // stretch picture with increased internal resolution
const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)virtualW, (float)virtualH); const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)virtualW, (float)virtualH);
D3D::context->RSSetViewports(1, &vp); D3D::g_context->RSSetViewports(1, &vp);
// set transformation // set transformation
if (NULL == efbcopycbuf[cbufid]) if (NULL == efbcopycbuf[cbufid])
@ -116,11 +109,11 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(28 * sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT); const D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(28 * sizeof(float), D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DEFAULT);
D3D11_SUBRESOURCE_DATA data; D3D11_SUBRESOURCE_DATA data;
data.pSysMem = colmat; data.pSysMem = colmat;
HRESULT hr = D3D::device->CreateBuffer(&cbdesc, &data, &efbcopycbuf[cbufid]); efbcopycbuf[cbufid] = CreateBufferShared(&cbdesc, &data);
CHECK(SUCCEEDED(hr), "Create efb copy constant buffer %d", cbufid); CHECK(efbcopycbuf[cbufid], "Create efb copy constant buffer %d", cbufid);
D3D::SetDebugObjectName((ID3D11DeviceChild*)efbcopycbuf[cbufid], "a constant buffer used in TextureCache::CopyRenderTargetToTexture"); D3D::SetDebugObjectName(efbcopycbuf[cbufid], "a constant buffer used in TextureCache::CopyRenderTargetToTexture");
} }
D3D::context->PSSetConstantBuffers(0, 1, &efbcopycbuf[cbufid]); D3D::g_context->PSSetConstantBuffers(0, 1, &efbcopycbuf[cbufid]);
const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect); const TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect);
// TODO: try targetSource.asRECT(); // TODO: try targetSource.asRECT();
@ -132,7 +125,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
else else
D3D::SetPointCopySampler(); D3D::SetPointCopySampler();
D3D::context->OMSetRenderTargets(1, &texture->GetRTV(), NULL); D3D::g_context->OMSetRenderTargets(1, &texture->GetRTV(), NULL);
// Create texture copy // Create texture copy
D3D::drawShadedTexQuad( D3D::drawShadedTexQuad(
@ -141,7 +134,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
(srcFormat == PIXELFMT_Z24) ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true), (srcFormat == PIXELFMT_Z24) ? PixelShaderCache::GetDepthMatrixProgram(true) : PixelShaderCache::GetColorMatrixProgram(true),
VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout()); VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout());
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); D3D::g_context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
g_renderer->RestoreAPIState(); g_renderer->RestoreAPIState();
} }
@ -150,7 +143,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
{ {
u8* dst = Memory::GetPointer(dstAddr); u8* dst = Memory::GetPointer(dstAddr);
size_t encodeSize = g_encoder->Encode(dst, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf); size_t encodeSize = g_encoder->Encode(dst, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf);
hash = GetHash64(dst, encodeSize, g_ActiveConfig.iSafeTextureCache_ColorSamples); hash = GetHash64(dst, (int)encodeSize, g_ActiveConfig.iSafeTextureCache_ColorSamples);
if (g_ActiveConfig.bEFBCopyCacheEnable) if (g_ActiveConfig.bEFBCopyCacheEnable)
{ {
// If the texture in RAM is already in the texture cache, // If the texture in RAM is already in the texture cache,
@ -159,7 +152,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
return; return;
} }
TextureCache::MakeRangeDynamic(dstAddr, encodeSize); TextureCache::MakeRangeDynamic(dstAddr, (u32)encodeSize);
} }
} }
@ -174,18 +167,12 @@ TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture(
TextureCache::TextureCache() TextureCache::TextureCache()
{ {
// FIXME: Is it safe here? // FIXME: Is it safe here?
g_encoder = new PSTextureEncoder; g_encoder.reset(new PSTextureEncoder);
g_encoder->Init();
} }
TextureCache::~TextureCache() TextureCache::~TextureCache()
{ {
for (unsigned int k = 0; k < MAX_COPY_BUFFERS; ++k) g_encoder.reset();
SAFE_RELEASE(efbcopycbuf[k]);
g_encoder->Shutdown();
delete g_encoder;
g_encoder = NULL;
} }
} }

View file

@ -33,12 +33,11 @@ public:
private: private:
struct TCacheEntry : TCacheEntryBase struct TCacheEntry : TCacheEntryBase
{ {
D3DTexture2D *const texture; std::unique_ptr<D3DTexture2D> const texture;
D3D11_USAGE usage; D3D11_USAGE usage;
TCacheEntry(D3DTexture2D *_tex) : texture(_tex) {} TCacheEntry(std::unique_ptr<D3DTexture2D>&& _tex) : texture(std::move(_tex)) {}
~TCacheEntry();
void Load(unsigned int width, unsigned int height, void Load(unsigned int width, unsigned int height,
unsigned int expanded_width, unsigned int levels, bool autogen_mips = false); unsigned int expanded_width, unsigned int levels, bool autogen_mips = false);

View file

@ -116,18 +116,13 @@ static const UINT MAX_BYTES_PER_ENCODE = MAX_BYTES_PER_BLOCK_ROW*(EFB_HEIGHT/4);
class TextureEncoder class TextureEncoder
{ {
public: public:
virtual ~TextureEncoder() {}
virtual ~TextureEncoder() { }
virtual void Init() = 0;
virtual void Shutdown() = 0;
// Returns size in bytes of encoded block of memory // Returns size in bytes of encoded block of memory
virtual size_t Encode(u8* dst, unsigned int dstFormat, virtual size_t Encode(u8* dst, unsigned int dstFormat,
unsigned int srcFormat, const EFBRectangle& srcRect, bool isIntensity, unsigned int srcFormat, const EFBRectangle& srcRect, bool isIntensity,
bool scaleByHalf) = 0; bool scaleByHalf) = 0;
}; };
} }

View file

@ -42,21 +42,21 @@ namespace DX11
const UINT IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE*2 * 16; const UINT IBUFFER_SIZE = VertexManager::MAXIBUFFERSIZE*2 * 16;
const UINT VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE * 16; const UINT VBUFFER_SIZE = VertexManager::MAXVBUFFERSIZE * 16;
void VertexManager::CreateDeviceObjects() VertexManager::VertexManager()
{ {
D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(IBUFFER_SIZE, D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(IBUFFER_SIZE,
D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D11_BIND_INDEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_indexBuffer)), m_indexBuffer = CreateBufferShared(&bufdesc, NULL);
"Failed to create index buffer."); CHECK(m_indexBuffer, "Failed to create index buffer.");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_indexBuffer, "index buffer of VertexManager"); D3D::SetDebugObjectName(m_indexBuffer, "index buffer of VertexManager");
bufdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; bufdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufdesc.ByteWidth = VBUFFER_SIZE; bufdesc.ByteWidth = VBUFFER_SIZE;
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, NULL, &m_vertexBuffer)), m_vertexBuffer = CreateBufferShared(&bufdesc, NULL);
"Failed to create vertex buffer."); CHECK(m_vertexBuffer, "Failed to create vertex buffer.");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_vertexBuffer, "vertex buffer of VertexManager"); D3D::SetDebugObjectName(m_vertexBuffer, "vertex buffer of VertexManager");
m_indexBufferCursor = 0; m_indexBufferCursor = 0;
m_vertexBufferCursor = 0; m_vertexBufferCursor = 0;
@ -65,28 +65,6 @@ void VertexManager::CreateDeviceObjects()
m_triangleDrawIndex = 0; m_triangleDrawIndex = 0;
m_lineDrawIndex = 0; m_lineDrawIndex = 0;
m_pointDrawIndex = 0; m_pointDrawIndex = 0;
m_lineShader.Init();
m_pointShader.Init();
}
void VertexManager::DestroyDeviceObjects()
{
m_pointShader.Shutdown();
m_lineShader.Shutdown();
SAFE_RELEASE(m_vertexBuffer);
SAFE_RELEASE(m_indexBuffer);
}
VertexManager::VertexManager()
{
CreateDeviceObjects();
}
VertexManager::~VertexManager()
{
DestroyDeviceObjects();
} }
void VertexManager::LoadBuffers() void VertexManager::LoadBuffers()
@ -97,16 +75,16 @@ void VertexManager::LoadBuffers()
if (m_vertexBufferCursor + vSize >= VBUFFER_SIZE) if (m_vertexBufferCursor + vSize >= VBUFFER_SIZE)
{ {
// Wrap around // Wrap around
D3D::context->Map(m_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); D3D::g_context->Map(m_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
m_vertexBufferCursor = 0; m_vertexBufferCursor = 0;
} }
else else
{ {
// Append data // Append data
D3D::context->Map(m_vertexBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map); D3D::g_context->Map(m_vertexBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map);
} }
memcpy((u8*)map.pData + m_vertexBufferCursor, LocalVBuffer, vSize); memcpy((u8*)map.pData + m_vertexBufferCursor, LocalVBuffer, vSize);
D3D::context->Unmap(m_vertexBuffer, 0); D3D::g_context->Unmap(m_vertexBuffer, 0);
m_vertexDrawOffset = m_vertexBufferCursor; m_vertexDrawOffset = m_vertexBufferCursor;
m_vertexBufferCursor += vSize; m_vertexBufferCursor += vSize;
@ -115,13 +93,13 @@ void VertexManager::LoadBuffers()
if (m_indexBufferCursor + iCount >= IBUFFER_SIZE/2) if (m_indexBufferCursor + iCount >= IBUFFER_SIZE/2)
{ {
// Wrap around // Wrap around
D3D::context->Map(m_indexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); D3D::g_context->Map(m_indexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
m_indexBufferCursor = 0; m_indexBufferCursor = 0;
} }
else else
{ {
// Append data // Append data
D3D::context->Map(m_indexBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map); D3D::g_context->Map(m_indexBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &map);
} }
m_triangleDrawIndex = m_indexBufferCursor; m_triangleDrawIndex = m_indexBufferCursor;
m_lineDrawIndex = m_triangleDrawIndex + IndexGenerator::GetTriangleindexLen(); m_lineDrawIndex = m_triangleDrawIndex + IndexGenerator::GetTriangleindexLen();
@ -129,7 +107,7 @@ void VertexManager::LoadBuffers()
memcpy((u16*)map.pData + m_triangleDrawIndex, TIBuffer, 2*IndexGenerator::GetTriangleindexLen()); memcpy((u16*)map.pData + m_triangleDrawIndex, TIBuffer, 2*IndexGenerator::GetTriangleindexLen());
memcpy((u16*)map.pData + m_lineDrawIndex, LIBuffer, 2*IndexGenerator::GetLineindexLen()); memcpy((u16*)map.pData + m_lineDrawIndex, LIBuffer, 2*IndexGenerator::GetLineindexLen());
memcpy((u16*)map.pData + m_pointDrawIndex, PIBuffer, 2*IndexGenerator::GetPointindexLen()); memcpy((u16*)map.pData + m_pointDrawIndex, PIBuffer, 2*IndexGenerator::GetPointindexLen());
D3D::context->Unmap(m_indexBuffer, 0); D3D::g_context->Unmap(m_indexBuffer, 0);
m_indexBufferCursor += iCount; m_indexBufferCursor += iCount;
} }
@ -139,13 +117,13 @@ static const float LINE_PT_TEX_OFFSETS[8] = {
void VertexManager::Draw(UINT stride) void VertexManager::Draw(UINT stride)
{ {
D3D::context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &m_vertexDrawOffset); D3D::g_context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &m_vertexDrawOffset);
D3D::context->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R16_UINT, 0); D3D::g_context->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R16_UINT, 0);
if (IndexGenerator::GetNumTriangles() > 0) if (IndexGenerator::GetNumTriangles() > 0)
{ {
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); D3D::g_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
D3D::context->DrawIndexed(IndexGenerator::GetTriangleindexLen(), m_triangleDrawIndex, 0); D3D::g_context->DrawIndexed(IndexGenerator::GetTriangleindexLen(), m_triangleDrawIndex, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
} }
// Disable culling for lines and points // Disable culling for lines and points
@ -160,11 +138,11 @@ void VertexManager::Draw(UINT stride)
if (m_lineShader.SetShader(g_nativeVertexFmt->m_components, lineWidth, texOffset, vpWidth, vpHeight)) if (m_lineShader.SetShader(g_nativeVertexFmt->m_components, lineWidth, texOffset, vpWidth, vpHeight))
{ {
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); D3D::g_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
D3D::context->DrawIndexed(IndexGenerator::GetLineindexLen(), m_lineDrawIndex, 0); D3D::g_context->DrawIndexed(IndexGenerator::GetLineindexLen(), m_lineDrawIndex, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
D3D::context->GSSetShader(NULL, NULL, 0); D3D::g_context->GSSetShader(NULL, NULL, 0);
} }
} }
if (IndexGenerator::GetNumPoints() > 0) if (IndexGenerator::GetNumPoints() > 0)
@ -176,11 +154,11 @@ void VertexManager::Draw(UINT stride)
if (m_pointShader.SetShader(g_nativeVertexFmt->m_components, pointSize, texOffset, vpWidth, vpHeight)) if (m_pointShader.SetShader(g_nativeVertexFmt->m_components, pointSize, texOffset, vpWidth, vpHeight))
{ {
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); D3D::g_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
D3D::context->DrawIndexed(IndexGenerator::GetPointindexLen(), m_pointDrawIndex, 0); D3D::g_context->DrawIndexed(IndexGenerator::GetPointindexLen(), m_pointDrawIndex, 0);
INCSTAT(stats.thisFrame.numIndexedDrawCalls); INCSTAT(stats.thisFrame.numIndexedDrawCalls);
D3D::context->GSSetShader(NULL, NULL, 0); D3D::g_context->GSSetShader(NULL, NULL, 0);
} }
} }
if (IndexGenerator::GetNumLines() > 0 || IndexGenerator::GetNumPoints() > 0) if (IndexGenerator::GetNumLines() > 0 || IndexGenerator::GetNumPoints() > 0)
@ -235,14 +213,14 @@ void VertexManager::vFlush()
bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate &&
bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
if (!PixelShaderCache::SetShader( if (!PixelShaderCache::LoadShader(
useDstAlpha ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE, useDstAlpha ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE,
g_nativeVertexFmt->m_components)) g_nativeVertexFmt->m_components))
{ {
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");}); GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
goto shader_fail; goto shader_fail;
} }
if (!VertexShaderCache::SetShader(g_nativeVertexFmt->m_components)) if (!VertexShaderCache::LoadShader(g_nativeVertexFmt->m_components))
{ {
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");}); GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
goto shader_fail; goto shader_fail;

View file

@ -29,13 +29,10 @@ class VertexManager : public ::VertexManager
{ {
public: public:
VertexManager(); VertexManager();
~VertexManager();
NativeVertexFormat* CreateNativeVertexFormat(); NativeVertexFormat* CreateNativeVertexFormat();
private: private:
void CreateDeviceObjects();
void DestroyDeviceObjects();
void LoadBuffers(); void LoadBuffers();
void Draw(UINT stride); void Draw(UINT stride);
// temp // temp
@ -47,8 +44,8 @@ private:
UINT m_triangleDrawIndex; UINT m_triangleDrawIndex;
UINT m_lineDrawIndex; UINT m_lineDrawIndex;
UINT m_pointDrawIndex; UINT m_pointDrawIndex;
ID3D11Buffer* m_indexBuffer; SharedPtr<ID3D11Buffer> m_indexBuffer;
ID3D11Buffer* m_vertexBuffer; SharedPtr<ID3D11Buffer> m_vertexBuffer;
LineGeometryShader m_lineShader; LineGeometryShader m_lineShader;
PointGeometryShader m_pointShader; PointGeometryShader m_pointShader;

View file

@ -36,12 +36,13 @@ bool vscbufchanged = true;
namespace DX11 { namespace DX11 {
VertexShaderCache::VSCache VertexShaderCache::vshaders; VertexShaderCache::VSCache VertexShaderCache::vshaders;
const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry; const VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry;
static ID3D11VertexShader* SimpleVertexShader = NULL; static SharedPtr<ID3D11VertexShader> SimpleVertexShader;
static ID3D11VertexShader* ClearVertexShader = NULL; static SharedPtr<ID3D11VertexShader> ClearVertexShader;
static ID3D11InputLayout* SimpleLayout = NULL;
static ID3D11InputLayout* ClearLayout = NULL; static SharedPtr<ID3D11InputLayout> SimpleLayout;
static SharedPtr<ID3D11InputLayout> ClearLayout;
LinearDiskCache<VERTEXSHADERUID, u8> g_vs_disk_cache; LinearDiskCache<VERTEXSHADERUID, u8> g_vs_disk_cache;
@ -50,17 +51,17 @@ ID3D11VertexShader* VertexShaderCache::GetClearVertexShader() { return ClearVert
ID3D11InputLayout* VertexShaderCache::GetSimpleInputLayout() { return SimpleLayout; } ID3D11InputLayout* VertexShaderCache::GetSimpleInputLayout() { return SimpleLayout; }
ID3D11InputLayout* VertexShaderCache::GetClearInputLayout() { return ClearLayout; } ID3D11InputLayout* VertexShaderCache::GetClearInputLayout() { return ClearLayout; }
ID3D11Buffer* vscbuf = NULL; SharedPtr<ID3D11Buffer> vscbuf;
ID3D11Buffer* &VertexShaderCache::GetConstantBuffer() ID3D11Buffer*const& VertexShaderCache::GetConstantBuffer()
{ {
// TODO: divide the global variables of the generated shaders into about 5 constant buffers to speed this up // TODO: divide the global variables of the generated shaders into about 5 constant buffers to speed this up
if (vscbufchanged) if (vscbufchanged)
{ {
D3D11_MAPPED_SUBRESOURCE map; D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(vscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); D3D::g_context->Map(vscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, vsconstants, sizeof(vsconstants)); memcpy(map.pData, vsconstants, sizeof(vsconstants));
D3D::context->Unmap(vscbuf, 0); D3D::g_context->Unmap(vscbuf, 0);
vscbufchanged = false; vscbufchanged = false;
} }
return vscbuf; return vscbuf;
@ -72,10 +73,11 @@ class VertexShaderCacheInserter : public LinearDiskCacheReader<VERTEXSHADERUID,
public: public:
void Read(const VERTEXSHADERUID &key, const u8 *value, u32 value_size) void Read(const VERTEXSHADERUID &key, const u8 *value, u32 value_size)
{ {
D3DBlob* blob = new D3DBlob(value_size, value); ID3D10Blob* blob = nullptr;
VertexShaderCache::InsertByteCode(key, blob); PD3D10CreateBlob(value_size, &blob);
blob->Release(); memcpy(blob->GetBufferPointer(), value, value_size); // TODO: i would like to eliminate this memcpy
VertexShaderCache::InsertByteCode(key, SharedPtr<ID3D10Blob>::FromPtr(blob));
} }
}; };
@ -127,26 +129,29 @@ void VertexShaderCache::Init()
unsigned int cbsize = ((sizeof(vsconstants))&(~0xf))+0x10; // must be a multiple of 16 unsigned int cbsize = ((sizeof(vsconstants))&(~0xf))+0x10; // must be a multiple of 16
D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
HRESULT hr = D3D::device->CreateBuffer(&cbdesc, NULL, &vscbuf); vscbuf = CreateBufferShared(&cbdesc, NULL);
CHECK(hr==S_OK, "Create vertex shader constant buffer (size=%u)", cbsize); CHECK(vscbuf, "Create vertex shader constant buffer (size=%u)", cbsize);
D3D::SetDebugObjectName((ID3D11DeviceChild*)vscbuf, "vertex shader constant buffer used to emulate the GX pipeline"); D3D::SetDebugObjectName(vscbuf, "vertex shader constant buffer used to emulate the GX pipeline");
D3DBlob* blob; {
D3D::CompileVertexShader(simple_shader_code, sizeof(simple_shader_code), &blob); auto const blob = D3D::CompileVertexShader(simple_shader_code, sizeof(simple_shader_code));
D3D::device->CreateInputLayout(simpleelems, 2, blob->Data(), blob->Size(), &SimpleLayout); SimpleLayout = CreateInputLayoutShared(simpleelems, 2, blob->GetBufferPointer(), blob->GetBufferSize());
SimpleVertexShader = D3D::CreateVertexShaderFromByteCode(blob); SimpleVertexShader = D3D::CreateVertexShaderFromByteCode(blob);
if (SimpleLayout == NULL || SimpleVertexShader == NULL) PanicAlert("Failed to create simple vertex shader or input layout at %s %d\n", __FILE__, __LINE__); if (SimpleLayout == NULL || !SimpleVertexShader)
blob->Release(); PanicAlert("Failed to create simple vertex shader or input layout at %s %d\n", __FILE__, __LINE__);
D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleVertexShader, "simple vertex shader"); D3D::SetDebugObjectName(SimpleVertexShader, "simple vertex shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)SimpleLayout, "simple input layout"); D3D::SetDebugObjectName(SimpleLayout, "simple input layout");
}
D3D::CompileVertexShader(clear_shader_code, sizeof(clear_shader_code), &blob); {
D3D::device->CreateInputLayout(clearelems, 2, blob->Data(), blob->Size(), &ClearLayout); auto const blob = D3D::CompileVertexShader(clear_shader_code, sizeof(clear_shader_code));
ClearLayout = CreateInputLayoutShared(clearelems, 2, blob->GetBufferPointer(), blob->GetBufferSize());
ClearVertexShader = D3D::CreateVertexShaderFromByteCode(blob); ClearVertexShader = D3D::CreateVertexShaderFromByteCode(blob);
if (ClearLayout == NULL || ClearVertexShader == NULL) PanicAlert("Failed to create clear vertex shader or input layout at %s %d\n", __FILE__, __LINE__); if (ClearLayout == NULL || !ClearVertexShader)
blob->Release(); PanicAlert("Failed to create clear vertex shader or input layout at %s %d\n", __FILE__, __LINE__);
D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearVertexShader, "clear vertex shader"); D3D::SetDebugObjectName(ClearVertexShader, "clear vertex shader");
D3D::SetDebugObjectName((ID3D11DeviceChild*)ClearLayout, "clear input layout"); D3D::SetDebugObjectName(ClearLayout, "clear input layout");
}
Clear(); Clear();
@ -178,34 +183,32 @@ void VertexShaderCache::Init()
void VertexShaderCache::Clear() void VertexShaderCache::Clear()
{ {
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter)
iter->second.Destroy();
vshaders.clear(); vshaders.clear();
} }
void VertexShaderCache::Shutdown() void VertexShaderCache::Shutdown()
{ {
SAFE_RELEASE(vscbuf); vscbuf.reset();
SAFE_RELEASE(SimpleVertexShader); SimpleVertexShader.reset();
SAFE_RELEASE(ClearVertexShader); ClearVertexShader.reset();
SAFE_RELEASE(SimpleLayout); SimpleLayout.reset();
SAFE_RELEASE(ClearLayout); ClearLayout.reset();
Clear(); Clear();
g_vs_disk_cache.Sync(); g_vs_disk_cache.Sync();
g_vs_disk_cache.Close(); g_vs_disk_cache.Close();
} }
bool VertexShaderCache::SetShader(u32 components) bool VertexShaderCache::LoadShader(u32 components)
{ {
VERTEXSHADERUID uid; VERTEXSHADERUID uid;
GetVertexShaderId(&uid, components); GetVertexShaderId(&uid, components);
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount) if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
{ {
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
return (vshaders[uid].shader != NULL); return (!!vshaders[uid].shader);
} }
memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID)); memcpy(&last_vertex_shader_uid, &uid, sizeof(VERTEXSHADERUID));
@ -218,39 +221,37 @@ bool VertexShaderCache::SetShader(u32 components)
last_entry = &entry; last_entry = &entry;
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
return (entry.shader != NULL); return (!!entry.shader);
} }
const char *code = GenerateVertexShaderCode(components, API_D3D11); const char *code = GenerateVertexShaderCode(components, API_D3D11);
D3DBlob* pbytecode = NULL; auto const pbytecode = D3D::CompileVertexShader(code, (int)strlen(code));
D3D::CompileVertexShader(code, (int)strlen(code), &pbytecode); if (!pbytecode)
if (pbytecode == NULL)
{ {
PanicAlert("Failed to compile Vertex Shader %s %d:\n\n%s", __FILE__, __LINE__, code); PanicAlert("Failed to compile Vertex Shader %s %d:\n\n%s", __FILE__, __LINE__, code);
GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
return false; return false;
} }
g_vs_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size()); g_vs_disk_cache.Append(uid, (u8*)pbytecode->GetBufferPointer(), (u32)pbytecode->GetBufferSize());
g_vs_disk_cache.Sync(); g_vs_disk_cache.Sync();
bool result = InsertByteCode(uid, pbytecode); bool result = InsertByteCode(uid, pbytecode);
pbytecode->Release();
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
return result; return result;
} }
bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, D3DBlob* bcodeblob) bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, SharedPtr<ID3D10Blob> bcodeblob)
{ {
ID3D11VertexShader* shader = D3D::CreateVertexShaderFromByteCode(bcodeblob); auto const shader = D3D::CreateVertexShaderFromByteCode(bcodeblob);
if (shader == NULL) if (!shader)
{ {
PanicAlert("Failed to create vertex shader from %p size %d at %s %d\n", bcodeblob->Data(), bcodeblob->Size(), __FILE__, __LINE__); PanicAlert("Failed to create vertex shader from %p size %d at %s %d\n",
bcodeblob->GetBufferPointer(), bcodeblob->GetBufferSize(), __FILE__, __LINE__);
return false; return false;
} }
// TODO: Somehow make the debug name a bit more specific // TODO: Somehow make the debug name a bit more specific
D3D::SetDebugObjectName((ID3D11DeviceChild*)shader, "a vertex shader of VertexShaderCache"); D3D::SetDebugObjectName(shader, "a vertex shader of VertexShaderCache");
// Make an entry in the table // Make an entry in the table
VSCacheEntry entry; VSCacheEntry entry;

View file

@ -20,12 +20,12 @@
#include <map> #include <map>
#include "D3DBase.h" #include "D3DUtil.h"
#include "D3DBlob.h"
class VERTEXSHADERUID; class VERTEXSHADERUID;
namespace DX11 { namespace DX11
{
class VertexShaderCache class VertexShaderCache
{ {
@ -33,37 +33,33 @@ public:
static void Init(); static void Init();
static void Clear(); static void Clear();
static void Shutdown(); static void Shutdown();
static bool SetShader(u32 components); // TODO: Should be renamed to LoadShader static bool LoadShader(u32 components);
static ID3D11VertexShader* GetActiveShader() { return last_entry->shader; } static SharedPtr<ID3D11VertexShader> GetActiveShader() { return last_entry->shader; }
static D3DBlob* GetActiveShaderBytecode() { return last_entry->bytecode; } static SharedPtr<ID3D10Blob> GetActiveShaderBytecode() { return last_entry->bytecode; }
static ID3D11Buffer* &GetConstantBuffer(); static ID3D11Buffer*const& GetConstantBuffer();
static ID3D11VertexShader* GetSimpleVertexShader(); static ID3D11VertexShader* GetSimpleVertexShader();
static ID3D11VertexShader* GetClearVertexShader(); static ID3D11VertexShader* GetClearVertexShader();
static ID3D11InputLayout* GetSimpleInputLayout(); static ID3D11InputLayout* GetSimpleInputLayout();
static ID3D11InputLayout* GetClearInputLayout(); static ID3D11InputLayout* GetClearInputLayout();
static bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, D3DBlob* bcodeblob); static bool VertexShaderCache::InsertByteCode(const VERTEXSHADERUID &uid, SharedPtr<ID3D10Blob> bcodeblob);
private: private:
struct VSCacheEntry struct VSCacheEntry
{ {
ID3D11VertexShader* shader; SharedPtr<ID3D11VertexShader> shader;
D3DBlob* bytecode; // needed to initialize the input layout SharedPtr<ID3D10Blob> bytecode; // needed to initialize the input layout
int frameCount; int frameCount;
VSCacheEntry() : shader(NULL), bytecode(NULL), frameCount(0) {} VSCacheEntry()
void SetByteCode(D3DBlob* blob) : frameCount(0)
{}
void SetByteCode(SharedPtr<ID3D10Blob> blob)
{ {
SAFE_RELEASE(bytecode);
bytecode = blob; bytecode = blob;
blob->AddRef();
}
void Destroy()
{
SAFE_RELEASE(shader);
SAFE_RELEASE(bytecode);
} }
}; };
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache; typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;

View file

@ -18,7 +18,6 @@
#include "XFBEncoder.h" #include "XFBEncoder.h"
#include "D3DBase.h" #include "D3DBase.h"
#include "D3DBlob.h"
#include "D3DShader.h" #include "D3DShader.h"
#include "Render.h" #include "Render.h"
#include "GfxState.h" #include "GfxState.h"
@ -144,16 +143,10 @@ static const struct QuadVertex
} QUAD_VERTS[4] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } }; } QUAD_VERTS[4] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } };
XFBEncoder::XFBEncoder() XFBEncoder::XFBEncoder()
: m_out(NULL), m_outRTV(NULL), m_outStage(NULL), m_encodeParams(NULL), : m_outRTV(NULL),
m_quad(NULL), m_vShader(NULL), m_quadLayout(NULL), m_pShader(NULL), m_xfbEncodeDepthState(NULL),
m_xfbEncodeBlendState(NULL), m_xfbEncodeDepthState(NULL),
m_xfbEncodeRastState(NULL), m_efbSampler(NULL) m_xfbEncodeRastState(NULL), m_efbSampler(NULL)
{ }
void XFBEncoder::Init()
{ {
HRESULT hr;
// Create output texture // Create output texture
// The pixel shader can generate one YUYV entry per pixel. One YUYV entry // The pixel shader can generate one YUYV entry per pixel. One YUYV entry
@ -161,15 +154,15 @@ void XFBEncoder::Init()
D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC( D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC(
DXGI_FORMAT_R8G8B8A8_UNORM, MAX_XFB_WIDTH/2, MAX_XFB_HEIGHT, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, MAX_XFB_WIDTH/2, MAX_XFB_HEIGHT, 1, 1,
D3D11_BIND_RENDER_TARGET); D3D11_BIND_RENDER_TARGET);
hr = D3D::device->CreateTexture2D(&t2dd, NULL, &m_out); m_out = CreateTexture2DShared(&t2dd, NULL);
CHECK(SUCCEEDED(hr), "create xfb encoder output texture"); CHECK(m_out, "create xfb encoder output texture");
D3D::SetDebugObjectName(m_out, "xfb encoder output texture"); D3D::SetDebugObjectName(m_out, "xfb encoder output texture");
// Create output render target view // Create output render target view
D3D11_RENDER_TARGET_VIEW_DESC rtvd = CD3D11_RENDER_TARGET_VIEW_DESC(m_out, D3D11_RENDER_TARGET_VIEW_DESC rtvd = CD3D11_RENDER_TARGET_VIEW_DESC(m_out,
D3D11_RTV_DIMENSION_TEXTURE2D, DXGI_FORMAT_R8G8B8A8_UNORM); D3D11_RTV_DIMENSION_TEXTURE2D, DXGI_FORMAT_R8G8B8A8_UNORM);
hr = D3D::device->CreateRenderTargetView(m_out, &rtvd, &m_outRTV); HRESULT hr = D3D::g_device->CreateRenderTargetView(m_out, &rtvd, &m_outRTV);
CHECK(SUCCEEDED(hr), "create xfb encoder output texture rtv"); CHECK(SUCCEEDED(hr), "create xfb encoder output texture rtv");
D3D::SetDebugObjectName(m_outRTV, "xfb encoder output rtv"); D3D::SetDebugObjectName(m_outRTV, "xfb encoder output rtv");
@ -178,16 +171,16 @@ void XFBEncoder::Init()
t2dd.Usage = D3D11_USAGE_STAGING; t2dd.Usage = D3D11_USAGE_STAGING;
t2dd.BindFlags = 0; t2dd.BindFlags = 0;
t2dd.CPUAccessFlags = D3D11_CPU_ACCESS_READ; t2dd.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
hr = D3D::device->CreateTexture2D(&t2dd, NULL, &m_outStage); m_outStage = CreateTexture2DShared(&t2dd, NULL);
CHECK(SUCCEEDED(hr), "create xfb encoder output staging buffer"); CHECK(m_outStage, "create xfb encoder output staging buffer");
D3D::SetDebugObjectName(m_outStage, "xfb encoder output staging buffer"); D3D::SetDebugObjectName(m_outStage, "xfb encoder output staging buffer");
// Create constant buffer for uploading params to shaders // Create constant buffer for uploading params to shaders
D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(XFBEncodeParams), D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(XFBEncodeParams),
D3D11_BIND_CONSTANT_BUFFER); D3D11_BIND_CONSTANT_BUFFER);
hr = D3D::device->CreateBuffer(&bd, NULL, &m_encodeParams); m_encodeParams = CreateBufferShared(&bd, NULL);
CHECK(SUCCEEDED(hr), "create xfb encode params buffer"); CHECK(m_encodeParams, "create xfb encode params buffer");
D3D::SetDebugObjectName(m_encodeParams, "xfb encoder params buffer"); D3D::SetDebugObjectName(m_encodeParams, "xfb encoder params buffer");
// Create vertex quad // Create vertex quad
@ -196,35 +189,24 @@ void XFBEncoder::Init()
D3D11_USAGE_IMMUTABLE); D3D11_USAGE_IMMUTABLE);
D3D11_SUBRESOURCE_DATA srd = { QUAD_VERTS, 0, 0 }; D3D11_SUBRESOURCE_DATA srd = { QUAD_VERTS, 0, 0 };
hr = D3D::device->CreateBuffer(&bd, &srd, &m_quad); m_quad = CreateBufferShared(&bd, &srd);
CHECK(SUCCEEDED(hr), "create xfb encode quad vertex buffer"); CHECK(m_quad, "create xfb encode quad vertex buffer");
D3D::SetDebugObjectName(m_quad, "xfb encoder quad vertex buffer"); D3D::SetDebugObjectName(m_quad, "xfb encoder quad vertex buffer");
// Create vertex shader // Create vertex shader
SharedPtr<ID3D10Blob> bytecode;
D3DBlob* bytecode = NULL; m_vShader = D3D::CompileAndCreateVertexShader(XFB_ENCODE_VS, sizeof(XFB_ENCODE_VS), std::addressof(bytecode));
if (!D3D::CompileVertexShader(XFB_ENCODE_VS, sizeof(XFB_ENCODE_VS), &bytecode)) CHECK(m_vShader, "compile/create xfb encode vertex shader");
{
ERROR_LOG(VIDEO, "XFB encode vertex shader failed to compile");
return;
}
hr = D3D::device->CreateVertexShader(bytecode->Data(), bytecode->Size(), NULL, &m_vShader);
CHECK(SUCCEEDED(hr), "create xfb encode vertex shader");
D3D::SetDebugObjectName(m_vShader, "xfb encoder vertex shader"); D3D::SetDebugObjectName(m_vShader, "xfb encoder vertex shader");
// Create input layout for vertex quad using bytecode from vertex shader // Create input layout for vertex quad using bytecode from vertex shader
m_quadLayout = CreateInputLayoutShared(QUAD_LAYOUT_DESC,
hr = D3D::device->CreateInputLayout(QUAD_LAYOUT_DESC, sizeof(QUAD_LAYOUT_DESC) / sizeof(D3D11_INPUT_ELEMENT_DESC),
sizeof(QUAD_LAYOUT_DESC)/sizeof(D3D11_INPUT_ELEMENT_DESC), bytecode->GetBufferPointer(), bytecode->GetBufferSize());
bytecode->Data(), bytecode->Size(), &m_quadLayout); CHECK(m_quadLayout, "create xfb encode quad vertex layout");
CHECK(SUCCEEDED(hr), "create xfb encode quad vertex layout");
D3D::SetDebugObjectName(m_quadLayout, "xfb encoder quad layout"); D3D::SetDebugObjectName(m_quadLayout, "xfb encoder quad layout");
bytecode->Release();
// Create pixel shader // Create pixel shader
m_pShader = D3D::CompileAndCreatePixelShader(XFB_ENCODE_PS, sizeof(XFB_ENCODE_PS)); m_pShader = D3D::CompileAndCreatePixelShader(XFB_ENCODE_PS, sizeof(XFB_ENCODE_PS));
if (!m_pShader) if (!m_pShader)
{ {
@ -235,52 +217,44 @@ void XFBEncoder::Init()
// Create blend state // Create blend state
D3D11_BLEND_DESC bld = CD3D11_BLEND_DESC(CD3D11_DEFAULT()); auto bld = CD3D11_BLEND_DESC(CD3D11_DEFAULT());
hr = D3D::device->CreateBlendState(&bld, &m_xfbEncodeBlendState); m_xfbEncodeBlendState = CreateBlendStateShared(&bld);
CHECK(SUCCEEDED(hr), "create xfb encode blend state"); CHECK(m_xfbEncodeBlendState, "create xfb encode blend state");
D3D::SetDebugObjectName(m_xfbEncodeBlendState, "xfb encoder blend state"); D3D::SetDebugObjectName(m_xfbEncodeBlendState, "xfb encoder blend state");
// Create depth state // Create depth state
D3D11_DEPTH_STENCIL_DESC dsd = CD3D11_DEPTH_STENCIL_DESC(CD3D11_DEFAULT()); auto dsd = CD3D11_DEPTH_STENCIL_DESC(CD3D11_DEFAULT());
dsd.DepthEnable = FALSE; dsd.DepthEnable = FALSE;
hr = D3D::device->CreateDepthStencilState(&dsd, &m_xfbEncodeDepthState); hr = D3D::g_device->CreateDepthStencilState(&dsd, &m_xfbEncodeDepthState);
CHECK(SUCCEEDED(hr), "create xfb encode depth state"); CHECK(SUCCEEDED(hr), "create xfb encode depth state");
D3D::SetDebugObjectName(m_xfbEncodeDepthState, "xfb encoder depth state"); D3D::SetDebugObjectName(m_xfbEncodeDepthState, "xfb encoder depth state");
// Create rasterizer state // Create rasterizer state
D3D11_RASTERIZER_DESC rd = CD3D11_RASTERIZER_DESC(CD3D11_DEFAULT()); auto rd = CD3D11_RASTERIZER_DESC(CD3D11_DEFAULT());
rd.CullMode = D3D11_CULL_NONE; rd.CullMode = D3D11_CULL_NONE;
rd.DepthClipEnable = FALSE; rd.DepthClipEnable = FALSE;
hr = D3D::device->CreateRasterizerState(&rd, &m_xfbEncodeRastState); hr = D3D::g_device->CreateRasterizerState(&rd, &m_xfbEncodeRastState);
CHECK(SUCCEEDED(hr), "create xfb encode rasterizer state"); CHECK(SUCCEEDED(hr), "create xfb encode rasterizer state");
D3D::SetDebugObjectName(m_xfbEncodeRastState, "xfb encoder rast state"); D3D::SetDebugObjectName(m_xfbEncodeRastState, "xfb encoder rast state");
// Create EFB texture sampler // Create EFB texture sampler
D3D11_SAMPLER_DESC sd = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT()); auto sd = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT());
// FIXME: Should we really use point sampling here? // FIXME: Should we really use point sampling here?
sd.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; sd.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
hr = D3D::device->CreateSamplerState(&sd, &m_efbSampler); hr = D3D::g_device->CreateSamplerState(&sd, &m_efbSampler);
CHECK(SUCCEEDED(hr), "create xfb encode texture sampler"); CHECK(SUCCEEDED(hr), "create xfb encode texture sampler");
D3D::SetDebugObjectName(m_efbSampler, "xfb encoder texture sampler"); D3D::SetDebugObjectName(m_efbSampler, "xfb encoder texture sampler");
} }
void XFBEncoder::Shutdown() XFBEncoder::~XFBEncoder()
{ {
SAFE_RELEASE(m_efbSampler); SAFE_RELEASE(m_efbSampler);
SAFE_RELEASE(m_xfbEncodeRastState); SAFE_RELEASE(m_xfbEncodeRastState);
SAFE_RELEASE(m_xfbEncodeDepthState); SAFE_RELEASE(m_xfbEncodeDepthState);
SAFE_RELEASE(m_xfbEncodeBlendState);
SAFE_RELEASE(m_pShader);
SAFE_RELEASE(m_quadLayout);
SAFE_RELEASE(m_vShader);
SAFE_RELEASE(m_quad);
SAFE_RELEASE(m_encodeParams);
SAFE_RELEASE(m_outStage);
SAFE_RELEASE(m_outRTV); SAFE_RELEASE(m_outRTV);
SAFE_RELEASE(m_out);
} }
void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcRect, float gamma) void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcRect, float gamma)
@ -293,8 +267,8 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR
// Set up all the state for XFB encoding // Set up all the state for XFB encoding
D3D::context->PSSetShader(m_pShader, NULL, 0); D3D::g_context->PSSetShader(m_pShader, NULL, 0);
D3D::context->VSSetShader(m_vShader, NULL, 0); D3D::g_context->VSSetShader(m_vShader, NULL, 0);
D3D::stateman->PushBlendState(m_xfbEncodeBlendState); D3D::stateman->PushBlendState(m_xfbEncodeBlendState);
D3D::stateman->PushDepthState(m_xfbEncodeDepthState); D3D::stateman->PushDepthState(m_xfbEncodeDepthState);
@ -302,13 +276,13 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR
D3D::stateman->Apply(); D3D::stateman->Apply();
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(width/2), FLOAT(height)); D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, FLOAT(width/2), FLOAT(height));
D3D::context->RSSetViewports(1, &vp); D3D::g_context->RSSetViewports(1, &vp);
D3D::context->IASetInputLayout(m_quadLayout); D3D::g_context->IASetInputLayout(m_quadLayout);
D3D::context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); D3D::g_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
UINT stride = sizeof(QuadVertex); UINT stride = sizeof(QuadVertex);
UINT offset = 0; UINT offset = 0;
D3D::context->IASetVertexBuffers(0, 1, &m_quad, &stride, &offset); D3D::g_context->IASetVertexBuffers(0, 1, &m_quad, &stride, &offset);
TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(srcRect); TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(srcRect);
@ -320,50 +294,50 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR
params.TexRight = FLOAT(targetRect.right) / g_renderer->GetFullTargetWidth(); params.TexRight = FLOAT(targetRect.right) / g_renderer->GetFullTargetWidth();
params.TexBottom = FLOAT(targetRect.bottom) / g_renderer->GetFullTargetHeight(); params.TexBottom = FLOAT(targetRect.bottom) / g_renderer->GetFullTargetHeight();
params.Gamma = gamma; params.Gamma = gamma;
D3D::context->UpdateSubresource(m_encodeParams, 0, NULL, &params, 0, 0); D3D::g_context->UpdateSubresource(m_encodeParams, 0, NULL, &params, 0, 0);
D3D::context->VSSetConstantBuffers(0, 1, &m_encodeParams); D3D::g_context->VSSetConstantBuffers(0, 1, &m_encodeParams);
D3D::context->OMSetRenderTargets(1, &m_outRTV, NULL); D3D::g_context->OMSetRenderTargets(1, &m_outRTV, NULL);
ID3D11ShaderResourceView* pEFB = FramebufferManager::GetEFBColorTexture()->GetSRV(); ID3D11ShaderResourceView* pEFB = FramebufferManager::GetEFBColorTexture()->GetSRV();
D3D::context->PSSetConstantBuffers(0, 1, &m_encodeParams); D3D::g_context->PSSetConstantBuffers(0, 1, &m_encodeParams);
D3D::context->PSSetShaderResources(0, 1, &pEFB); D3D::g_context->PSSetShaderResources(0, 1, &pEFB);
D3D::context->PSSetSamplers(0, 1, &m_efbSampler); D3D::g_context->PSSetSamplers(0, 1, &m_efbSampler);
// Encode! // Encode!
D3D::context->Draw(4, 0); D3D::g_context->Draw(4, 0);
// Copy to staging buffer // Copy to staging buffer
D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, width/2, height, 1); D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, width/2, height, 1);
D3D::context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox); D3D::g_context->CopySubresourceRegion(m_outStage, 0, 0, 0, 0, m_out, 0, &srcBox);
// Clean up state // Clean up state
IUnknown* nullDummy = NULL; IUnknown* nullDummy = NULL;
D3D::context->PSSetSamplers(0, 1, (ID3D11SamplerState**)&nullDummy); D3D::g_context->PSSetSamplers(0, 1, (ID3D11SamplerState**)&nullDummy);
D3D::context->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&nullDummy); D3D::g_context->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&nullDummy);
D3D::context->PSSetConstantBuffers(0, 1, (ID3D11Buffer**)&nullDummy); D3D::g_context->PSSetConstantBuffers(0, 1, (ID3D11Buffer**)&nullDummy);
D3D::context->OMSetRenderTargets(0, NULL, NULL); D3D::g_context->OMSetRenderTargets(0, NULL, NULL);
D3D::context->VSSetConstantBuffers(0, 1, (ID3D11Buffer**)&nullDummy); D3D::g_context->VSSetConstantBuffers(0, 1, (ID3D11Buffer**)&nullDummy);
D3D::stateman->PopRasterizerState(); D3D::stateman->PopRasterizerState();
D3D::stateman->PopDepthState(); D3D::stateman->PopDepthState();
D3D::stateman->PopBlendState(); D3D::stateman->PopBlendState();
D3D::context->PSSetShader(NULL, NULL, 0); D3D::g_context->PSSetShader(NULL, NULL, 0);
D3D::context->VSSetShader(NULL, NULL, 0); D3D::g_context->VSSetShader(NULL, NULL, 0);
// Transfer staging buffer to GameCube/Wii RAM // Transfer staging buffer to GameCube/Wii RAM
D3D11_MAPPED_SUBRESOURCE map = { 0 }; D3D11_MAPPED_SUBRESOURCE map = { 0 };
hr = D3D::context->Map(m_outStage, 0, D3D11_MAP_READ, 0, &map); hr = D3D::g_context->Map(m_outStage, 0, D3D11_MAP_READ, 0, &map);
CHECK(SUCCEEDED(hr), "map staging buffer"); CHECK(SUCCEEDED(hr), "map staging buffer");
u8* src = (u8*)map.pData; u8* src = (u8*)map.pData;
@ -374,12 +348,12 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR
src += map.RowPitch; src += map.RowPitch;
} }
D3D::context->Unmap(m_outStage, 0); D3D::g_context->Unmap(m_outStage, 0);
// Restore API // Restore API
g_renderer->RestoreAPIState(); g_renderer->RestoreAPIState();
D3D::context->OMSetRenderTargets(1, D3D::g_context->OMSetRenderTargets(1,
&FramebufferManager::GetEFBColorTexture()->GetRTV(), &FramebufferManager::GetEFBColorTexture()->GetRTV(),
FramebufferManager::GetEFBDepthTexture()->GetDSV()); FramebufferManager::GetEFBDepthTexture()->GetDSV());
} }

View file

@ -20,47 +20,32 @@
#include "VideoCommon.h" #include "VideoCommon.h"
struct ID3D11Texture2D; #include "D3DUtil.h"
struct ID3D11RenderTargetView;
struct ID3D11Buffer;
struct ID3D11VertexShader;
struct ID3D11PixelShader;
struct ID3D11InputLayout;
struct ID3D11BlendState;
struct ID3D11DepthStencilState;
struct ID3D11RasterizerState;
struct ID3D11SamplerState;
namespace DX11 namespace DX11
{ {
class XFBEncoder class XFBEncoder
{ {
public: public:
XFBEncoder(); XFBEncoder();
~XFBEncoder();
void Init();
void Shutdown();
void Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcRect, float gamma); void Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcRect, float gamma);
private: private:
SharedPtr<ID3D11Texture2D> m_out;
ID3D11Texture2D* m_out;
ID3D11RenderTargetView* m_outRTV; ID3D11RenderTargetView* m_outRTV;
ID3D11Texture2D* m_outStage; SharedPtr<ID3D11Texture2D> m_outStage;
ID3D11Buffer* m_encodeParams; SharedPtr<ID3D11Buffer> m_encodeParams;
ID3D11Buffer* m_quad; SharedPtr<ID3D11Buffer> m_quad;
ID3D11VertexShader* m_vShader; SharedPtr<ID3D11VertexShader> m_vShader;
ID3D11InputLayout* m_quadLayout; SharedPtr<ID3D11InputLayout> m_quadLayout;
ID3D11PixelShader* m_pShader; SharedPtr<ID3D11PixelShader> m_pShader;
ID3D11BlendState* m_xfbEncodeBlendState; SharedPtr<ID3D11BlendState> m_xfbEncodeBlendState;
ID3D11DepthStencilState* m_xfbEncodeDepthState; ID3D11DepthStencilState* m_xfbEncodeDepthState;
ID3D11RasterizerState* m_xfbEncodeRastState; ID3D11RasterizerState* m_xfbEncodeRastState;
ID3D11SamplerState* m_efbSampler; ID3D11SamplerState* m_efbSampler;
}; };
} }

View file

@ -121,9 +121,8 @@ void VideoBackend::ShowConfig(void *_hParent)
if (g_Config.backend_info.Adapters.size() == g_Config.iAdapter) if (g_Config.backend_info.Adapters.size() == g_Config.iAdapter)
{ {
char buf[32]; char buf[32];
std::vector<DXGI_SAMPLE_DESC> modes; auto const modes = DX11::D3D::EnumAAModes(ad);
DX11::D3D::EnumAAModes(ad, modes); for (size_t i = 0; i < modes.size(); ++i)
for (unsigned int i = 0; i < modes.size(); ++i)
{ {
if (i == 0) sprintf_s(buf, 32, "None"); if (i == 0) sprintf_s(buf, 32, "None");
else if (modes[i].Quality) sprintf_s(buf, 32, "%d samples (quality level %d)", modes[i].Count, modes[i].Quality); else if (modes[i].Quality) sprintf_s(buf, 32, "%d samples (quality level %d)", modes[i].Count, modes[i].Quality);

View file

@ -115,7 +115,10 @@ LPDIRECT3DPIXELSHADER9 PixelShaderCache::ReinterpRGBA6ToRGB8()
" ocol0 /= 255.f;\n" " ocol0 /= 255.f;\n"
"}\n" "}\n"
}; };
if (!s_rgba6_to_rgb8) s_rgba6_to_rgb8 = D3D::CompileAndCreatePixelShader(code, (int)strlen(code));
if (!s_rgba6_to_rgb8)
s_rgba6_to_rgb8 = D3D::CompileAndCreatePixelShader(code, (int)strlen(code));
return s_rgba6_to_rgb8; return s_rgba6_to_rgb8;
} }