mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
D3D: Moved render state cache into separate source files.
Refactored StateCache::Get() to early out for narrower indentation. Added comments to clarify ownership of objects returned by StateCache::Get().
This commit is contained in:
parent
f434bd7d3f
commit
2e4667caaa
@ -50,6 +50,7 @@
|
||||
<ClCompile Include="PointGeometryShader.cpp" />
|
||||
<ClCompile Include="PSTextureEncoder.cpp" />
|
||||
<ClCompile Include="Render.cpp" />
|
||||
<ClCompile Include="StateCache.cpp" />
|
||||
<ClCompile Include="Television.cpp" />
|
||||
<ClCompile Include="TextureCache.cpp" />
|
||||
<ClCompile Include="VertexManager.cpp" />
|
||||
@ -72,6 +73,7 @@
|
||||
<ClInclude Include="PointGeometryShader.h" />
|
||||
<ClInclude Include="PSTextureEncoder.h" />
|
||||
<ClInclude Include="Render.h" />
|
||||
<ClInclude Include="StateCache.h" />
|
||||
<ClInclude Include="Television.h" />
|
||||
<ClInclude Include="TextureCache.h" />
|
||||
<ClInclude Include="TextureEncoder.h" />
|
||||
@ -91,4 +93,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="D3D">
|
||||
@ -67,6 +67,9 @@
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="StateCache.cpp">
|
||||
<Filter>Render</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="D3DBase.h">
|
||||
@ -129,5 +132,8 @@
|
||||
<ClInclude Include="Globals.h" />
|
||||
<ClInclude Include="main.h" />
|
||||
<ClInclude Include="VideoBackend.h" />
|
||||
<ClInclude Include="StateCache.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -21,6 +21,7 @@
|
||||
#include "VideoBackends/D3D/GfxState.h"
|
||||
#include "VideoBackends/D3D/PixelShaderCache.h"
|
||||
#include "VideoBackends/D3D/Render.h"
|
||||
#include "VideoBackends/D3D/StateCache.h"
|
||||
#include "VideoBackends/D3D/Television.h"
|
||||
#include "VideoBackends/D3D/TextureCache.h"
|
||||
#include "VideoBackends/D3D/VertexShaderCache.h"
|
||||
@ -54,49 +55,6 @@ ID3D11RasterizerState* resetraststate = nullptr;
|
||||
|
||||
static ID3D11Texture2D* s_screenshot_texture = nullptr;
|
||||
|
||||
union RasterizerState
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 cull_mode : 2;
|
||||
u32 wireframe : 1;
|
||||
};
|
||||
|
||||
u32 packed;
|
||||
};
|
||||
|
||||
union BlendState
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 blend_enable : 1;
|
||||
u32 blend_op : 3;
|
||||
u32 write_mask : 4;
|
||||
u32 src_blend : 5;
|
||||
u32 dst_blend : 5;
|
||||
u32 use_dst_alpha : 1;
|
||||
};
|
||||
|
||||
u32 packed;
|
||||
};
|
||||
|
||||
union SamplerState
|
||||
{
|
||||
struct
|
||||
{
|
||||
u64 min_filter : 3;
|
||||
u64 mag_filter : 1;
|
||||
u64 min_lod : 8;
|
||||
u64 max_lod : 8;
|
||||
s64 lod_bias : 8;
|
||||
u64 wrap_s : 2;
|
||||
u64 wrap_t : 2;
|
||||
u64 max_anisotropy : 5;
|
||||
};
|
||||
|
||||
u64 packed;
|
||||
};
|
||||
|
||||
// GX pipeline state
|
||||
struct
|
||||
{
|
||||
@ -107,302 +65,7 @@ struct
|
||||
|
||||
} gx_state;
|
||||
|
||||
class GXStateCache
|
||||
{
|
||||
public:
|
||||
|
||||
ID3D11SamplerState* Get(SamplerState state)
|
||||
{
|
||||
ID3D11SamplerState* res = nullptr;
|
||||
|
||||
auto it = m_sampler.find(state.packed);
|
||||
|
||||
if (it != m_sampler.end())
|
||||
{
|
||||
res = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
enum
|
||||
{
|
||||
TEXF_NONE = 0,
|
||||
TEXF_POINT = 1,
|
||||
TEXF_LINEAR = 2
|
||||
};
|
||||
|
||||
const unsigned int d3dMipFilters[4] =
|
||||
{
|
||||
TEXF_NONE,
|
||||
TEXF_POINT,
|
||||
TEXF_LINEAR,
|
||||
TEXF_NONE, //reserved
|
||||
};
|
||||
const D3D11_TEXTURE_ADDRESS_MODE d3dClamps[4] =
|
||||
{
|
||||
D3D11_TEXTURE_ADDRESS_CLAMP,
|
||||
D3D11_TEXTURE_ADDRESS_WRAP,
|
||||
D3D11_TEXTURE_ADDRESS_MIRROR,
|
||||
D3D11_TEXTURE_ADDRESS_WRAP //reserved
|
||||
};
|
||||
|
||||
D3D11_SAMPLER_DESC sampdc = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT());
|
||||
|
||||
unsigned int mip = d3dMipFilters[state.min_filter & 3];
|
||||
|
||||
if (state.max_anisotropy)
|
||||
{
|
||||
sampdc.Filter = D3D11_FILTER_ANISOTROPIC;
|
||||
sampdc.MaxAnisotropy = state.max_anisotropy;
|
||||
}
|
||||
else if (state.min_filter & 4) // linear min filter
|
||||
{
|
||||
if (state.mag_filter) // linear mag filter
|
||||
{
|
||||
if (mip == TEXF_NONE)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||
else if (mip == TEXF_POINT)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||
else if (mip == TEXF_LINEAR)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
}
|
||||
else // point mag filter
|
||||
{
|
||||
if (mip == TEXF_NONE)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
|
||||
else if (mip == TEXF_POINT)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
|
||||
else if (mip == TEXF_LINEAR)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
|
||||
}
|
||||
}
|
||||
else // point min filter
|
||||
{
|
||||
if (state.mag_filter) // linear mag filter
|
||||
{
|
||||
if (mip == TEXF_NONE)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
|
||||
else if (mip == TEXF_POINT)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
|
||||
else if (mip == TEXF_LINEAR)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
|
||||
}
|
||||
else // point mag filter
|
||||
{
|
||||
if (mip == TEXF_NONE)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
else if (mip == TEXF_POINT)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
else if (mip == TEXF_LINEAR)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
sampdc.AddressU = d3dClamps[state.wrap_s];
|
||||
sampdc.AddressV = d3dClamps[state.wrap_t];
|
||||
|
||||
sampdc.MaxLOD = (mip == TEXF_NONE) ? 0.0f : (float)state.max_lod / 16.f;
|
||||
sampdc.MinLOD = (float)state.min_lod / 16.f;
|
||||
sampdc.MipLODBias = (s32)state.lod_bias / 32.0f;
|
||||
|
||||
HRESULT hr = D3D::device->CreateSamplerState(&sampdc, &res);
|
||||
if (FAILED(hr)) PanicAlert("Fail %s %d\n", __FILE__, __LINE__);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)res, "sampler state used to emulate the GX pipeline");
|
||||
m_sampler.insert(std::make_pair(state.packed, res));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ID3D11BlendState* Get(BlendState state)
|
||||
{
|
||||
ID3D11BlendState* res = nullptr;
|
||||
|
||||
auto it = m_blend.find(state.packed);
|
||||
|
||||
if (it != m_blend.end())
|
||||
{
|
||||
res = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D11_BLEND_DESC blenddc = CD3D11_BLEND_DESC(CD3D11_DEFAULT());
|
||||
|
||||
blenddc.AlphaToCoverageEnable = FALSE;
|
||||
blenddc.IndependentBlendEnable = FALSE;
|
||||
blenddc.RenderTarget[0].BlendEnable = state.blend_enable;
|
||||
blenddc.RenderTarget[0].RenderTargetWriteMask = (D3D11_COLOR_WRITE_ENABLE)state.write_mask;
|
||||
blenddc.RenderTarget[0].SrcBlend = (D3D11_BLEND)state.src_blend;
|
||||
blenddc.RenderTarget[0].DestBlend = (D3D11_BLEND)state.dst_blend;
|
||||
blenddc.RenderTarget[0].BlendOp = (D3D11_BLEND_OP)state.blend_op;
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = (D3D11_BLEND)state.src_blend;
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = (D3D11_BLEND)state.dst_blend;
|
||||
blenddc.RenderTarget[0].BlendOpAlpha = (D3D11_BLEND_OP)state.blend_op;
|
||||
|
||||
if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_SRC_COLOR)
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_INV_SRC_COLOR)
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_DEST_COLOR)
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_INV_DEST_COLOR)
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
|
||||
else
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = blenddc.RenderTarget[0].SrcBlend;
|
||||
|
||||
if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_SRC_COLOR)
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_SRC_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_INV_SRC_COLOR)
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_DEST_COLOR)
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_INV_DEST_COLOR)
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
|
||||
else
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = blenddc.RenderTarget[0].DestBlend;
|
||||
|
||||
if (state.use_dst_alpha)
|
||||
{
|
||||
// Colors should blend against SRC1_ALPHA
|
||||
if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_SRC_ALPHA)
|
||||
blenddc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC1_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_INV_SRC_ALPHA)
|
||||
blenddc.RenderTarget[0].SrcBlend = D3D11_BLEND_INV_SRC1_ALPHA;
|
||||
|
||||
// Colors should blend against SRC1_ALPHA
|
||||
if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_SRC_ALPHA)
|
||||
blenddc.RenderTarget[0].DestBlend = D3D11_BLEND_SRC1_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_INV_SRC_ALPHA)
|
||||
blenddc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC1_ALPHA;
|
||||
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
blenddc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
}
|
||||
|
||||
HRESULT hr = D3D::device->CreateBlendState(&blenddc, &res);
|
||||
if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)res, "blend state used to emulate the GX pipeline");
|
||||
m_blend.insert(std::make_pair(state.packed, res));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ID3D11RasterizerState* Get(RasterizerState state)
|
||||
{
|
||||
ID3D11RasterizerState* res = nullptr;
|
||||
|
||||
auto it = m_raster.find(state.packed);
|
||||
|
||||
if (it != m_raster.end())
|
||||
{
|
||||
res = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D11_RASTERIZER_DESC rastdc = CD3D11_RASTERIZER_DESC(state.wireframe ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID,
|
||||
(D3D11_CULL_MODE)state.cull_mode,
|
||||
false, 0, 0.f, 0, false, true, false, false);
|
||||
|
||||
HRESULT hr = D3D::device->CreateRasterizerState(&rastdc, &res);
|
||||
if (FAILED(hr)) PanicAlert("Failed to create rasterizer state at %s %d\n", __FILE__, __LINE__);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)res, "rasterizer state used to emulate the GX pipeline");
|
||||
m_raster.insert(std::make_pair(state.packed, res));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ID3D11DepthStencilState* Get(ZMode state)
|
||||
{
|
||||
ID3D11DepthStencilState* res = nullptr;
|
||||
|
||||
auto it = m_depth.find(state.hex);
|
||||
if (it != m_depth.end())
|
||||
{
|
||||
res = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D11_DEPTH_STENCIL_DESC depthdc = CD3D11_DEPTH_STENCIL_DESC(CD3D11_DEFAULT());
|
||||
|
||||
depthdc.DepthEnable = TRUE;
|
||||
depthdc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
||||
depthdc.DepthFunc = D3D11_COMPARISON_LESS;
|
||||
depthdc.StencilEnable = FALSE;
|
||||
depthdc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
|
||||
depthdc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
|
||||
|
||||
const D3D11_COMPARISON_FUNC d3dCmpFuncs[8] =
|
||||
{
|
||||
D3D11_COMPARISON_NEVER,
|
||||
D3D11_COMPARISON_LESS,
|
||||
D3D11_COMPARISON_EQUAL,
|
||||
D3D11_COMPARISON_LESS_EQUAL,
|
||||
D3D11_COMPARISON_GREATER,
|
||||
D3D11_COMPARISON_NOT_EQUAL,
|
||||
D3D11_COMPARISON_GREATER_EQUAL,
|
||||
D3D11_COMPARISON_ALWAYS
|
||||
};
|
||||
|
||||
if (state.testenable)
|
||||
{
|
||||
depthdc.DepthEnable = TRUE;
|
||||
depthdc.DepthWriteMask = state.updateenable ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
depthdc.DepthFunc = d3dCmpFuncs[state.func];
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the test is disabled write is disabled too
|
||||
depthdc.DepthEnable = FALSE;
|
||||
depthdc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
}
|
||||
|
||||
HRESULT hr = D3D::device->CreateDepthStencilState(&depthdc, &res);
|
||||
if (SUCCEEDED(hr)) D3D::SetDebugObjectName((ID3D11DeviceChild*)res, "depth-stencil state used to emulate the GX pipeline");
|
||||
else PanicAlert("Failed to create depth state at %s %d\n", __FILE__, __LINE__);
|
||||
|
||||
m_depth.insert(std::make_pair(state.hex, res));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
for (auto it : m_depth)
|
||||
{
|
||||
SAFE_RELEASE(it.second);
|
||||
}
|
||||
m_depth.clear();
|
||||
|
||||
for (auto it : m_raster)
|
||||
{
|
||||
SAFE_RELEASE(it.second);
|
||||
}
|
||||
m_raster.clear();
|
||||
|
||||
for (auto it : m_blend)
|
||||
{
|
||||
SAFE_RELEASE(it.second);
|
||||
}
|
||||
m_blend.clear();
|
||||
|
||||
for (auto it : m_sampler)
|
||||
{
|
||||
SAFE_RELEASE(it.second);
|
||||
}
|
||||
m_sampler.clear();
|
||||
}
|
||||
|
||||
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<u64, ID3D11SamplerState*> m_sampler;
|
||||
|
||||
} gx_state_cache;
|
||||
StateCache gx_state_cache;
|
||||
|
||||
void SetupDeviceObjects()
|
||||
{
|
||||
|
280
Source/Core/VideoBackends/D3D/StateCache.cpp
Normal file
280
Source/Core/VideoBackends/D3D/StateCache.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "VideoBackends/D3D/StateCache.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
ID3D11SamplerState* StateCache::Get(SamplerState state)
|
||||
{
|
||||
auto it = m_sampler.find(state.packed);
|
||||
|
||||
if (it != m_sampler.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
const unsigned int d3dMipFilters[4] =
|
||||
{
|
||||
TexMode0::TEXF_NONE,
|
||||
TexMode0::TEXF_POINT,
|
||||
TexMode0::TEXF_LINEAR,
|
||||
TexMode0::TEXF_NONE, //reserved
|
||||
};
|
||||
const D3D11_TEXTURE_ADDRESS_MODE d3dClamps[4] =
|
||||
{
|
||||
D3D11_TEXTURE_ADDRESS_CLAMP,
|
||||
D3D11_TEXTURE_ADDRESS_WRAP,
|
||||
D3D11_TEXTURE_ADDRESS_MIRROR,
|
||||
D3D11_TEXTURE_ADDRESS_WRAP //reserved
|
||||
};
|
||||
|
||||
D3D11_SAMPLER_DESC sampdc = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT());
|
||||
|
||||
unsigned int mip = d3dMipFilters[state.min_filter & 3];
|
||||
|
||||
if (state.max_anisotropy)
|
||||
{
|
||||
sampdc.Filter = D3D11_FILTER_ANISOTROPIC;
|
||||
sampdc.MaxAnisotropy = state.max_anisotropy;
|
||||
}
|
||||
else if (state.min_filter & 4) // linear min filter
|
||||
{
|
||||
if (state.mag_filter) // linear mag filter
|
||||
{
|
||||
if (mip == TexMode0::TEXF_NONE)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||
else if (mip == TexMode0::TEXF_POINT)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||
else if (mip == TexMode0::TEXF_LINEAR)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
}
|
||||
else // point mag filter
|
||||
{
|
||||
if (mip == TexMode0::TEXF_NONE)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
|
||||
else if (mip == TexMode0::TEXF_POINT)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
|
||||
else if (mip == TexMode0::TEXF_LINEAR)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
|
||||
}
|
||||
}
|
||||
else // point min filter
|
||||
{
|
||||
if (state.mag_filter) // linear mag filter
|
||||
{
|
||||
if (mip == TexMode0::TEXF_NONE)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
|
||||
else if (mip == TexMode0::TEXF_POINT)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
|
||||
else if (mip == TexMode0::TEXF_LINEAR)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
|
||||
}
|
||||
else // point mag filter
|
||||
{
|
||||
if (mip == TexMode0::TEXF_NONE)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
else if (mip == TexMode0::TEXF_POINT)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
else if (mip == TexMode0::TEXF_LINEAR)
|
||||
sampdc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
sampdc.AddressU = d3dClamps[state.wrap_s];
|
||||
sampdc.AddressV = d3dClamps[state.wrap_t];
|
||||
|
||||
sampdc.MaxLOD = (mip == TexMode0::TEXF_NONE) ? 0.0f : (float)state.max_lod / 16.f;
|
||||
sampdc.MinLOD = (float)state.min_lod / 16.f;
|
||||
sampdc.MipLODBias = (s32)state.lod_bias / 32.0f;
|
||||
|
||||
ID3D11SamplerState* res = nullptr;
|
||||
|
||||
HRESULT hr = D3D::device->CreateSamplerState(&sampdc, &res);
|
||||
if (FAILED(hr)) PanicAlert("Fail %s %d\n", __FILE__, __LINE__);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)res, "sampler state used to emulate the GX pipeline");
|
||||
m_sampler.insert(std::make_pair(state.packed, res));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ID3D11BlendState* StateCache::Get(BlendState state)
|
||||
{
|
||||
auto it = m_blend.find(state.packed);
|
||||
|
||||
if (it != m_blend.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
D3D11_BLEND_DESC blenddc = CD3D11_BLEND_DESC(CD3D11_DEFAULT());
|
||||
|
||||
blenddc.AlphaToCoverageEnable = FALSE;
|
||||
blenddc.IndependentBlendEnable = FALSE;
|
||||
blenddc.RenderTarget[0].BlendEnable = state.blend_enable;
|
||||
blenddc.RenderTarget[0].RenderTargetWriteMask = (D3D11_COLOR_WRITE_ENABLE)state.write_mask;
|
||||
blenddc.RenderTarget[0].SrcBlend = (D3D11_BLEND)state.src_blend;
|
||||
blenddc.RenderTarget[0].DestBlend = (D3D11_BLEND)state.dst_blend;
|
||||
blenddc.RenderTarget[0].BlendOp = (D3D11_BLEND_OP)state.blend_op;
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = (D3D11_BLEND)state.src_blend;
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = (D3D11_BLEND)state.dst_blend;
|
||||
blenddc.RenderTarget[0].BlendOpAlpha = (D3D11_BLEND_OP)state.blend_op;
|
||||
|
||||
if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_SRC_COLOR)
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_INV_SRC_COLOR)
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_DEST_COLOR)
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_DEST_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_INV_DEST_COLOR)
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
|
||||
else
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = blenddc.RenderTarget[0].SrcBlend;
|
||||
|
||||
if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_SRC_COLOR)
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_SRC_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_INV_SRC_COLOR)
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_DEST_COLOR)
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_INV_DEST_COLOR)
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA;
|
||||
else
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = blenddc.RenderTarget[0].DestBlend;
|
||||
|
||||
if (state.use_dst_alpha)
|
||||
{
|
||||
// Colors should blend against SRC1_ALPHA
|
||||
if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_SRC_ALPHA)
|
||||
blenddc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC1_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_INV_SRC_ALPHA)
|
||||
blenddc.RenderTarget[0].SrcBlend = D3D11_BLEND_INV_SRC1_ALPHA;
|
||||
|
||||
// Colors should blend against SRC1_ALPHA
|
||||
if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_SRC_ALPHA)
|
||||
blenddc.RenderTarget[0].DestBlend = D3D11_BLEND_SRC1_ALPHA;
|
||||
else if (blenddc.RenderTarget[0].DestBlend == D3D11_BLEND_INV_SRC_ALPHA)
|
||||
blenddc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC1_ALPHA;
|
||||
|
||||
blenddc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
||||
blenddc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
blenddc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
}
|
||||
|
||||
ID3D11BlendState* res = nullptr;
|
||||
|
||||
HRESULT hr = D3D::device->CreateBlendState(&blenddc, &res);
|
||||
if (FAILED(hr)) PanicAlert("Failed to create blend state at %s %d\n", __FILE__, __LINE__);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)res, "blend state used to emulate the GX pipeline");
|
||||
m_blend.insert(std::make_pair(state.packed, res));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ID3D11RasterizerState* StateCache::Get(RasterizerState state)
|
||||
{
|
||||
auto it = m_raster.find(state.packed);
|
||||
|
||||
if (it != m_raster.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
D3D11_RASTERIZER_DESC rastdc = CD3D11_RASTERIZER_DESC(state.wireframe ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID,
|
||||
(D3D11_CULL_MODE)state.cull_mode,
|
||||
false, 0, 0.f, 0, false, true, false, false);
|
||||
|
||||
ID3D11RasterizerState* res = nullptr;
|
||||
|
||||
HRESULT hr = D3D::device->CreateRasterizerState(&rastdc, &res);
|
||||
if (FAILED(hr)) PanicAlert("Failed to create rasterizer state at %s %d\n", __FILE__, __LINE__);
|
||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)res, "rasterizer state used to emulate the GX pipeline");
|
||||
m_raster.insert(std::make_pair(state.packed, res));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ID3D11DepthStencilState* StateCache::Get(ZMode state)
|
||||
{
|
||||
auto it = m_depth.find(state.hex);
|
||||
|
||||
if (it != m_depth.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
D3D11_DEPTH_STENCIL_DESC depthdc = CD3D11_DEPTH_STENCIL_DESC(CD3D11_DEFAULT());
|
||||
|
||||
depthdc.DepthEnable = TRUE;
|
||||
depthdc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
||||
depthdc.DepthFunc = D3D11_COMPARISON_LESS;
|
||||
depthdc.StencilEnable = FALSE;
|
||||
depthdc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
|
||||
depthdc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
|
||||
|
||||
const D3D11_COMPARISON_FUNC d3dCmpFuncs[8] =
|
||||
{
|
||||
D3D11_COMPARISON_NEVER,
|
||||
D3D11_COMPARISON_LESS,
|
||||
D3D11_COMPARISON_EQUAL,
|
||||
D3D11_COMPARISON_LESS_EQUAL,
|
||||
D3D11_COMPARISON_GREATER,
|
||||
D3D11_COMPARISON_NOT_EQUAL,
|
||||
D3D11_COMPARISON_GREATER_EQUAL,
|
||||
D3D11_COMPARISON_ALWAYS
|
||||
};
|
||||
|
||||
if (state.testenable)
|
||||
{
|
||||
depthdc.DepthEnable = TRUE;
|
||||
depthdc.DepthWriteMask = state.updateenable ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
depthdc.DepthFunc = d3dCmpFuncs[state.func];
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the test is disabled write is disabled too
|
||||
depthdc.DepthEnable = FALSE;
|
||||
depthdc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
}
|
||||
|
||||
ID3D11DepthStencilState* res = nullptr;
|
||||
|
||||
HRESULT hr = D3D::device->CreateDepthStencilState(&depthdc, &res);
|
||||
if (SUCCEEDED(hr)) D3D::SetDebugObjectName((ID3D11DeviceChild*)res, "depth-stencil state used to emulate the GX pipeline");
|
||||
else PanicAlert("Failed to create depth state at %s %d\n", __FILE__, __LINE__);
|
||||
|
||||
m_depth.insert(std::make_pair(state.hex, res));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void StateCache::Clear()
|
||||
{
|
||||
for (auto it : m_depth)
|
||||
{
|
||||
SAFE_RELEASE(it.second);
|
||||
}
|
||||
m_depth.clear();
|
||||
|
||||
for (auto it : m_raster)
|
||||
{
|
||||
SAFE_RELEASE(it.second);
|
||||
}
|
||||
m_raster.clear();
|
||||
|
||||
for (auto it : m_blend)
|
||||
{
|
||||
SAFE_RELEASE(it.second);
|
||||
}
|
||||
m_blend.clear();
|
||||
|
||||
for (auto it : m_sampler)
|
||||
{
|
||||
SAFE_RELEASE(it.second);
|
||||
}
|
||||
m_sampler.clear();
|
||||
}
|
||||
|
||||
} // namespace DX11
|
82
Source/Core/VideoBackends/D3D/StateCache.h
Normal file
82
Source/Core/VideoBackends/D3D/StateCache.h
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoBackends/D3D/D3DBase.h"
|
||||
#include "VideoCommon/BPMemory.h"
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
||||
union RasterizerState
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 cull_mode : 2;
|
||||
u32 wireframe : 1;
|
||||
};
|
||||
|
||||
u32 packed;
|
||||
};
|
||||
|
||||
union BlendState
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 blend_enable : 1;
|
||||
u32 blend_op : 3;
|
||||
u32 write_mask : 4;
|
||||
u32 src_blend : 5;
|
||||
u32 dst_blend : 5;
|
||||
u32 use_dst_alpha : 1;
|
||||
};
|
||||
|
||||
u32 packed;
|
||||
};
|
||||
|
||||
union SamplerState
|
||||
{
|
||||
struct
|
||||
{
|
||||
u64 min_filter : 3;
|
||||
u64 mag_filter : 1;
|
||||
u64 min_lod : 8;
|
||||
u64 max_lod : 8;
|
||||
s64 lod_bias : 8;
|
||||
u64 wrap_s : 2;
|
||||
u64 wrap_t : 2;
|
||||
u64 max_anisotropy : 5;
|
||||
};
|
||||
|
||||
u64 packed;
|
||||
};
|
||||
|
||||
class StateCache
|
||||
{
|
||||
public:
|
||||
|
||||
// Get existing or create new render state.
|
||||
// Returned objects is owned by the cache and does not need to be released.
|
||||
ID3D11SamplerState* Get(SamplerState state);
|
||||
ID3D11BlendState* Get(BlendState state);
|
||||
ID3D11RasterizerState* Get(RasterizerState state);
|
||||
ID3D11DepthStencilState* Get(ZMode state);
|
||||
|
||||
// Release all cached states and clear hash tables.
|
||||
void Clear();
|
||||
|
||||
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<u64, ID3D11SamplerState*> m_sampler;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -413,6 +413,13 @@ union RAS1_IREF
|
||||
|
||||
union TexMode0
|
||||
{
|
||||
enum TextureFilter : u32
|
||||
{
|
||||
TEXF_NONE = 0,
|
||||
TEXF_POINT = 1,
|
||||
TEXF_LINEAR = 2
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
u32 wrap_s : 2;
|
||||
|
Loading…
Reference in New Issue
Block a user