VideoBackends: Add AbstractShader and AbstractPipeline classes

This commit is contained in:
Stenzek
2018-02-22 22:02:34 +10:00
parent 31111ef143
commit fec6bb4d56
47 changed files with 1825 additions and 33 deletions
@@ -13,6 +13,10 @@ set(SRCS
D3DTexture.h
D3DUtil.cpp
D3DUtil.h
DXPipeline.cpp
DXPipeline.h
DXShader.cpp
DXShader.h
DXTexture.cpp
DXTexture.h
FramebufferManager.cpp
@@ -43,6 +43,8 @@
<ClCompile Include="D3DState.cpp" />
<ClCompile Include="D3DTexture.cpp" />
<ClCompile Include="D3DUtil.cpp" />
<ClCompile Include="DXPipeline.cpp" />
<ClCompile Include="DXShader.cpp" />
<ClCompile Include="DXTexture.cpp" />
<ClCompile Include="FramebufferManager.cpp" />
<ClCompile Include="GeometryShaderCache.cpp" />
@@ -64,6 +66,8 @@
<ClInclude Include="D3DState.h" />
<ClInclude Include="D3DTexture.h" />
<ClInclude Include="D3DUtil.h" />
<ClInclude Include="DXPipeline.h" />
<ClInclude Include="DXShader.h" />
<ClInclude Include="DXTexture.h" />
<ClInclude Include="FramebufferManager.h" />
<ClInclude Include="GeometryShaderCache.h" />
@@ -64,6 +64,12 @@
<ClCompile Include="DXTexture.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="DXShader.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="DXPipeline.cpp">
<Filter>Render</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="D3DBase.h">
@@ -118,5 +124,11 @@
<ClInclude Include="DXTexture.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="DXShader.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="DXPipeline.h">
<Filter>Render</Filter>
</ClInclude>
</ItemGroup>
</Project>
@@ -0,0 +1,96 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <algorithm>
#include <cstring>
#include "Common/Assert.h"
#include "Common/Logging/Log.h"
#include "VideoBackends/D3D/D3DBase.h"
#include "VideoBackends/D3D/D3DState.h"
#include "VideoBackends/D3D/DXPipeline.h"
#include "VideoBackends/D3D/DXShader.h"
#include "VideoBackends/D3D/DXTexture.h"
#include "VideoBackends/D3D/Render.h"
#include "VideoBackends/D3D/VertexManager.h"
namespace DX11
{
DXPipeline::DXPipeline(ID3D11InputLayout* input_layout, ID3D11VertexShader* vertex_shader,
ID3D11GeometryShader* geometry_shader, ID3D11PixelShader* pixel_shader,
ID3D11RasterizerState* rasterizer_state,
ID3D11DepthStencilState* depth_state, ID3D11BlendState* blend_state,
D3D11_PRIMITIVE_TOPOLOGY primitive_topology)
: m_input_layout(input_layout), m_vertex_shader(vertex_shader),
m_geometry_shader(geometry_shader), m_pixel_shader(pixel_shader),
m_rasterizer_state(rasterizer_state), m_depth_state(depth_state), m_blend_state(blend_state),
m_primitive_topology(primitive_topology)
{
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();
}
std::unique_ptr<DXPipeline> DXPipeline::Create(const AbstractPipelineConfig& config)
{
StateCache& state_cache = static_cast<Renderer*>(g_renderer.get())->GetStateCache();
ID3D11RasterizerState* rasterizer_state = state_cache.Get(config.rasterization_state);
ID3D11DepthStencilState* depth_state = state_cache.Get(config.depth_state);
ID3D11BlendState* blend_state = state_cache.Get(config.blending_state);
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);
const DXShader* pixel_shader = static_cast<const DXShader*>(config.pixel_shader);
_assert_(vertex_shader != nullptr && pixel_shader != nullptr);
ID3D11InputLayout* input_layout =
const_cast<D3DVertexFormat*>(static_cast<const D3DVertexFormat*>(config.vertex_format))
->GetInputLayout(vertex_shader->GetByteCode());
return std::make_unique<DXPipeline>(input_layout, vertex_shader->GetD3DVertexShader(),
geometry_shader ? geometry_shader->GetD3DGeometryShader() :
nullptr,
pixel_shader->GetD3DPixelShader(), rasterizer_state,
depth_state, blend_state, primitive_topology);
}
} // namespace DX11
@@ -0,0 +1,43 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <d3d11.h>
#include <memory>
#include "VideoCommon/AbstractPipeline.h"
namespace DX11
{
class DXPipeline final : public AbstractPipeline
{
public:
DXPipeline(ID3D11InputLayout* input_layout, ID3D11VertexShader* vertex_shader,
ID3D11GeometryShader* geometry_shader, ID3D11PixelShader* pixel_shader,
ID3D11RasterizerState* rasterizer_state, ID3D11DepthStencilState* depth_state,
ID3D11BlendState* blend_state, D3D11_PRIMITIVE_TOPOLOGY primitive_topology);
~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; }
D3D11_PRIMITIVE_TOPOLOGY GetPrimitiveTopology() const { return m_primitive_topology; }
bool HasGeometryShader() const { return m_geometry_shader != nullptr; }
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;
D3D11_PRIMITIVE_TOPOLOGY m_primitive_topology;
};
} // namespace DX11
+183
View File
@@ -0,0 +1,183 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Common/Assert.h"
#include "VideoBackends/D3D/D3DBase.h"
#include "VideoBackends/D3D/D3DShader.h"
#include "VideoBackends/D3D/DXShader.h"
namespace DX11
{
DXShader::DXShader(D3DBlob* bytecode, ID3D11VertexShader* vs)
: AbstractShader(ShaderStage::Vertex), m_bytecode(bytecode), m_shader(vs)
{
}
DXShader::DXShader(D3DBlob* bytecode, ID3D11GeometryShader* gs)
: AbstractShader(ShaderStage::Geometry), m_bytecode(bytecode), m_shader(gs)
{
}
DXShader::DXShader(D3DBlob* bytecode, ID3D11PixelShader* ps)
: AbstractShader(ShaderStage::Pixel), m_bytecode(bytecode), m_shader(ps)
{
}
DXShader::DXShader(D3DBlob* bytecode, ID3D11ComputeShader* cs)
: AbstractShader(ShaderStage::Compute), m_bytecode(bytecode), m_shader(cs)
{
}
DXShader::~DXShader()
{
m_shader->Release();
m_bytecode->Release();
}
D3DBlob* DXShader::GetByteCode() const
{
return m_bytecode;
}
ID3D11VertexShader* DXShader::GetD3DVertexShader() const
{
_dbg_assert_(VIDEO, m_stage == ShaderStage::Vertex);
return static_cast<ID3D11VertexShader*>(m_shader);
}
ID3D11GeometryShader* DXShader::GetD3DGeometryShader() const
{
_dbg_assert_(VIDEO, m_stage == ShaderStage::Geometry);
return static_cast<ID3D11GeometryShader*>(m_shader);
}
ID3D11PixelShader* DXShader::GetD3DPixelShader() const
{
_dbg_assert_(VIDEO, m_stage == ShaderStage::Pixel);
return static_cast<ID3D11PixelShader*>(m_shader);
}
ID3D11ComputeShader* DXShader::GetD3DComputeShader() const
{
_dbg_assert_(VIDEO, m_stage == ShaderStage::Compute);
return static_cast<ID3D11ComputeShader*>(m_shader);
}
bool DXShader::HasBinary() const
{
_assert_(m_bytecode);
return true;
}
AbstractShader::BinaryData DXShader::GetBinary() const
{
return BinaryData(m_bytecode->Data(), m_bytecode->Data() + m_bytecode->Size());
}
std::unique_ptr<DXShader> DXShader::CreateFromBlob(ShaderStage stage, D3DBlob* bytecode)
{
switch (stage)
{
case ShaderStage::Vertex:
{
ID3D11VertexShader* vs = D3D::CreateVertexShaderFromByteCode(bytecode);
if (vs)
return std::make_unique<DXShader>(bytecode, vs);
}
break;
case ShaderStage::Geometry:
{
ID3D11GeometryShader* gs = D3D::CreateGeometryShaderFromByteCode(bytecode);
if (gs)
return std::make_unique<DXShader>(bytecode, gs);
}
break;
case ShaderStage::Pixel:
{
ID3D11PixelShader* ps = D3D::CreatePixelShaderFromByteCode(bytecode);
if (ps)
return std::make_unique<DXShader>(bytecode, ps);
}
break;
case ShaderStage::Compute:
{
ID3D11ComputeShader* cs = D3D::CreateComputeShaderFromByteCode(bytecode);
if (cs)
return std::make_unique<DXShader>(bytecode, cs);
}
break;
default:
break;
}
return nullptr;
}
std::unique_ptr<DXShader> DXShader::CreateFromSource(ShaderStage stage, const char* source,
size_t length)
{
D3DBlob* bytecode;
switch (stage)
{
case ShaderStage::Vertex:
{
if (!D3D::CompileVertexShader(std::string(source, length), &bytecode))
return nullptr;
}
break;
case ShaderStage::Geometry:
{
if (!D3D::CompileGeometryShader(std::string(source, length), &bytecode))
return nullptr;
}
break;
case ShaderStage::Pixel:
{
if (!D3D::CompilePixelShader(std::string(source, length), &bytecode))
return nullptr;
}
break;
case ShaderStage::Compute:
{
if (!D3D::CompileComputeShader(std::string(source, length), &bytecode))
return nullptr;
}
default:
return nullptr;
}
std::unique_ptr<DXShader> shader = CreateFromBlob(stage, bytecode);
if (!shader)
{
bytecode->Release();
return nullptr;
}
return shader;
}
std::unique_ptr<DXShader> DXShader::CreateFromBinary(ShaderStage stage, const void* data,
size_t length)
{
D3DBlob* bytecode = new D3DBlob(static_cast<unsigned int>(length), static_cast<const u8*>(data));
std::unique_ptr<DXShader> shader = CreateFromBlob(stage, bytecode);
if (!shader)
{
bytecode->Release();
return nullptr;
}
return shader;
}
} // namespace DX11
+48
View File
@@ -0,0 +1,48 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <cstddef>
#include <d3d11.h>
#include <memory>
#include "Common/CommonTypes.h"
#include "VideoBackends/D3D/D3DBlob.h"
#include "VideoCommon/AbstractShader.h"
namespace DX11
{
class DXShader final : public AbstractShader
{
public:
// Note: vs/gs/ps/cs references are transferred.
DXShader(D3DBlob* bytecode, ID3D11VertexShader* vs);
DXShader(D3DBlob* bytecode, ID3D11GeometryShader* gs);
DXShader(D3DBlob* bytecode, ID3D11PixelShader* ps);
DXShader(D3DBlob* bytecode, ID3D11ComputeShader* cs);
~DXShader() override;
D3DBlob* GetByteCode() const;
ID3D11VertexShader* GetD3DVertexShader() const;
ID3D11GeometryShader* GetD3DGeometryShader() const;
ID3D11PixelShader* GetD3DPixelShader() const;
ID3D11ComputeShader* GetD3DComputeShader() const;
bool HasBinary() const override;
BinaryData GetBinary() const override;
// Creates a new shader object. The reference to bytecode is not transfered upon failure.
static std::unique_ptr<DXShader> CreateFromBlob(ShaderStage stage, D3DBlob* bytecode);
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;
D3DBlob* m_bytecode;
};
} // namespace DX11
@@ -119,20 +119,20 @@ D3DVertexFormat::~D3DVertexFormat()
SAFE_RELEASE(m_layout);
}
void D3DVertexFormat::SetInputLayout(D3DBlob* vs_bytecode)
ID3D11InputLayout* D3DVertexFormat::GetInputLayout(D3DBlob* vs_bytecode)
{
if (!m_layout)
{
// CreateInputLayout requires a shader input, but it only looks at the
// signature of the shader, so we don't need to recompute it if the shader
// changes.
HRESULT hr = DX11::D3D::device->CreateInputLayout(
m_elems.data(), m_num_elems, vs_bytecode->Data(), vs_bytecode->Size(), &m_layout);
if (FAILED(hr))
PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__);
DX11::D3D::SetDebugObjectName(m_layout, "input layout used to emulate the GX pipeline");
}
DX11::D3D::stateman->SetInputLayout(m_layout);
if (m_layout)
return m_layout;
// CreateInputLayout requires a shader input, but it only looks at the
// signature of the shader, so we don't need to recompute it if the shader
// changes.
HRESULT hr = DX11::D3D::device->CreateInputLayout(
m_elems.data(), m_num_elems, vs_bytecode->Data(), vs_bytecode->Size(), &m_layout);
if (FAILED(hr))
PanicAlert("Failed to create input layout, %s %d\n", __FILE__, __LINE__);
DX11::D3D::SetDebugObjectName(m_layout, "input layout used to emulate the GX pipeline");
return m_layout;
}
} // namespace DX11
+124
View File
@@ -13,6 +13,7 @@
#include <strsafe.h>
#include <tuple>
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Common/MathUtil.h"
@@ -23,6 +24,8 @@
#include "VideoBackends/D3D/D3DBase.h"
#include "VideoBackends/D3D/D3DState.h"
#include "VideoBackends/D3D/D3DUtil.h"
#include "VideoBackends/D3D/DXPipeline.h"
#include "VideoBackends/D3D/DXShader.h"
#include "VideoBackends/D3D/DXTexture.h"
#include "VideoBackends/D3D/FramebufferManager.h"
#include "VideoBackends/D3D/GeometryShaderCache.h"
@@ -41,6 +44,12 @@
namespace DX11
{
// Reserve 512KB for vertices, and 64KB for uniforms.
// This should be sufficient for our usages, and if more is required,
// we split it into multiple draws.
constexpr u32 UTILITY_VBO_SIZE = 512 * 1024;
constexpr u32 UTILITY_UBO_SIZE = 64 * 1024;
// Nvidia stereo blitting struct defined in "nvstereo.h" from the Nvidia SDK
typedef struct _Nv_Stereo_Image_Header
{
@@ -165,6 +174,16 @@ void Renderer::SetupDeviceObjects()
D3D::SetDebugObjectName(m_reset_rast_state, "rasterizer state for Renderer::ResetAPIState");
m_screenshot_texture = nullptr;
CD3D11_BUFFER_DESC vbo_desc(UTILITY_VBO_SIZE, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC,
D3D11_CPU_ACCESS_WRITE);
hr = D3D::device->CreateBuffer(&vbo_desc, nullptr, &m_utility_vertex_buffer);
CHECK(SUCCEEDED(hr), "Create utility VBO");
CD3D11_BUFFER_DESC ubo_desc(UTILITY_UBO_SIZE, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC,
D3D11_CPU_ACCESS_WRITE);
hr = D3D::device->CreateBuffer(&ubo_desc, nullptr, &m_utility_uniform_buffer);
CHECK(SUCCEEDED(hr), "Create utility UBO");
}
// Kill off all device objects
@@ -184,6 +203,8 @@ void Renderer::TeardownDeviceObjects()
SAFE_RELEASE(m_reset_rast_state);
SAFE_RELEASE(m_screenshot_texture);
SAFE_RELEASE(m_3d_vision_texture);
SAFE_RELEASE(m_utility_vertex_buffer);
SAFE_RELEASE(m_utility_uniform_buffer);
}
void Renderer::Create3DVisionTexture(int width, int height)
@@ -229,6 +250,109 @@ void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
D3D::DrawTextScaled(static_cast<float>(left), static_cast<float>(top), 20.f, 0.0f, color, text);
}
std::unique_ptr<AbstractShader> Renderer::CreateShaderFromSource(ShaderStage stage,
const char* source, size_t length)
{
return DXShader::CreateFromSource(stage, source, length);
}
std::unique_ptr<AbstractShader> Renderer::CreateShaderFromBinary(ShaderStage stage,
const void* data, size_t length)
{
return DXShader::CreateFromBinary(stage, data, length);
}
std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config)
{
return DXPipeline::Create(config);
}
void Renderer::UpdateUtilityUniformBuffer(const void* uniforms, u32 uniforms_size)
{
_dbg_assert_(VIDEO, uniforms_size > 0 && uniforms_size < UTILITY_UBO_SIZE);
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = D3D::context->Map(m_utility_uniform_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
CHECK(SUCCEEDED(hr), "Map utility UBO");
std::memcpy(mapped.pData, uniforms, uniforms_size);
D3D::context->Unmap(m_utility_uniform_buffer, 0);
}
void Renderer::UpdateUtilityVertexBuffer(const void* vertices, u32 vertex_stride, u32 num_vertices)
{
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = D3D::context->Map(m_utility_vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
CHECK(SUCCEEDED(hr), "Map utility VBO");
std::memcpy(mapped.pData, vertices, num_vertices * vertex_stride);
D3D::context->Unmap(m_utility_vertex_buffer, 0);
}
void Renderer::SetPipeline(const AbstractPipeline* pipeline)
{
const DXPipeline* dx_pipeline = static_cast<const DXPipeline*>(pipeline);
D3D::stateman->SetRasterizerState(dx_pipeline->GetRasterizerState());
D3D::stateman->SetDepthState(dx_pipeline->GetDepthState());
D3D::stateman->SetBlendState(dx_pipeline->GetBlendState());
D3D::stateman->SetPrimitiveTopology(dx_pipeline->GetPrimitiveTopology());
D3D::stateman->SetInputLayout(dx_pipeline->GetInputLayout());
D3D::stateman->SetVertexShader(dx_pipeline->GetVertexShader());
D3D::stateman->SetGeometryShader(dx_pipeline->GetGeometryShader());
D3D::stateman->SetPixelShader(dx_pipeline->GetPixelShader());
}
void Renderer::DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
u32 vertex_stride, u32 num_vertices)
{
// Textures are fine, they're set directly via SetTexture.
// Since samplers are set via gx_state, we need to fix this up here.
for (size_t stage = 0; stage < m_gx_state.samplers.size(); stage++)
D3D::stateman->SetSampler(stage, m_state_cache.Get(m_gx_state.samplers[stage]));
// Copy in uniforms.
if (uniforms_size > 0)
{
UpdateUtilityUniformBuffer(uniforms, uniforms_size);
D3D::stateman->SetVertexConstants(m_utility_uniform_buffer);
D3D::stateman->SetPixelConstants(m_utility_uniform_buffer);
D3D::stateman->SetGeometryConstants(m_utility_uniform_buffer);
}
// If the vertices are larger than our buffer, we need to break it up into multiple draws.
const char* vertices_ptr = static_cast<const char*>(vertices);
while (num_vertices > 0)
{
u32 vertices_this_draw = num_vertices;
if (vertices_ptr)
{
vertices_this_draw = std::min(vertices_this_draw, UTILITY_VBO_SIZE / vertex_stride);
_dbg_assert_(VIDEO, vertices_this_draw > 0);
UpdateUtilityVertexBuffer(vertices_ptr, vertex_stride, vertices_this_draw);
D3D::stateman->SetVertexBuffer(m_utility_vertex_buffer, vertex_stride, 0);
}
// Apply pending state and draw.
D3D::stateman->Apply();
D3D::context->Draw(vertices_this_draw, 0);
vertices_ptr += vertex_stride * vertices_this_draw;
num_vertices -= vertices_this_draw;
}
}
void Renderer::DispatchComputeShader(const AbstractShader* shader, const void* uniforms,
u32 uniforms_size, u32 groups_x, u32 groups_y, u32 groups_z)
{
D3D::stateman->SetComputeShader(static_cast<const DXShader*>(shader)->GetD3DComputeShader());
if (uniforms_size > 0)
{
UpdateUtilityUniformBuffer(uniforms, uniforms_size);
D3D::stateman->SetComputeConstants(m_utility_uniform_buffer);
}
D3D::stateman->Apply();
D3D::context->Dispatch(groups_x, groups_y, groups_z);
}
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
{
TargetRectangle result;
+18
View File
@@ -5,6 +5,7 @@
#pragma once
#include <array>
#include <d3d11.h>
#include <string>
#include "VideoBackends/D3D/D3DState.h"
#include "VideoCommon/RenderBase.h"
@@ -25,7 +26,13 @@ public:
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
size_t length) override;
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
void SetPipeline(const AbstractPipeline* pipeline) override;
void SetBlendingState(const BlendingState& state) override;
void SetScissorRect(const MathUtil::Rectangle<int>& rc) override;
void SetRasterizationState(const RasterizationState& state) override;
@@ -63,6 +70,11 @@ public:
void ReinterpretPixelData(unsigned int convtype) override;
void DrawUtilityPipeline(const void* uniforms, u32 uniforms_size, const void* vertices,
u32 vertex_stride, u32 num_vertices) override;
void DispatchComputeShader(const AbstractShader* shader, const void* uniforms, u32 uniforms_size,
u32 groups_x, u32 groups_y, u32 groups_z) override;
private:
struct GXPipelineState
{
@@ -82,6 +94,9 @@ private:
void BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D* src_texture,
u32 src_width, u32 src_height, float Gamma);
void UpdateUtilityUniformBuffer(const void* uniforms, u32 uniforms_size);
void UpdateUtilityVertexBuffer(const void* vertices, u32 vertex_stride, u32 num_vertices);
StateCache m_state_cache;
GXPipelineState m_gx_state;
@@ -94,6 +109,9 @@ private:
ID3D11Texture2D* m_screenshot_texture = nullptr;
D3DTexture2D* m_3d_vision_texture = nullptr;
ID3D11Buffer* m_utility_vertex_buffer = nullptr;
ID3D11Buffer* m_utility_uniform_buffer = nullptr;
u32 m_last_multisamples = 1;
bool m_last_stereo_mode = false;
bool m_last_fullscreen_state = false;
@@ -23,7 +23,7 @@ class D3DVertexFormat : public NativeVertexFormat
public:
D3DVertexFormat(const PortableVertexDeclaration& vtx_decl);
~D3DVertexFormat();
void SetInputLayout(D3DBlob* vs_bytecode);
ID3D11InputLayout* GetInputLayout(D3DBlob* vs_bytecode);
private:
std::array<D3D11_INPUT_ELEMENT_DESC, 32> m_elems{};
@@ -260,7 +260,7 @@ bool VertexShaderCache::SetShader(D3DVertexFormat* vertex_format)
if (!last_entry->shader)
return false;
vertex_format->SetInputLayout(last_entry->bytecode);
D3D::stateman->SetInputLayout(vertex_format->GetInputLayout(last_entry->bytecode));
D3D::stateman->SetVertexShader(last_entry->shader);
return true;
}
@@ -279,7 +279,7 @@ bool VertexShaderCache::SetShader(D3DVertexFormat* vertex_format)
if (!last_entry->shader)
return false;
vertex_format->SetInputLayout(last_entry->bytecode);
D3D::stateman->SetInputLayout(vertex_format->GetInputLayout(last_entry->bytecode));
D3D::stateman->SetVertexShader(last_entry->shader);
return true;
}
@@ -324,7 +324,7 @@ bool VertexShaderCache::SetUberShader(D3DVertexFormat* vertex_format)
if (!last_uber_entry->shader)
return false;
uber_vertex_format->SetInputLayout(last_uber_entry->bytecode);
D3D::stateman->SetInputLayout(uber_vertex_format->GetInputLayout(last_uber_entry->bytecode));
D3D::stateman->SetVertexShader(last_uber_entry->shader);
return true;
}
@@ -340,7 +340,7 @@ bool VertexShaderCache::SetUberShader(D3DVertexFormat* vertex_format)
if (!last_uber_entry->shader)
return false;
uber_vertex_format->SetInputLayout(last_uber_entry->bytecode);
D3D::stateman->SetInputLayout(uber_vertex_format->GetInputLayout(last_uber_entry->bytecode));
D3D::stateman->SetVertexShader(last_uber_entry->shader);
return true;
}
+36
View File
@@ -7,6 +7,8 @@
#include "VideoBackends/Null/NullTexture.h"
#include "VideoBackends/Null/Render.h"
#include "VideoCommon/AbstractPipeline.h"
#include "VideoCommon/AbstractShader.h"
#include "VideoCommon/VideoConfig.h"
namespace Null
@@ -33,6 +35,40 @@ std::unique_ptr<AbstractStagingTexture> Renderer::CreateStagingTexture(StagingTe
return std::make_unique<NullStagingTexture>(type, config);
}
class NullShader final : public AbstractShader
{
public:
explicit NullShader(ShaderStage stage) : AbstractShader(stage) {}
~NullShader() = default;
bool HasBinary() const override { return false; }
BinaryData GetBinary() const override { return {}; }
};
std::unique_ptr<AbstractShader> Renderer::CreateShaderFromSource(ShaderStage stage,
const char* source, size_t length)
{
return std::make_unique<NullShader>(stage);
}
std::unique_ptr<AbstractShader> Renderer::CreateShaderFromBinary(ShaderStage stage,
const void* data, size_t length)
{
return std::make_unique<NullShader>(stage);
}
class NullPipeline final : public AbstractPipeline
{
public:
NullPipeline() : AbstractPipeline() {}
~NullPipeline() override = default;
};
std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config)
{
return std::make_unique<NullPipeline>();
}
void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
{
NOTICE_LOG(VIDEO, "RenderText: %s", text.c_str());
+6
View File
@@ -18,6 +18,12 @@ public:
std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;
std::unique_ptr<AbstractShader> CreateShaderFromSource(ShaderStage stage, const char* source,
size_t length) override;
std::unique_ptr<AbstractShader> CreateShaderFromBinary(ShaderStage stage, const void* data,
size_t length) override;
std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config) override;
void RenderText(const std::string& pstr, int left, int top, u32 color) override;
u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override { return 0; }
void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override {}
@@ -3,6 +3,8 @@ set(SRCS
FramebufferManager.cpp
main.cpp
NativeVertexFormat.cpp
OGLPipeline.cpp
OGLShader.cpp
OGLTexture.cpp
PerfQuery.cpp
PostProcessing.cpp
@@ -36,6 +36,8 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemGroup>
<ClCompile Include="OGLPipeline.cpp" />
<ClCompile Include="OGLShader.cpp" />
<ClCompile Include="OGLTexture.cpp" />
<ClCompile Include="BoundingBox.cpp" />
<ClCompile Include="FramebufferManager.cpp" />
@@ -53,6 +55,8 @@
<ClCompile Include="VertexManager.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="OGLPipeline.h" />
<ClInclude Include="OGLShader.h" />
<ClInclude Include="OGLTexture.h" />
<ClInclude Include="BoundingBox.h" />
<ClInclude Include="FramebufferManager.h" />
@@ -56,6 +56,12 @@
<ClCompile Include="OGLTexture.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="OGLShader.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="OGLPipeline.cpp">
<Filter>Render</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="VertexManager.h">
@@ -99,6 +105,12 @@
<ClInclude Include="OGLTexture.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="OGLShader.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="OGLPipeline.h">
<Filter>Render</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />
@@ -0,0 +1,62 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Common/Assert.h"
#include "VideoBackends/OGL/OGLPipeline.h"
#include "VideoBackends/OGL/OGLShader.h"
#include "VideoBackends/OGL/ProgramShaderCache.h"
#include "VideoBackends/OGL/Render.h"
#include "VideoBackends/OGL/VertexManager.h"
namespace OGL
{
static GLenum MapToGLPrimitive(PrimitiveType primitive_type)
{
switch (primitive_type)
{
case PrimitiveType::Points:
return GL_POINTS;
case PrimitiveType::Lines:
return GL_LINES;
case PrimitiveType::Triangles:
return GL_TRIANGLES;
case PrimitiveType::TriangleStrip:
return GL_TRIANGLE_STRIP;
default:
return 0;
}
}
OGLPipeline::OGLPipeline(const GLVertexFormat* vertex_format,
const RasterizationState& rasterization_state,
const DepthState& depth_state, const BlendingState& blending_state,
const PipelineProgram* program, GLuint gl_primitive)
: m_vertex_format(vertex_format), m_rasterization_state(rasterization_state),
m_depth_state(depth_state), m_blending_state(blending_state), m_program(program),
m_gl_primitive(gl_primitive)
{
}
OGLPipeline::~OGLPipeline()
{
// We don't want to destroy the shaders.
ProgramShaderCache::ReleasePipelineProgram(m_program);
}
std::unique_ptr<OGLPipeline> OGLPipeline::Create(const AbstractPipelineConfig& config)
{
const PipelineProgram* program =
ProgramShaderCache::GetPipelineProgram(static_cast<const OGLShader*>(config.vertex_shader),
static_cast<const OGLShader*>(config.geometry_shader),
static_cast<const OGLShader*>(config.pixel_shader));
if (!program)
return nullptr;
const GLVertexFormat* vertex_format = static_cast<const GLVertexFormat*>(config.vertex_format);
GLenum gl_primitive = MapToGLPrimitive(config.rasterization_state.primitive);
return std::make_unique<OGLPipeline>(vertex_format, config.rasterization_state,
config.depth_state, config.blending_state, program,
gl_primitive);
}
} // namespace OGL
@@ -0,0 +1,43 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include "Common/GL/GLUtil.h"
#include "VideoBackends/OGL/ProgramShaderCache.h"
#include "VideoCommon/AbstractPipeline.h"
#include "VideoCommon/RenderState.h"
namespace OGL
{
class OGLPipeline final : public AbstractPipeline
{
public:
explicit OGLPipeline(const GLVertexFormat* vertex_format,
const RasterizationState& rasterization_state, const DepthState& depth_state,
const BlendingState& blending_state, const PipelineProgram* program,
GLenum gl_primitive);
~OGLPipeline() override;
const GLVertexFormat* GetVertexFormat() const { return m_vertex_format; }
const RasterizationState& GetRasterizationState() const { return m_rasterization_state; }
const DepthState& GetDepthState() const { return m_depth_state; }
const BlendingState& GetBlendingState() const { return m_blending_state; }
const PipelineProgram* GetProgram() const { return m_program; }
bool HasVertexInput() const { return m_vertex_format != nullptr; }
GLenum GetGLPrimitive() const { return m_gl_primitive; }
static std::unique_ptr<OGLPipeline> Create(const AbstractPipelineConfig& config);
private:
const GLVertexFormat* m_vertex_format;
RasterizationState m_rasterization_state;
DepthState m_depth_state;
BlendingState m_blending_state;
const PipelineProgram* m_program;
GLenum m_gl_primitive;
};
} // namespace OGL
@@ -0,0 +1,77 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "VideoBackends/OGL/OGLShader.h"
#include "VideoBackends/OGL/ProgramShaderCache.h"
namespace OGL
{
static GLenum GetGLShaderTypeForStage(ShaderStage stage)
{
switch (stage)
{
case ShaderStage::Vertex:
return GL_VERTEX_SHADER;
case ShaderStage::Geometry:
return GL_GEOMETRY_SHADER;
case ShaderStage::Pixel:
return GL_FRAGMENT_SHADER;
case ShaderStage::Compute:
return GL_COMPUTE_SHADER;
default:
return 0;
}
}
OGLShader::OGLShader(ShaderStage stage, GLenum gl_type, GLuint shader_id)
: AbstractShader(stage), m_type(gl_type), m_id(shader_id)
{
}
OGLShader::OGLShader(GLuint compute_program_id)
: AbstractShader(ShaderStage::Compute), m_type(GL_COMPUTE_SHADER), m_id(compute_program_id)
{
}
OGLShader::~OGLShader()
{
if (m_stage != ShaderStage::Compute)
glDeleteShader(m_id);
else
glDeleteProgram(m_compute_program_id);
}
bool OGLShader::HasBinary() const
{
// NOTE: GL shaders do not have binaries, programs do.
return false;
}
AbstractShader::BinaryData OGLShader::GetBinary() const
{
return {};
}
std::unique_ptr<OGLShader> OGLShader::CreateFromSource(ShaderStage stage, const char* source,
size_t length)
{
if (stage != ShaderStage::Compute)
{
GLenum shader_type = GetGLShaderTypeForStage(stage);
GLuint shader_id =
ProgramShaderCache::CompileSingleShader(shader_type, std::string(source, length));
if (!shader_id)
return nullptr;
return std::make_unique<OGLShader>(stage, shader_type, shader_id);
}
// Compute shaders.
SHADER prog;
if (!ProgramShaderCache::CompileComputeShader(prog, std::string(source, length)))
return nullptr;
return std::make_unique<OGLShader>(prog.glprogid);
}
} // namespace OGL

Some files were not shown because too many files have changed in this diff Show More