Starting framework for static mesh rendering
This commit is contained in:
@@ -26,12 +26,12 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target
|
||||
{
|
||||
result += pLightEnv.directionalLights[i].illuminate(lightingParams, brdf);
|
||||
}
|
||||
for(uint i = 0; i < lightCount; ++i)
|
||||
for(uint i = 0; i < pLightEnv.numPointLights; ++i)
|
||||
{
|
||||
uint lightIndex = pLightCullingData.lightIndexList[startOffset + i];
|
||||
result += pLightEnv.pointLights[lightIndex].illuminate(lightingParams, brdf);
|
||||
//uint lightIndex = pLightCullingData.lightIndexList[startOffset + i];
|
||||
result += pLightEnv.pointLights[i].illuminate(lightingParams, brdf);
|
||||
}
|
||||
result += brdf.evaluateAmbient();
|
||||
//result += brdf.evaluateAmbient();
|
||||
// gamma correction
|
||||
result = result / (result + float3(1.0));
|
||||
result = pow(result, float3(1.0/2.2));
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import Common;
|
||||
import BRDF;
|
||||
import Scene;
|
||||
import VertexData;
|
||||
import MaterialParameter;
|
||||
|
||||
struct PrimitiveAttributes
|
||||
{
|
||||
uint cull: SV_CullPrimitive;
|
||||
};
|
||||
|
||||
[numthreads(MESH_GROUP_SIZE, 1, 1)]
|
||||
[outputtopology("triangle")]
|
||||
[shader("mesh")]
|
||||
void meshMain(
|
||||
in uint threadID: SV_GroupIndex,
|
||||
in uint groupID: SV_GroupID,
|
||||
out vertices FragmentParameter vertices[MAX_VERTICES],
|
||||
out indices uint3 indices[MAX_PRIMITIVES]
|
||||
){
|
||||
MeshletDescription m = pScene.meshletInfos[groupID];
|
||||
SetMeshOutputCounts(m.vertexCount, m.primitiveCount);
|
||||
|
||||
for(uint i = threadID; i < MAX_PRIMITIVES; i += MESH_GROUP_SIZE)
|
||||
{
|
||||
uint p = min(i, m.primitiveCount - 1);
|
||||
{
|
||||
uint local_idx0 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 0];
|
||||
uint local_idx1 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 1];
|
||||
uint local_idx2 = pScene.primitiveIndices[m.primitiveOffset + (p * 3) + 2];
|
||||
indices[p] = uint3(local_idx0, local_idx1, local_idx2);
|
||||
}
|
||||
}
|
||||
for(uint i = threadID; i < MAX_VERTICES; i+=MESH_GROUP_SIZE)
|
||||
{
|
||||
uint v = min(i, m.vertexCount - 1);
|
||||
{
|
||||
uint vertexIndex = pScene.vertexIndices[m.vertexOffset + v];
|
||||
VertexAttributes attr = pVertexData.getAttributes(md.indicesOffset + vertexIndex);
|
||||
vertices[v] = attr.getParameter(float4x4(1.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,11 +58,16 @@ float4 screenToView(float4 screen)
|
||||
return clipToView(clip);
|
||||
}
|
||||
|
||||
float4 screenToModel(float4x4 inverseTransform, float4 screen)
|
||||
float4 screenToWorld(float4 screen)
|
||||
{
|
||||
float4 view = screenToView(screen);
|
||||
|
||||
float4 world = viewToWorld(view);
|
||||
return viewToWorld(view);
|
||||
}
|
||||
|
||||
float4 screenToModel(float4x4 inverseTransform, float4 screen)
|
||||
{
|
||||
float4 world = screenToWorld(screen);
|
||||
|
||||
return worldToModel(inverseTransform, world);
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path&
|
||||
texPath = (meshDirectory / texPath).replace_extension("png");
|
||||
if (tex->mHeight == 0)
|
||||
{
|
||||
std::cout << "Dumping texture " << texPath << std::endl;
|
||||
// already compressed, just dump it to the disk
|
||||
std::ofstream file(texPath, std::ios::binary);
|
||||
file.write((const char*)tex->pcData, tex->mWidth);
|
||||
@@ -76,6 +77,7 @@ void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path&
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Writing extracted png " << texPath << std::endl;
|
||||
// recompress data so that the TextureLoader can read it
|
||||
unsigned char* texData = new unsigned char[tex->mWidth * tex->mHeight * 4];
|
||||
convertAssimpARGB(texData, tex->pcData, tex->mWidth * tex->mHeight);
|
||||
@@ -412,8 +414,8 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array<PTextureAsset>&
|
||||
case aiShadingMode_Toon:
|
||||
brdf.profile = "CelShading";
|
||||
break;
|
||||
case aiShadingMode_CookTorrance:
|
||||
default:
|
||||
case aiShadingMode_CookTorrance:
|
||||
brdf.profile = "CookTorrance";
|
||||
brdf.variables["roughness"] = outputRoughness;
|
||||
brdf.variables["metallic"] = outputMetallic;
|
||||
|
||||
@@ -61,7 +61,12 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset)
|
||||
auto ktxFile = args.filePath;
|
||||
ktxFile.replace_extension("ktx");
|
||||
std::stringstream ss;
|
||||
ss << "toktx --encode etc1s " << ktxFile << " " << args.filePath;
|
||||
ss << "toktx --encode etc1s ";
|
||||
if (args.type == TextureImportType::TEXTURE_NORMAL)
|
||||
{
|
||||
ss << "--normal_mode ";
|
||||
}
|
||||
ss << ktxFile << " " << args.filePath;
|
||||
system(ss.str().c_str());
|
||||
args.filePath = ktxFile;
|
||||
}
|
||||
|
||||
+1
-4
@@ -58,15 +58,12 @@ int main() {
|
||||
AssetImporter::importMesh(MeshImportArgs{
|
||||
.filePath = sourcePath / "import/models/cube.fbx",
|
||||
});
|
||||
//AssetImporter::importMesh(MeshImportArgs{
|
||||
// .filePath = sourcePath / "import/models/Arissa.fbx",
|
||||
// });
|
||||
AssetImporter::importMesh(MeshImportArgs{
|
||||
.filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb",
|
||||
.importPath = "Whitechapel"
|
||||
});
|
||||
//AssetImporter::importMesh(MeshImportArgs{
|
||||
// .filePath = sourcePath / "import/models/Volvo S90/Volvo S90.fbx",
|
||||
// .filePath = sourcePath / "import/models/Volvo S90/Volvo S90.blend",
|
||||
// .importPath = "Volvo",
|
||||
// });
|
||||
WindowCreateInfo mainWindowInfo;
|
||||
|
||||
@@ -14,6 +14,8 @@ struct KeyboardInput
|
||||
float mouseY;
|
||||
float deltaX;
|
||||
float deltaY;
|
||||
float scrollX;
|
||||
float scrollY;
|
||||
};
|
||||
} // namespace Component
|
||||
} // namespace Seele
|
||||
@@ -8,6 +8,7 @@ namespace Component
|
||||
struct Mesh
|
||||
{
|
||||
PMeshAsset asset;
|
||||
bool isStatic = true;
|
||||
};
|
||||
} // namespace Component
|
||||
} // namespace Seele
|
||||
|
||||
@@ -14,8 +14,8 @@ public:
|
||||
virtual ~RenderCommand();
|
||||
virtual void setViewport(Gfx::PViewport viewport) = 0;
|
||||
virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) = 0;
|
||||
virtual void bindDescriptor(Gfx::PDescriptorSet set) = 0;
|
||||
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) = 0;
|
||||
virtual void bindDescriptor(Gfx::PDescriptorSet set, Array<uint32> dynamicOffsets = {}) = 0;
|
||||
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets, Array<uint32> dynamicOffsets = {}) = 0;
|
||||
virtual void bindVertexBuffer(const Array<PVertexBuffer>& buffer) = 0;
|
||||
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) = 0;
|
||||
virtual void pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) = 0;
|
||||
@@ -31,8 +31,8 @@ public:
|
||||
ComputeCommand();
|
||||
virtual ~ComputeCommand();
|
||||
virtual void bindPipeline(Gfx::PComputePipeline pipeline) = 0;
|
||||
virtual void bindDescriptor(Gfx::PDescriptorSet set) = 0;
|
||||
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) = 0;
|
||||
virtual void bindDescriptor(Gfx::PDescriptorSet set, Array<uint32> dynamicOffsets = {}) = 0;
|
||||
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets, Array<uint32> dynamicOffsets = {}) = 0;
|
||||
virtual void pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) = 0;
|
||||
virtual void dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) = 0;
|
||||
std::string name;
|
||||
|
||||
@@ -24,7 +24,7 @@ struct GraphicsInitializer
|
||||
: applicationName("SeeleEngine")
|
||||
, engineName("SeeleEngine")
|
||||
, windowLayoutFile(nullptr)
|
||||
, layers{}
|
||||
, layers{"VK_LAYER_LUNARG_monitor"}
|
||||
, instanceExtensions{}
|
||||
, deviceExtensions{"VK_KHR_swapchain"}
|
||||
, windowHandle(nullptr)
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
#include "Material/MaterialInstance.h"
|
||||
#include "Graphics/Descriptor.h"
|
||||
#include "Graphics/Command.h"
|
||||
#include "Graphics/StaticMeshVertexData.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
BasePass::BasePass(Gfx::PGraphics graphics, PScene scene)
|
||||
: RenderPass(graphics, scene)
|
||||
, descriptorSets(6)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -56,19 +56,103 @@ void BasePass::render()
|
||||
opaqueCulling->writeChanges();
|
||||
transparentCulling->writeChanges();
|
||||
|
||||
graphics->beginRenderPass(renderPass);
|
||||
Array<Gfx::ORenderCommand> commands;
|
||||
// Static Meshes
|
||||
{
|
||||
Gfx::ShaderPermutation permutation;
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
permutation.setTaskFile("MeshletBasePass");
|
||||
permutation.setMeshFile("MeshletBasePass");
|
||||
permutation.setTaskFile("StaticMeshletPass");
|
||||
permutation.setMeshFile("StaticMeshletPass");
|
||||
}
|
||||
else
|
||||
{
|
||||
permutation.setVertexFile("LegacyBasePass");
|
||||
permutation.setVertexFile("StaticLegacyPass");
|
||||
}
|
||||
permutation.setFragmentFile("BasePass");
|
||||
StaticMeshVertexData* vd = StaticMeshVertexData::getInstance();
|
||||
permutation.setVertexData(vd->getTypeName());
|
||||
for (const auto& [_, mappings] : vd->getStaticMeshes())
|
||||
{
|
||||
for (const auto& mapping : mappings)
|
||||
{
|
||||
permutation.setMaterial(mapping.material->getBaseMaterial()->getName());
|
||||
Gfx::PermutationId id(permutation);
|
||||
|
||||
Gfx::ORenderCommand command = graphics->createRenderCommand("BaseRender");
|
||||
command->setViewport(viewport);
|
||||
|
||||
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
|
||||
assert(collection != nullptr);
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
Gfx::MeshPipelineCreateInfo pipelineInfo;
|
||||
pipelineInfo.taskShader = collection->taskShader;
|
||||
pipelineInfo.meshShader = collection->meshShader;
|
||||
pipelineInfo.fragmentShader = collection->fragmentShader;
|
||||
pipelineInfo.pipelineLayout = collection->pipelineLayout;
|
||||
pipelineInfo.renderPass = renderPass;
|
||||
pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL;
|
||||
pipelineInfo.multisampleState.samples = viewport->getSamples();
|
||||
pipelineInfo.colorBlend.attachmentCount = 1;
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
else
|
||||
{
|
||||
Gfx::LegacyPipelineCreateInfo pipelineInfo;
|
||||
pipelineInfo.vertexShader = collection->vertexShader;
|
||||
pipelineInfo.fragmentShader = collection->fragmentShader;
|
||||
pipelineInfo.pipelineLayout = collection->pipelineLayout;
|
||||
pipelineInfo.renderPass = renderPass;
|
||||
pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL;
|
||||
pipelineInfo.multisampleState.samples = viewport->getSamples();
|
||||
pipelineInfo.colorBlend.attachmentCount = 1;
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
command->bindDescriptor(vd->getVertexDataSet());
|
||||
command->bindDescriptor(viewParamsSet);
|
||||
command->bindDescriptor(scene->getLightEnvironment()->getDescriptorSet());
|
||||
command->bindDescriptor(opaqueCulling);
|
||||
command->bindDescriptor(mapping.material->getDescriptorSet());
|
||||
command->bindDescriptor(vd->getInstanceDataSet(), {0, 0});
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
command->drawMesh(vd->getMeshData(mapping.mapped).size(), 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
command->bindIndexBuffer(vd->getIndexBuffer());
|
||||
uint32 instanceOffset = 0;
|
||||
for (const auto& meshData : vd->getMeshData(mapping.mapped))
|
||||
{
|
||||
if (meshData.numIndices > 0)
|
||||
{
|
||||
command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, meshData.indicesOffset, instanceOffset);
|
||||
}
|
||||
instanceOffset++;
|
||||
}
|
||||
}
|
||||
|
||||
commands.add(std::move(command));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Others
|
||||
{
|
||||
Gfx::ShaderPermutation permutation;
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
permutation.setTaskFile("MeshletPass");
|
||||
permutation.setMeshFile("MeshletPass");
|
||||
}
|
||||
else
|
||||
{
|
||||
permutation.setVertexFile("LegacyPass");
|
||||
}
|
||||
permutation.setFragmentFile("BasePass");
|
||||
graphics->beginRenderPass(renderPass);
|
||||
Array<Gfx::ORenderCommand> commands;
|
||||
for (VertexData* vertexData : VertexData::getList())
|
||||
{
|
||||
permutation.setVertexData(vertexData->getTypeName());
|
||||
@@ -125,16 +209,16 @@ void BasePass::render()
|
||||
for (const auto& [_, instance] : materialData.instances)
|
||||
{
|
||||
command->bindDescriptor(instance.materialInstance->getDescriptorSet());
|
||||
command->bindDescriptor(instance.descriptorSet);
|
||||
command->bindDescriptor(vertexData->getInstanceDataSet(), {instance.descriptorOffset, instance.descriptorOffset});
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
command->drawMesh(instance.meshes.size(), 1, 1);
|
||||
command->drawMesh(vertexData->getMeshData(instance.meshId).size(), 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
command->bindIndexBuffer(vertexData->getIndexBuffer());
|
||||
uint32 instanceOffset = 0;
|
||||
for (const auto& [instance, meshData] : instance.meshes)
|
||||
for (const auto& meshData : vertexData->getMeshData(instance.meshId))
|
||||
{
|
||||
if (meshData.numIndices > 0)
|
||||
{
|
||||
@@ -147,6 +231,8 @@ void BasePass::render()
|
||||
commands.add(std::move(command));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
graphics->executeCommands(std::move(commands));
|
||||
graphics->endRenderPass();
|
||||
}
|
||||
@@ -177,18 +263,20 @@ void BasePass::publishOutputs()
|
||||
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "BasePass", "MeshletBasePass", true, true, "BasePass", true, true, "MeshletBasePass");
|
||||
graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "BasePass", "MeshletPass", true, true, "BasePass", true, true, "MeshBasePass");
|
||||
graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "StaticBasePass", "StaticMeshletPass", true, true, "BasePass", true, true, "StaticMeshletPass");
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "BasePass", "LegacyBasePass", true, true, "BasePass");
|
||||
graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "BasePass", "LegacyPass", true, true, "BasePass");
|
||||
graphics->getShaderCompiler()->registerRenderPass(basePassLayout, "StaticBasePass", "StaticLegacyPass", true, true, "BasePass");
|
||||
}
|
||||
}
|
||||
|
||||
void BasePass::createRenderPass()
|
||||
{
|
||||
depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH");
|
||||
depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR);
|
||||
depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
|
||||
depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL);
|
||||
depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
|
||||
|
||||
@@ -17,7 +17,6 @@ public:
|
||||
virtual void endFrame() override;
|
||||
virtual void publishOutputs() override;
|
||||
virtual void createRenderPass() override;
|
||||
static void modifyRenderPassMacros(Map<const char*, const char*>& defines);
|
||||
private:
|
||||
Gfx::RenderTargetAttachment colorAttachment;
|
||||
Gfx::RenderTargetAttachment depthAttachment;
|
||||
@@ -28,22 +27,10 @@ private:
|
||||
|
||||
Gfx::PDescriptorSet opaqueCulling;
|
||||
Gfx::PDescriptorSet transparentCulling;
|
||||
Array<Gfx::PDescriptorSet> descriptorSets;
|
||||
//Array<Gfx::PDescriptorSet> descriptorSets;
|
||||
PCameraActor source;
|
||||
Gfx::OPipelineLayout basePassLayout;
|
||||
// Set 0: viewParameter, provided by renderpass
|
||||
static constexpr uint32 INDEX_VIEW_PARAMS = 0;
|
||||
// Set 1: vertex buffers, provided by vertexdata
|
||||
static constexpr uint32 INDEX_VERTEX_DATA = 1;
|
||||
// Set 2: instance data, provided by vertexdata
|
||||
static constexpr uint32 INDEX_SCENE_DATA = 2;
|
||||
// Set 3: light environment, provided by lightenv
|
||||
static constexpr uint32 INDEX_LIGHT_ENV = 3;
|
||||
// Set 4: material data, generated from material
|
||||
static constexpr uint32 INDEX_MATERIAL = 4;
|
||||
// Set 5: light culling data
|
||||
Gfx::ODescriptorLayout lightCullingLayout;
|
||||
static constexpr uint32 INDEX_LIGHT_CULLING = 5;
|
||||
};
|
||||
DEFINE_REF(BasePass)
|
||||
} // namespace Seele
|
||||
|
||||
@@ -15,6 +15,10 @@ target_sources(Engine
|
||||
RenderPass.cpp
|
||||
SkyboxRenderPass.h
|
||||
SkyboxRenderPass.cpp
|
||||
StaticDepthPrepass.h
|
||||
StaticDepthPrepass.cpp
|
||||
StaticBasePass.h
|
||||
StaticBasePass.cpp
|
||||
TextPass.h
|
||||
TextPass.cpp
|
||||
UIPass.h
|
||||
@@ -31,5 +35,7 @@ target_sources(Engine
|
||||
RenderGraphResources.h
|
||||
RenderPass.h
|
||||
SkyboxRenderPass.h
|
||||
StaticDepthPrepass.h
|
||||
StaticBasePass.h
|
||||
TextPass.h
|
||||
UIPass.h)
|
||||
@@ -9,22 +9,22 @@
|
||||
#include "Math/Vector.h"
|
||||
#include "RenderGraph.h"
|
||||
#include "Graphics/Command.h"
|
||||
#include "Graphics/StaticMeshVertexData.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, PScene scene)
|
||||
: RenderPass(graphics, scene)
|
||||
, descriptorSets(3)
|
||||
{
|
||||
depthPrepassLayout = graphics->createPipelineLayout("DepthPrepassLayout");
|
||||
depthPrepassLayout->addDescriptorLayout(viewParamsLayout);
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "MeshletBasePass", false, false, "", true, true, "MeshletBasePass");
|
||||
graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "MeshletPass", false, false, "", true, true, "MeshletPass");
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "LegacyBasePass");
|
||||
graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "LegacyPass");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,38 +35,40 @@ DepthPrepass::~DepthPrepass()
|
||||
void DepthPrepass::beginFrame(const Component::Camera& cam)
|
||||
{
|
||||
RenderPass::beginFrame(cam);
|
||||
descriptorSets[INDEX_VIEW_PARAMS] = viewParamsSet;
|
||||
}
|
||||
|
||||
void DepthPrepass::render()
|
||||
{
|
||||
graphics->beginRenderPass(renderPass);
|
||||
Array<Gfx::ORenderCommand> commands;
|
||||
|
||||
// Others
|
||||
{
|
||||
Gfx::ShaderPermutation permutation;
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
permutation.setTaskFile("MeshletBasePass");
|
||||
permutation.setMeshFile("MeshletBasePass");
|
||||
permutation.setTaskFile("MeshletPass");
|
||||
permutation.setMeshFile("MeshletPass");
|
||||
}
|
||||
else
|
||||
{
|
||||
permutation.setVertexFile("LegacyBasePass");
|
||||
permutation.setVertexFile("LegacyPass");
|
||||
}
|
||||
graphics->beginRenderPass(renderPass);
|
||||
Array<Gfx::ORenderCommand> commands;
|
||||
for (VertexData* vertexData : VertexData::getList())
|
||||
{
|
||||
permutation.setVertexData(vertexData->getTypeName());
|
||||
const auto& materials = vertexData->getMaterialData();
|
||||
for (const auto& [_, materialData] : materials)
|
||||
{
|
||||
// Create Pipeline(Material, VertexData)
|
||||
// Create Pipeline(VertexData)
|
||||
// Descriptors:
|
||||
// ViewData => global, static
|
||||
// Material => per material
|
||||
// VertexData => per meshtype
|
||||
// SceneData => per material instance
|
||||
permutation.setMaterial(materialData.material->getName());
|
||||
Gfx::PermutationId id(permutation);
|
||||
|
||||
Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender");
|
||||
Gfx::ORenderCommand command = graphics->createRenderCommand("BaseRender");
|
||||
command->setViewport(viewport);
|
||||
|
||||
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
|
||||
@@ -81,6 +83,7 @@ void DepthPrepass::render()
|
||||
pipelineInfo.renderPass = renderPass;
|
||||
pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER;
|
||||
pipelineInfo.multisampleState.samples = viewport->getSamples();
|
||||
pipelineInfo.colorBlend.attachmentCount = 1;
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
@@ -91,39 +94,40 @@ void DepthPrepass::render()
|
||||
pipelineInfo.fragmentShader = collection->fragmentShader;
|
||||
pipelineInfo.pipelineLayout = collection->pipelineLayout;
|
||||
pipelineInfo.renderPass = renderPass;
|
||||
//pipelineInfo.depthStencilState.depthWriteEnable = false;
|
||||
pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER;
|
||||
pipelineInfo.multisampleState.samples = viewport->getSamples();
|
||||
pipelineInfo.colorBlend.attachmentCount = 1;
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
|
||||
descriptorSets[INDEX_VERTEX_DATA] = vertexData->getVertexDataSet();
|
||||
command->bindDescriptor(vertexData->getVertexDataSet());
|
||||
command->bindDescriptor(viewParamsSet);
|
||||
for (const auto& [_, instance] : materialData.instances)
|
||||
{
|
||||
//descriptorSets[INDEX_MATERIAL] = instance.materialInstance->getDescriptorSet();
|
||||
descriptorSets[INDEX_SCENE_DATA] = instance.descriptorSet;
|
||||
command->bindDescriptor(descriptorSets);
|
||||
command->bindDescriptor(vertexData->getInstanceDataSet(), { instance.descriptorOffset, instance.descriptorOffset });
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
command->drawMesh(instance.meshes.size(), 1, 1);
|
||||
command->drawMesh(vertexData->getMeshData(instance.meshId).size(), 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
command->bindIndexBuffer(vertexData->getIndexBuffer());
|
||||
uint32 instanceOffset = 0;
|
||||
for (const auto& [_, meshData] : instance.meshes)
|
||||
for (const auto& meshData : vertexData->getMeshData(instance.meshId))
|
||||
{
|
||||
if (meshData.numIndices > 0)
|
||||
{
|
||||
command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, meshData.indicesOffset, instanceOffset++);
|
||||
command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, meshData.indicesOffset, instanceOffset);
|
||||
}
|
||||
instanceOffset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
commands.add(std::move(command));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
graphics->executeCommands(std::move(commands));
|
||||
graphics->endRenderPass();
|
||||
}
|
||||
@@ -134,56 +138,8 @@ void DepthPrepass::endFrame()
|
||||
|
||||
void DepthPrepass::publishOutputs()
|
||||
{
|
||||
// If we render to a part of an image, the depth buffer itself must
|
||||
// still match the size of the whole image or their coordinate systems go out of sync
|
||||
TextureCreateInfo depthBufferInfo = {
|
||||
.format = Gfx::SE_FORMAT_D32_SFLOAT,
|
||||
.width = viewport->getOwner()->getFramebufferWidth(),
|
||||
.height = viewport->getOwner()->getFramebufferHeight(),
|
||||
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
||||
};
|
||||
depthBuffer = graphics->createTexture2D(depthBufferInfo);
|
||||
depthAttachment =
|
||||
Gfx::RenderTargetAttachment(depthBuffer,
|
||||
Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_GENERAL,
|
||||
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
|
||||
resources->registerRenderPassOutput("DEPTHPREPASS_DEPTH", depthAttachment);
|
||||
}
|
||||
|
||||
void DepthPrepass::createRenderPass()
|
||||
{
|
||||
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
|
||||
.depthAttachment = depthAttachment,
|
||||
};
|
||||
Array<Gfx::SubPassDependency> dependency = {
|
||||
{
|
||||
.srcSubpass = ~0U,
|
||||
.dstSubpass = 0,
|
||||
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
|
||||
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
},
|
||||
{
|
||||
.srcSubpass = 0,
|
||||
.dstSubpass = ~0U,
|
||||
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||
.dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT,
|
||||
},
|
||||
{
|
||||
.srcSubpass = 0,
|
||||
.dstSubpass = ~0U,
|
||||
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
|
||||
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
|
||||
}
|
||||
};
|
||||
renderPass = graphics->createRenderPass(std::move(layout), dependency, viewport);
|
||||
}
|
||||
|
||||
void DepthPrepass::modifyRenderPassMacros(Map<const char*, const char*>&)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -16,20 +16,10 @@ public:
|
||||
virtual void endFrame() override;
|
||||
virtual void publishOutputs() override;
|
||||
virtual void createRenderPass() override;
|
||||
static void modifyRenderPassMacros(Map<const char*, const char*>& defines);
|
||||
private:
|
||||
Gfx::RenderTargetAttachment depthAttachment;
|
||||
Gfx::OTexture2D depthBuffer;
|
||||
|
||||
Array<Gfx::PDescriptorSet> descriptorSets;
|
||||
|
||||
Gfx::OPipelineLayout depthPrepassLayout;
|
||||
// Set 0: viewParameter
|
||||
static constexpr uint32 INDEX_VIEW_PARAMS = 0;
|
||||
// Set 0: vertices, from VertexData
|
||||
constexpr static uint32 INDEX_VERTEX_DATA = 1;
|
||||
// Set 2: mesh data, either index buffer or meshlet data
|
||||
constexpr static uint32 INDEX_SCENE_DATA = 2;
|
||||
Gfx::ODescriptorLayout sceneDataLayout;
|
||||
};
|
||||
DEFINE_REF(DepthPrepass)
|
||||
|
||||
@@ -20,7 +20,6 @@ public:
|
||||
virtual void endFrame() override;
|
||||
virtual void publishOutputs() override;
|
||||
virtual void createRenderPass() override;
|
||||
static void modifyRenderPassMacros(Map<const char*, const char*>& defines);
|
||||
private:
|
||||
void setupFrustums();
|
||||
static constexpr uint32 BLOCK_SIZE = 32;
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
#include "StaticDepthPrepass.h"
|
||||
#include "Graphics/StaticMeshVertexData.h"
|
||||
#include "Graphics/Shader.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
StaticDepthPrepass::StaticDepthPrepass(Gfx::PGraphics graphics, PScene scene)
|
||||
: RenderPass(graphics, scene)
|
||||
{
|
||||
depthPrepassLayout = graphics->createPipelineLayout("DepthPrepassLayout");
|
||||
depthPrepassLayout->addDescriptorLayout(viewParamsLayout);
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "MeshletPass", false, false, "", true, true, "MeshletPass");
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics->getShaderCompiler()->registerRenderPass(depthPrepassLayout, "DepthPass", "LegacyPass");
|
||||
}
|
||||
}
|
||||
|
||||
StaticDepthPrepass::~StaticDepthPrepass()
|
||||
{
|
||||
}
|
||||
|
||||
void StaticDepthPrepass::beginFrame(const Component::Camera& cam)
|
||||
{
|
||||
RenderPass::beginFrame(cam);
|
||||
}
|
||||
|
||||
void StaticDepthPrepass::render()
|
||||
{
|
||||
// Static Meshes
|
||||
{
|
||||
Gfx::ShaderPermutation permutation;
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
permutation.setTaskFile("StaticMeshletPass");
|
||||
permutation.setMeshFile("StaticMeshletPass");
|
||||
}
|
||||
else
|
||||
{
|
||||
permutation.setVertexFile("LegacyPass");
|
||||
}
|
||||
StaticMeshVertexData* vd = StaticMeshVertexData::getInstance();
|
||||
permutation.setVertexData(vd->getTypeName());
|
||||
for (const auto& [_, mappings] : vd->)
|
||||
{
|
||||
permutation.setMaterial(mapping.material->getBaseMaterial()->getName());
|
||||
Gfx::PermutationId id(permutation);
|
||||
|
||||
Gfx::ORenderCommand command = graphics->createRenderCommand("DepthRender");
|
||||
command->setViewport(viewport);
|
||||
|
||||
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
|
||||
assert(collection != nullptr);
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
Gfx::MeshPipelineCreateInfo pipelineInfo;
|
||||
pipelineInfo.taskShader = collection->taskShader;
|
||||
pipelineInfo.meshShader = collection->meshShader;
|
||||
pipelineInfo.fragmentShader = collection->fragmentShader;
|
||||
pipelineInfo.pipelineLayout = collection->pipelineLayout;
|
||||
pipelineInfo.renderPass = renderPass;
|
||||
pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL;
|
||||
pipelineInfo.multisampleState.samples = viewport->getSamples();
|
||||
pipelineInfo.colorBlend.attachmentCount = 1;
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
else
|
||||
{
|
||||
Gfx::LegacyPipelineCreateInfo pipelineInfo;
|
||||
pipelineInfo.vertexShader = collection->vertexShader;
|
||||
pipelineInfo.fragmentShader = collection->fragmentShader;
|
||||
pipelineInfo.pipelineLayout = collection->pipelineLayout;
|
||||
pipelineInfo.renderPass = renderPass;
|
||||
pipelineInfo.depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL;
|
||||
pipelineInfo.multisampleState.samples = viewport->getSamples();
|
||||
pipelineInfo.colorBlend.attachmentCount = 1;
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
command->bindDescriptor(viewParamsSet);
|
||||
command->bindDescriptor(vd->getVertexDataSet());
|
||||
command->bindDescriptor(vd->getInstanceDataSet(), { 0, 0 });
|
||||
if (graphics->supportMeshShading())
|
||||
{
|
||||
command->drawMesh(vd->getMeshData(mapping.mapped).size(), 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
command->bindIndexBuffer(vd->getIndexBuffer());
|
||||
uint32 instanceOffset = 0;
|
||||
for (const auto& meshData : vd->getMeshData(mapping.mapped))
|
||||
{
|
||||
if (meshData.numIndices > 0)
|
||||
{
|
||||
command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, meshData.indicesOffset, instanceOffset);
|
||||
}
|
||||
instanceOffset++;
|
||||
}
|
||||
}
|
||||
|
||||
commands.add(std::move(command));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StaticDepthPrepass::endFrame()
|
||||
{
|
||||
}
|
||||
|
||||
void StaticDepthPrepass::publishOutputs()
|
||||
{
|
||||
// If we render to a part of an image, the depth buffer itself must
|
||||
// still match the size of the whole image or their coordinate systems go out of sync
|
||||
TextureCreateInfo depthBufferInfo = {
|
||||
.format = Gfx::SE_FORMAT_D32_SFLOAT,
|
||||
.width = viewport->getOwner()->getFramebufferWidth(),
|
||||
.height = viewport->getOwner()->getFramebufferHeight(),
|
||||
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
||||
};
|
||||
depthBuffer = graphics->createTexture2D(depthBufferInfo);
|
||||
depthAttachment =
|
||||
Gfx::RenderTargetAttachment(depthBuffer,
|
||||
Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_GENERAL,
|
||||
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
|
||||
resources->registerRenderPassOutput("DEPTHPREPASS_DEPTH", depthAttachment);
|
||||
}
|
||||
|
||||
void StaticDepthPrepass::createRenderPass()
|
||||
{
|
||||
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
|
||||
.depthAttachment = depthAttachment,
|
||||
};
|
||||
Array<Gfx::SubPassDependency> dependency = {
|
||||
{
|
||||
.srcSubpass = ~0U,
|
||||
.dstSubpass = 0,
|
||||
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
|
||||
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
},
|
||||
{
|
||||
.srcSubpass = 0,
|
||||
.dstSubpass = ~0U,
|
||||
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||
.dstStage = Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccess = Gfx::SE_ACCESS_SHADER_READ_BIT,
|
||||
},
|
||||
{
|
||||
.srcSubpass = 0,
|
||||
.dstSubpass = ~0U,
|
||||
.srcStage = Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||
.dstStage = Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
|
||||
.srcAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccess = Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
|
||||
}
|
||||
};
|
||||
renderPass = graphics->createRenderPass(std::move(layout), dependency, viewport);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "RenderPass.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
class StaticDepthPrepass : public RenderPass
|
||||
{
|
||||
public:
|
||||
StaticDepthPrepass(Gfx::PGraphics graphics, PScene scene);
|
||||
StaticDepthPrepass(StaticDepthPrepass&&) = default;
|
||||
StaticDepthPrepass& operator=(StaticDepthPrepass&&) = default;
|
||||
virtual ~StaticDepthPrepass();
|
||||
virtual void beginFrame(const Component::Camera& cam) override;
|
||||
virtual void render() override;
|
||||
virtual void endFrame() override;
|
||||
virtual void publishOutputs() override;
|
||||
virtual void createRenderPass() override;
|
||||
private:
|
||||
Gfx::RenderTargetAttachment depthAttachment;
|
||||
Gfx::OTexture2D depthBuffer;
|
||||
Gfx::OPipelineLayout depthPrepassLayout;
|
||||
Gfx::ODescriptorLayout sceneDataLayout;
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "StaticMeshVertexData.h"
|
||||
#include "Graphics.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
@@ -192,6 +193,43 @@ Gfx::PDescriptorSet StaticMeshVertexData::getVertexDataSet()
|
||||
return descriptorSet;
|
||||
}
|
||||
|
||||
void StaticMeshVertexData::registerStaticMesh(entt::entity id, const Array<OMesh>& meshes, const Component::Transform& transform)
|
||||
{
|
||||
std::unique_lock l(vertexDataLock);
|
||||
std::unique_lock l2(mutex);
|
||||
for (auto& mesh : meshes)
|
||||
{
|
||||
uint64 numVertices = meshVertexCounts[mesh->id];
|
||||
uint64 offset = meshOffsets[mesh->id];
|
||||
MeshId mapped = VertexData::allocateVertexData(numVertices);
|
||||
Array<Vector> pos(numVertices);
|
||||
Matrix4 matrix = transform.toMatrix();
|
||||
for (uint64 i = 0; i < numVertices; ++i)
|
||||
{
|
||||
pos[i] = matrix * Vector4(positionData[offset + i], 1);
|
||||
}
|
||||
loadPositions(mapped, pos);
|
||||
Array<Vector2> tex(numVertices);
|
||||
for (size_t i = 0; i < MAX_TEXCOORDS; ++i)
|
||||
{
|
||||
std::memcpy(tex.data(), texCoordsData[i].data() + offset, numVertices * sizeof(Vector2));
|
||||
loadTexCoords(mapped, i, tex);
|
||||
}
|
||||
Array<Vector> aux(numVertices);
|
||||
std::memcpy(aux.data(), normalData.data() + offset, numVertices * sizeof(Vector));
|
||||
loadNormals(mapped, aux);
|
||||
std::memcpy(aux.data(), biTangentData.data() + offset, numVertices * sizeof(Vector));
|
||||
loadBiTangents(mapped, aux);
|
||||
std::memcpy(aux.data(), colorData.data() + offset, numVertices * sizeof(Vector));
|
||||
loadColors(mapped, aux);
|
||||
staticMeshes[id].add(StaticMeshMapping{
|
||||
.original = mesh->id,
|
||||
.mapped = mapped,
|
||||
.material = mesh->referencedMaterial->getHandle(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void StaticMeshVertexData::resizeBuffers()
|
||||
{
|
||||
ShaderBufferCreateInfo createInfo = {
|
||||
|
||||
@@ -3,12 +3,19 @@
|
||||
#include "Graphics/Command.h"
|
||||
#include "Math/Vector.h"
|
||||
#include "VertexData.h"
|
||||
#include "entt/entt.hpp"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
class StaticMeshVertexData : public VertexData
|
||||
{
|
||||
public:
|
||||
struct StaticMeshMapping
|
||||
{
|
||||
MeshId original;
|
||||
MeshId mapped;
|
||||
PMaterialInstance material;
|
||||
};
|
||||
StaticMeshVertexData();
|
||||
virtual ~StaticMeshVertexData();
|
||||
static StaticMeshVertexData* getInstance();
|
||||
@@ -26,9 +33,12 @@ public:
|
||||
virtual Gfx::PDescriptorLayout getVertexDataLayout() override;
|
||||
virtual Gfx::PDescriptorSet getVertexDataSet() override;
|
||||
virtual std::string getTypeName() const override { return "StaticMeshVertexData"; }
|
||||
void registerStaticMesh(const Array<OMesh>& meshes, const Component::Transform& transform);
|
||||
private:
|
||||
virtual void resizeBuffers() override;
|
||||
virtual void updateBuffers() override;
|
||||
Array<MeshletDescription> staticMeshlets;
|
||||
|
||||
std::mutex mutex;
|
||||
Gfx::OShaderBuffer positions;
|
||||
Array<Vector> positionData;
|
||||
|
||||
@@ -36,16 +36,18 @@ void VertexData::updateMesh(PMesh mesh, Component::Transform& transform)
|
||||
MaterialData& matData = materialData[mat->getName()];
|
||||
matData.material = mat;
|
||||
MaterialInstanceData& matInstanceData = matData.instances[referencedInstance->getId()];
|
||||
matInstanceData.descriptorOffset = instanceData.size();
|
||||
matInstanceData.numMeshes = 0;
|
||||
matInstanceData.meshId = mesh->id;
|
||||
for (const auto& data : meshData[mesh->id])
|
||||
{
|
||||
Matrix4 transformMatrix = transform.toMatrix() * mesh->transform;
|
||||
matInstanceData.meshes.add(MeshInstanceData{
|
||||
.instance = InstanceData {
|
||||
instanceData.add(InstanceData {
|
||||
.transformMatrix = transformMatrix,
|
||||
.inverseTransformMatrix = glm::inverse(transformMatrix),
|
||||
},
|
||||
.data = data,
|
||||
});
|
||||
instanceMeshData.add(data);
|
||||
matInstanceData.numMeshes++;
|
||||
for (size_t i = 0; i < 0; ++i)
|
||||
{
|
||||
auto bounding = meshlets[data.meshletOffset + i].bounding;
|
||||
@@ -94,18 +96,7 @@ void VertexData::createDescriptors()
|
||||
{
|
||||
std::unique_lock l(materialDataLock);
|
||||
instanceDataLayout->reset();
|
||||
for (const auto& [_, mat] : materialData)
|
||||
{
|
||||
for (auto& [_, matInst] : mat.instances)
|
||||
{
|
||||
Array<InstanceData> instanceData;
|
||||
Array<MeshData> meshes;
|
||||
for (auto& inst : matInst.meshes)
|
||||
{
|
||||
meshes.add(inst.data);
|
||||
instanceData.add(inst.instance);
|
||||
}
|
||||
matInst.instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData = {
|
||||
.size = sizeof(InstanceData) * instanceData.size(),
|
||||
.data = (uint8*)instanceData.data(),
|
||||
@@ -114,38 +105,36 @@ void VertexData::createDescriptors()
|
||||
.dynamic = false,
|
||||
.name = "InstanceBuffer"
|
||||
});
|
||||
matInst.instanceBuffer->pipelineBarrier(
|
||||
instanceBuffer->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
Gfx::SE_ACCESS_MEMORY_READ_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT
|
||||
);
|
||||
matInst.descriptorSet = instanceDataLayout->allocateDescriptorSet();
|
||||
descriptorSet = instanceDataLayout->allocateDescriptorSet();
|
||||
|
||||
matInst.meshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData = {
|
||||
.size = sizeof(MeshData) * meshes.size(),
|
||||
.data = (uint8*)meshes.data(),
|
||||
.size = sizeof(MeshData) * instanceMeshData.size(),
|
||||
.data = (uint8*)instanceMeshData.data(),
|
||||
},
|
||||
.numElements = meshes.size(),
|
||||
.numElements = instanceMeshData.size(),
|
||||
.dynamic = false,
|
||||
.name = "MeshDataBuffer"
|
||||
});
|
||||
matInst.meshDataBuffer->pipelineBarrier(
|
||||
instanceMeshDataBuffer->pipelineBarrier(
|
||||
Gfx::SE_ACCESS_TRANSFER_WRITE_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
Gfx::SE_ACCESS_MEMORY_READ_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT
|
||||
);
|
||||
matInst.descriptorSet->updateBuffer(0, matInst.instanceBuffer);
|
||||
matInst.descriptorSet->updateBuffer(1, matInst.meshDataBuffer);
|
||||
matInst.descriptorSet->updateBuffer(2, meshletBuffer);
|
||||
matInst.descriptorSet->updateBuffer(3, primitiveIndicesBuffer);
|
||||
matInst.descriptorSet->updateBuffer(4, vertexIndicesBuffer);
|
||||
descriptorSet->updateBuffer(0, instanceBuffer);
|
||||
descriptorSet->updateBuffer(1, instanceMeshDataBuffer);
|
||||
descriptorSet->updateBuffer(2, meshletBuffer);
|
||||
descriptorSet->updateBuffer(3, primitiveIndicesBuffer);
|
||||
descriptorSet->updateBuffer(4, vertexIndicesBuffer);
|
||||
|
||||
matInst.descriptorSet->writeChanges();
|
||||
}
|
||||
}
|
||||
descriptorSet->writeChanges();
|
||||
}
|
||||
|
||||
void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets)
|
||||
@@ -264,7 +253,7 @@ List<VertexData*> VertexData::getList()
|
||||
return vertexDataList;
|
||||
}
|
||||
|
||||
VertexData* Seele::VertexData::findByTypeName(std::string name)
|
||||
VertexData* VertexData::findByTypeName(std::string name)
|
||||
{
|
||||
for (auto vd : vertexDataList)
|
||||
{
|
||||
@@ -276,15 +265,16 @@ VertexData* Seele::VertexData::findByTypeName(std::string name)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Seele::VertexData::init(Gfx::PGraphics _graphics)
|
||||
void VertexData::init(Gfx::PGraphics _graphics)
|
||||
{
|
||||
graphics = _graphics;
|
||||
verticesAllocated = NUM_DEFAULT_ELEMENTS;
|
||||
instanceDataLayout = graphics->createDescriptorLayout("pScene");
|
||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,});
|
||||
|
||||
// instanceData
|
||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,});
|
||||
// meshData
|
||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,});
|
||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,});
|
||||
// meshletData
|
||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
||||
// primitiveIndices
|
||||
@@ -299,6 +289,8 @@ void Seele::VertexData::init(Gfx::PGraphics _graphics)
|
||||
|
||||
void VertexData::destroy()
|
||||
{
|
||||
instanceBuffer = nullptr;
|
||||
instanceMeshDataBuffer = nullptr;
|
||||
instanceDataLayout = nullptr;
|
||||
meshletBuffer = nullptr;
|
||||
vertexIndicesBuffer = nullptr;
|
||||
|
||||
@@ -43,18 +43,12 @@ public:
|
||||
uint32 indicesOffset = 0;
|
||||
uint32 pad0[3];
|
||||
};
|
||||
struct MeshInstanceData
|
||||
{
|
||||
InstanceData instance;
|
||||
MeshData data;
|
||||
};
|
||||
struct MaterialInstanceData
|
||||
{
|
||||
PMaterialInstance materialInstance;
|
||||
Gfx::OShaderBuffer instanceBuffer;
|
||||
Gfx::OShaderBuffer meshDataBuffer;
|
||||
Gfx::PDescriptorSet descriptorSet;
|
||||
Array<MeshInstanceData> meshes;
|
||||
uint32 descriptorOffset;
|
||||
uint64 numMeshes;
|
||||
MeshId meshId;
|
||||
};
|
||||
struct MaterialData
|
||||
{
|
||||
@@ -76,6 +70,7 @@ public:
|
||||
virtual std::string getTypeName() const = 0;
|
||||
Gfx::PIndexBuffer getIndexBuffer() { return indexBuffer; }
|
||||
Gfx::PDescriptorLayout getInstanceDataLayout() { return instanceDataLayout; }
|
||||
Gfx::PDescriptorSet getInstanceDataSet() { return descriptorSet; }
|
||||
const Map<std::string, MaterialData>& getMaterialData() const { return materialData; }
|
||||
const Array<MeshData>& getMeshData(MeshId id) { return meshData[id]; }
|
||||
static List<VertexData*> getList();
|
||||
@@ -89,10 +84,10 @@ protected:
|
||||
struct MeshletDescription
|
||||
{
|
||||
AABB bounding;
|
||||
uint32_t vertexCount;
|
||||
uint32_t primitiveCount;
|
||||
uint32_t vertexOffset;
|
||||
uint32_t primitiveOffset;
|
||||
uint32 vertexCount;
|
||||
uint32 primitiveCount;
|
||||
uint32 vertexOffset;
|
||||
uint32 primitiveOffset;
|
||||
Vector color;
|
||||
float pad;
|
||||
};
|
||||
@@ -114,6 +109,12 @@ protected:
|
||||
Gfx::OShaderBuffer primitiveIndicesBuffer;
|
||||
// for legacy pipeline
|
||||
Gfx::OIndexBuffer indexBuffer;
|
||||
// Material data
|
||||
Array<InstanceData> instanceData;
|
||||
Gfx::OShaderBuffer instanceBuffer;
|
||||
Array<MeshData> instanceMeshData;
|
||||
Gfx::OShaderBuffer instanceMeshDataBuffer;
|
||||
Gfx::PDescriptorSet descriptorSet;
|
||||
uint64 idCounter;
|
||||
uint64 head;
|
||||
uint64 verticesAllocated;
|
||||
|
||||
@@ -270,7 +270,7 @@ void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline)
|
||||
pipeline = gfxPipeline.cast<GraphicsPipeline>();
|
||||
pipeline->bind(handle);
|
||||
}
|
||||
void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
|
||||
void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array<uint32> dynamicOffsets)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
auto descriptor = descriptorSet.cast<DescriptorSet>();
|
||||
@@ -279,9 +279,9 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
|
||||
descriptor->bind();
|
||||
|
||||
VkDescriptorSet setHandle = descriptor->getHandle();
|
||||
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), pipeline->getPipelineLayout()->findParameter(descriptorSet->getName()), 1, &setHandle, 0, nullptr);
|
||||
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), pipeline->getPipelineLayout()->findParameter(descriptorSet->getName()), 1, &setHandle, dynamicOffsets.size(), dynamicOffsets.data());
|
||||
}
|
||||
void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets)
|
||||
void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets, Array<uint32> dynamicOffsets)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()];
|
||||
@@ -294,7 +294,7 @@ void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorS
|
||||
boundDescriptors.add(descriptorSet.getHandle());
|
||||
sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle();
|
||||
}
|
||||
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, 0, nullptr);
|
||||
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, dynamicOffsets.size(), dynamicOffsets.data());
|
||||
delete[] sets;
|
||||
}
|
||||
void RenderCommand::bindVertexBuffer(const Array<Gfx::PVertexBuffer>& streams)
|
||||
@@ -407,7 +407,7 @@ void ComputeCommand::bindPipeline(Gfx::PComputePipeline computePipeline)
|
||||
pipeline->bind(handle);
|
||||
}
|
||||
|
||||
void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
|
||||
void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array<uint32> dynamicOffsets)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
auto descriptor = descriptorSet.cast<DescriptorSet>();
|
||||
@@ -416,10 +416,10 @@ void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
|
||||
descriptor->bind();
|
||||
|
||||
VkDescriptorSet setHandle = descriptor->getHandle();
|
||||
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), pipeline->getPipelineLayout()->findParameter(descriptorSet->getName()), 1, &setHandle, 0, nullptr);
|
||||
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), pipeline->getPipelineLayout()->findParameter(descriptorSet->getName()), 1, &setHandle, dynamicOffsets.size(), dynamicOffsets.data());
|
||||
}
|
||||
|
||||
void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets)
|
||||
void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets, Array<uint32> dynamicOffsets)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()];
|
||||
@@ -433,7 +433,7 @@ void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptor
|
||||
boundDescriptors.add(descriptorSet.getHandle());
|
||||
sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle();
|
||||
}
|
||||
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, 0, nullptr);
|
||||
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, dynamicOffsets.size(), dynamicOffsets.data());
|
||||
delete[] sets;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,8 +72,8 @@ public:
|
||||
bool isReady();
|
||||
virtual void setViewport(Gfx::PViewport viewport) override;
|
||||
virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) override;
|
||||
virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet) override;
|
||||
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets) override;
|
||||
virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array<uint32> dynamicOffsets) override;
|
||||
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets, Array<uint32> dynamicOffsets) override;
|
||||
virtual void bindVertexBuffer(const Array<Gfx::PVertexBuffer>& buffers) override;
|
||||
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) override;
|
||||
virtual void pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size,
|
||||
@@ -107,8 +107,8 @@ public:
|
||||
void reset();
|
||||
bool isReady();
|
||||
virtual void bindPipeline(Gfx::PComputePipeline pipeline) override;
|
||||
virtual void bindDescriptor(Gfx::PDescriptorSet set) override;
|
||||
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) override;
|
||||
virtual void bindDescriptor(Gfx::PDescriptorSet set, Array<uint32> dynamicOffsets) override;
|
||||
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets, Array<uint32> dynamicOffsets) override;
|
||||
virtual void pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size,
|
||||
const void* data) override;
|
||||
virtual void dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) override;
|
||||
|
||||
@@ -22,10 +22,14 @@ void KeyboardInput::update(Component::KeyboardInput& input)
|
||||
input.mouseY = mouseY;
|
||||
input.mouse1 = mouse1;
|
||||
input.mouse2 = mouse2;
|
||||
input.scrollX = scrollX;
|
||||
input.scrollY = scrollY;
|
||||
deltaX = mouseX - lastMouseX;
|
||||
deltaY = mouseY - lastMouseY;
|
||||
lastMouseX = mouseX;
|
||||
lastMouseY = mouseY;
|
||||
scrollX = 0;
|
||||
scrollY = 0;
|
||||
}
|
||||
|
||||
void KeyboardInput::keyCallback(KeyCode code, InputAction action, KeyModifier)
|
||||
@@ -50,3 +54,9 @@ void KeyboardInput::mouseButtonCallback(MouseButton button, InputAction action,
|
||||
mouse2 = action != InputAction::RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardInput::scrollCallback(double xScroll, double yScroll)
|
||||
{
|
||||
scrollX = xScroll;
|
||||
scrollY = yScroll;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public:
|
||||
void keyCallback(KeyCode code, InputAction action, KeyModifier modifier);
|
||||
void mouseCallback(double xPos, double yPos);
|
||||
void mouseButtonCallback(MouseButton button, InputAction action, KeyModifier modifier);
|
||||
void scrollCallback(double xScroll, double yScroll);
|
||||
private:
|
||||
Seele::StaticArray<bool, (size_t)KeyCode::KEY_LAST> keys;
|
||||
bool mouse1 = false;
|
||||
@@ -25,6 +26,8 @@ private:
|
||||
float mouseY = 0;
|
||||
float deltaX = 0;
|
||||
float deltaY = 0;
|
||||
float scrollX = 0;
|
||||
float scrollY = 0;
|
||||
};
|
||||
DEFINE_REF(KeyboardInput)
|
||||
}
|
||||
|
||||
@@ -108,8 +108,9 @@ void GameView::mouseButtonCallback(MouseButton button, InputAction action, KeyMo
|
||||
keyboardSystem->mouseButtonCallback(button, action, modifier);
|
||||
}
|
||||
|
||||
void GameView::scrollCallback(double, double)
|
||||
void GameView::scrollCallback(double xScroll, double yScroll)
|
||||
{
|
||||
keyboardSystem->scrollCallback(xScroll, yScroll);
|
||||
}
|
||||
|
||||
void GameView::fileCallback(int, const char**)
|
||||
|
||||
Reference in New Issue
Block a user