Renderer: Move cull mode to a rasterization state object

Also moves logic for primitive handling to VideoCommon.
This commit is contained in:
Stenzek
2017-04-30 18:07:57 +10:00
parent 2869c570f1
commit 836b9b9acb
38 changed files with 389 additions and 450 deletions

View File

@ -434,25 +434,27 @@ ID3D11BlendState* StateCache::Get(BlendingState state)
return res;
}
ID3D11RasterizerState* StateCache::Get(RasterizerState state)
ID3D11RasterizerState* StateCache::Get(RasterizationState state)
{
auto it = m_raster.find(state.packed);
auto it = m_raster.find(state.hex);
if (it != m_raster.end())
return it->second;
D3D11_RASTERIZER_DESC rastdc = CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID, state.cull_mode, false, 0,
0.f, 0, false, true, false, false);
static constexpr std::array<D3D11_CULL_MODE, 4> cull_modes = {
{D3D11_CULL_NONE, D3D11_CULL_BACK, D3D11_CULL_FRONT, D3D11_CULL_BACK}};
D3D11_RASTERIZER_DESC desc = {};
desc.FillMode = D3D11_FILL_SOLID;
desc.CullMode = cull_modes[state.cullmode];
desc.ScissorEnable = TRUE;
ID3D11RasterizerState* res = nullptr;
HRESULT hr = D3D::device->CreateRasterizerState(&rastdc, &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");
m_raster.emplace(state.packed, res);
m_raster.emplace(state.hex, res);
return res;
}
@ -531,4 +533,12 @@ void StateCache::Clear()
m_sampler.clear();
}
D3D11_PRIMITIVE_TOPOLOGY StateCache::GetPrimitiveTopology(PrimitiveType primitive)
{
static constexpr std::array<D3D11_PRIMITIVE_TOPOLOGY, 4> primitives = {
{D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, D3D11_PRIMITIVE_TOPOLOGY_LINELIST,
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP}};
return primitives[static_cast<u32>(primitive)];
}
} // namespace DX11

View File

@ -20,13 +20,6 @@ struct ID3D11RasterizerState;
namespace DX11
{
union RasterizerState
{
BitField<0, 2, D3D11_CULL_MODE> cull_mode;
u32 packed;
};
union SamplerState
{
BitField<0, 3, u64> min_filter;
@ -48,12 +41,15 @@ public:
// Returned objects is owned by the cache and does not need to be released.
ID3D11SamplerState* Get(SamplerState state);
ID3D11BlendState* Get(BlendingState state);
ID3D11RasterizerState* Get(RasterizerState state);
ID3D11RasterizerState* Get(RasterizationState state);
ID3D11DepthStencilState* Get(DepthState state);
// Release all cached states and clear hash tables.
void Clear();
// Convert RasterState primitive type to D3D11 primitive topology.
static D3D11_PRIMITIVE_TOPOLOGY GetPrimitiveTopology(PrimitiveType primitive);
private:
std::unordered_map<u32, ID3D11DepthStencilState*> m_depth;
std::unordered_map<u32, ID3D11RasterizerState*> m_raster;

View File

@ -207,7 +207,7 @@ void GeometryShaderCache::Shutdown()
g_gs_disk_cache.Close();
}
bool GeometryShaderCache::SetShader(u32 primitive_type)
bool GeometryShaderCache::SetShader(PrimitiveType primitive_type)
{
GeometryShaderUid uid = GetGeometryShaderUid(primitive_type);
if (last_entry && uid == last_uid)

View File

@ -18,7 +18,7 @@ public:
static void Reload();
static void Clear();
static void Shutdown();
static bool SetShader(u32 primitive_type);
static bool SetShader(PrimitiveType primitive_type);
static bool CompileShader(const GeometryShaderUid& uid);
static bool InsertByteCode(const GeometryShaderUid& uid, const u8* bytecode, size_t len);
static void PrecompileShaders();

View File

@ -61,7 +61,7 @@ struct GXPipelineState
std::array<SamplerState, 8> samplers;
BlendingState blend;
DepthState zmode;
RasterizerState raster;
RasterizationState raster;
};
static u32 s_last_multisamples = 1;
@ -254,8 +254,7 @@ Renderer::Renderer() : ::Renderer(D3D::GetBackBufferWidth(), D3D::GetBackBufferH
s_gx_state.zmode.testenable = false;
s_gx_state.zmode.updateenable = false;
s_gx_state.zmode.func = ZMode::NEVER;
s_gx_state.raster.cull_mode = D3D11_CULL_NONE;
s_gx_state.raster.cullmode = GenMode::CULL_NONE;
// Clear EFB textures
constexpr std::array<float, 4> clear_color{{0.f, 0.f, 0.f, 1.f}};
@ -867,6 +866,8 @@ void Renderer::ApplyState()
D3D::stateman->PushBlendState(s_gx_state_cache.Get(s_gx_state.blend));
D3D::stateman->PushDepthState(s_gx_state_cache.Get(s_gx_state.zmode));
D3D::stateman->PushRasterizerState(s_gx_state_cache.Get(s_gx_state.raster));
D3D::stateman->SetPrimitiveTopology(
StateCache::GetPrimitiveTopology(s_gx_state.raster.primitive));
FramebufferManager::SetIntegerEFBRenderTarget(s_gx_state.blend.logicopenable);
for (size_t stage = 0; stage < s_gx_state.samplers.size(); stage++)
@ -891,29 +892,9 @@ void Renderer::RestoreState()
D3D::stateman->PopRasterizerState();
}
void Renderer::ApplyCullDisable()
void Renderer::SetRasterizationState(const RasterizationState& state)
{
RasterizerState rast = s_gx_state.raster;
rast.cull_mode = D3D11_CULL_NONE;
ID3D11RasterizerState* raststate = s_gx_state_cache.Get(rast);
D3D::stateman->PushRasterizerState(raststate);
}
void Renderer::RestoreCull()
{
D3D::stateman->PopRasterizerState();
}
void Renderer::SetGenerationMode()
{
constexpr std::array<D3D11_CULL_MODE, 4> d3d_cull_modes{{
D3D11_CULL_NONE, D3D11_CULL_BACK, D3D11_CULL_FRONT, D3D11_CULL_BACK,
}};
// rastdc.FrontCounterClockwise must be false for this to work
// TODO: GX_CULL_ALL not supported, yet!
s_gx_state.raster.cull_mode = d3d_cull_modes[bpmem.genMode.cullmode];
s_gx_state.raster.hex = state.hex;
}
void Renderer::SetDepthState(const DepthState& state)

View File

@ -21,7 +21,7 @@ public:
void SetBlendingState(const BlendingState& state) override;
void SetScissorRect(const EFBRectangle& rc) override;
void SetGenerationMode() override;
void SetRasterizationState(const RasterizationState& state) override;
void SetDepthState(const DepthState& state) override;
void SetSamplerState(int stage, int texindex, bool custom_tex) override;
void SetInterlacingMode() override;
@ -33,9 +33,6 @@ public:
void ApplyState() override;
void RestoreState() override;
void ApplyCullDisable();
void RestoreCull();
void RenderText(const std::string& text, int left, int top, u32 color) override;
u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override;

View File

@ -127,28 +127,10 @@ void VertexManager::Draw(u32 stride)
u32 baseVertex = m_vertexDrawOffset / stride;
u32 startIndex = m_indexDrawOffset / sizeof(u16);
switch (m_current_primitive_type)
{
case PRIMITIVE_POINTS:
D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
static_cast<Renderer*>(g_renderer.get())->ApplyCullDisable();
break;
case PRIMITIVE_LINES:
D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
static_cast<Renderer*>(g_renderer.get())->ApplyCullDisable();
break;
case PRIMITIVE_TRIANGLES:
D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
break;
}
D3D::stateman->Apply();
D3D::context->DrawIndexed(indices, startIndex, baseVertex);
INCSTAT(stats.thisFrame.numDrawCalls);
if (m_current_primitive_type != PRIMITIVE_TRIANGLES)
static_cast<Renderer*>(g_renderer.get())->RestoreCull();
}
void VertexManager::vFlush()