Shader/pipeline abstraction
This commit is contained in:
parent
9b967e3751
commit
dbf31ff75d
|
@ -37,6 +37,8 @@
|
||||||
<ClCompile Include="gpu\d3d11\shader_compiler.cpp" />
|
<ClCompile Include="gpu\d3d11\shader_compiler.cpp" />
|
||||||
<ClCompile Include="gpu\d3d11\stream_buffer.cpp" />
|
<ClCompile Include="gpu\d3d11\stream_buffer.cpp" />
|
||||||
<ClCompile Include="gpu\d3d11_device.cpp" />
|
<ClCompile Include="gpu\d3d11_device.cpp" />
|
||||||
|
<ClCompile Include="gpu\d3d11_pipeline.cpp" />
|
||||||
|
<ClCompile Include="gpu\d3d11_shader.cpp" />
|
||||||
<ClCompile Include="gpu\d3d11_texture.cpp" />
|
<ClCompile Include="gpu\d3d11_texture.cpp" />
|
||||||
<ClCompile Include="gpu\d3d12\context.cpp" />
|
<ClCompile Include="gpu\d3d12\context.cpp" />
|
||||||
<ClCompile Include="gpu\d3d12\descriptor_heap_manager.cpp" />
|
<ClCompile Include="gpu\d3d12\descriptor_heap_manager.cpp" />
|
||||||
|
@ -161,6 +163,8 @@
|
||||||
<ClInclude Include="gpu\d3d11\shader_compiler.h" />
|
<ClInclude Include="gpu\d3d11\shader_compiler.h" />
|
||||||
<ClInclude Include="gpu\d3d11\stream_buffer.h" />
|
<ClInclude Include="gpu\d3d11\stream_buffer.h" />
|
||||||
<ClInclude Include="gpu\d3d11_device.h" />
|
<ClInclude Include="gpu\d3d11_device.h" />
|
||||||
|
<ClInclude Include="gpu\d3d11_pipeline.h" />
|
||||||
|
<ClInclude Include="gpu\d3d11_shader.h" />
|
||||||
<ClInclude Include="gpu\d3d_shaders.h" />
|
<ClInclude Include="gpu\d3d_shaders.h" />
|
||||||
<ClInclude Include="gpu\d3d11_texture.h" />
|
<ClInclude Include="gpu\d3d11_texture.h" />
|
||||||
<ClInclude Include="gpu\d3d12\context.h" />
|
<ClInclude Include="gpu\d3d12\context.h" />
|
||||||
|
@ -197,6 +201,8 @@
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="gpu\gpu_device.h" />
|
<ClInclude Include="gpu\gpu_device.h" />
|
||||||
|
<ClInclude Include="gpu\gpu_pipeline.h" />
|
||||||
|
<ClInclude Include="gpu\gpu_shader.h" />
|
||||||
<ClInclude Include="gpu\gpu_texture.h" />
|
<ClInclude Include="gpu\gpu_texture.h" />
|
||||||
<ClInclude Include="gpu\imgui_impl_dx12.h" />
|
<ClInclude Include="gpu\imgui_impl_dx12.h" />
|
||||||
<ClInclude Include="gpu\imgui_impl_opengl3.h" />
|
<ClInclude Include="gpu\imgui_impl_opengl3.h" />
|
||||||
|
|
|
@ -188,6 +188,12 @@
|
||||||
<ClCompile Include="gpu\d3d11_texture.cpp">
|
<ClCompile Include="gpu\d3d11_texture.cpp">
|
||||||
<Filter>gpu</Filter>
|
<Filter>gpu</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="gpu\d3d11_shader.cpp">
|
||||||
|
<Filter>gpu</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="gpu\d3d11_pipeline.cpp">
|
||||||
|
<Filter>gpu</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="types.h" />
|
<ClInclude Include="types.h" />
|
||||||
|
@ -395,6 +401,18 @@
|
||||||
<ClInclude Include="gpu\d3d_shaders.h">
|
<ClInclude Include="gpu\d3d_shaders.h">
|
||||||
<Filter>gpu</Filter>
|
<Filter>gpu</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="gpu\gpu_pipeline.h">
|
||||||
|
<Filter>gpu</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="gpu\gpu_shader.h">
|
||||||
|
<Filter>gpu</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="gpu\d3d11_shader.h">
|
||||||
|
<Filter>gpu</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="gpu\d3d11_pipeline.h">
|
||||||
|
<Filter>gpu</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="gpu">
|
<Filter Include="gpu">
|
||||||
|
|
|
@ -8,15 +8,20 @@
|
||||||
#include "d3d11/stream_buffer.h"
|
#include "d3d11/stream_buffer.h"
|
||||||
#include "d3d11_texture.h"
|
#include "d3d11_texture.h"
|
||||||
#include "gpu_device.h"
|
#include "gpu_device.h"
|
||||||
|
#include "gpu_pipeline.h"
|
||||||
#include "postprocessing_chain.h"
|
#include "postprocessing_chain.h"
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
#include <dxgi.h>
|
#include <dxgi.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <wrl/client.h>
|
#include <wrl/client.h>
|
||||||
|
|
||||||
|
class D3D11Pipeline;
|
||||||
|
class D3D11Shader;
|
||||||
|
|
||||||
class D3D11Device final : public GPUDevice
|
class D3D11Device final : public GPUDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -65,6 +70,11 @@ public:
|
||||||
void ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src,
|
void ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src,
|
||||||
u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height) override;
|
u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height) override;
|
||||||
|
|
||||||
|
std::unique_ptr<GPUShader> CreateShaderFromBinary(GPUShader::Stage stage, gsl::span<const u8> data) override;
|
||||||
|
std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShader::Stage stage, const std::string_view& source,
|
||||||
|
std::vector<u8>* out_binary = nullptr) override;
|
||||||
|
std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config) override;
|
||||||
|
|
||||||
bool GetHostRefreshRate(float* refresh_rate) override;
|
bool GetHostRefreshRate(float* refresh_rate) override;
|
||||||
|
|
||||||
bool SetGPUTimingEnabled(bool enabled) override;
|
bool SetGPUTimingEnabled(bool enabled) override;
|
||||||
|
@ -78,7 +88,12 @@ public:
|
||||||
|
|
||||||
static AdapterAndModeList StaticGetAdapterAndModeList();
|
static AdapterAndModeList StaticGetAdapterAndModeList();
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
|
using RasterizationStateMap = std::unordered_map<u8, ComPtr<ID3D11RasterizerState>>;
|
||||||
|
using DepthStateMap = std::unordered_map<u8, ComPtr<ID3D11DepthStencilState>>;
|
||||||
|
using BlendStateMap = std::unordered_map<u32, ComPtr<ID3D11BlendState>>;
|
||||||
|
using InputLayoutMap = std::unordered_map<GPUPipeline::InputLayout, ComPtr<ID3D11InputLayout>, GPUPipeline::InputLayoutHash>;
|
||||||
|
|
||||||
static constexpr u32 DISPLAY_UNIFORM_BUFFER_SIZE = 64;
|
static constexpr u32 DISPLAY_UNIFORM_BUFFER_SIZE = 64;
|
||||||
static constexpr u32 IMGUI_VERTEX_BUFFER_SIZE = 4 * 1024 * 1024;
|
static constexpr u32 IMGUI_VERTEX_BUFFER_SIZE = 4 * 1024 * 1024;
|
||||||
static constexpr u32 IMGUI_INDEX_BUFFER_SIZE = 2 * 1024 * 1024;
|
static constexpr u32 IMGUI_INDEX_BUFFER_SIZE = 2 * 1024 * 1024;
|
||||||
|
@ -98,6 +113,11 @@ protected:
|
||||||
bool CreateSwapChain(const DXGI_MODE_DESC* fullscreen_mode);
|
bool CreateSwapChain(const DXGI_MODE_DESC* fullscreen_mode);
|
||||||
bool CreateSwapChainRTV();
|
bool CreateSwapChainRTV();
|
||||||
|
|
||||||
|
ComPtr<ID3D11RasterizerState> GetRasterizationState(const GPUPipeline::RasterizationState& rs);
|
||||||
|
ComPtr<ID3D11DepthStencilState> GetDepthState(const GPUPipeline::DepthState& ds);
|
||||||
|
ComPtr<ID3D11BlendState> GetBlendState(const GPUPipeline::BlendState& bs);
|
||||||
|
ComPtr<ID3D11InputLayout> GetInputLayout(const GPUPipeline::InputLayout& il, const D3D11Shader* vs);
|
||||||
|
|
||||||
void RenderDisplay();
|
void RenderDisplay();
|
||||||
void RenderSoftwareCursor();
|
void RenderSoftwareCursor();
|
||||||
void RenderImGui();
|
void RenderImGui();
|
||||||
|
@ -142,6 +162,11 @@ protected:
|
||||||
ComPtr<ID3D11SamplerState> m_linear_sampler;
|
ComPtr<ID3D11SamplerState> m_linear_sampler;
|
||||||
ComPtr<ID3D11SamplerState> m_border_sampler;
|
ComPtr<ID3D11SamplerState> m_border_sampler;
|
||||||
|
|
||||||
|
RasterizationStateMap m_rasterization_states;
|
||||||
|
DepthStateMap m_depth_states;
|
||||||
|
BlendStateMap m_blend_states;
|
||||||
|
InputLayoutMap m_input_layouts;
|
||||||
|
|
||||||
D3D11::StreamBuffer m_display_uniform_buffer;
|
D3D11::StreamBuffer m_display_uniform_buffer;
|
||||||
ComPtr<ID3D11Texture2D> m_readback_staging_texture;
|
ComPtr<ID3D11Texture2D> m_readback_staging_texture;
|
||||||
DXGI_FORMAT m_readback_staging_texture_format = DXGI_FORMAT_UNKNOWN;
|
DXGI_FORMAT m_readback_staging_texture_format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
|
|
@ -0,0 +1,242 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>
|
||||||
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
|
#include "d3d11_pipeline.h"
|
||||||
|
#include "d3d11_device.h"
|
||||||
|
#include "d3d11_shader.h"
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/log.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
Log_SetChannel(D3D11Device);
|
||||||
|
|
||||||
|
D3D11Pipeline::D3D11Pipeline(ComPtr<ID3D11RasterizerState> rs, ComPtr<ID3D11DepthStencilState> ds,
|
||||||
|
ComPtr<ID3D11BlendState> bs, ComPtr<ID3D11InputLayout> il, ComPtr<ID3D11VertexShader> vs,
|
||||||
|
ComPtr<ID3D11PixelShader> ps, D3D11_PRIMITIVE_TOPOLOGY topology)
|
||||||
|
: m_rs(std::move(rs)), m_ds(std::move(ds)), m_bs(std::move(bs)), m_il(std::move(il)), m_vs(std::move(vs)),
|
||||||
|
m_ps(std::move(ps)), m_topology(topology)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11Pipeline::~D3D11Pipeline() = default;
|
||||||
|
|
||||||
|
void D3D11Pipeline::SetDebugName(const std::string_view& name)
|
||||||
|
{
|
||||||
|
UnreachableCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D11Pipeline::Bind(ID3D11DeviceContext* context)
|
||||||
|
{
|
||||||
|
context->IASetInputLayout(GetInputLayout());
|
||||||
|
context->IASetPrimitiveTopology(GetPrimitiveTopology());
|
||||||
|
context->RSSetState(GetRasterizerState());
|
||||||
|
context->OMSetDepthStencilState(GetDepthStencilState(), 0);
|
||||||
|
context->OMSetBlendState(GetBlendState(), nullptr, 0xFFFFFFFFu);
|
||||||
|
context->VSSetShader(GetVertexShader(), nullptr, 0);
|
||||||
|
context->PSSetShader(GetPixelShader(), nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11Device::ComPtr<ID3D11RasterizerState> D3D11Device::GetRasterizationState(const GPUPipeline::RasterizationState& rs)
|
||||||
|
{
|
||||||
|
ComPtr<ID3D11RasterizerState> drs;
|
||||||
|
|
||||||
|
const auto it = m_rasterization_states.find(rs.key);
|
||||||
|
if (it != m_rasterization_states.end())
|
||||||
|
{
|
||||||
|
drs = it->second;
|
||||||
|
return drs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr std::array<D3D11_CULL_MODE, static_cast<u32>(GPUPipeline::CullMode::MaxCount)> cull_mapping = {{
|
||||||
|
D3D11_CULL_NONE, // None
|
||||||
|
D3D11_CULL_FRONT, // Front
|
||||||
|
D3D11_CULL_BACK, // Back
|
||||||
|
}};
|
||||||
|
|
||||||
|
D3D11_RASTERIZER_DESC desc = {};
|
||||||
|
desc.FillMode = D3D11_FILL_SOLID;
|
||||||
|
desc.CullMode = cull_mapping[static_cast<u8>(rs.cull_mode.GetValue())];
|
||||||
|
desc.ScissorEnable = TRUE;
|
||||||
|
// desc.MultisampleEnable ???
|
||||||
|
|
||||||
|
HRESULT hr = m_device->CreateRasterizerState(&desc, drs.GetAddressOf());
|
||||||
|
if (FAILED(hr))
|
||||||
|
Log_ErrorPrintf("Failed to create depth state with %08X", hr);
|
||||||
|
|
||||||
|
m_rasterization_states.emplace(rs.key, drs);
|
||||||
|
return drs;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11Device::ComPtr<ID3D11DepthStencilState> D3D11Device::GetDepthState(const GPUPipeline::DepthState& ds)
|
||||||
|
{
|
||||||
|
ComPtr<ID3D11DepthStencilState> dds;
|
||||||
|
|
||||||
|
const auto it = m_depth_states.find(ds.key);
|
||||||
|
if (it != m_depth_states.end())
|
||||||
|
{
|
||||||
|
dds = it->second;
|
||||||
|
return dds;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr std::array<D3D11_COMPARISON_FUNC, static_cast<u32>(GPUPipeline::DepthFunc::MaxCount)> func_mapping =
|
||||||
|
{{
|
||||||
|
D3D11_COMPARISON_NEVER, // Never
|
||||||
|
D3D11_COMPARISON_ALWAYS, // Always
|
||||||
|
D3D11_COMPARISON_LESS, // Less
|
||||||
|
D3D11_COMPARISON_LESS_EQUAL, // LessEqual
|
||||||
|
D3D11_COMPARISON_GREATER, // Greater
|
||||||
|
D3D11_COMPARISON_GREATER_EQUAL, // GreaterEqual
|
||||||
|
D3D11_COMPARISON_EQUAL, // Equal
|
||||||
|
}};
|
||||||
|
|
||||||
|
D3D11_DEPTH_STENCIL_DESC desc = {};
|
||||||
|
desc.DepthEnable = ds.depth_test != GPUPipeline::DepthFunc::Never;
|
||||||
|
desc.DepthFunc = func_mapping[static_cast<u8>(ds.depth_test.GetValue())];
|
||||||
|
desc.DepthWriteMask = ds.depth_write ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||||
|
|
||||||
|
HRESULT hr = m_device->CreateDepthStencilState(&desc, dds.GetAddressOf());
|
||||||
|
if (FAILED(hr))
|
||||||
|
Log_ErrorPrintf("Failed to create depth state with %08X", hr);
|
||||||
|
|
||||||
|
m_depth_states.emplace(ds.key, dds);
|
||||||
|
return dds;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11Device::ComPtr<ID3D11BlendState> D3D11Device::GetBlendState(const GPUPipeline::BlendState& bs)
|
||||||
|
{
|
||||||
|
ComPtr<ID3D11BlendState> dbs;
|
||||||
|
|
||||||
|
const auto it = m_blend_states.find(bs.key);
|
||||||
|
if (it != m_blend_states.end())
|
||||||
|
{
|
||||||
|
dbs = it->second;
|
||||||
|
return dbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr std::array<D3D11_BLEND, static_cast<u32>(GPUPipeline::BlendFunc::MaxCount)> blend_mapping = {{
|
||||||
|
D3D11_BLEND_ZERO, // Zero
|
||||||
|
D3D11_BLEND_ONE, // One
|
||||||
|
D3D11_BLEND_SRC_COLOR, // SrcColor
|
||||||
|
D3D11_BLEND_INV_SRC_COLOR, // InvSrcColor
|
||||||
|
D3D11_BLEND_DEST_COLOR, // DstColor
|
||||||
|
D3D11_BLEND_INV_DEST_COLOR, // InvDstColor
|
||||||
|
D3D11_BLEND_SRC_ALPHA, // SrcAlpha
|
||||||
|
D3D11_BLEND_INV_SRC_ALPHA, // InvSrcAlpha
|
||||||
|
D3D11_BLEND_SRC1_ALPHA, // SrcAlpha1
|
||||||
|
D3D11_BLEND_INV_SRC1_ALPHA, // InvSrcAlpha1
|
||||||
|
D3D11_BLEND_DEST_ALPHA, // DstAlpha
|
||||||
|
D3D11_BLEND_INV_DEST_ALPHA, // InvDstAlpha
|
||||||
|
}};
|
||||||
|
|
||||||
|
static constexpr std::array<D3D11_BLEND_OP, static_cast<u32>(GPUPipeline::BlendOp::MaxCount)> op_mapping = {{
|
||||||
|
D3D11_BLEND_OP_ADD, // Add
|
||||||
|
D3D11_BLEND_OP_SUBTRACT, // Subtract
|
||||||
|
D3D11_BLEND_OP_REV_SUBTRACT, // ReverseSubtract
|
||||||
|
D3D11_BLEND_OP_MIN, // Min
|
||||||
|
D3D11_BLEND_OP_MAX, // Max
|
||||||
|
}};
|
||||||
|
|
||||||
|
D3D11_BLEND_DESC blend_desc = {};
|
||||||
|
D3D11_RENDER_TARGET_BLEND_DESC& tgt_desc = blend_desc.RenderTarget[0];
|
||||||
|
tgt_desc.BlendEnable = bs.enable;
|
||||||
|
tgt_desc.RenderTargetWriteMask = bs.write_mask;
|
||||||
|
if (bs.enable)
|
||||||
|
{
|
||||||
|
tgt_desc.SrcBlend = blend_mapping[static_cast<u8>(bs.src_blend.GetValue())];
|
||||||
|
tgt_desc.DestBlend = blend_mapping[static_cast<u8>(bs.dst_blend.GetValue())];
|
||||||
|
tgt_desc.BlendOp = op_mapping[static_cast<u8>(bs.blend_op.GetValue())];
|
||||||
|
tgt_desc.SrcBlendAlpha = blend_mapping[static_cast<u8>(bs.src_alpha_blend.GetValue())];
|
||||||
|
tgt_desc.DestBlendAlpha = blend_mapping[static_cast<u8>(bs.dst_alpha_blend.GetValue())];
|
||||||
|
tgt_desc.BlendOpAlpha = op_mapping[static_cast<u8>(bs.alpha_blend_op.GetValue())];
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT hr = m_device->CreateBlendState(&blend_desc, dbs.GetAddressOf());
|
||||||
|
if (FAILED(hr))
|
||||||
|
Log_ErrorPrintf("Failed to create blend state with %08X", hr);
|
||||||
|
|
||||||
|
m_blend_states.emplace(bs.key, dbs);
|
||||||
|
return dbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11Device::ComPtr<ID3D11InputLayout> D3D11Device::GetInputLayout(const GPUPipeline::InputLayout& il,
|
||||||
|
const D3D11Shader* vs)
|
||||||
|
{
|
||||||
|
ComPtr<ID3D11InputLayout> dil;
|
||||||
|
const auto it = m_input_layouts.find(il);
|
||||||
|
if (it != m_input_layouts.end())
|
||||||
|
{
|
||||||
|
dil = it->second;
|
||||||
|
return dil;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr std::array<const char*, static_cast<u32>(GPUPipeline::VertexAttribute::Semantic::MaxCount)>
|
||||||
|
semantics = {{
|
||||||
|
"POSITION", // Position
|
||||||
|
"TEXCOORD", // Texcoord
|
||||||
|
"COLOR", // Color
|
||||||
|
}};
|
||||||
|
|
||||||
|
static constexpr u32 MAX_COMPONENTS = 4;
|
||||||
|
static constexpr const DXGI_FORMAT
|
||||||
|
format_mapping[static_cast<u8>(GPUPipeline::VertexAttribute::Type::MaxCount)][MAX_COMPONENTS] = {
|
||||||
|
{DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT,
|
||||||
|
DXGI_FORMAT_R32G32B32A32_FLOAT}, // Float
|
||||||
|
{DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UINT}, // UInt8
|
||||||
|
{DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_SINT}, // SInt8
|
||||||
|
{DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM}, // UNorm8
|
||||||
|
{DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R16G16B16A16_UINT}, // UInt16
|
||||||
|
{DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R16G16B16A16_SINT}, // SInt16
|
||||||
|
{DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R16G16B16A16_UNORM}, // UNorm16
|
||||||
|
{DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32A32_UINT}, // UInt32
|
||||||
|
{DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32A32_SINT}, // SInt32
|
||||||
|
};
|
||||||
|
|
||||||
|
D3D11_INPUT_ELEMENT_DESC* elems =
|
||||||
|
static_cast<D3D11_INPUT_ELEMENT_DESC*>(alloca(sizeof(D3D11_INPUT_ELEMENT_DESC) * il.vertex_attributes.size()));
|
||||||
|
for (size_t i = 0; i < il.vertex_attributes.size(); i++)
|
||||||
|
{
|
||||||
|
const GPUPipeline::VertexAttribute& va = il.vertex_attributes[i];
|
||||||
|
Assert(va.components > 0 && va.components < MAX_COMPONENTS);
|
||||||
|
|
||||||
|
D3D11_INPUT_ELEMENT_DESC& elem = elems[i];
|
||||||
|
elem.SemanticName = semantics[static_cast<u8>(va.semantic.GetValue())];
|
||||||
|
elem.SemanticIndex = va.semantic_index;
|
||||||
|
elem.Format = format_mapping[static_cast<u8>(va.type.GetValue())][va.components - 1];
|
||||||
|
elem.InputSlot = 0;
|
||||||
|
elem.AlignedByteOffset = va.offset;
|
||||||
|
elem.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||||
|
elem.InstanceDataStepRate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT hr = m_device->CreateInputLayout(elems, static_cast<UINT>(il.vertex_attributes.size()),
|
||||||
|
vs->GetBytecode().data(), vs->GetBytecode().size(), dil.GetAddressOf());
|
||||||
|
if (FAILED(hr))
|
||||||
|
Log_ErrorPrintf("Failed to create input layout with %08X", hr);
|
||||||
|
|
||||||
|
m_input_layouts.emplace(il, dil);
|
||||||
|
return dil;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GPUPipeline> D3D11Device::CreatePipeline(const GPUPipeline::GraphicsConfig& config)
|
||||||
|
{
|
||||||
|
ComPtr<ID3D11RasterizerState> rs = GetRasterizationState(config.rasterization);
|
||||||
|
ComPtr<ID3D11DepthStencilState> ds = GetDepthState(config.depth);
|
||||||
|
ComPtr<ID3D11BlendState> bs = GetBlendState(config.blend);
|
||||||
|
|
||||||
|
static constexpr std::array<D3D11_PRIMITIVE_TOPOLOGY, static_cast<u32>(GPUPipeline::Primitive::MaxCount)> primitives =
|
||||||
|
{{
|
||||||
|
D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, // Points
|
||||||
|
D3D11_PRIMITIVE_TOPOLOGY_LINELIST, // Lines
|
||||||
|
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, // Triangles
|
||||||
|
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, // TriangleStrips
|
||||||
|
}};
|
||||||
|
|
||||||
|
return std::unique_ptr<GPUPipeline>(
|
||||||
|
new D3D11Pipeline(std::move(rs), std::move(ds), std::move(bs), nullptr,
|
||||||
|
static_cast<const D3D11Shader*>(config.vertex_shader)->GetD3DVertexShader(),
|
||||||
|
static_cast<const D3D11Shader*>(config.pixel_shader)->GetD3DPixelShader(),
|
||||||
|
primitives[static_cast<u8>(config.primitive)]));
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>
|
||||||
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gpu_pipeline.h"
|
||||||
|
|
||||||
|
#include "common/windows_headers.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <d3d11.h>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
|
#include "gsl/span"
|
||||||
|
|
||||||
|
class D3D11Device;
|
||||||
|
|
||||||
|
class D3D11Pipeline final : public GPUPipeline
|
||||||
|
{
|
||||||
|
friend D3D11Device;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
~D3D11Pipeline() override;
|
||||||
|
|
||||||
|
void SetDebugName(const std::string_view& name) override;
|
||||||
|
|
||||||
|
ALWAYS_INLINE ID3D11RasterizerState* GetRasterizerState() const { return m_rs.Get(); }
|
||||||
|
ALWAYS_INLINE ID3D11DepthStencilState* GetDepthStencilState() const { return m_ds.Get(); }
|
||||||
|
ALWAYS_INLINE ID3D11BlendState* GetBlendState() const { return m_bs.Get(); }
|
||||||
|
ALWAYS_INLINE ID3D11InputLayout* GetInputLayout() const { return m_il.Get(); }
|
||||||
|
ALWAYS_INLINE ID3D11VertexShader* GetVertexShader() const { return m_vs.Get(); }
|
||||||
|
ALWAYS_INLINE ID3D11PixelShader* GetPixelShader() const { return m_ps.Get(); }
|
||||||
|
ALWAYS_INLINE D3D11_PRIMITIVE_TOPOLOGY GetPrimitiveTopology() const { return m_topology; }
|
||||||
|
|
||||||
|
void Bind(ID3D11DeviceContext* context);
|
||||||
|
|
||||||
|
private:
|
||||||
|
D3D11Pipeline(ComPtr<ID3D11RasterizerState> rs, ComPtr<ID3D11DepthStencilState> ds, ComPtr<ID3D11BlendState> bs,
|
||||||
|
ComPtr<ID3D11InputLayout> il, ComPtr<ID3D11VertexShader> vs, ComPtr<ID3D11PixelShader> ps,
|
||||||
|
D3D11_PRIMITIVE_TOPOLOGY topology);
|
||||||
|
|
||||||
|
ComPtr<ID3D11RasterizerState> m_rs;
|
||||||
|
ComPtr<ID3D11DepthStencilState> m_ds;
|
||||||
|
ComPtr<ID3D11BlendState> m_bs;
|
||||||
|
ComPtr<ID3D11InputLayout> m_il;
|
||||||
|
ComPtr<ID3D11VertexShader> m_vs;
|
||||||
|
ComPtr<ID3D11PixelShader> m_ps;
|
||||||
|
D3D11_PRIMITIVE_TOPOLOGY m_topology;
|
||||||
|
};
|
|
@ -0,0 +1,113 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>
|
||||||
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
|
#include "d3d11_shader.h"
|
||||||
|
#include "d3d11/shader_compiler.h"
|
||||||
|
#include "d3d11_device.h"
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
|
||||||
|
D3D11Shader::D3D11Shader(Stage stage, Microsoft::WRL::ComPtr<ID3D11DeviceChild> shader)
|
||||||
|
: GPUShader(stage), m_shader(std::move(shader))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11Shader::~D3D11Shader() = default;
|
||||||
|
|
||||||
|
ID3D11VertexShader* D3D11Shader::GetD3DVertexShader() const
|
||||||
|
{
|
||||||
|
DebugAssert(m_stage == Stage::Vertex);
|
||||||
|
return static_cast<ID3D11VertexShader*>(m_shader.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
ID3D11PixelShader* D3D11Shader::GetD3DPixelShader() const
|
||||||
|
{
|
||||||
|
DebugAssert(m_stage == Stage::Pixel);
|
||||||
|
return static_cast<ID3D11PixelShader*>(m_shader.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
ID3D11ComputeShader* D3D11Shader::GetD3DComputeShader() const
|
||||||
|
{
|
||||||
|
DebugAssert(m_stage == Stage::Compute);
|
||||||
|
return static_cast<ID3D11ComputeShader*>(m_shader.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D11Shader::SetDebugName(const std::string_view& name)
|
||||||
|
{
|
||||||
|
Panic("Implement me");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GPUShader> D3D11Device::CreateShaderFromBinary(GPUShader::Stage stage, gsl::span<const u8> data)
|
||||||
|
{
|
||||||
|
ComPtr<ID3D11DeviceChild> shader;
|
||||||
|
std::vector<u8> bytecode;
|
||||||
|
switch (stage)
|
||||||
|
{
|
||||||
|
case GPUShader::Stage::Vertex:
|
||||||
|
shader = D3D11::ShaderCompiler::CreateVertexShader(D3D11Device::GetD3DDevice(), data.data(), data.size());
|
||||||
|
bytecode.resize(data.size());
|
||||||
|
std::memcpy(bytecode.data(), data.data(), data.size());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GPUShader::Stage::Pixel:
|
||||||
|
shader = D3D11::ShaderCompiler::CreatePixelShader(D3D11Device::GetD3DDevice(), data.data(), data.size());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GPUShader::Stage::Compute:
|
||||||
|
shader = D3D11::ShaderCompiler::CreateComputeShader(D3D11Device::GetD3DDevice(), data.data(), data.size());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
UnreachableCode();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shader)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return std::unique_ptr<GPUShader>(new D3D11Shader(stage, std::move(shader), std::move(bytecode)));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GPUShader> D3D11Device::CreateShaderFromSource(GPUShader::Stage stage, const std::string_view& source,
|
||||||
|
std::vector<u8>* out_binary /* = nullptr */)
|
||||||
|
{
|
||||||
|
// TODO: This shouldn't be dependent on build type.
|
||||||
|
#ifdef _DEBUG
|
||||||
|
constexpr bool debug = true;
|
||||||
|
#else
|
||||||
|
constexpr bool debug = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ComPtr<ID3DBlob> blob;
|
||||||
|
switch (stage)
|
||||||
|
{
|
||||||
|
case GPUShader::Stage::Vertex:
|
||||||
|
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Vertex, m_device->GetFeatureLevel(),
|
||||||
|
source, debug);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GPUShader::Stage::Pixel:
|
||||||
|
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Pixel, m_device->GetFeatureLevel(),
|
||||||
|
source, debug);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GPUShader::Stage::Compute:
|
||||||
|
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Compute, m_device->GetFeatureLevel(),
|
||||||
|
source, debug);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
UnreachableCode();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_binary)
|
||||||
|
{
|
||||||
|
const size_t size = blob->GetBufferSize();
|
||||||
|
out_binary->resize(size);
|
||||||
|
std::memcpy(out_binary->data(), blob->GetBufferPointer(), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreateShaderFromBinary(
|
||||||
|
stage, gsl::span<const u8>(static_cast<const u8*>(blob->GetBufferPointer()), blob->GetBufferSize()));
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>
|
||||||
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gpu_shader.h"
|
||||||
|
|
||||||
|
#include "common/windows_headers.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <d3d11.h>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
|
#include "gsl/span"
|
||||||
|
|
||||||
|
class D3D11Device;
|
||||||
|
|
||||||
|
class D3D11Shader final : public GPUShader
|
||||||
|
{
|
||||||
|
friend D3D11Device;
|
||||||
|
|
||||||
|
public:
|
||||||
|
~D3D11Shader() override;
|
||||||
|
|
||||||
|
ID3D11VertexShader* GetD3DVertexShader() const;
|
||||||
|
ID3D11PixelShader* GetD3DPixelShader() const;
|
||||||
|
ID3D11ComputeShader* GetD3DComputeShader() const;
|
||||||
|
|
||||||
|
ALWAYS_INLINE const std::vector<u8>& GetBytecode() const { return m_bytecode; }
|
||||||
|
|
||||||
|
void SetDebugName(const std::string_view& name) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
D3D11Shader(Stage stage, Microsoft::WRL::ComPtr<ID3D11DeviceChild> shader, std::vector<u8> bytecode);
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11DeviceChild> m_shader;
|
||||||
|
std::vector<u8> m_bytecode; // only for VS
|
||||||
|
};
|
|
@ -6,6 +6,7 @@
|
||||||
#include "common/align.h"
|
#include "common/align.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/file_system.h"
|
#include "common/file_system.h"
|
||||||
|
#include "common/hash_combine.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "common/timer.h"
|
#include "common/timer.h"
|
||||||
|
@ -22,6 +23,75 @@ Log_SetChannel(GPUDevice);
|
||||||
|
|
||||||
std::unique_ptr<GPUDevice> g_host_display;
|
std::unique_ptr<GPUDevice> g_host_display;
|
||||||
|
|
||||||
|
size_t GPUPipeline::InputLayoutHash::operator()(const InputLayout& il) const
|
||||||
|
{
|
||||||
|
std::size_t h = 0;
|
||||||
|
hash_combine(h, il.vertex_attributes.size(), il.vertex_stride);
|
||||||
|
|
||||||
|
for (const VertexAttribute& va : il.vertex_attributes)
|
||||||
|
hash_combine(h, va.key);
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPUPipeline::InputLayout::operator==(const InputLayout& rhs) const
|
||||||
|
{
|
||||||
|
return (vertex_stride == rhs.vertex_stride && vertex_attributes.size() == rhs.vertex_attributes.size() &&
|
||||||
|
std::memcmp(vertex_attributes.data(), rhs.vertex_attributes.data(),
|
||||||
|
sizeof(VertexAttribute) * rhs.vertex_attributes.size()) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPUPipeline::InputLayout::operator!=(const InputLayout& rhs) const
|
||||||
|
{
|
||||||
|
return (vertex_stride != rhs.vertex_stride ||
|
||||||
|
vertex_attributes.size() != rhs.vertex_attributes.size() &&
|
||||||
|
std::memcmp(vertex_attributes.data(), rhs.vertex_attributes.data(),
|
||||||
|
sizeof(VertexAttribute) * rhs.vertex_attributes.size()) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GPUPipeline::RasterizationState GPUPipeline::RasterizationState::GetNoCullState()
|
||||||
|
{
|
||||||
|
RasterizationState ret = {};
|
||||||
|
ret.cull_mode = CullMode::None;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
GPUPipeline::DepthState GPUPipeline::DepthState::GetNoTestsState()
|
||||||
|
{
|
||||||
|
DepthState ret = {};
|
||||||
|
ret.depth_test = DepthFunc::Always;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
GPUPipeline::DepthState GPUPipeline::DepthState::GetAlwaysWriteState()
|
||||||
|
{
|
||||||
|
DepthState ret = {};
|
||||||
|
ret.depth_test = DepthFunc::Always;
|
||||||
|
ret.depth_write = true;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
GPUPipeline::BlendState GPUPipeline::BlendState::GetNoBlendingState()
|
||||||
|
{
|
||||||
|
BlendState ret = {};
|
||||||
|
ret.write_mask = 0xf;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
GPUPipeline::BlendState GPUPipeline::BlendState::GetAlphaBlendingState()
|
||||||
|
{
|
||||||
|
BlendState ret = {};
|
||||||
|
ret.enable = true;
|
||||||
|
ret.src_blend = BlendFunc::SrcAlpha;
|
||||||
|
ret.dst_blend = BlendFunc::InvSrcAlpha;
|
||||||
|
ret.blend_op = BlendOp::Add;
|
||||||
|
ret.src_alpha_blend = BlendFunc::One;
|
||||||
|
ret.dst_alpha_blend = BlendFunc::Zero;
|
||||||
|
ret.alpha_blend_op = BlendOp::Add;
|
||||||
|
ret.write_mask = 0xf;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
GPUDevice::~GPUDevice() = default;
|
GPUDevice::~GPUDevice() = default;
|
||||||
|
|
||||||
RenderAPI GPUDevice::GetPreferredAPI()
|
RenderAPI GPUDevice::GetPreferredAPI()
|
||||||
|
@ -54,6 +124,28 @@ void GPUDevice::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32
|
||||||
UnreachableCode();
|
UnreachableCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GPUShader> GPUDevice::CreateShaderFromBinary(GPUShader::Stage stage, gsl::span<const u8> data)
|
||||||
|
{
|
||||||
|
// TODO: REMOVE ME
|
||||||
|
UnreachableCode();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GPUShader> GPUDevice::CreateShaderFromSource(GPUShader::Stage stage, const std::string_view& source,
|
||||||
|
std::vector<u8>* out_binary /* = nullptr */)
|
||||||
|
{
|
||||||
|
// TODO: REMOVE ME
|
||||||
|
UnreachableCode();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GPUPipeline> GPUDevice::CreatePipeline(const GPUPipeline::GraphicsConfig& config)
|
||||||
|
{
|
||||||
|
// TODO: REMOVE ME
|
||||||
|
UnreachableCode();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
bool GPUDevice::ParseFullscreenMode(const std::string_view& mode, u32* width, u32* height, float* refresh_rate)
|
bool GPUDevice::ParseFullscreenMode(const std::string_view& mode, u32* width, u32* height, float* refresh_rate)
|
||||||
{
|
{
|
||||||
if (!mode.empty())
|
if (!mode.empty())
|
||||||
|
|
|
@ -2,10 +2,16 @@
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "gpu_pipeline.h"
|
||||||
|
#include "gpu_shader.h"
|
||||||
|
#include "gpu_texture.h"
|
||||||
|
|
||||||
#include "common/rectangle.h"
|
#include "common/rectangle.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "common/window_info.h"
|
#include "common/window_info.h"
|
||||||
#include "gpu_texture.h"
|
|
||||||
|
#include "gsl/span"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
@ -101,6 +107,12 @@ public:
|
||||||
GPUTexture* src, u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width,
|
GPUTexture* src, u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width,
|
||||||
u32 height);
|
u32 height);
|
||||||
|
|
||||||
|
/// Shader abstraction.
|
||||||
|
virtual std::unique_ptr<GPUShader> CreateShaderFromBinary(GPUShader::Stage stage, gsl::span<const u8> data);
|
||||||
|
virtual std::unique_ptr<GPUShader> CreateShaderFromSource(GPUShader::Stage stage, const std::string_view& source,
|
||||||
|
std::vector<u8>* out_binary = nullptr);
|
||||||
|
virtual std::unique_ptr<GPUPipeline> CreatePipeline(const GPUPipeline::GraphicsConfig& config);
|
||||||
|
|
||||||
/// Returns false if the window was completely occluded.
|
/// Returns false if the window was completely occluded.
|
||||||
virtual bool Render(bool skip_present) = 0;
|
virtual bool Render(bool skip_present) = 0;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,199 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>
|
||||||
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gpu_texture.h"
|
||||||
|
|
||||||
|
#include "common/bitfield.h"
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
#include "gsl/span"
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
class GPUShader;
|
||||||
|
|
||||||
|
class GPUPipeline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Layout : u8
|
||||||
|
{
|
||||||
|
// 128 byte UBO via push constants, 1 texture.
|
||||||
|
SingleTexture,
|
||||||
|
|
||||||
|
MaxCount
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Primitive : u8
|
||||||
|
{
|
||||||
|
Points,
|
||||||
|
Lines,
|
||||||
|
Triangles,
|
||||||
|
TriangleStrips,
|
||||||
|
|
||||||
|
MaxCount
|
||||||
|
};
|
||||||
|
|
||||||
|
union VertexAttribute
|
||||||
|
{
|
||||||
|
enum class Semantic : u8
|
||||||
|
{
|
||||||
|
Position,
|
||||||
|
Texcoord,
|
||||||
|
Color,
|
||||||
|
|
||||||
|
MaxCount
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Type : u8
|
||||||
|
{
|
||||||
|
Float,
|
||||||
|
UInt8,
|
||||||
|
SInt8,
|
||||||
|
UNorm8,
|
||||||
|
UInt16,
|
||||||
|
SInt16,
|
||||||
|
UNorm16,
|
||||||
|
UInt32,
|
||||||
|
SInt32,
|
||||||
|
|
||||||
|
MaxCount
|
||||||
|
};
|
||||||
|
|
||||||
|
BitField<u32, Semantic, 0, 3> semantic;
|
||||||
|
BitField<u32, u8, 4, 8> semantic_index;
|
||||||
|
BitField<u32, Type, 12, 4> type;
|
||||||
|
BitField<u32, u8, 16, 2> components;
|
||||||
|
BitField<u32, u8, 18, 8> offset;
|
||||||
|
u32 key;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InputLayout
|
||||||
|
{
|
||||||
|
gsl::span<const VertexAttribute> vertex_attributes;
|
||||||
|
u32 vertex_stride;
|
||||||
|
|
||||||
|
bool operator==(const InputLayout& rhs) const;
|
||||||
|
bool operator!=(const InputLayout& rhs) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InputLayoutHash
|
||||||
|
{
|
||||||
|
size_t operator()(const InputLayout& il) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class CullMode : u8
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Front,
|
||||||
|
Back,
|
||||||
|
|
||||||
|
MaxCount
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class DepthFunc : u8
|
||||||
|
{
|
||||||
|
Never,
|
||||||
|
Always,
|
||||||
|
Less,
|
||||||
|
LessEqual,
|
||||||
|
Greater,
|
||||||
|
GreaterEqual,
|
||||||
|
Equal,
|
||||||
|
|
||||||
|
MaxCount
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BlendFunc : u8
|
||||||
|
{
|
||||||
|
Zero,
|
||||||
|
One,
|
||||||
|
SrcColor,
|
||||||
|
InvSrcColor,
|
||||||
|
DstColor,
|
||||||
|
InvDstColor,
|
||||||
|
SrcAlpha,
|
||||||
|
InvSrcAlpha,
|
||||||
|
SrcAlpha1,
|
||||||
|
InvSrcAlpha1,
|
||||||
|
DstAlpha,
|
||||||
|
InvDstAlpha,
|
||||||
|
|
||||||
|
MaxCount
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BlendOp : u8
|
||||||
|
{
|
||||||
|
Add,
|
||||||
|
Subtract,
|
||||||
|
ReverseSubtract,
|
||||||
|
Min,
|
||||||
|
Max,
|
||||||
|
|
||||||
|
MaxCount
|
||||||
|
};
|
||||||
|
|
||||||
|
union RasterizationState
|
||||||
|
{
|
||||||
|
BitField<u8, CullMode, 0, 2> cull_mode;
|
||||||
|
u8 key;
|
||||||
|
|
||||||
|
static RasterizationState GetNoCullState();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DepthState
|
||||||
|
{
|
||||||
|
BitField<u8, DepthFunc, 0, 3> depth_test;
|
||||||
|
BitField<u8, bool, 4, 1> depth_write;
|
||||||
|
u8 key;
|
||||||
|
|
||||||
|
static DepthState GetNoTestsState();
|
||||||
|
static DepthState GetAlwaysWriteState();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BlendState
|
||||||
|
{
|
||||||
|
BitField<u32, bool, 0, 1> enable;
|
||||||
|
BitField<u32, BlendFunc, 1, 4> src_blend;
|
||||||
|
BitField<u32, BlendFunc, 5, 4> src_alpha_blend;
|
||||||
|
BitField<u32, BlendFunc, 9, 4> dst_blend;
|
||||||
|
BitField<u32, BlendFunc, 13, 4> dst_alpha_blend;
|
||||||
|
BitField<u32, BlendOp, 17, 3> blend_op;
|
||||||
|
BitField<u32, BlendOp, 20, 3> alpha_blend_op;
|
||||||
|
BitField<u32, bool, 24, 1> write_r;
|
||||||
|
BitField<u32, bool, 25, 1> write_g;
|
||||||
|
BitField<u32, bool, 26, 1> write_b;
|
||||||
|
BitField<u32, bool, 27, 1> write_a;
|
||||||
|
BitField<u32, u8, 24, 4> write_mask;
|
||||||
|
u32 key;
|
||||||
|
|
||||||
|
static BlendState GetNoBlendingState();
|
||||||
|
static BlendState GetAlphaBlendingState();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GraphicsConfig
|
||||||
|
{
|
||||||
|
Layout layout;
|
||||||
|
|
||||||
|
Primitive primitive;
|
||||||
|
InputLayout input_layout;
|
||||||
|
|
||||||
|
RasterizationState rasterization;
|
||||||
|
DepthState depth;
|
||||||
|
BlendState blend;
|
||||||
|
|
||||||
|
const GPUShader* vertex_shader;
|
||||||
|
const GPUShader* pixel_shader;
|
||||||
|
|
||||||
|
GPUTexture::Format color_format;
|
||||||
|
GPUTexture::Format depth_format;
|
||||||
|
u32 samples;
|
||||||
|
bool per_sample_shading;
|
||||||
|
};
|
||||||
|
|
||||||
|
GPUPipeline() = default;
|
||||||
|
virtual ~GPUPipeline() = default;
|
||||||
|
|
||||||
|
virtual void SetDebugName(const std::string_view& name) = 0;
|
||||||
|
};
|
|
@ -0,0 +1,29 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Connor McLaughlin <stenzek@gmail.com>
|
||||||
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
class GPUShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Stage
|
||||||
|
{
|
||||||
|
Vertex,
|
||||||
|
Pixel,
|
||||||
|
Compute
|
||||||
|
};
|
||||||
|
|
||||||
|
GPUShader(Stage stage) : m_stage(stage) {}
|
||||||
|
virtual ~GPUShader() = default;
|
||||||
|
|
||||||
|
ALWAYS_INLINE Stage GetStage() const { return m_stage; }
|
||||||
|
|
||||||
|
virtual void SetDebugName(const std::string_view& name) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Stage m_stage;
|
||||||
|
};
|
Loading…
Reference in New Issue