2015-05-24 04:55:12 +00:00
|
|
|
// Copyright 2009 Dolphin Emulator Project
|
2021-07-05 01:22:19 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2010-06-09 01:37:08 +00:00
|
|
|
|
2016-09-24 09:16:52 +00:00
|
|
|
#include "VideoBackends/Software/SWVertexLoader.h"
|
|
|
|
|
2017-08-19 15:08:09 +00:00
|
|
|
#include <cstddef>
|
2014-12-22 16:25:05 +00:00
|
|
|
#include <limits>
|
|
|
|
|
2016-09-24 09:16:52 +00:00
|
|
|
#include "Common/Assert.h"
|
2014-09-08 01:06:58 +00:00
|
|
|
#include "Common/CommonTypes.h"
|
2016-09-24 09:16:52 +00:00
|
|
|
#include "Common/Logging/Log.h"
|
2014-02-17 10:18:15 +00:00
|
|
|
|
2015-10-09 18:50:36 +00:00
|
|
|
#include "VideoBackends/Software/DebugUtil.h"
|
2014-10-21 06:01:38 +00:00
|
|
|
#include "VideoBackends/Software/NativeVertexFormat.h"
|
2015-10-09 18:50:36 +00:00
|
|
|
#include "VideoBackends/Software/Rasterizer.h"
|
2019-02-15 01:59:50 +00:00
|
|
|
#include "VideoBackends/Software/SWRenderer.h"
|
2015-10-09 18:50:36 +00:00
|
|
|
#include "VideoBackends/Software/Tev.h"
|
2014-02-17 10:18:15 +00:00
|
|
|
#include "VideoBackends/Software/TransformUnit.h"
|
|
|
|
|
2017-01-31 05:41:12 +00:00
|
|
|
#include "VideoCommon/CPMemory.h"
|
2016-01-31 19:51:55 +00:00
|
|
|
#include "VideoCommon/DataReader.h"
|
2015-10-09 18:50:36 +00:00
|
|
|
#include "VideoCommon/IndexGenerator.h"
|
|
|
|
#include "VideoCommon/OpcodeDecoding.h"
|
|
|
|
#include "VideoCommon/PixelShaderManager.h"
|
|
|
|
#include "VideoCommon/Statistics.h"
|
2014-12-13 00:51:14 +00:00
|
|
|
#include "VideoCommon/VertexLoaderBase.h"
|
2015-05-29 12:42:45 +00:00
|
|
|
#include "VideoCommon/VertexLoaderManager.h"
|
2022-04-14 05:03:34 +00:00
|
|
|
#include "VideoCommon/VertexShaderManager.h"
|
2016-01-17 21:54:31 +00:00
|
|
|
#include "VideoCommon/VideoConfig.h"
|
2015-10-09 18:50:36 +00:00
|
|
|
#include "VideoCommon/XFMemory.h"
|
2010-06-09 01:37:08 +00:00
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
SWVertexLoader::SWVertexLoader() = default;
|
2015-05-29 12:42:45 +00:00
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
SWVertexLoader::~SWVertexLoader() = default;
|
2018-11-27 07:16:53 +00:00
|
|
|
|
2021-11-30 01:51:02 +00:00
|
|
|
DataReader SWVertexLoader::PrepareForAdditionalData(OpcodeDecoder::Primitive primitive, u32 count,
|
|
|
|
u32 stride, bool cullall)
|
|
|
|
{
|
|
|
|
// The software renderer needs cullall to be false for zfreeze to work
|
|
|
|
return VertexManagerBase::PrepareForAdditionalData(primitive, count, stride, false);
|
|
|
|
}
|
|
|
|
|
2018-11-27 07:16:53 +00:00
|
|
|
void SWVertexLoader::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_vertex)
|
2015-10-09 18:50:36 +00:00
|
|
|
{
|
|
|
|
DebugUtil::OnObjectBegin();
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2021-04-30 21:57:12 +00:00
|
|
|
using OpcodeDecoder::Primitive;
|
|
|
|
Primitive primitive_type = Primitive::GX_DRAW_QUADS;
|
2016-08-22 03:46:52 +00:00
|
|
|
switch (m_current_primitive_type)
|
2015-10-09 18:50:36 +00:00
|
|
|
{
|
2017-04-30 08:07:57 +00:00
|
|
|
case PrimitiveType::Points:
|
2021-04-30 21:57:12 +00:00
|
|
|
primitive_type = Primitive::GX_DRAW_POINTS;
|
2015-10-09 18:50:36 +00:00
|
|
|
break;
|
2017-04-30 08:07:57 +00:00
|
|
|
case PrimitiveType::Lines:
|
2021-04-30 21:57:12 +00:00
|
|
|
primitive_type = Primitive::GX_DRAW_LINES;
|
2015-10-09 18:50:36 +00:00
|
|
|
break;
|
2017-04-30 08:07:57 +00:00
|
|
|
case PrimitiveType::Triangles:
|
2021-04-30 21:57:12 +00:00
|
|
|
primitive_type = Primitive::GX_DRAW_TRIANGLES;
|
2017-04-30 08:07:57 +00:00
|
|
|
break;
|
|
|
|
case PrimitiveType::TriangleStrip:
|
2021-04-30 21:57:12 +00:00
|
|
|
primitive_type = Primitive::GX_DRAW_TRIANGLE_STRIP;
|
2015-10-09 18:50:36 +00:00
|
|
|
break;
|
|
|
|
}
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2021-06-09 11:42:21 +00:00
|
|
|
// Flush bounding box here because software overrides the base function
|
|
|
|
if (g_renderer->IsBBoxEnabled())
|
|
|
|
g_renderer->BBoxFlush();
|
|
|
|
|
2021-04-30 21:57:12 +00:00
|
|
|
m_setup_unit.Init(primitive_type);
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2015-10-09 18:50:36 +00:00
|
|
|
// set all states with are stored within video sw
|
|
|
|
for (int i = 0; i < 4; i++)
|
2014-12-07 20:51:45 +00:00
|
|
|
{
|
2016-03-06 10:03:45 +00:00
|
|
|
Rasterizer::SetTevReg(i, Tev::RED_C, PixelShaderManager::constants.kcolors[i][0]);
|
|
|
|
Rasterizer::SetTevReg(i, Tev::GRN_C, PixelShaderManager::constants.kcolors[i][1]);
|
|
|
|
Rasterizer::SetTevReg(i, Tev::BLU_C, PixelShaderManager::constants.kcolors[i][2]);
|
|
|
|
Rasterizer::SetTevReg(i, Tev::ALP_C, PixelShaderManager::constants.kcolors[i][3]);
|
2014-12-07 20:51:45 +00:00
|
|
|
}
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2019-12-05 15:01:33 +00:00
|
|
|
for (u32 i = 0; i < m_index_generator.GetIndexLen(); i++)
|
2015-10-09 18:50:36 +00:00
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
const u16 index = m_cpu_index_buffer[i];
|
2018-10-14 22:09:17 +00:00
|
|
|
memset(static_cast<void*>(&m_vertex), 0, sizeof(m_vertex));
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2017-09-09 19:13:17 +00:00
|
|
|
// parse the videocommon format to our own struct format (m_vertex)
|
2021-04-30 21:48:27 +00:00
|
|
|
SetFormat();
|
2015-10-09 18:50:36 +00:00
|
|
|
ParseVertex(VertexLoaderManager::GetCurrentVertexFormat()->GetVertexDeclaration(), index);
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2015-10-09 18:50:36 +00:00
|
|
|
// transform this vertex so that it can be used for rasterization (outVertex)
|
2017-09-09 19:13:17 +00:00
|
|
|
OutputVertexData* outVertex = m_setup_unit.GetVertex();
|
|
|
|
TransformUnit::TransformPosition(&m_vertex, outVertex);
|
2017-08-19 15:08:09 +00:00
|
|
|
outVertex->normal = {};
|
2022-04-22 19:50:44 +00:00
|
|
|
if (VertexLoaderManager::g_current_components & VB_HAS_NORMAL)
|
2022-04-14 05:03:34 +00:00
|
|
|
TransformUnit::TransformNormal(&m_vertex, outVertex);
|
2017-09-09 19:13:17 +00:00
|
|
|
TransformUnit::TransformColor(&m_vertex, outVertex);
|
2021-01-04 07:22:48 +00:00
|
|
|
TransformUnit::TransformTexCoord(&m_vertex, outVertex);
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2015-10-09 18:50:36 +00:00
|
|
|
// assemble and rasterize the primitive
|
2017-09-09 19:13:17 +00:00
|
|
|
m_setup_unit.SetupVertex();
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2019-07-11 03:34:50 +00:00
|
|
|
INCSTAT(g_stats.this_frame.num_vertices_loaded)
|
2015-10-09 18:50:36 +00:00
|
|
|
}
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2015-10-09 18:50:36 +00:00
|
|
|
DebugUtil::OnObjectEnd();
|
|
|
|
}
|
2014-12-07 20:51:45 +00:00
|
|
|
|
2021-04-30 21:48:27 +00:00
|
|
|
void SWVertexLoader::SetFormat()
|
2015-10-09 18:50:36 +00:00
|
|
|
{
|
2017-09-09 19:13:17 +00:00
|
|
|
m_vertex.posMtx = xfmem.MatrixIndexA.PosNormalMtxIdx;
|
|
|
|
m_vertex.texMtx[0] = xfmem.MatrixIndexA.Tex0MtxIdx;
|
|
|
|
m_vertex.texMtx[1] = xfmem.MatrixIndexA.Tex1MtxIdx;
|
|
|
|
m_vertex.texMtx[2] = xfmem.MatrixIndexA.Tex2MtxIdx;
|
|
|
|
m_vertex.texMtx[3] = xfmem.MatrixIndexA.Tex3MtxIdx;
|
|
|
|
m_vertex.texMtx[4] = xfmem.MatrixIndexB.Tex4MtxIdx;
|
|
|
|
m_vertex.texMtx[5] = xfmem.MatrixIndexB.Tex5MtxIdx;
|
|
|
|
m_vertex.texMtx[6] = xfmem.MatrixIndexB.Tex6MtxIdx;
|
|
|
|
m_vertex.texMtx[7] = xfmem.MatrixIndexB.Tex7MtxIdx;
|
2014-12-07 20:51:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T, typename I>
|
|
|
|
static T ReadNormalized(I value)
|
|
|
|
{
|
|
|
|
T casted = (T)value;
|
|
|
|
if (!std::numeric_limits<T>::is_integer && std::numeric_limits<I>::is_integer)
|
2009-10-12 00:48:24 +00:00
|
|
|
{
|
2014-12-07 20:51:45 +00:00
|
|
|
// normalize if non-float is converted to a float
|
|
|
|
casted *= (T)(1.0 / std::numeric_limits<I>::max());
|
2009-10-12 00:48:24 +00:00
|
|
|
}
|
2014-12-07 20:51:45 +00:00
|
|
|
return casted;
|
|
|
|
}
|
2010-06-09 01:37:08 +00:00
|
|
|
|
2014-12-07 20:51:45 +00:00
|
|
|
template <typename T, bool swap = false>
|
2015-03-14 09:15:19 +00:00
|
|
|
static void ReadVertexAttribute(T* dst, DataReader src, const AttributeFormat& format,
|
|
|
|
int base_component, int components, bool reverse)
|
2014-12-07 20:51:45 +00:00
|
|
|
{
|
|
|
|
if (format.enable)
|
2009-10-12 00:48:24 +00:00
|
|
|
{
|
2014-12-07 20:51:45 +00:00
|
|
|
src.Skip(format.offset);
|
2021-06-26 19:48:28 +00:00
|
|
|
src.Skip(base_component * GetElementSize(format.type));
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2015-03-14 09:15:19 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < std::min(format.components - base_component, components); i++)
|
2009-10-12 00:48:24 +00:00
|
|
|
{
|
2015-03-14 09:15:19 +00:00
|
|
|
int i_dst = reverse ? components - i - 1 : i;
|
2014-12-07 20:51:45 +00:00
|
|
|
switch (format.type)
|
|
|
|
{
|
2021-06-26 19:48:28 +00:00
|
|
|
case ComponentFormat::UByte:
|
2014-12-07 20:51:45 +00:00
|
|
|
dst[i_dst] = ReadNormalized<T, u8>(src.Read<u8, swap>());
|
|
|
|
break;
|
2021-06-26 19:48:28 +00:00
|
|
|
case ComponentFormat::Byte:
|
2014-12-07 20:51:45 +00:00
|
|
|
dst[i_dst] = ReadNormalized<T, s8>(src.Read<s8, swap>());
|
|
|
|
break;
|
2021-06-26 19:48:28 +00:00
|
|
|
case ComponentFormat::UShort:
|
2014-12-07 20:51:45 +00:00
|
|
|
dst[i_dst] = ReadNormalized<T, u16>(src.Read<u16, swap>());
|
|
|
|
break;
|
2021-06-26 19:48:28 +00:00
|
|
|
case ComponentFormat::Short:
|
2014-12-07 20:51:45 +00:00
|
|
|
dst[i_dst] = ReadNormalized<T, s16>(src.Read<s16, swap>());
|
|
|
|
break;
|
2021-06-26 19:48:28 +00:00
|
|
|
case ComponentFormat::Float:
|
2014-12-07 20:51:45 +00:00
|
|
|
dst[i_dst] = ReadNormalized<T, float>(src.Read<float, swap>());
|
|
|
|
break;
|
|
|
|
}
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2021-06-26 19:48:28 +00:00
|
|
|
ASSERT_MSG(VIDEO, !format.integer || format.type != ComponentFormat::Float,
|
2018-03-15 00:34:35 +00:00
|
|
|
"only non-float values are allowed to be streamed as integer");
|
2009-10-12 00:48:24 +00:00
|
|
|
}
|
2015-03-14 09:15:19 +00:00
|
|
|
for (; i < components; i++)
|
|
|
|
{
|
|
|
|
int i_dst = reverse ? components - i - 1 : i;
|
|
|
|
dst[i_dst] = i == 3;
|
|
|
|
}
|
2009-10-12 00:48:24 +00:00
|
|
|
}
|
2014-12-07 20:51:45 +00:00
|
|
|
}
|
2010-06-09 01:37:08 +00:00
|
|
|
|
2017-01-31 05:41:12 +00:00
|
|
|
static void ParseColorAttributes(InputVertexData* dst, DataReader& src,
|
|
|
|
const PortableVertexDeclaration& vdec)
|
|
|
|
{
|
2021-02-23 03:03:06 +00:00
|
|
|
const auto set_default_color = [](std::array<u8, 4>& color) {
|
|
|
|
color[Tev::ALP_C] = g_ActiveConfig.iMissingColorValue & 0xFF;
|
|
|
|
color[Tev::BLU_C] = (g_ActiveConfig.iMissingColorValue >> 8) & 0xFF;
|
|
|
|
color[Tev::GRN_C] = (g_ActiveConfig.iMissingColorValue >> 16) & 0xFF;
|
|
|
|
color[Tev::RED_C] = (g_ActiveConfig.iMissingColorValue >> 24) & 0xFF;
|
2017-01-31 05:41:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if (vdec.colors[0].enable)
|
|
|
|
{
|
|
|
|
// Use color0 for channel 0, and color1 for channel 1 if both colors 0 and 1 are present.
|
|
|
|
ReadVertexAttribute<u8>(dst->color[0].data(), src, vdec.colors[0], 0, 4, true);
|
|
|
|
if (vdec.colors[1].enable)
|
|
|
|
ReadVertexAttribute<u8>(dst->color[1].data(), src, vdec.colors[1], 0, 4, true);
|
|
|
|
else
|
2021-02-23 03:03:06 +00:00
|
|
|
set_default_color(dst->color[1]);
|
2017-01-31 05:41:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If only one of the color attributes is enabled, it is directed to color 0.
|
|
|
|
if (vdec.colors[1].enable)
|
|
|
|
ReadVertexAttribute<u8>(dst->color[0].data(), src, vdec.colors[1], 0, 4, true);
|
|
|
|
else
|
2021-02-23 03:03:06 +00:00
|
|
|
set_default_color(dst->color[0]);
|
|
|
|
set_default_color(dst->color[1]);
|
2017-01-31 05:41:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-09 18:50:36 +00:00
|
|
|
void SWVertexLoader::ParseVertex(const PortableVertexDeclaration& vdec, int index)
|
2014-12-07 20:51:45 +00:00
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
DataReader src(m_cpu_vertex_buffer.data(),
|
|
|
|
m_cpu_vertex_buffer.data() + m_cpu_vertex_buffer.size());
|
2015-10-09 18:50:36 +00:00
|
|
|
src.Skip(index * vdec.stride);
|
2013-10-29 05:23:17 +00:00
|
|
|
|
2017-09-09 19:13:17 +00:00
|
|
|
ReadVertexAttribute<float>(&m_vertex.position[0], src, vdec.position, 0, 3, false);
|
2013-10-29 05:23:17 +00:00
|
|
|
|
2017-09-09 19:13:17 +00:00
|
|
|
for (std::size_t i = 0; i < m_vertex.normal.size(); i++)
|
2014-12-07 20:51:45 +00:00
|
|
|
{
|
2017-09-09 19:13:17 +00:00
|
|
|
ReadVertexAttribute<float>(&m_vertex.normal[i][0], src, vdec.normals[i], 0, 3, false);
|
2009-10-12 00:48:24 +00:00
|
|
|
}
|
2022-04-14 05:03:34 +00:00
|
|
|
if (!vdec.normals[1].enable)
|
|
|
|
{
|
|
|
|
m_vertex.normal[1][0] = VertexShaderManager::constants.cached_tangent[0];
|
|
|
|
m_vertex.normal[1][1] = VertexShaderManager::constants.cached_tangent[1];
|
|
|
|
m_vertex.normal[1][2] = VertexShaderManager::constants.cached_tangent[2];
|
|
|
|
}
|
|
|
|
if (!vdec.normals[2].enable)
|
|
|
|
{
|
|
|
|
m_vertex.normal[2][0] = VertexShaderManager::constants.cached_binormal[0];
|
|
|
|
m_vertex.normal[2][1] = VertexShaderManager::constants.cached_binormal[1];
|
|
|
|
m_vertex.normal[2][2] = VertexShaderManager::constants.cached_binormal[2];
|
|
|
|
}
|
2010-06-09 01:37:08 +00:00
|
|
|
|
2017-01-31 05:41:12 +00:00
|
|
|
ParseColorAttributes(&m_vertex, src, vdec);
|
2010-06-09 01:37:08 +00:00
|
|
|
|
2017-09-09 19:13:17 +00:00
|
|
|
for (std::size_t i = 0; i < m_vertex.texCoords.size(); i++)
|
2009-10-12 00:48:24 +00:00
|
|
|
{
|
2017-09-09 19:13:17 +00:00
|
|
|
ReadVertexAttribute<float>(m_vertex.texCoords[i].data(), src, vdec.texcoords[i], 0, 2, false);
|
2010-06-09 01:37:08 +00:00
|
|
|
|
2014-12-07 20:51:45 +00:00
|
|
|
// the texmtr is stored as third component of the texCoord
|
|
|
|
if (vdec.texcoords[i].components >= 3)
|
|
|
|
{
|
2017-09-09 19:13:17 +00:00
|
|
|
ReadVertexAttribute<u8>(&m_vertex.texMtx[i], src, vdec.texcoords[i], 2, 1, false);
|
2014-12-07 20:51:45 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-09 01:37:08 +00:00
|
|
|
|
2017-09-09 19:13:17 +00:00
|
|
|
ReadVertexAttribute<u8>(&m_vertex.posMtx, src, vdec.posmtx, 0, 1, false);
|
2009-10-12 00:48:24 +00:00
|
|
|
}
|