2019-03-28 10:35:46 +00:00
|
|
|
// Copyright 2019 Dolphin Emulator Project
|
2021-07-05 01:22:19 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2019-03-28 10:35:46 +00:00
|
|
|
|
2020-09-15 13:01:29 +00:00
|
|
|
#include "VideoBackends/D3D12/DX12VertexFormat.h"
|
2019-03-28 10:35:46 +00:00
|
|
|
|
|
|
|
#include "Common/Assert.h"
|
2021-06-26 19:48:28 +00:00
|
|
|
#include "Common/EnumMap.h"
|
2019-03-28 10:35:46 +00:00
|
|
|
|
|
|
|
#include "VideoCommon/VertexLoaderManager.h"
|
|
|
|
#include "VideoCommon/VertexShaderGen.h"
|
|
|
|
|
|
|
|
namespace DX12
|
|
|
|
{
|
2021-06-26 19:48:28 +00:00
|
|
|
static DXGI_FORMAT VarToDXGIFormat(ComponentFormat t, u32 components, bool integer)
|
2019-03-28 10:35:46 +00:00
|
|
|
{
|
2021-06-26 19:48:28 +00:00
|
|
|
using ComponentArray = std::array<DXGI_FORMAT, 4>;
|
|
|
|
static constexpr auto f = [](ComponentArray a) { return a; }; // Deduction helper
|
|
|
|
|
2019-03-28 10:35:46 +00:00
|
|
|
// NOTE: 3-component formats are not valid.
|
2021-06-26 19:48:28 +00:00
|
|
|
static constexpr Common::EnumMap<ComponentArray, ComponentFormat::Float> float_type_lookup = {
|
|
|
|
f({DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM,
|
|
|
|
DXGI_FORMAT_R8G8B8A8_UNORM}), // UByte
|
|
|
|
f({DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM,
|
|
|
|
DXGI_FORMAT_R8G8B8A8_SNORM}), // Byte
|
|
|
|
f({DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM,
|
|
|
|
DXGI_FORMAT_R16G16B16A16_UNORM}), // UShort
|
|
|
|
f({DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R16G16B16A16_SNORM,
|
|
|
|
DXGI_FORMAT_R16G16B16A16_SNORM}), // Short
|
|
|
|
f({DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT,
|
|
|
|
DXGI_FORMAT_R32G32B32A32_FLOAT}), // Float
|
2019-03-28 10:35:46 +00:00
|
|
|
};
|
|
|
|
|
2021-06-26 19:48:28 +00:00
|
|
|
static constexpr Common::EnumMap<ComponentArray, ComponentFormat::Float> integer_type_lookup = {
|
|
|
|
f({DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8B8A8_UINT,
|
|
|
|
DXGI_FORMAT_R8G8B8A8_UINT}), // UByte
|
|
|
|
f({DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8B8A8_SINT,
|
|
|
|
DXGI_FORMAT_R8G8B8A8_SINT}), // Byte
|
|
|
|
f({DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16B16A16_UINT,
|
|
|
|
DXGI_FORMAT_R16G16B16A16_UINT}), // UShort
|
|
|
|
f({DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16B16A16_SINT,
|
|
|
|
DXGI_FORMAT_R16G16B16A16_SINT}), // Short
|
|
|
|
f({DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32B32_FLOAT,
|
|
|
|
DXGI_FORMAT_R32G32B32A32_FLOAT}), // Float
|
2019-03-28 10:35:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
ASSERT(components > 0 && components <= 4);
|
|
|
|
return integer ? integer_type_lookup[t][components - 1] : float_type_lookup[t][components - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
DXVertexFormat::DXVertexFormat(const PortableVertexDeclaration& vtx_decl)
|
|
|
|
: NativeVertexFormat(vtx_decl)
|
|
|
|
{
|
|
|
|
MapAttributes();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DXVertexFormat::GetInputLayoutDesc(D3D12_INPUT_LAYOUT_DESC* desc) const
|
|
|
|
{
|
|
|
|
desc->pInputElementDescs = m_attribute_descriptions.data();
|
|
|
|
desc->NumElements = m_num_attributes;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DXVertexFormat::AddAttribute(const char* semantic_name, u32 semantic_index, u32 slot,
|
|
|
|
DXGI_FORMAT format, u32 offset)
|
|
|
|
{
|
|
|
|
ASSERT(m_num_attributes < MAX_VERTEX_ATTRIBUTES);
|
|
|
|
|
|
|
|
auto* attr_desc = &m_attribute_descriptions[m_num_attributes];
|
|
|
|
attr_desc->SemanticName = semantic_name;
|
|
|
|
attr_desc->SemanticIndex = semantic_index;
|
|
|
|
attr_desc->Format = format;
|
|
|
|
attr_desc->InputSlot = slot;
|
|
|
|
attr_desc->AlignedByteOffset = offset;
|
|
|
|
attr_desc->InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
|
|
|
|
attr_desc->InstanceDataStepRate = 0;
|
|
|
|
|
|
|
|
m_num_attributes++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DXVertexFormat::MapAttributes()
|
|
|
|
{
|
|
|
|
m_num_attributes = 0;
|
|
|
|
|
|
|
|
if (m_decl.position.enable)
|
|
|
|
{
|
|
|
|
AddAttribute(
|
|
|
|
"POSITION", 0, 0,
|
|
|
|
VarToDXGIFormat(m_decl.position.type, m_decl.position.components, m_decl.position.integer),
|
|
|
|
m_decl.position.offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
if (m_decl.normals[i].enable)
|
|
|
|
{
|
2022-04-22 19:50:44 +00:00
|
|
|
static constexpr std::array<const char*, 3> NAMES = {"NORMAL", "TANGENT", "BINORMAL"};
|
|
|
|
AddAttribute(NAMES[i], 0, 0,
|
2019-03-28 10:35:46 +00:00
|
|
|
VarToDXGIFormat(m_decl.normals[i].type, m_decl.normals[i].components,
|
|
|
|
m_decl.normals[i].integer),
|
|
|
|
m_decl.normals[i].offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if (m_decl.colors[i].enable)
|
|
|
|
{
|
|
|
|
AddAttribute("COLOR", i, 0,
|
|
|
|
VarToDXGIFormat(m_decl.colors[i].type, m_decl.colors[i].components,
|
|
|
|
m_decl.colors[i].integer),
|
|
|
|
m_decl.colors[i].offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
if (m_decl.texcoords[i].enable)
|
|
|
|
{
|
|
|
|
AddAttribute("TEXCOORD", i, 0,
|
|
|
|
VarToDXGIFormat(m_decl.texcoords[i].type, m_decl.texcoords[i].components,
|
|
|
|
m_decl.texcoords[i].integer),
|
|
|
|
m_decl.texcoords[i].offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_decl.posmtx.enable)
|
|
|
|
{
|
|
|
|
AddAttribute(
|
|
|
|
"BLENDINDICES", 0, 0,
|
|
|
|
VarToDXGIFormat(m_decl.posmtx.type, m_decl.posmtx.components, m_decl.posmtx.integer),
|
|
|
|
m_decl.posmtx.offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace DX12
|