mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Merge pull request #7869 from stenzek/d3dcommon
D3D: Move sharable D3D11/D3D12 code to common library
This commit is contained in:
@@ -11,6 +11,7 @@ add_library(common
|
||||
Crypto/ec.cpp
|
||||
Debug/MemoryPatches.cpp
|
||||
Debug/Watches.cpp
|
||||
DynamicLibrary.cpp
|
||||
ENetUtil.cpp
|
||||
File.cpp
|
||||
FileSearch.cpp
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
<ClInclude Include="DebugInterface.h" />
|
||||
<ClInclude Include="Debug\MemoryPatches.h" />
|
||||
<ClInclude Include="Debug\Watches.h" />
|
||||
<ClInclude Include="DynamicLibrary.h" />
|
||||
<ClInclude Include="ENetUtil.h" />
|
||||
<ClInclude Include="Event.h" />
|
||||
<ClInclude Include="File.h" />
|
||||
@@ -184,6 +185,7 @@
|
||||
<ClCompile Include="Config\Layer.cpp" />
|
||||
<ClCompile Include="Debug\MemoryPatches.cpp" />
|
||||
<ClCompile Include="Debug\Watches.cpp" />
|
||||
<ClCompile Include="DynamicLibrary.cpp" />
|
||||
<ClCompile Include="ENetUtil.cpp" />
|
||||
<ClCompile Include="File.cpp" />
|
||||
<ClCompile Include="FileSearch.cpp" />
|
||||
@@ -258,4 +260,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -276,6 +276,8 @@
|
||||
<ClInclude Include="GL\GLContext.h">
|
||||
<Filter>GL\GLInterface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VariantUtil.h" />
|
||||
<ClInclude Include="DynamicLibrary.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CDUtils.cpp" />
|
||||
@@ -357,6 +359,7 @@
|
||||
<ClCompile Include="GL\GLContext.cpp">
|
||||
<Filter>GL\GLInterface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DynamicLibrary.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
@@ -364,4 +367,4 @@
|
||||
<ItemGroup>
|
||||
<Natvis Include="BitField.natvis" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -0,0 +1,100 @@
|
||||
// Copyright 2019 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Common/DynamicLibrary.h"
|
||||
#include <cstring>
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
namespace Common
|
||||
{
|
||||
DynamicLibrary::DynamicLibrary() = default;
|
||||
|
||||
DynamicLibrary::DynamicLibrary(const char* filename)
|
||||
{
|
||||
Open(filename);
|
||||
}
|
||||
|
||||
DynamicLibrary::~DynamicLibrary()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
std::string DynamicLibrary::GetUnprefixedFilename(const char* filename)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return std::string(filename) + ".dll";
|
||||
#elif defined(__APPLE__)
|
||||
return std::string(filename) + ".dylib";
|
||||
#else
|
||||
return std::string(filename) + ".so";
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string DynamicLibrary::GetVersionedFilename(const char* libname, int major, int minor)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
if (major >= 0 && minor >= 0)
|
||||
return StringFromFormat("%s-%d-%d.dll", libname, major, minor);
|
||||
else if (major >= 0)
|
||||
return StringFromFormat("%s-%d.dll", libname, major);
|
||||
else
|
||||
return StringFromFormat("%s.dll", libname);
|
||||
#elif defined(__APPLE__)
|
||||
const char* prefix = std::strncmp(libname, "lib", 3) ? "lib" : "";
|
||||
if (major >= 0 && minor >= 0)
|
||||
return StringFromFormat("%s%s.%d.%d.dylib", prefix, libname, major, minor);
|
||||
else if (major >= 0)
|
||||
return StringFromFormat("%s%s.%d.dylib", prefix, libname, major);
|
||||
else
|
||||
return StringFromFormat("%s%s.dylib", prefix, libname);
|
||||
#else
|
||||
const char* prefix = std::strncmp(libname, "lib", 3) ? "lib" : "";
|
||||
if (major >= 0 && minor >= 0)
|
||||
return StringFromFormat("%s%s.so.%d.%d", prefix, libname, major, minor);
|
||||
else if (major >= 0)
|
||||
return StringFromFormat("%s%s.so.%d", prefix, libname, major);
|
||||
else
|
||||
return StringFromFormat("%s%s.so", prefix, libname);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool DynamicLibrary::Open(const char* filename)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
m_handle = reinterpret_cast<void*>(LoadLibraryA(filename));
|
||||
#else
|
||||
m_handle = dlopen(filename, RTLD_NOW);
|
||||
#endif
|
||||
return m_handle != nullptr;
|
||||
}
|
||||
|
||||
void DynamicLibrary::Close()
|
||||
{
|
||||
if (!IsOpen())
|
||||
return;
|
||||
|
||||
#ifdef _WIN32
|
||||
FreeLibrary(reinterpret_cast<HMODULE>(m_handle));
|
||||
#else
|
||||
dlclose(m_handle);
|
||||
#endif
|
||||
m_handle = nullptr;
|
||||
}
|
||||
|
||||
void* DynamicLibrary::GetSymbolAddress(const char* name) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return reinterpret_cast<void*>(GetProcAddress(reinterpret_cast<HMODULE>(m_handle), name));
|
||||
#else
|
||||
return reinterpret_cast<void*>(dlsym(m_handle, name));
|
||||
#endif
|
||||
}
|
||||
} // namespace Common
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright 2019 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
|
||||
namespace Common
|
||||
{
|
||||
/**
|
||||
* Provides a platform-independent interface for loading a dynamic library and retrieving symbols.
|
||||
* The interface maintains an internal reference count to allow one handle to be shared between
|
||||
* multiple users.
|
||||
*/
|
||||
class DynamicLibrary final
|
||||
{
|
||||
public:
|
||||
// Default constructor, does not load a library.
|
||||
DynamicLibrary();
|
||||
|
||||
// Automatically loads the specified library. Call IsOpen() to check validity before use.
|
||||
DynamicLibrary(const char* filename);
|
||||
|
||||
// Closes the library.
|
||||
~DynamicLibrary();
|
||||
|
||||
// Returns the specified library name with the platform-specific suffix added.
|
||||
static std::string GetUnprefixedFilename(const char* filename);
|
||||
|
||||
// Returns the specified library name in platform-specific format.
|
||||
// Major/minor versions will not be included if set to -1.
|
||||
// If libname already contains the "lib" prefix, it will not be added again.
|
||||
// Windows: LIBNAME-MAJOR-MINOR.dll
|
||||
// Linux: libLIBNAME.so.MAJOR.MINOR
|
||||
// Mac: libLIBNAME.MAJOR.MINOR.dylib
|
||||
static std::string GetVersionedFilename(const char* libname, int major = -1, int minor = -1);
|
||||
|
||||
// Returns true if a module is loaded, otherwise false.
|
||||
bool IsOpen() const { return m_handle != nullptr; }
|
||||
|
||||
// Loads (or replaces) the handle with the specified library file name.
|
||||
// Returns true if the library was loaded and can be used.
|
||||
bool Open(const char* filename);
|
||||
|
||||
// Unloads the library, any function pointers from this library are no longer valid.
|
||||
void Close();
|
||||
|
||||
// Returns the address of the specified symbol (function or variable) as an untyped pointer.
|
||||
// If the specified symbol does not exist in this library, nullptr is returned.
|
||||
void* GetSymbolAddress(const char* name) const;
|
||||
|
||||
// Obtains the address of the specified symbol, automatically casting to the correct type.
|
||||
// Returns true if the symbol was found and assigned, otherwise false.
|
||||
template <typename T>
|
||||
bool GetSymbol(const char* name, T* ptr) const
|
||||
{
|
||||
*ptr = reinterpret_cast<T>(GetSymbolAddress(name));
|
||||
return *ptr != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// Platform-dependent data type representing a dynamic library handle.
|
||||
void* m_handle = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
@@ -4,6 +4,7 @@ add_subdirectory(Software)
|
||||
add_subdirectory(Vulkan)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
add_subdirectory(D3DCommon)
|
||||
add_subdirectory(D3D)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -6,17 +6,18 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3DCommon/Common.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
static ID3D11Buffer* s_bbox_buffer;
|
||||
static ID3D11Buffer* s_bbox_staging_buffer;
|
||||
static ID3D11UnorderedAccessView* s_bbox_uav;
|
||||
static ComPtr<ID3D11Buffer> s_bbox_buffer;
|
||||
static ComPtr<ID3D11Buffer> s_bbox_staging_buffer;
|
||||
static ComPtr<ID3D11UnorderedAccessView> s_bbox_uav;
|
||||
|
||||
ID3D11UnorderedAccessView*& BBox::GetUAV()
|
||||
ID3D11UnorderedAccessView* BBox::GetUAV()
|
||||
{
|
||||
return s_bbox_uav;
|
||||
return s_bbox_uav.Get();
|
||||
}
|
||||
|
||||
void BBox::Init()
|
||||
@@ -35,7 +36,7 @@ void BBox::Init()
|
||||
HRESULT hr;
|
||||
hr = D3D::device->CreateBuffer(&desc, &data, &s_bbox_buffer);
|
||||
CHECK(SUCCEEDED(hr), "Create BoundingBox Buffer.");
|
||||
D3D::SetDebugObjectName(s_bbox_buffer, "BoundingBox Buffer");
|
||||
D3DCommon::SetDebugObjectName(s_bbox_buffer.Get(), "BoundingBox Buffer");
|
||||
|
||||
// Second to use as a staging buffer.
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
@@ -43,7 +44,7 @@ void BBox::Init()
|
||||
desc.BindFlags = 0;
|
||||
hr = D3D::device->CreateBuffer(&desc, nullptr, &s_bbox_staging_buffer);
|
||||
CHECK(SUCCEEDED(hr), "Create BoundingBox Staging Buffer.");
|
||||
D3D::SetDebugObjectName(s_bbox_staging_buffer, "BoundingBox Staging Buffer");
|
||||
D3DCommon::SetDebugObjectName(s_bbox_staging_buffer.Get(), "BoundingBox Staging Buffer");
|
||||
|
||||
// UAV is required to allow concurrent access.
|
||||
D3D11_UNORDERED_ACCESS_VIEW_DESC UAVdesc = {};
|
||||
@@ -52,37 +53,37 @@ void BBox::Init()
|
||||
UAVdesc.Buffer.FirstElement = 0;
|
||||
UAVdesc.Buffer.Flags = 0;
|
||||
UAVdesc.Buffer.NumElements = 4;
|
||||
hr = D3D::device->CreateUnorderedAccessView(s_bbox_buffer, &UAVdesc, &s_bbox_uav);
|
||||
hr = D3D::device->CreateUnorderedAccessView(s_bbox_buffer.Get(), &UAVdesc, &s_bbox_uav);
|
||||
CHECK(SUCCEEDED(hr), "Create BoundingBox UAV.");
|
||||
D3D::SetDebugObjectName(s_bbox_uav, "BoundingBox UAV");
|
||||
D3D::stateman->SetOMUAV(s_bbox_uav);
|
||||
D3DCommon::SetDebugObjectName(s_bbox_uav.Get(), "BoundingBox UAV");
|
||||
D3D::stateman->SetOMUAV(s_bbox_uav.Get());
|
||||
}
|
||||
}
|
||||
|
||||
void BBox::Shutdown()
|
||||
{
|
||||
SAFE_RELEASE(s_bbox_buffer);
|
||||
SAFE_RELEASE(s_bbox_staging_buffer);
|
||||
SAFE_RELEASE(s_bbox_uav);
|
||||
s_bbox_uav.Reset();
|
||||
s_bbox_staging_buffer.Reset();
|
||||
s_bbox_buffer.Reset();
|
||||
}
|
||||
|
||||
void BBox::Set(int index, int value)
|
||||
{
|
||||
D3D11_BOX box{index * sizeof(s32), 0, 0, (index + 1) * sizeof(s32), 1, 1};
|
||||
D3D::context->UpdateSubresource(s_bbox_buffer, 0, &box, &value, 0, 0);
|
||||
D3D::context->UpdateSubresource(s_bbox_buffer.Get(), 0, &box, &value, 0, 0);
|
||||
}
|
||||
|
||||
int BBox::Get(int index)
|
||||
{
|
||||
int data = 0;
|
||||
D3D::context->CopyResource(s_bbox_staging_buffer, s_bbox_buffer);
|
||||
D3D::context->CopyResource(s_bbox_staging_buffer.Get(), s_bbox_buffer.Get());
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
HRESULT hr = D3D::context->Map(s_bbox_staging_buffer, 0, D3D11_MAP_READ, 0, &map);
|
||||
HRESULT hr = D3D::context->Map(s_bbox_staging_buffer.Get(), 0, D3D11_MAP_READ, 0, &map);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
data = ((s32*)map.pData)[index];
|
||||
}
|
||||
D3D::context->Unmap(s_bbox_staging_buffer, 0);
|
||||
D3D::context->Unmap(s_bbox_staging_buffer.Get(), 0);
|
||||
return data;
|
||||
}
|
||||
}; // namespace DX11
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace DX11
|
||||
class BBox
|
||||
{
|
||||
public:
|
||||
static ID3D11UnorderedAccessView*& GetUAV();
|
||||
static ID3D11UnorderedAccessView* GetUAV();
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
|
||||
|
||||
@@ -26,4 +26,5 @@ target_link_libraries(videod3d
|
||||
PUBLIC
|
||||
common
|
||||
videocommon
|
||||
videod3dcommon
|
||||
)
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
<ClCompile Include="NativeVertexFormat.cpp" />
|
||||
<ClCompile Include="PerfQuery.cpp" />
|
||||
<ClCompile Include="Render.cpp" />
|
||||
<ClCompile Include="SwapChain.cpp" />
|
||||
<ClCompile Include="VertexManager.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -57,6 +58,7 @@
|
||||
<ClInclude Include="DXTexture.h" />
|
||||
<ClInclude Include="PerfQuery.h" />
|
||||
<ClInclude Include="Render.h" />
|
||||
<ClInclude Include="SwapChain.h" />
|
||||
<ClInclude Include="VertexManager.h" />
|
||||
<ClInclude Include="VideoBackend.h" />
|
||||
</ItemGroup>
|
||||
@@ -64,6 +66,9 @@
|
||||
<ProjectReference Include="$(CoreDir)VideoCommon\VideoCommon.vcxproj">
|
||||
<Project>{3de9ee35-3e91-4f27-a014-2866ad8c3fe3}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\D3DCommon\D3DCommon.vcxproj">
|
||||
<Project>{dea96cf2-f237-4a1a-b32f-c916769efb50}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
<ClCompile Include="DXPipeline.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SwapChain.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="D3DBase.h">
|
||||
@@ -70,5 +73,8 @@
|
||||
<ClInclude Include="DXPipeline.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SwapChain.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,90 +9,37 @@
|
||||
#include <d3dcompiler.h>
|
||||
#include <dxgi1_5.h>
|
||||
#include <vector>
|
||||
#include <wrl/client.h>
|
||||
|
||||
#include "Common/Common.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
#define SAFE_RELEASE(x) \
|
||||
{ \
|
||||
if (x) \
|
||||
(x)->Release(); \
|
||||
(x) = nullptr; \
|
||||
}
|
||||
#define SAFE_DELETE(x) \
|
||||
{ \
|
||||
delete (x); \
|
||||
(x) = nullptr; \
|
||||
}
|
||||
#define SAFE_DELETE_ARRAY(x) \
|
||||
{ \
|
||||
delete[](x); \
|
||||
(x) = nullptr; \
|
||||
}
|
||||
#define CHECK(cond, Message, ...) \
|
||||
if (!(cond)) \
|
||||
{ \
|
||||
PanicAlert("%s failed in %s at line %d: " Message, __func__, __FILE__, __LINE__, __VA_ARGS__); \
|
||||
}
|
||||
|
||||
class DXTexture;
|
||||
class DXFramebuffer;
|
||||
namespace DX11
|
||||
{
|
||||
using Microsoft::WRL::ComPtr;
|
||||
class SwapChain;
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
HRESULT LoadDXGI();
|
||||
HRESULT LoadD3D();
|
||||
HRESULT LoadD3DCompiler();
|
||||
void UnloadDXGI();
|
||||
void UnloadD3D();
|
||||
void UnloadD3DCompiler();
|
||||
extern ComPtr<IDXGIFactory2> dxgi_factory;
|
||||
extern ComPtr<ID3D11Device> device;
|
||||
extern ComPtr<ID3D11Device1> device1;
|
||||
extern ComPtr<ID3D11DeviceContext> context;
|
||||
extern D3D_FEATURE_LEVEL feature_level;
|
||||
|
||||
D3D_FEATURE_LEVEL GetFeatureLevel(IDXGIAdapter* adapter);
|
||||
std::vector<DXGI_SAMPLE_DESC> EnumAAModes(IDXGIAdapter* adapter);
|
||||
bool Create(u32 adapter_index, bool enable_debug_layer);
|
||||
void Destroy();
|
||||
|
||||
HRESULT Create(HWND wnd);
|
||||
void Close();
|
||||
|
||||
extern ID3D11Device* device;
|
||||
extern ID3D11Device1* device1;
|
||||
extern ID3D11DeviceContext* context;
|
||||
extern IDXGISwapChain1* swapchain;
|
||||
|
||||
void Reset(HWND new_wnd);
|
||||
void ResizeSwapChain();
|
||||
void Present();
|
||||
|
||||
DXTexture* GetSwapChainTexture();
|
||||
DXFramebuffer* GetSwapChainFramebuffer();
|
||||
const char* PixelShaderVersionString();
|
||||
const char* GeometryShaderVersionString();
|
||||
const char* VertexShaderVersionString();
|
||||
const char* ComputeShaderVersionString();
|
||||
bool BGRATexturesSupported();
|
||||
bool AllowTearingSupported();
|
||||
|
||||
u32 GetMaxTextureSize(D3D_FEATURE_LEVEL feature_level);
|
||||
|
||||
HRESULT SetFullscreenState(bool enable_fullscreen);
|
||||
bool GetFullscreenState();
|
||||
|
||||
// This function will assign a name to the given resource.
|
||||
// The DirectX debug layer will make it easier to identify resources that way,
|
||||
// e.g. when listing up all resources who have unreleased references.
|
||||
void SetDebugObjectName(ID3D11DeviceChild* resource, const char* name);
|
||||
std::string GetDebugObjectName(ID3D11DeviceChild* resource);
|
||||
// Returns a list of supported AA modes for the current device.
|
||||
std::vector<u32> GetAAModes(u32 adapter_index);
|
||||
|
||||
} // namespace D3D
|
||||
|
||||
typedef HRESULT(WINAPI* CREATEDXGIFACTORY)(REFIID, void**);
|
||||
extern CREATEDXGIFACTORY PCreateDXGIFactory;
|
||||
typedef HRESULT(WINAPI* D3D11CREATEDEVICE)(IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT,
|
||||
CONST D3D_FEATURE_LEVEL*, UINT, UINT, ID3D11Device**,
|
||||
D3D_FEATURE_LEVEL*, ID3D11DeviceContext**);
|
||||
|
||||
extern pD3DCompile PD3DCompile;
|
||||
|
||||
} // namespace DX11
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/DXTexture.h"
|
||||
#include "VideoBackends/D3DCommon/Common.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
namespace D3D
|
||||
{
|
||||
StateManager* stateman;
|
||||
std::unique_ptr<StateManager> stateman;
|
||||
|
||||
StateManager::StateManager() = default;
|
||||
StateManager::~StateManager() = default;
|
||||
@@ -298,27 +299,14 @@ void StateManager::SyncComputeBindings()
|
||||
}
|
||||
} // namespace D3D
|
||||
|
||||
StateCache::~StateCache()
|
||||
{
|
||||
for (auto& it : m_depth)
|
||||
SAFE_RELEASE(it.second);
|
||||
|
||||
for (auto& it : m_raster)
|
||||
SAFE_RELEASE(it.second);
|
||||
|
||||
for (auto& it : m_blend)
|
||||
SAFE_RELEASE(it.second);
|
||||
|
||||
for (auto& it : m_sampler)
|
||||
SAFE_RELEASE(it.second);
|
||||
}
|
||||
StateCache::~StateCache() = default;
|
||||
|
||||
ID3D11SamplerState* StateCache::Get(SamplerState state)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(m_lock);
|
||||
auto it = m_sampler.find(state.hex);
|
||||
if (it != m_sampler.end())
|
||||
return it->second;
|
||||
return it->second.Get();
|
||||
|
||||
D3D11_SAMPLER_DESC sampdc = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT());
|
||||
if (state.mipmap_filter == SamplerState::Filter::Linear)
|
||||
@@ -358,14 +346,11 @@ ID3D11SamplerState* StateCache::Get(SamplerState state)
|
||||
sampdc.MaxAnisotropy = 1u << g_ActiveConfig.iMaxAnisotropy;
|
||||
}
|
||||
|
||||
ID3D11SamplerState* res = nullptr;
|
||||
ComPtr<ID3D11SamplerState> res;
|
||||
HRESULT hr = D3D::device->CreateSamplerState(&sampdc, &res);
|
||||
if (FAILED(hr))
|
||||
PanicAlert("Fail %s %d\n", __FILE__, __LINE__);
|
||||
|
||||
D3D::SetDebugObjectName(res, "sampler state used to emulate the GX pipeline");
|
||||
CHECK(SUCCEEDED(hr), "Creating D3D sampler state failed");
|
||||
m_sampler.emplace(state.hex, res);
|
||||
return res;
|
||||
return res.Get();
|
||||
}
|
||||
|
||||
ID3D11BlendState* StateCache::Get(BlendingState state)
|
||||
@@ -373,7 +358,7 @@ ID3D11BlendState* StateCache::Get(BlendingState state)
|
||||
std::lock_guard<std::mutex> guard(m_lock);
|
||||
auto it = m_blend.find(state.hex);
|
||||
if (it != m_blend.end())
|
||||
return it->second;
|
||||
return it->second.Get();
|
||||
|
||||
if (state.logicopenable && D3D::device1)
|
||||
{
|
||||
@@ -400,7 +385,6 @@ ID3D11BlendState* StateCache::Get(BlendingState state)
|
||||
HRESULT hr = D3D::device1->CreateBlendState1(&desc, &res);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
D3D::SetDebugObjectName(res, "blend state used to emulate the GX pipeline");
|
||||
m_blend.emplace(state.hex, res);
|
||||
return res;
|
||||
}
|
||||
@@ -440,15 +424,11 @@ ID3D11BlendState* StateCache::Get(BlendingState state)
|
||||
tdesc.BlendOp = state.subtract ? D3D11_BLEND_OP_REV_SUBTRACT : D3D11_BLEND_OP_ADD;
|
||||
tdesc.BlendOpAlpha = state.subtractAlpha ? D3D11_BLEND_OP_REV_SUBTRACT : D3D11_BLEND_OP_ADD;
|
||||
|
||||
ID3D11BlendState* res = nullptr;
|
||||
|
||||
ComPtr<ID3D11BlendState> res;
|
||||
HRESULT hr = D3D::device->CreateBlendState(&desc, &res);
|
||||
if (FAILED(hr))
|
||||
PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
|
||||
|
||||
D3D::SetDebugObjectName(res, "blend state used to emulate the GX pipeline");
|
||||
CHECK(SUCCEEDED(hr), "Creating D3D blend state failed");
|
||||
m_blend.emplace(state.hex, res);
|
||||
return res;
|
||||
return res.Get();
|
||||
}
|
||||
|
||||
ID3D11RasterizerState* StateCache::Get(RasterizationState state)
|
||||
@@ -456,7 +436,7 @@ ID3D11RasterizerState* StateCache::Get(RasterizationState state)
|
||||
std::lock_guard<std::mutex> guard(m_lock);
|
||||
auto it = m_raster.find(state.hex);
|
||||
if (it != m_raster.end())
|
||||
return it->second;
|
||||
return it->second.Get();
|
||||
|
||||
static constexpr std::array<D3D11_CULL_MODE, 4> cull_modes = {
|
||||
{D3D11_CULL_NONE, D3D11_CULL_BACK, D3D11_CULL_FRONT, D3D11_CULL_BACK}};
|
||||
@@ -466,14 +446,11 @@ ID3D11RasterizerState* StateCache::Get(RasterizationState state)
|
||||
desc.CullMode = cull_modes[state.cullmode];
|
||||
desc.ScissorEnable = TRUE;
|
||||
|
||||
ID3D11RasterizerState* res = nullptr;
|
||||
ComPtr<ID3D11RasterizerState> res;
|
||||
HRESULT hr = D3D::device->CreateRasterizerState(&desc, &res);
|
||||
if (FAILED(hr))
|
||||
PanicAlert("Failed to create rasterizer state at %s %d\n", __FILE__, __LINE__);
|
||||
|
||||
D3D::SetDebugObjectName(res, "rasterizer state used to emulate the GX pipeline");
|
||||
CHECK(SUCCEEDED(hr), "Creating D3D rasterizer state failed");
|
||||
m_raster.emplace(state.hex, res);
|
||||
return res;
|
||||
return res.Get();
|
||||
}
|
||||
|
||||
ID3D11DepthStencilState* StateCache::Get(DepthState state)
|
||||
@@ -481,7 +458,7 @@ ID3D11DepthStencilState* StateCache::Get(DepthState state)
|
||||
std::lock_guard<std::mutex> guard(m_lock);
|
||||
auto it = m_depth.find(state.hex);
|
||||
if (it != m_depth.end())
|
||||
return it->second;
|
||||
return it->second.Get();
|
||||
|
||||
D3D11_DEPTH_STENCIL_DESC depthdc = CD3D11_DEPTH_STENCIL_DESC(CD3D11_DEFAULT());
|
||||
|
||||
@@ -512,17 +489,11 @@ ID3D11DepthStencilState* StateCache::Get(DepthState state)
|
||||
depthdc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
}
|
||||
|
||||
ID3D11DepthStencilState* res = nullptr;
|
||||
|
||||
ComPtr<ID3D11DepthStencilState> res;
|
||||
HRESULT hr = D3D::device->CreateDepthStencilState(&depthdc, &res);
|
||||
if (SUCCEEDED(hr))
|
||||
D3D::SetDebugObjectName(res, "depth-stencil state used to emulate the GX pipeline");
|
||||
else
|
||||
PanicAlert("Failed to create depth state at %s %d\n", __FILE__, __LINE__);
|
||||
|
||||
CHECK(SUCCEEDED(hr), "Creating D3D depth stencil state failed");
|
||||
m_depth.emplace(state.hex, res);
|
||||
|
||||
return res;
|
||||
return res.Get();
|
||||
}
|
||||
|
||||
D3D11_PRIMITIVE_TOPOLOGY StateCache::GetPrimitiveTopology(PrimitiveType primitive)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -34,10 +35,10 @@ public:
|
||||
static D3D11_PRIMITIVE_TOPOLOGY GetPrimitiveTopology(PrimitiveType primitive);
|
||||
|
||||
private:
|
||||
std::unordered_map<u32, ID3D11DepthStencilState*> m_depth;
|
||||
std::unordered_map<u32, ID3D11RasterizerState*> m_raster;
|
||||
std::unordered_map<u32, ID3D11BlendState*> m_blend;
|
||||
std::unordered_map<SamplerState::StorageType, ID3D11SamplerState*> m_sampler;
|
||||
std::unordered_map<u32, ComPtr<ID3D11DepthStencilState>> m_depth;
|
||||
std::unordered_map<u32, ComPtr<ID3D11RasterizerState>> m_raster;
|
||||
std::unordered_map<u32, ComPtr<ID3D11BlendState>> m_blend;
|
||||
std::unordered_map<SamplerState::StorageType, ComPtr<ID3D11SamplerState>> m_sampler;
|
||||
std::mutex m_lock;
|
||||
};
|
||||
|
||||
@@ -296,7 +297,7 @@ private:
|
||||
ID3D11ComputeShader* m_compute_shader = nullptr;
|
||||
};
|
||||
|
||||
extern StateManager* stateman;
|
||||
extern std::unique_ptr<StateManager> stateman;
|
||||
|
||||
} // namespace D3D
|
||||
|
||||
|
||||
@@ -28,39 +28,9 @@ DXPipeline::DXPipeline(ID3D11InputLayout* input_layout, ID3D11VertexShader* vert
|
||||
m_rasterizer_state(rasterizer_state), m_depth_state(depth_state), m_blend_state(blend_state),
|
||||
m_primitive_topology(primitive_topology), m_use_logic_op(use_logic_op)
|
||||
{
|
||||
if (m_input_layout)
|
||||
m_input_layout->AddRef();
|
||||
if (m_vertex_shader)
|
||||
m_vertex_shader->AddRef();
|
||||
if (m_geometry_shader)
|
||||
m_geometry_shader->AddRef();
|
||||
if (m_pixel_shader)
|
||||
m_pixel_shader->AddRef();
|
||||
if (m_rasterizer_state)
|
||||
m_rasterizer_state->AddRef();
|
||||
if (m_depth_state)
|
||||
m_depth_state->AddRef();
|
||||
if (m_blend_state)
|
||||
m_blend_state->AddRef();
|
||||
}
|
||||
|
||||
DXPipeline::~DXPipeline()
|
||||
{
|
||||
if (m_input_layout)
|
||||
m_input_layout->Release();
|
||||
if (m_vertex_shader)
|
||||
m_vertex_shader->Release();
|
||||
if (m_geometry_shader)
|
||||
m_geometry_shader->Release();
|
||||
if (m_pixel_shader)
|
||||
m_pixel_shader->Release();
|
||||
if (m_rasterizer_state)
|
||||
m_rasterizer_state->Release();
|
||||
if (m_depth_state)
|
||||
m_depth_state->Release();
|
||||
if (m_blend_state)
|
||||
m_blend_state->Release();
|
||||
}
|
||||
DXPipeline::~DXPipeline() = default;
|
||||
|
||||
std::unique_ptr<DXPipeline> DXPipeline::Create(const AbstractPipelineConfig& config)
|
||||
{
|
||||
@@ -71,12 +41,7 @@ std::unique_ptr<DXPipeline> DXPipeline::Create(const AbstractPipelineConfig& con
|
||||
D3D11_PRIMITIVE_TOPOLOGY primitive_topology =
|
||||
StateCache::GetPrimitiveTopology(config.rasterization_state.primitive);
|
||||
if (!rasterizer_state || !depth_state || !blend_state)
|
||||
{
|
||||
SAFE_RELEASE(rasterizer_state);
|
||||
SAFE_RELEASE(depth_state);
|
||||
SAFE_RELEASE(blend_state);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const DXShader* vertex_shader = static_cast<const DXShader*>(config.vertex_shader);
|
||||
const DXShader* geometry_shader = static_cast<const DXShader*>(config.geometry_shader);
|
||||
|
||||
@@ -20,13 +20,13 @@ public:
|
||||
bool use_logic_op);
|
||||
~DXPipeline() override;
|
||||
|
||||
ID3D11InputLayout* GetInputLayout() const { return m_input_layout; }
|
||||
ID3D11VertexShader* GetVertexShader() const { return m_vertex_shader; }
|
||||
ID3D11GeometryShader* GetGeometryShader() const { return m_geometry_shader; }
|
||||
ID3D11PixelShader* GetPixelShader() const { return m_pixel_shader; }
|
||||
ID3D11RasterizerState* GetRasterizerState() const { return m_rasterizer_state; }
|
||||
ID3D11DepthStencilState* GetDepthState() const { return m_depth_state; }
|
||||
ID3D11BlendState* GetBlendState() const { return m_blend_state; }
|
||||
ID3D11InputLayout* GetInputLayout() const { return m_input_layout.Get(); }
|
||||
ID3D11VertexShader* GetVertexShader() const { return m_vertex_shader.Get(); }
|
||||
ID3D11GeometryShader* GetGeometryShader() const { return m_geometry_shader.Get(); }
|
||||
ID3D11PixelShader* GetPixelShader() const { return m_pixel_shader.Get(); }
|
||||
ID3D11RasterizerState* GetRasterizerState() const { return m_rasterizer_state.Get(); }
|
||||
ID3D11DepthStencilState* GetDepthState() const { return m_depth_state.Get(); }
|
||||
ID3D11BlendState* GetBlendState() const { return m_blend_state.Get(); }
|
||||
D3D11_PRIMITIVE_TOPOLOGY GetPrimitiveTopology() const { return m_primitive_topology; }
|
||||
bool HasGeometryShader() const { return m_geometry_shader != nullptr; }
|
||||
bool UseLogicOp() const { return m_use_logic_op; }
|
||||
@@ -34,13 +34,13 @@ public:
|
||||
static std::unique_ptr<DXPipeline> Create(const AbstractPipelineConfig& config);
|
||||
|
||||
private:
|
||||
ID3D11InputLayout* m_input_layout;
|
||||
ID3D11VertexShader* m_vertex_shader;
|
||||
ID3D11GeometryShader* m_geometry_shader;
|
||||
ID3D11PixelShader* m_pixel_shader;
|
||||
ID3D11RasterizerState* m_rasterizer_state;
|
||||
ID3D11DepthStencilState* m_depth_state;
|
||||
ID3D11BlendState* m_blend_state;
|
||||
ComPtr<ID3D11InputLayout> m_input_layout;
|
||||
ComPtr<ID3D11VertexShader> m_vertex_shader;
|
||||
ComPtr<ID3D11GeometryShader> m_geometry_shader;
|
||||
ComPtr<ID3D11PixelShader> m_pixel_shader;
|
||||
ComPtr<ID3D11RasterizerState> m_rasterizer_state;
|
||||
ComPtr<ID3D11DepthStencilState> m_depth_state;
|
||||
ComPtr<ID3D11BlendState> m_blend_state;
|
||||
D3D11_PRIMITIVE_TOPOLOGY m_primitive_topology;
|
||||
bool m_use_logic_op;
|
||||
};
|
||||
|
||||
@@ -2,62 +2,41 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3D/DXShader.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
#include "Common/Assert.h"
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
DXShader::DXShader(ShaderStage stage, BinaryData bytecode, ID3D11DeviceChild* shader)
|
||||
: AbstractShader(stage), m_bytecode(bytecode), m_shader(shader)
|
||||
: D3DCommon::Shader(stage, std::move(bytecode)), m_shader(shader)
|
||||
{
|
||||
}
|
||||
|
||||
DXShader::~DXShader()
|
||||
{
|
||||
m_shader->Release();
|
||||
}
|
||||
DXShader::~DXShader() = default;
|
||||
|
||||
ID3D11VertexShader* DXShader::GetD3DVertexShader() const
|
||||
{
|
||||
DEBUG_ASSERT(m_stage == ShaderStage::Vertex);
|
||||
return static_cast<ID3D11VertexShader*>(m_shader);
|
||||
return static_cast<ID3D11VertexShader*>(m_shader.Get());
|
||||
}
|
||||
|
||||
ID3D11GeometryShader* DXShader::GetD3DGeometryShader() const
|
||||
{
|
||||
DEBUG_ASSERT(m_stage == ShaderStage::Geometry);
|
||||
return static_cast<ID3D11GeometryShader*>(m_shader);
|
||||
return static_cast<ID3D11GeometryShader*>(m_shader.Get());
|
||||
}
|
||||
|
||||
ID3D11PixelShader* DXShader::GetD3DPixelShader() const
|
||||
{
|
||||
DEBUG_ASSERT(m_stage == ShaderStage::Pixel);
|
||||
return static_cast<ID3D11PixelShader*>(m_shader);
|
||||
return static_cast<ID3D11PixelShader*>(m_shader.Get());
|
||||
}
|
||||
|
||||
ID3D11ComputeShader* DXShader::GetD3DComputeShader() const
|
||||
{
|
||||
DEBUG_ASSERT(m_stage == ShaderStage::Compute);
|
||||
return static_cast<ID3D11ComputeShader*>(m_shader);
|
||||
}
|
||||
|
||||
bool DXShader::HasBinary() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
AbstractShader::BinaryData DXShader::GetBinary() const
|
||||
{
|
||||
return m_bytecode;
|
||||
return static_cast<ID3D11ComputeShader*>(m_shader.Get());
|
||||
}
|
||||
|
||||
std::unique_ptr<DXShader> DXShader::CreateFromBytecode(ShaderStage stage, BinaryData bytecode)
|
||||
@@ -66,48 +45,48 @@ std::unique_ptr<DXShader> DXShader::CreateFromBytecode(ShaderStage stage, Binary
|
||||
{
|
||||
case ShaderStage::Vertex:
|
||||
{
|
||||
ID3D11VertexShader* vs;
|
||||
ComPtr<ID3D11VertexShader> vs;
|
||||
HRESULT hr = D3D::device->CreateVertexShader(bytecode.data(), bytecode.size(), nullptr, &vs);
|
||||
CHECK(SUCCEEDED(hr), "Create vertex shader");
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
|
||||
return std::make_unique<DXShader>(ShaderStage::Vertex, std::move(bytecode), vs);
|
||||
return std::make_unique<DXShader>(ShaderStage::Vertex, std::move(bytecode), vs.Get());
|
||||
}
|
||||
|
||||
case ShaderStage::Geometry:
|
||||
{
|
||||
ID3D11GeometryShader* gs;
|
||||
ComPtr<ID3D11GeometryShader> gs;
|
||||
HRESULT hr = D3D::device->CreateGeometryShader(bytecode.data(), bytecode.size(), nullptr, &gs);
|
||||
CHECK(SUCCEEDED(hr), "Create geometry shader");
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
|
||||
return std::make_unique<DXShader>(ShaderStage::Geometry, std::move(bytecode), gs);
|
||||
return std::make_unique<DXShader>(ShaderStage::Geometry, std::move(bytecode), gs.Get());
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderStage::Pixel:
|
||||
{
|
||||
ID3D11PixelShader* ps;
|
||||
ComPtr<ID3D11PixelShader> ps;
|
||||
HRESULT hr = D3D::device->CreatePixelShader(bytecode.data(), bytecode.size(), nullptr, &ps);
|
||||
CHECK(SUCCEEDED(hr), "Create pixel shader");
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
|
||||
return std::make_unique<DXShader>(ShaderStage::Pixel, std::move(bytecode), ps);
|
||||
return std::make_unique<DXShader>(ShaderStage::Pixel, std::move(bytecode), ps.Get());
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderStage::Compute:
|
||||
{
|
||||
ID3D11ComputeShader* cs;
|
||||
ComPtr<ID3D11ComputeShader> cs;
|
||||
HRESULT hr = D3D::device->CreateComputeShader(bytecode.data(), bytecode.size(), nullptr, &cs);
|
||||
CHECK(SUCCEEDED(hr), "Create compute shader");
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
|
||||
return std::make_unique<DXShader>(ShaderStage::Compute, std::move(bytecode), cs);
|
||||
return std::make_unique<DXShader>(ShaderStage::Compute, std::move(bytecode), cs.Get());
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -117,86 +96,4 @@ std::unique_ptr<DXShader> DXShader::CreateFromBytecode(ShaderStage stage, Binary
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const char* GetCompileTarget(ShaderStage stage)
|
||||
{
|
||||
switch (stage)
|
||||
{
|
||||
case ShaderStage::Vertex:
|
||||
return D3D::VertexShaderVersionString();
|
||||
case ShaderStage::Geometry:
|
||||
return D3D::GeometryShaderVersionString();
|
||||
case ShaderStage::Pixel:
|
||||
return D3D::PixelShaderVersionString();
|
||||
case ShaderStage::Compute:
|
||||
return D3D::ComputeShaderVersionString();
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
bool DXShader::CompileShader(BinaryData* out_bytecode, ShaderStage stage, const char* source,
|
||||
size_t length)
|
||||
{
|
||||
static constexpr D3D_SHADER_MACRO macros[] = {{"API_D3D", "1"}, {nullptr, nullptr}};
|
||||
const UINT flags = g_ActiveConfig.bEnableValidationLayer ?
|
||||
(D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION) :
|
||||
(D3DCOMPILE_OPTIMIZATION_LEVEL3 | D3DCOMPILE_SKIP_VALIDATION);
|
||||
const char* target = GetCompileTarget(stage);
|
||||
|
||||
ID3DBlob* code = nullptr;
|
||||
ID3DBlob* errors = nullptr;
|
||||
HRESULT hr = PD3DCompile(source, length, nullptr, macros, nullptr, "main", target, flags, 0,
|
||||
&code, &errors);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
static int num_failures = 0;
|
||||
std::string filename = StringFromFormat(
|
||||
"%sbad_%s_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), target, num_failures++);
|
||||
std::ofstream file;
|
||||
File::OpenFStream(file, filename, std::ios_base::out);
|
||||
file.write(source, length);
|
||||
file << "\n";
|
||||
file.write(static_cast<const char*>(errors->GetBufferPointer()), errors->GetBufferSize());
|
||||
file.close();
|
||||
|
||||
PanicAlert("Failed to compile %s:\nDebug info (%s):\n%s", filename.c_str(), target,
|
||||
static_cast<const char*>(errors->GetBufferPointer()));
|
||||
errors->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errors && errors->GetBufferSize() > 0)
|
||||
{
|
||||
WARN_LOG(VIDEO, "%s compilation succeeded with warnings:\n%s", target,
|
||||
static_cast<const char*>(errors->GetBufferPointer()));
|
||||
}
|
||||
SAFE_RELEASE(errors);
|
||||
|
||||
out_bytecode->resize(code->GetBufferSize());
|
||||
std::memcpy(out_bytecode->data(), code->GetBufferPointer(), code->GetBufferSize());
|
||||
code->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<DXShader> DXShader::CreateFromSource(ShaderStage stage, const char* source,
|
||||
size_t length)
|
||||
{
|
||||
BinaryData bytecode;
|
||||
if (!CompileShader(&bytecode, stage, source, length))
|
||||
return nullptr;
|
||||
|
||||
return CreateFromBytecode(stage, std::move(bytecode));
|
||||
}
|
||||
|
||||
std::unique_ptr<DXShader> DXShader::CreateFromBinary(ShaderStage stage, const void* data,
|
||||
size_t length)
|
||||
{
|
||||
if (length == 0)
|
||||
return nullptr;
|
||||
|
||||
BinaryData bytecode(length);
|
||||
std::memcpy(bytecode.data(), data, length);
|
||||
return CreateFromBytecode(stage, std::move(bytecode));
|
||||
}
|
||||
} // namespace DX11
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
#include <d3d11.h>
|
||||
#include <memory>
|
||||
|
||||
#include "VideoCommon/AbstractShader.h"
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoBackends/D3DCommon/Shader.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
class DXShader final : public AbstractShader
|
||||
class DXShader final : public D3DCommon::Shader
|
||||
{
|
||||
public:
|
||||
DXShader(ShaderStage stage, BinaryData bytecode, ID3D11DeviceChild* shader);
|
||||
@@ -23,22 +23,10 @@ public:
|
||||
ID3D11PixelShader* GetD3DPixelShader() const;
|
||||
ID3D11ComputeShader* GetD3DComputeShader() const;
|
||||
|
||||
bool HasBinary() const override;
|
||||
BinaryData GetBinary() const override;
|
||||
|
||||
// Creates a new shader object.
|
||||
static std::unique_ptr<DXShader> CreateFromBytecode(ShaderStage stage, BinaryData bytecode);
|
||||
static bool CompileShader(BinaryData* out_bytecode, ShaderStage stage, const char* source,
|
||||
size_t length);
|
||||
|
||||
static std::unique_ptr<DXShader> CreateFromBinary(ShaderStage stage, const void* data,
|
||||
size_t length);
|
||||
static std::unique_ptr<DXShader> CreateFromSource(ShaderStage stage, const char* source,
|
||||
size_t length);
|
||||
|
||||
private:
|
||||
ID3D11DeviceChild* m_shader;
|
||||
BinaryData m_bytecode;
|
||||
ComPtr<ID3D11DeviceChild> m_shader;
|
||||
};
|
||||
|
||||
} // namespace DX11
|
||||
|
||||
@@ -11,141 +11,27 @@
|
||||
|
||||
#include "VideoBackends/D3D/D3DState.h"
|
||||
#include "VideoBackends/D3D/DXTexture.h"
|
||||
#include "VideoBackends/D3DCommon/Common.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
namespace
|
||||
{
|
||||
DXGI_FORMAT GetDXGIFormatForHostFormat(AbstractTextureFormat format, bool typeless)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case AbstractTextureFormat::DXT1:
|
||||
return DXGI_FORMAT_BC1_UNORM;
|
||||
case AbstractTextureFormat::DXT3:
|
||||
return DXGI_FORMAT_BC2_UNORM;
|
||||
case AbstractTextureFormat::DXT5:
|
||||
return DXGI_FORMAT_BC3_UNORM;
|
||||
case AbstractTextureFormat::BPTC:
|
||||
return DXGI_FORMAT_BC7_UNORM;
|
||||
case AbstractTextureFormat::RGBA8:
|
||||
return typeless ? DXGI_FORMAT_R8G8B8A8_TYPELESS : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case AbstractTextureFormat::BGRA8:
|
||||
return typeless ? DXGI_FORMAT_B8G8R8A8_TYPELESS : DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
case AbstractTextureFormat::R16:
|
||||
return typeless ? DXGI_FORMAT_R16_TYPELESS : DXGI_FORMAT_R16_UNORM;
|
||||
case AbstractTextureFormat::R32F:
|
||||
return typeless ? DXGI_FORMAT_R32_TYPELESS : DXGI_FORMAT_R32_FLOAT;
|
||||
case AbstractTextureFormat::D16:
|
||||
return DXGI_FORMAT_R16_TYPELESS;
|
||||
case AbstractTextureFormat::D24_S8:
|
||||
return DXGI_FORMAT_R24G8_TYPELESS;
|
||||
case AbstractTextureFormat::D32F:
|
||||
return DXGI_FORMAT_R32_TYPELESS;
|
||||
case AbstractTextureFormat::D32F_S8:
|
||||
return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
||||
default:
|
||||
PanicAlert("Unhandled texture format.");
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
DXGI_FORMAT GetSRVFormatForHostFormat(AbstractTextureFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case AbstractTextureFormat::DXT1:
|
||||
return DXGI_FORMAT_BC1_UNORM;
|
||||
case AbstractTextureFormat::DXT3:
|
||||
return DXGI_FORMAT_BC2_UNORM;
|
||||
case AbstractTextureFormat::DXT5:
|
||||
return DXGI_FORMAT_BC3_UNORM;
|
||||
case AbstractTextureFormat::BPTC:
|
||||
return DXGI_FORMAT_BC7_UNORM;
|
||||
case AbstractTextureFormat::RGBA8:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case AbstractTextureFormat::BGRA8:
|
||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
case AbstractTextureFormat::R16:
|
||||
return DXGI_FORMAT_R16_UNORM;
|
||||
case AbstractTextureFormat::R32F:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case AbstractTextureFormat::D16:
|
||||
return DXGI_FORMAT_R16_UNORM;
|
||||
case AbstractTextureFormat::D24_S8:
|
||||
return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
||||
case AbstractTextureFormat::D32F:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case AbstractTextureFormat::D32F_S8:
|
||||
return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
|
||||
default:
|
||||
PanicAlert("Unhandled SRV format");
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
DXGI_FORMAT GetRTVFormatForHostFormat(AbstractTextureFormat format, bool integer)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case AbstractTextureFormat::RGBA8:
|
||||
return integer ? DXGI_FORMAT_R8G8B8A8_UINT : DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case AbstractTextureFormat::BGRA8:
|
||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
case AbstractTextureFormat::R16:
|
||||
return integer ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R16_UNORM;
|
||||
case AbstractTextureFormat::R32F:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
default:
|
||||
PanicAlert("Unhandled RTV format");
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
DXGI_FORMAT GetDSVFormatForHostFormat(AbstractTextureFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case AbstractTextureFormat::D16:
|
||||
return DXGI_FORMAT_D16_UNORM;
|
||||
case AbstractTextureFormat::D24_S8:
|
||||
return DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
case AbstractTextureFormat::D32F:
|
||||
return DXGI_FORMAT_D32_FLOAT;
|
||||
case AbstractTextureFormat::D32F_S8:
|
||||
return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
|
||||
default:
|
||||
PanicAlert("Unhandled DSV format");
|
||||
return DXGI_FORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
DXTexture::DXTexture(const TextureConfig& tex_config, ID3D11Texture2D* d3d_texture,
|
||||
ID3D11ShaderResourceView* d3d_srv, ID3D11UnorderedAccessView* d3d_uav)
|
||||
: AbstractTexture(tex_config), m_d3d_texture(d3d_texture), m_d3d_srv(d3d_srv),
|
||||
m_d3d_uav(d3d_uav)
|
||||
DXTexture::DXTexture(const TextureConfig& config, ID3D11Texture2D* texture)
|
||||
: AbstractTexture(config), m_texture(texture)
|
||||
{
|
||||
}
|
||||
|
||||
DXTexture::~DXTexture()
|
||||
{
|
||||
if (m_d3d_uav)
|
||||
m_d3d_uav->Release();
|
||||
|
||||
if (m_d3d_srv)
|
||||
{
|
||||
if (D3D::stateman->UnsetTexture(m_d3d_srv) != 0)
|
||||
D3D::stateman->ApplyTextures();
|
||||
|
||||
m_d3d_srv->Release();
|
||||
}
|
||||
m_d3d_texture->Release();
|
||||
if (m_srv && D3D::stateman->UnsetTexture(m_srv.Get()) != 0)
|
||||
D3D::stateman->ApplyTextures();
|
||||
}
|
||||
|
||||
std::unique_ptr<DXTexture> DXTexture::Create(const TextureConfig& config)
|
||||
{
|
||||
// Use typeless to create the texture when it's a render target, so we can alias it with an
|
||||
// integer format (for EFB).
|
||||
const DXGI_FORMAT tex_format = GetDXGIFormatForHostFormat(config.format, config.IsRenderTarget());
|
||||
const DXGI_FORMAT srv_format = GetSRVFormatForHostFormat(config.format);
|
||||
const DXGI_FORMAT tex_format =
|
||||
D3DCommon::GetDXGIFormatForAbstractFormat(config.format, config.IsRenderTarget());
|
||||
UINT bindflags = D3D11_BIND_SHADER_RESOURCE;
|
||||
if (config.IsRenderTarget())
|
||||
bindflags |= IsDepthFormat(config.format) ? D3D11_BIND_DEPTH_STENCIL : D3D11_BIND_RENDER_TARGET;
|
||||
@@ -154,7 +40,7 @@ std::unique_ptr<DXTexture> DXTexture::Create(const TextureConfig& config)
|
||||
|
||||
CD3D11_TEXTURE2D_DESC desc(tex_format, config.width, config.height, config.layers, config.levels,
|
||||
bindflags, D3D11_USAGE_DEFAULT, 0, config.samples, 0, 0);
|
||||
ID3D11Texture2D* d3d_texture;
|
||||
ComPtr<ID3D11Texture2D> d3d_texture;
|
||||
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, &d3d_texture);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
@@ -163,36 +49,69 @@ std::unique_ptr<DXTexture> DXTexture::Create(const TextureConfig& config)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ID3D11ShaderResourceView* d3d_srv;
|
||||
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(d3d_texture,
|
||||
config.IsMultisampled() ?
|
||||
D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY :
|
||||
D3D11_SRV_DIMENSION_TEXTURE2DARRAY,
|
||||
srv_format, 0, config.levels, 0, config.layers);
|
||||
hr = D3D::device->CreateShaderResourceView(d3d_texture, &srv_desc, &d3d_srv);
|
||||
std::unique_ptr<DXTexture> tex(new DXTexture(config, d3d_texture.Get()));
|
||||
if (!tex->CreateSRV() || (config.IsComputeImage() && !tex->CreateUAV()))
|
||||
return nullptr;
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
std::unique_ptr<DXTexture> DXTexture::CreateAdopted(ID3D11Texture2D* texture)
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
texture->GetDesc(&desc);
|
||||
|
||||
// Convert to our texture config format.
|
||||
TextureConfig config(desc.Width, desc.Height, desc.MipLevels, desc.ArraySize,
|
||||
desc.SampleDesc.Count,
|
||||
D3DCommon::GetAbstractFormatForDXGIFormat(desc.Format), 0);
|
||||
if (desc.BindFlags & D3D11_BIND_RENDER_TARGET)
|
||||
config.flags |= AbstractTextureFlag_RenderTarget;
|
||||
if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS)
|
||||
config.flags |= AbstractTextureFlag_ComputeImage;
|
||||
|
||||
std::unique_ptr<DXTexture> tex(new DXTexture(config, texture));
|
||||
if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE && !tex->CreateSRV())
|
||||
return nullptr;
|
||||
if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS && !tex->CreateUAV())
|
||||
return nullptr;
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
bool DXTexture::CreateSRV()
|
||||
{
|
||||
const CD3D11_SHADER_RESOURCE_VIEW_DESC desc(
|
||||
m_texture.Get(),
|
||||
m_config.IsMultisampled() ? D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY :
|
||||
D3D11_SRV_DIMENSION_TEXTURE2DARRAY,
|
||||
D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), 0, m_config.levels, 0,
|
||||
m_config.layers);
|
||||
HRESULT hr = D3D::device->CreateShaderResourceView(m_texture.Get(), &desc, &m_srv);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("Failed to create %ux%ux%u D3D SRV", config.width, config.height, config.layers);
|
||||
d3d_texture->Release();
|
||||
return nullptr;
|
||||
PanicAlert("Failed to create %ux%ux%u D3D SRV", m_config.width, m_config.height,
|
||||
m_config.layers);
|
||||
return false;
|
||||
}
|
||||
|
||||
ID3D11UnorderedAccessView* d3d_uav = nullptr;
|
||||
if (config.IsComputeImage())
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DXTexture::CreateUAV()
|
||||
{
|
||||
const CD3D11_UNORDERED_ACCESS_VIEW_DESC desc(
|
||||
m_texture.Get(), D3D11_UAV_DIMENSION_TEXTURE2DARRAY,
|
||||
D3DCommon::GetSRVFormatForAbstractFormat(m_config.format), 0, 0, m_config.layers);
|
||||
HRESULT hr = D3D::device->CreateUnorderedAccessView(m_texture.Get(), &desc, &m_uav);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
const CD3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc(
|
||||
d3d_texture, D3D11_UAV_DIMENSION_TEXTURE2DARRAY, srv_format, 0, 0, config.layers);
|
||||
hr = D3D::device->CreateUnorderedAccessView(d3d_texture, &uav_desc, &d3d_uav);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PanicAlert("Failed to create %ux%ux%u D3D UAV", config.width, config.height, config.layers);
|
||||
d3d_uav->Release();
|
||||
d3d_texture->Release();
|
||||
return nullptr;
|
||||
}
|
||||
PanicAlert("Failed to create %ux%ux%u D3D UAV", m_config.width, m_config.height,
|
||||
m_config.layers);
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::make_unique<DXTexture>(config, d3d_texture, d3d_srv, d3d_uav);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DXTexture::CopyRectangleFromTexture(const AbstractTexture* src,
|
||||
@@ -213,8 +132,8 @@ void DXTexture::CopyRectangleFromTexture(const AbstractTexture* src,
|
||||
src_box.back = 1;
|
||||
|
||||
D3D::context->CopySubresourceRegion(
|
||||
m_d3d_texture, D3D11CalcSubresource(dst_level, dst_layer, m_config.levels), dst_rect.left,
|
||||
dst_rect.top, 0, srcentry->m_d3d_texture,
|
||||
m_texture.Get(), D3D11CalcSubresource(dst_level, dst_layer, m_config.levels), dst_rect.left,
|
||||
dst_rect.top, 0, srcentry->m_texture.Get(),
|
||||
D3D11CalcSubresource(src_level, src_layer, srcentry->m_config.levels), &src_box);
|
||||
}
|
||||
|
||||
@@ -228,16 +147,16 @@ void DXTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::R
|
||||
rect.top + rect.GetHeight() <= static_cast<int>(srcentry->m_config.height));
|
||||
|
||||
D3D::context->ResolveSubresource(
|
||||
m_d3d_texture, D3D11CalcSubresource(level, layer, m_config.levels), srcentry->m_d3d_texture,
|
||||
D3D11CalcSubresource(level, layer, srcentry->m_config.levels),
|
||||
GetDXGIFormatForHostFormat(m_config.format, false));
|
||||
m_texture.Get(), D3D11CalcSubresource(level, layer, m_config.levels),
|
||||
srcentry->m_texture.Get(), D3D11CalcSubresource(level, layer, srcentry->m_config.levels),
|
||||
D3DCommon::GetDXGIFormatForAbstractFormat(m_config.format, false));
|
||||
}
|
||||
|
||||
void DXTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
size_t src_pitch = CalculateStrideForFormat(m_config.format, row_length);
|
||||
D3D::context->UpdateSubresource(m_d3d_texture, level, nullptr, buffer,
|
||||
D3D::context->UpdateSubresource(m_texture.Get(), level, nullptr, buffer,
|
||||
static_cast<UINT>(src_pitch), 0);
|
||||
}
|
||||
|
||||
@@ -251,7 +170,6 @@ DXStagingTexture::~DXStagingTexture()
|
||||
{
|
||||
if (IsMapped())
|
||||
DXStagingTexture::Unmap();
|
||||
SAFE_RELEASE(m_tex);
|
||||
}
|
||||
|
||||
std::unique_ptr<DXStagingTexture> DXStagingTexture::Create(StagingTextureType type,
|
||||
@@ -275,16 +193,16 @@ std::unique_ptr<DXStagingTexture> DXStagingTexture::Create(StagingTextureType ty
|
||||
cpu_flags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
|
||||
}
|
||||
|
||||
CD3D11_TEXTURE2D_DESC desc(GetDXGIFormatForHostFormat(config.format, false), config.width,
|
||||
config.height, 1, 1, 0, usage, cpu_flags);
|
||||
CD3D11_TEXTURE2D_DESC desc(D3DCommon::GetDXGIFormatForAbstractFormat(config.format, false),
|
||||
config.width, config.height, 1, 1, 0, usage, cpu_flags);
|
||||
|
||||
ID3D11Texture2D* texture;
|
||||
ComPtr<ID3D11Texture2D> texture;
|
||||
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, &texture);
|
||||
CHECK(SUCCEEDED(hr), "Create staging texture");
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
|
||||
return std::unique_ptr<DXStagingTexture>(new DXStagingTexture(type, config, texture));
|
||||
return std::unique_ptr<DXStagingTexture>(new DXStagingTexture(type, config, texture.Get()));
|
||||
}
|
||||
|
||||
void DXStagingTexture::CopyFromTexture(const AbstractTexture* src,
|
||||
@@ -307,14 +225,14 @@ void DXStagingTexture::CopyFromTexture(const AbstractTexture* src,
|
||||
{
|
||||
// Copy whole resource, needed for depth textures.
|
||||
D3D::context->CopySubresourceRegion(
|
||||
m_tex, 0, 0, 0, 0, static_cast<const DXTexture*>(src)->GetD3DTexture(),
|
||||
m_tex.Get(), 0, 0, 0, 0, static_cast<const DXTexture*>(src)->GetD3DTexture(),
|
||||
D3D11CalcSubresource(src_level, src_layer, src->GetLevels()), nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
CD3D11_BOX src_box(src_rect.left, src_rect.top, 0, src_rect.right, src_rect.bottom, 1);
|
||||
D3D::context->CopySubresourceRegion(
|
||||
m_tex, 0, static_cast<u32>(dst_rect.left), static_cast<u32>(dst_rect.top), 0,
|
||||
m_tex.Get(), 0, static_cast<u32>(dst_rect.left), static_cast<u32>(dst_rect.top), 0,
|
||||
static_cast<const DXTexture*>(src)->GetD3DTexture(),
|
||||
D3D11CalcSubresource(src_level, src_layer, src->GetLevels()), &src_box);
|
||||
}
|
||||
@@ -342,7 +260,8 @@ void DXStagingTexture::CopyToTexture(const MathUtil::Rectangle<int>& src_rect, A
|
||||
{
|
||||
D3D::context->CopySubresourceRegion(
|
||||
static_cast<const DXTexture*>(dst)->GetD3DTexture(),
|
||||
D3D11CalcSubresource(dst_level, dst_layer, dst->GetLevels()), 0, 0, 0, m_tex, 0, nullptr);
|
||||
D3D11CalcSubresource(dst_level, dst_layer, dst->GetLevels()), 0, 0, 0, m_tex.Get(), 0,
|
||||
nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -350,7 +269,8 @@ void DXStagingTexture::CopyToTexture(const MathUtil::Rectangle<int>& src_rect, A
|
||||
D3D::context->CopySubresourceRegion(
|
||||
static_cast<const DXTexture*>(dst)->GetD3DTexture(),
|
||||
D3D11CalcSubresource(dst_level, dst_layer, dst->GetLevels()),
|
||||
static_cast<u32>(dst_rect.left), static_cast<u32>(dst_rect.top), 0, m_tex, 0, &src_box);
|
||||
static_cast<u32>(dst_rect.left), static_cast<u32>(dst_rect.top), 0, m_tex.Get(), 0,
|
||||
&src_box);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,7 +288,7 @@ bool DXStagingTexture::Map()
|
||||
map_type = D3D11_MAP_READ_WRITE;
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE sr;
|
||||
HRESULT hr = D3D::context->Map(m_tex, 0, map_type, 0, &sr);
|
||||
HRESULT hr = D3D::context->Map(m_tex.Get(), 0, map_type, 0, &sr);
|
||||
CHECK(SUCCEEDED(hr), "Map readback texture");
|
||||
if (FAILED(hr))
|
||||
return false;
|
||||
@@ -383,7 +303,7 @@ void DXStagingTexture::Unmap()
|
||||
if (!m_map_pointer)
|
||||
return;
|
||||
|
||||
D3D::context->Unmap(m_tex, 0);
|
||||
D3D::context->Unmap(m_tex.Get(), 0);
|
||||
m_map_pointer = nullptr;
|
||||
}
|
||||
|
||||
@@ -404,15 +324,7 @@ DXFramebuffer::DXFramebuffer(AbstractTexture* color_attachment, AbstractTexture*
|
||||
{
|
||||
}
|
||||
|
||||
DXFramebuffer::~DXFramebuffer()
|
||||
{
|
||||
if (m_rtv)
|
||||
m_rtv->Release();
|
||||
if (m_integer_rtv)
|
||||
m_integer_rtv->Release();
|
||||
if (m_dsv)
|
||||
m_dsv->Release();
|
||||
}
|
||||
DXFramebuffer::~DXFramebuffer() = default;
|
||||
|
||||
std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment,
|
||||
DXTexture* depth_attachment)
|
||||
@@ -430,21 +342,24 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
|
||||
const u32 layers = either_attachment->GetLayers();
|
||||
const u32 samples = either_attachment->GetSamples();
|
||||
|
||||
ID3D11RenderTargetView* rtv = nullptr;
|
||||
ID3D11RenderTargetView* integer_rtv = nullptr;
|
||||
ComPtr<ID3D11RenderTargetView> rtv;
|
||||
ComPtr<ID3D11RenderTargetView> integer_rtv;
|
||||
if (color_attachment)
|
||||
{
|
||||
CD3D11_RENDER_TARGET_VIEW_DESC desc(
|
||||
color_attachment->IsMultisampled() ? D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY :
|
||||
D3D11_RTV_DIMENSION_TEXTURE2DARRAY,
|
||||
GetRTVFormatForHostFormat(color_attachment->GetFormat(), false), 0, 0,
|
||||
D3DCommon::GetRTVFormatForAbstractFormat(color_attachment->GetFormat(), false), 0, 0,
|
||||
color_attachment->GetLayers());
|
||||
HRESULT hr =
|
||||
D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc, &rtv);
|
||||
CHECK(SUCCEEDED(hr), "Create render target view for framebuffer");
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
|
||||
// Only create the integer RTV on Win8+.
|
||||
DXGI_FORMAT integer_format = GetRTVFormatForHostFormat(color_attachment->GetFormat(), true);
|
||||
DXGI_FORMAT integer_format =
|
||||
D3DCommon::GetRTVFormatForAbstractFormat(color_attachment->GetFormat(), true);
|
||||
if (D3D::device1 && integer_format != desc.Format)
|
||||
{
|
||||
desc.Format = integer_format;
|
||||
@@ -454,22 +369,24 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11DepthStencilView* dsv = nullptr;
|
||||
ComPtr<ID3D11DepthStencilView> dsv;
|
||||
if (depth_attachment)
|
||||
{
|
||||
const CD3D11_DEPTH_STENCIL_VIEW_DESC desc(
|
||||
depth_attachment->GetConfig().IsMultisampled() ? D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY :
|
||||
D3D11_DSV_DIMENSION_TEXTURE2DARRAY,
|
||||
GetDSVFormatForHostFormat(depth_attachment->GetFormat()), 0, 0,
|
||||
D3DCommon::GetDSVFormatForAbstractFormat(depth_attachment->GetFormat()), 0, 0,
|
||||
depth_attachment->GetLayers(), 0);
|
||||
HRESULT hr =
|
||||
D3D::device->CreateDepthStencilView(depth_attachment->GetD3DTexture(), &desc, &dsv);
|
||||
CHECK(SUCCEEDED(hr), "Create depth stencil view for framebuffer");
|
||||
if (FAILED(hr))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<DXFramebuffer>(color_attachment, depth_attachment, color_format,
|
||||
depth_format, width, height, layers, samples, rtv,
|
||||
integer_rtv, dsv);
|
||||
depth_format, width, height, layers, samples, rtv.Get(),
|
||||
integer_rtv.Get(), dsv.Get());
|
||||
}
|
||||
|
||||
} // namespace DX11
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user