Compile morph pipelines asynchronously.

This commit is contained in:
Skyth 2025-01-14 18:48:00 +03:00
parent 028767b33a
commit babad3402c
5 changed files with 192 additions and 34 deletions

View file

@ -0,0 +1,26 @@
#pragma once
#include <boost/smart_ptr/shared_ptr.h>
#include <Hedgehog/Database/System/hhDatabaseData.h>
namespace Hedgehog::Mirage
{
class CMaterialData;
class CMeshIndexData : public Hedgehog::Database::CDatabaseData
{
public:
be<uint32_t> m_IndexNum;
be<uint32_t> m_NodeNum;
xpointer<uint8_t> m_pNodeIndices;
xpointer<void> m_pD3DIndexBuffer;
boost::shared_ptr<CMaterialData> m_spMaterial;
};
SWA_ASSERT_OFFSETOF(CMeshIndexData, m_IndexNum, 0xC);
SWA_ASSERT_OFFSETOF(CMeshIndexData, m_NodeNum, 0x10);
SWA_ASSERT_OFFSETOF(CMeshIndexData, m_pNodeIndices, 0x14);
SWA_ASSERT_OFFSETOF(CMeshIndexData, m_pD3DIndexBuffer, 0x18);
SWA_ASSERT_OFFSETOF(CMeshIndexData, m_spMaterial, 0x1C);
SWA_ASSERT_SIZEOF(CMeshIndexData, 0x24);
}

View file

@ -0,0 +1,38 @@
#pragma once
#include <boost/smart_ptr/shared_ptr.h>
#include <Hedgehog/Base/Container/hhVector.h>
#include <Hedgehog/Database/System/hhDatabaseData.h>
#include <Hedgehog/MirageCore/Misc/hhVertexDeclarationPtr.h>
namespace Hedgehog::Mirage
{
class CMorphTargetData;
class CMeshIndexData;
class CMorphModelData : public Hedgehog::Database::CDatabaseData
{
public:
be<uint32_t> m_VertexNum;
be<uint32_t> m_VertexSize;
be<uint32_t> m_MorphTargetVertexSize;
xpointer<void> m_pD3DVertexBuffer;
CVertexDeclarationPtr m_VertexDeclarationPtr;
hh::vector<boost::shared_ptr<CMorphTargetData>> m_MorphTargetList;
hh::vector<boost::shared_ptr<CMeshIndexData>> m_OpaqueMeshList;
hh::vector<boost::shared_ptr<CMeshIndexData>> m_TransparentMeshList;
hh::vector<boost::shared_ptr<CMeshIndexData>> m_PunchThroughMeshList;
};
SWA_ASSERT_OFFSETOF(CMorphModelData, m_VertexNum, 0xC);
SWA_ASSERT_OFFSETOF(CMorphModelData, m_VertexSize, 0x10);
SWA_ASSERT_OFFSETOF(CMorphModelData, m_MorphTargetVertexSize, 0x14);
SWA_ASSERT_OFFSETOF(CMorphModelData, m_pD3DVertexBuffer, 0x18);
SWA_ASSERT_OFFSETOF(CMorphModelData, m_VertexDeclarationPtr, 0x1C);
SWA_ASSERT_OFFSETOF(CMorphModelData, m_MorphTargetList, 0x24);
SWA_ASSERT_OFFSETOF(CMorphModelData, m_OpaqueMeshList, 0x34);
SWA_ASSERT_OFFSETOF(CMorphModelData, m_TransparentMeshList, 0x44);
SWA_ASSERT_OFFSETOF(CMorphModelData, m_PunchThroughMeshList, 0x54);
SWA_ASSERT_SIZEOF(CMorphModelData, 0x64);
}

View file

@ -31,7 +31,9 @@
#include "Hedgehog/MirageCore/Misc/hhVertexDeclarationPtr.h" #include "Hedgehog/MirageCore/Misc/hhVertexDeclarationPtr.h"
#include "Hedgehog/MirageCore/RenderData/hhMaterialData.h" #include "Hedgehog/MirageCore/RenderData/hhMaterialData.h"
#include "Hedgehog/MirageCore/RenderData/hhMeshData.h" #include "Hedgehog/MirageCore/RenderData/hhMeshData.h"
#include "Hedgehog/MirageCore/RenderData/hhMeshIndexData.h"
#include "Hedgehog/MirageCore/RenderData/hhModelData.h" #include "Hedgehog/MirageCore/RenderData/hhModelData.h"
#include "Hedgehog/MirageCore/RenderData/hhMorphModelData.h"
#include "Hedgehog/MirageCore/RenderData/hhNodeGroupModelData.h" #include "Hedgehog/MirageCore/RenderData/hhNodeGroupModelData.h"
#include "Hedgehog/MirageCore/RenderData/hhPixelShaderCodeData.h" #include "Hedgehog/MirageCore/RenderData/hhPixelShaderCodeData.h"
#include "Hedgehog/MirageCore/RenderData/hhPixelShaderData.h" #include "Hedgehog/MirageCore/RenderData/hhPixelShaderData.h"

View file

@ -3183,6 +3183,12 @@ static void SanitizePipelineState(PipelineState& pipelineState)
pipelineState.blendOpAlpha = RenderBlendOperation::ADD; pipelineState.blendOpAlpha = RenderBlendOperation::ADD;
} }
for (size_t i = 0; i < 16; i++)
{
if (!pipelineState.vertexDeclaration->vertexStreams[i])
pipelineState.vertexStrides[i] = 0;
}
uint32_t specConstantsMask = 0; uint32_t specConstantsMask = 0;
if (pipelineState.vertexShader->shaderCacheEntry != nullptr) if (pipelineState.vertexShader->shaderCacheEntry != nullptr)
specConstantsMask |= pipelineState.vertexShader->shaderCacheEntry->specConstantsMask; specConstantsMask |= pipelineState.vertexShader->shaderCacheEntry->specConstantsMask;
@ -3964,6 +3970,8 @@ static GuestVertexDeclaration* CreateVertexDeclarationWithoutAddRef(GuestVertexE
break; break;
} }
vertexDeclaration->vertexStreams[vertexElement->stream] = true;
++vertexElement; ++vertexElement;
} }
@ -5220,28 +5228,42 @@ enum class MeshLayer
Special Special
}; };
static void CompileMeshPipeline(Hedgehog::Mirage::CMeshData* mesh, MeshLayer layer, CompilationArgs& args) struct Mesh
{ {
if (mesh->m_spMaterial.get() == nullptr || mesh->m_spMaterial->m_spShaderListData.get() == nullptr) uint32_t vertexSize{};
uint32_t morphTargetVertexSize{};
GuestVertexDeclaration* vertexDeclaration{};
Hedgehog::Mirage::CMaterialData* material{};
MeshLayer layer{};
bool morphModel{};
};
static void CompileMeshPipeline(const Mesh& mesh, CompilationArgs& args)
{
if (mesh.material == nullptr || mesh.material->m_spShaderListData.get() == nullptr)
return; return;
auto& material = mesh->m_spMaterial; auto& shaderList = mesh.material->m_spShaderListData;
auto& shaderList = material->m_spShaderListData;
bool isFur = strstr(shaderList->m_TypeAndName.c_str(), "Fur") != nullptr; bool isFur = !mesh.morphModel &&
bool isSky = strstr(shaderList->m_TypeAndName.c_str(), "Sky") != nullptr; strstr(shaderList->m_TypeAndName.c_str(), "Fur") != nullptr;
bool isSonicMouth = strcmp(material->m_TypeAndName.c_str() + 2, "sonic_gm_mouth_duble") == 0 &&
bool isSky = !mesh.morphModel &&
strstr(shaderList->m_TypeAndName.c_str(), "Sky") != nullptr;
bool isSonicMouth = !mesh.morphModel &&
strcmp(mesh.material->m_TypeAndName.c_str() + 2, "sonic_gm_mouth_duble") == 0 &&
strcmp(shaderList->m_TypeAndName.c_str() + 3, "SonicSkin_dspf[b]") == 0; strcmp(shaderList->m_TypeAndName.c_str() + 3, "SonicSkin_dspf[b]") == 0;
bool compiledOutsideMainFramebuffer = !isFur && !isSky; bool compiledOutsideMainFramebuffer = !isFur && !isSky;
bool constTexCoord = true; bool constTexCoord = true;
if (material->m_spTexsetData.get() != nullptr) if (mesh.material->m_spTexsetData.get() != nullptr)
{ {
for (size_t i = 1; i < material->m_spTexsetData->m_TextureList.size(); i++) for (size_t i = 1; i < mesh.material->m_spTexsetData->m_TextureList.size(); i++)
{ {
if (material->m_spTexsetData->m_TextureList[i]->m_TexcoordIndex != if (mesh.material->m_spTexsetData->m_TextureList[i]->m_TexcoordIndex !=
material->m_spTexsetData->m_TextureList[0]->m_TexcoordIndex) mesh.material->m_spTexsetData->m_TextureList[0]->m_TexcoordIndex)
{ {
constTexCoord = false; constTexCoord = false;
break; break;
@ -5249,14 +5271,12 @@ static void CompileMeshPipeline(Hedgehog::Mirage::CMeshData* mesh, MeshLayer lay
} }
} }
auto vertexDeclaration = reinterpret_cast<GuestVertexDeclaration*>(mesh->m_VertexDeclarationPtr.m_pD3DVertexDeclaration.get());
// Shadow pipeline. // Shadow pipeline.
if (compiledOutsideMainFramebuffer && (layer == MeshLayer::Opaque || layer == MeshLayer::PunchThrough)) if (compiledOutsideMainFramebuffer && (mesh.layer == MeshLayer::Opaque || mesh.layer == MeshLayer::PunchThrough))
{ {
PipelineState pipelineState{}; PipelineState pipelineState{};
if (layer == MeshLayer::PunchThrough) if (mesh.layer == MeshLayer::PunchThrough)
{ {
pipelineState.vertexShader = FindShaderCacheEntry(0xDD4FA7BB53876300)->guestShader; pipelineState.vertexShader = FindShaderCacheEntry(0xDD4FA7BB53876300)->guestShader;
pipelineState.pixelShader = FindShaderCacheEntry(0xE2ECA594590DDE8B)->guestShader; pipelineState.pixelShader = FindShaderCacheEntry(0xE2ECA594590DDE8B)->guestShader;
@ -5266,35 +5286,49 @@ static void CompileMeshPipeline(Hedgehog::Mirage::CMeshData* mesh, MeshLayer lay
pipelineState.vertexShader = FindShaderCacheEntry(0x8E4BB23465BD909E)->guestShader; pipelineState.vertexShader = FindShaderCacheEntry(0x8E4BB23465BD909E)->guestShader;
} }
pipelineState.vertexDeclaration = vertexDeclaration; pipelineState.vertexDeclaration = mesh.vertexDeclaration;
pipelineState.cullMode = material->m_DoubleSided ? RenderCullMode::NONE : RenderCullMode::BACK; pipelineState.cullMode = mesh.material->m_DoubleSided ? RenderCullMode::NONE : RenderCullMode::BACK;
pipelineState.zFunc = RenderComparisonFunction::LESS_EQUAL; pipelineState.zFunc = RenderComparisonFunction::LESS_EQUAL;
pipelineState.depthBias = (1 << 24) * (*reinterpret_cast<be<float>*>(g_memory.Translate(0x83302760))); pipelineState.depthBias = (1 << 24) * (*reinterpret_cast<be<float>*>(g_memory.Translate(0x83302760)));
pipelineState.slopeScaledDepthBias = *reinterpret_cast<be<float>*>(g_memory.Translate(0x83302764)); pipelineState.slopeScaledDepthBias = *reinterpret_cast<be<float>*>(g_memory.Translate(0x83302764));
pipelineState.colorWriteEnable = 0; pipelineState.colorWriteEnable = 0;
pipelineState.primitiveTopology = RenderPrimitiveTopology::TRIANGLE_STRIP; pipelineState.primitiveTopology = RenderPrimitiveTopology::TRIANGLE_STRIP;
pipelineState.vertexStrides[0] = mesh->m_VertexSize; pipelineState.vertexStrides[0] = mesh.vertexSize;
pipelineState.depthStencilFormat = RenderFormat::D32_FLOAT; pipelineState.depthStencilFormat = RenderFormat::D32_FLOAT;
if (layer == MeshLayer::PunchThrough) if (mesh.layer == MeshLayer::PunchThrough)
pipelineState.specConstants |= SPEC_CONSTANT_ALPHA_TEST; pipelineState.specConstants |= SPEC_CONSTANT_ALPHA_TEST;
const char* name = (mesh.layer == MeshLayer::PunchThrough ? "MakeShadowMapTransparent" : "MakeShadowMap");
SanitizePipelineState(pipelineState); SanitizePipelineState(pipelineState);
EnqueueGraphicsPipelineCompilation(pipelineState, args.holderPair, layer == MeshLayer::PunchThrough ? "MakeShadowMapTransparent" : "MakeShadowMap"); EnqueueGraphicsPipelineCompilation(pipelineState, args.holderPair, name);
// Morph models have 4 targets where unused targets default to the first vertex stream.
if (mesh.morphModel)
{
for (size_t i = 0; i < 5; i++)
{
for (size_t j = 0; j < 4; j++)
pipelineState.vertexStrides[j + 1] = i > j ? mesh.morphTargetVertexSize : mesh.vertexSize;
SanitizePipelineState(pipelineState);
EnqueueGraphicsPipelineCompilation(pipelineState, args.holderPair, name);
}
}
} }
// Motion blur pipeline. We could normally do the player here only, but apparently Werehog enemies also have object blur. // Motion blur pipeline. We could normally do the player here only, but apparently Werehog enemies also have object blur.
// TODO: Do punch through meshes get rendered? // TODO: Do punch through meshes get rendered?
if (compiledOutsideMainFramebuffer && args.hasMoreThanOneBone && layer == MeshLayer::Opaque) if (!mesh.morphModel && compiledOutsideMainFramebuffer && args.hasMoreThanOneBone && mesh.layer == MeshLayer::Opaque)
{ {
PipelineState pipelineState{}; PipelineState pipelineState{};
pipelineState.vertexShader = FindShaderCacheEntry(0x4620B236DC38100C)->guestShader; pipelineState.vertexShader = FindShaderCacheEntry(0x4620B236DC38100C)->guestShader;
pipelineState.pixelShader = FindShaderCacheEntry(0xBBDB735BEACC8F41)->guestShader; pipelineState.pixelShader = FindShaderCacheEntry(0xBBDB735BEACC8F41)->guestShader;
pipelineState.vertexDeclaration = vertexDeclaration; pipelineState.vertexDeclaration = mesh.vertexDeclaration;
pipelineState.cullMode = RenderCullMode::NONE; pipelineState.cullMode = RenderCullMode::NONE;
pipelineState.zFunc = RenderComparisonFunction::GREATER_EQUAL; pipelineState.zFunc = RenderComparisonFunction::GREATER_EQUAL;
pipelineState.primitiveTopology = RenderPrimitiveTopology::TRIANGLE_STRIP; pipelineState.primitiveTopology = RenderPrimitiveTopology::TRIANGLE_STRIP;
pipelineState.vertexStrides[0] = mesh->m_VertexSize; pipelineState.vertexStrides[0] = mesh.vertexSize;
pipelineState.renderTargetFormat = RenderFormat::R8G8B8A8_UNORM; pipelineState.renderTargetFormat = RenderFormat::R8G8B8A8_UNORM;
pipelineState.depthStencilFormat = RenderFormat::D32_FLOAT; pipelineState.depthStencilFormat = RenderFormat::D32_FLOAT;
pipelineState.specConstants = SPEC_CONSTANT_REVERSE_Z; pipelineState.specConstants = SPEC_CONSTANT_REVERSE_Z;
@ -5322,7 +5356,8 @@ static void CompileMeshPipeline(Hedgehog::Mirage::CMeshData* mesh, MeshLayer lay
if ((defaultFindResult->second.m_SubPermutations.get() & (1 << pixelShaderSubPermutationsToCompile)) == 0) pixelShaderSubPermutationsToCompile &= ~0x1; if ((defaultFindResult->second.m_SubPermutations.get() & (1 << pixelShaderSubPermutationsToCompile)) == 0) pixelShaderSubPermutationsToCompile &= ~0x1;
if ((defaultFindResult->second.m_SubPermutations.get() & (1 << pixelShaderSubPermutationsToCompile)) == 0) pixelShaderSubPermutationsToCompile &= ~0x2; if ((defaultFindResult->second.m_SubPermutations.get() & (1 << pixelShaderSubPermutationsToCompile)) == 0) pixelShaderSubPermutationsToCompile &= ~0x2;
guest_stack_var<Hedgehog::Base::CStringSymbol> noneSymbol(reinterpret_cast<const char*>(g_memory.Translate(0x8200D938))); uint32_t noneStr = mesh.morphModel ? 0x820D72F0 : 0x8200D938; // "p" for morph, "none" for regular
guest_stack_var<Hedgehog::Base::CStringSymbol> noneSymbol(reinterpret_cast<const char*>(g_memory.Translate(noneStr)));
auto noneFindResult = defaultFindResult->second.m_VertexShaderPermutations.find(*noneSymbol); auto noneFindResult = defaultFindResult->second.m_VertexShaderPermutations.find(*noneSymbol);
if (noneFindResult == defaultFindResult->second.m_VertexShaderPermutations.end()) if (noneFindResult == defaultFindResult->second.m_VertexShaderPermutations.end())
return; return;
@ -5333,15 +5368,17 @@ static void CompileMeshPipeline(Hedgehog::Mirage::CMeshData* mesh, MeshLayer lay
if ((noneFindResult->second->m_SubPermutations.get() & (1 << vertexShaderSubPermutationsToCompile)) == 0) if ((noneFindResult->second->m_SubPermutations.get() & (1 << vertexShaderSubPermutationsToCompile)) == 0)
vertexShaderSubPermutationsToCompile &= ~0x1; vertexShaderSubPermutationsToCompile &= ~0x1;
auto vertexDeclaration = mesh.vertexDeclaration;
// Fur requires an instanced variant of the vertex declaration. // Fur requires an instanced variant of the vertex declaration.
if (isFur) if (isFur)
{ {
GuestVertexElement vertexElements[64]; GuestVertexElement vertexElements[64];
memcpy(vertexElements, vertexDeclaration->vertexElements.get(), (vertexDeclaration->vertexElementCount - 1) * sizeof(GuestVertexElement)); memcpy(vertexElements, mesh.vertexDeclaration->vertexElements.get(), (mesh.vertexDeclaration->vertexElementCount - 1) * sizeof(GuestVertexElement));
vertexElements[vertexDeclaration->vertexElementCount - 1] = { 1, 0, 0x2C82A1, 0, 0, 1 }; vertexElements[mesh.vertexDeclaration->vertexElementCount - 1] = { 1, 0, 0x2C82A1, 0, 0, 1 };
vertexElements[vertexDeclaration->vertexElementCount] = { 2, 0, 0x2C83A4, 0, 0, 2 }; vertexElements[mesh.vertexDeclaration->vertexElementCount] = { 2, 0, 0x2C83A4, 0, 0, 2 };
vertexElements[vertexDeclaration->vertexElementCount + 1] = D3DDECL_END(); vertexElements[mesh.vertexDeclaration->vertexElementCount + 1] = D3DDECL_END();
vertexDeclaration = CreateVertexDeclarationWithoutAddRef(vertexElements); vertexDeclaration = CreateVertexDeclarationWithoutAddRef(vertexElements);
} }
@ -5361,16 +5398,16 @@ static void CompileMeshPipeline(Hedgehog::Mirage::CMeshData* mesh, MeshLayer lay
pipelineState.pixelShader = reinterpret_cast<GuestShader*>(pixelShader->m_spCode->m_pD3DPixelShader.get()); pipelineState.pixelShader = reinterpret_cast<GuestShader*>(pixelShader->m_spCode->m_pD3DPixelShader.get());
pipelineState.vertexDeclaration = vertexDeclaration; pipelineState.vertexDeclaration = vertexDeclaration;
pipelineState.instancing = isFur; pipelineState.instancing = isFur;
pipelineState.zWriteEnable = !isSky && layer != MeshLayer::Transparent; pipelineState.zWriteEnable = !isSky && mesh.layer != MeshLayer::Transparent;
pipelineState.srcBlend = RenderBlend::SRC_ALPHA; pipelineState.srcBlend = RenderBlend::SRC_ALPHA;
pipelineState.destBlend = material->m_Additive ? RenderBlend::ONE : RenderBlend::INV_SRC_ALPHA; pipelineState.destBlend = mesh.material->m_Additive ? RenderBlend::ONE : RenderBlend::INV_SRC_ALPHA;
pipelineState.cullMode = material->m_DoubleSided ? RenderCullMode::NONE : RenderCullMode::BACK; pipelineState.cullMode = mesh.material->m_DoubleSided ? RenderCullMode::NONE : RenderCullMode::BACK;
pipelineState.zFunc = RenderComparisonFunction::GREATER_EQUAL; // Reverse Z pipelineState.zFunc = RenderComparisonFunction::GREATER_EQUAL; // Reverse Z
pipelineState.alphaBlendEnable = layer == MeshLayer::Transparent || layer == MeshLayer::Special; pipelineState.alphaBlendEnable = mesh.layer == MeshLayer::Transparent || mesh.layer == MeshLayer::Special;
pipelineState.srcBlendAlpha = RenderBlend::SRC_ALPHA; pipelineState.srcBlendAlpha = RenderBlend::SRC_ALPHA;
pipelineState.destBlendAlpha = RenderBlend::INV_SRC_ALPHA; pipelineState.destBlendAlpha = RenderBlend::INV_SRC_ALPHA;
pipelineState.primitiveTopology = RenderPrimitiveTopology::TRIANGLE_STRIP; pipelineState.primitiveTopology = RenderPrimitiveTopology::TRIANGLE_STRIP;
pipelineState.vertexStrides[0] = mesh->m_VertexSize; pipelineState.vertexStrides[0] = mesh.vertexSize;
pipelineState.vertexStrides[1] = isFur ? 4 : 0; pipelineState.vertexStrides[1] = isFur ? 4 : 0;
pipelineState.vertexStrides[2] = isFur ? 4 : 0; pipelineState.vertexStrides[2] = isFur ? 4 : 0;
pipelineState.renderTargetFormat = RenderFormat::R16G16B16A16_FLOAT; pipelineState.renderTargetFormat = RenderFormat::R16G16B16A16_FLOAT;
@ -5383,7 +5420,7 @@ static void CompileMeshPipeline(Hedgehog::Mirage::CMeshData* mesh, MeshLayer lay
if (Config::GITextureFiltering == EGITextureFiltering::Bicubic) if (Config::GITextureFiltering == EGITextureFiltering::Bicubic)
pipelineState.specConstants |= SPEC_CONSTANT_BICUBIC_GI_FILTER; pipelineState.specConstants |= SPEC_CONSTANT_BICUBIC_GI_FILTER;
if (layer == MeshLayer::PunchThrough) if (mesh.layer == MeshLayer::PunchThrough)
{ {
if (Config::AntiAliasing != EAntiAliasing::None && Config::TransparencyAntiAliasing) if (Config::AntiAliasing != EAntiAliasing::None && Config::TransparencyAntiAliasing)
{ {
@ -5403,6 +5440,19 @@ static void CompileMeshPipeline(Hedgehog::Mirage::CMeshData* mesh, MeshLayer lay
{ {
SanitizePipelineState(pipelineStateToCreate); SanitizePipelineState(pipelineStateToCreate);
EnqueueGraphicsPipelineCompilation(pipelineStateToCreate, args.holderPair, shaderList->m_TypeAndName.c_str() + 3); EnqueueGraphicsPipelineCompilation(pipelineStateToCreate, args.holderPair, shaderList->m_TypeAndName.c_str() + 3);
// Morph models have 4 targets where unused targets default to the first vertex stream.
if (mesh.morphModel)
{
for (size_t i = 0; i < 5; i++)
{
for (size_t j = 0; j < 4; j++)
pipelineStateToCreate.vertexStrides[j + 1] = i > j ? mesh.morphTargetVertexSize : mesh.vertexSize;
SanitizePipelineState(pipelineStateToCreate);
EnqueueGraphicsPipelineCompilation(pipelineStateToCreate, args.holderPair, shaderList->m_TypeAndName.c_str() + 3);
}
}
}; };
createGraphicsPipeline(pipelineState); createGraphicsPipeline(pipelineState);
@ -5454,6 +5504,32 @@ static void CompileMeshPipeline(Hedgehog::Mirage::CMeshData* mesh, MeshLayer lay
} }
} }
static void CompileMeshPipeline(Hedgehog::Mirage::CMeshData* mesh, MeshLayer layer, CompilationArgs& args)
{
CompileMeshPipeline(Mesh
{
mesh->m_VertexSize,
0,
reinterpret_cast<GuestVertexDeclaration*>(mesh->m_VertexDeclarationPtr.m_pD3DVertexDeclaration.get()),
mesh->m_spMaterial.get(),
layer,
false
}, args);
}
static void CompileMeshPipeline(Hedgehog::Mirage::CMorphModelData* morphModel, Hedgehog::Mirage::CMeshIndexData* mesh, MeshLayer layer, CompilationArgs& args)
{
CompileMeshPipeline(Mesh
{
morphModel->m_VertexSize,
morphModel->m_MorphTargetVertexSize,
reinterpret_cast<GuestVertexDeclaration*>(morphModel->m_VertexDeclarationPtr.m_pD3DVertexDeclaration.get()),
mesh->m_spMaterial.get(),
layer,
true
}, args);
}
template<typename T> template<typename T>
static void CompileMeshPipelines(const T& modelData, CompilationArgs& args) static void CompileMeshPipelines(const T& modelData, CompilationArgs& args)
{ {
@ -5493,6 +5569,21 @@ static void CompileMeshPipelines(const T& modelData, CompilationArgs& args)
for (auto& mesh : modelData.m_PunchThroughMeshes) for (auto& mesh : modelData.m_PunchThroughMeshes)
CompileMeshPipeline(mesh.get(), MeshLayer::PunchThrough, args); CompileMeshPipeline(mesh.get(), MeshLayer::PunchThrough, args);
if constexpr (std::is_same_v<T, Hedgehog::Mirage::CModelData>)
{
for (auto& morphModel : modelData.m_MorphModels)
{
for (auto& mesh : morphModel->m_OpaqueMeshList)
CompileMeshPipeline(morphModel.get(), mesh.get(), MeshLayer::Opaque, args);
for (auto& mesh : morphModel->m_TransparentMeshList)
CompileMeshPipeline(morphModel.get(), mesh.get(), MeshLayer::Transparent, args);
for (auto& mesh : morphModel->m_PunchThroughMeshList)
CompileMeshPipeline(morphModel.get(), mesh.get(), MeshLayer::PunchThrough, args);
}
}
} }
static void CompileParticleMaterialPipeline(const Hedgehog::Sparkle::CParticleMaterial& material, DatabaseDataHolderPair& holderPair) static void CompileParticleMaterialPipeline(const Hedgehog::Sparkle::CParticleMaterial& material, DatabaseDataHolderPair& holderPair)

View file

@ -270,6 +270,7 @@ struct GuestVertexDeclaration : GuestResource
uint32_t vertexElementCount = 0; uint32_t vertexElementCount = 0;
uint32_t swappedTexcoords = 0; uint32_t swappedTexcoords = 0;
bool hasR11G11B10Normal = false; bool hasR11G11B10Normal = false;
bool vertexStreams[16]{};
uint32_t indexVertexStream = 0; uint32_t indexVertexStream = 0;
}; };