Merge pull request #7869 from stenzek/d3dcommon

D3D: Move sharable D3D11/D3D12 code to common library
This commit is contained in:
Connor McLaughlin
2019-03-29 20:40:06 +10:00
committed by GitHub
50 changed files with 1761 additions and 1423 deletions
+1
View File
@@ -11,6 +11,7 @@ add_library(common
Crypto/ec.cpp
Debug/MemoryPatches.cpp
Debug/Watches.cpp
DynamicLibrary.cpp
ENetUtil.cpp
File.cpp
FileSearch.cpp
+3 -1
View File
@@ -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>
+4 -1
View File
@@ -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>
+100
View File
@@ -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
+67
View File
@@ -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
+1
View File
@@ -4,6 +4,7 @@ add_subdirectory(Software)
add_subdirectory(Vulkan)
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
add_subdirectory(D3DCommon)
add_subdirectory(D3D)
endif()
+18 -17
View File
@@ -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
+1 -1
View File
@@ -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
+14 -67
View File
@@ -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
+19 -48
View File
@@ -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 -5
View File
@@ -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
+1 -36
View File
@@ -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);
+14 -14
View File
@@ -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;
};
+16 -119
View File
@@ -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
+4 -16
View File
@@ -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
+96 -179
View File
@@ -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