Adding transparency support
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import Common;
|
import Common;
|
||||||
import Scene;
|
import Scene;
|
||||||
|
import Bounding;
|
||||||
|
|
||||||
groupshared MeshPayload p;
|
groupshared MeshPayload p;
|
||||||
groupshared uint head;
|
groupshared uint head;
|
||||||
@@ -7,6 +8,7 @@ groupshared MeshData mesh;
|
|||||||
groupshared InstanceData instance;
|
groupshared InstanceData instance;
|
||||||
groupshared Frustum viewFrustum;
|
groupshared Frustum viewFrustum;
|
||||||
groupshared float4x4 modelViewProjection;
|
groupshared float4x4 modelViewProjection;
|
||||||
|
groupshared bool meshVisible;
|
||||||
|
|
||||||
struct DepthData
|
struct DepthData
|
||||||
{
|
{
|
||||||
@@ -16,6 +18,60 @@ struct DepthData
|
|||||||
|
|
||||||
ParameterBlock<DepthData> pDepthAttachment;
|
ParameterBlock<DepthData> pDepthAttachment;
|
||||||
|
|
||||||
|
bool isBoxVisible(AABB bounding)
|
||||||
|
{
|
||||||
|
uint2 mipDimensions = uint2((uint(pViewParams.screenDimensions.x) + BLOCK_SIZE - 1) / BLOCK_SIZE, (uint(pViewParams.screenDimensions.y) + BLOCK_SIZE - 1) / BLOCK_SIZE);
|
||||||
|
// now we calculate what mip level we need to only sample up to 4 texels covering the entire meshlet
|
||||||
|
uint2 screenCornerMin = mipDimensions;
|
||||||
|
uint2 screenCornerMax = uint2(0, 0);
|
||||||
|
// we use reverse depth, so higher values are closer
|
||||||
|
float maxDepth = 0;
|
||||||
|
{
|
||||||
|
float4 corners[8];
|
||||||
|
corners[0] = float4(bounding.min.x, bounding.min.y, bounding.min.z, 1.0f);
|
||||||
|
corners[1] = float4(bounding.min.x, bounding.min.y, bounding.max.z, 1.0f);
|
||||||
|
corners[2] = float4(bounding.min.x, bounding.max.y, bounding.min.z, 1.0f);
|
||||||
|
corners[3] = float4(bounding.min.x, bounding.max.y, bounding.max.z, 1.0f);
|
||||||
|
corners[4] = float4(bounding.max.x, bounding.min.y, bounding.min.z, 1.0f);
|
||||||
|
corners[5] = float4(bounding.max.x, bounding.min.y, bounding.max.z, 1.0f);
|
||||||
|
corners[6] = float4(bounding.max.x, bounding.max.y, bounding.min.z, 1.0f);
|
||||||
|
corners[7] = float4(bounding.max.x, bounding.max.y, bounding.max.z, 1.0f);
|
||||||
|
for(uint i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
float4 clipCorner = mul(modelViewProjection, corners[i]);
|
||||||
|
float4 screenCorner = clipToScreen(clipCorner) / BLOCK_SIZE;
|
||||||
|
screenCornerMin = uint2(min(screenCornerMin.x, uint(screenCorner.x)), min(screenCornerMin.y, uint(screenCorner.y)));
|
||||||
|
screenCornerMax = uint2(max(screenCornerMax.x, uint(screenCorner.x)), max(screenCornerMax.y, uint(screenCorner.y)));
|
||||||
|
maxDepth = max(maxDepth, screenCorner.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint mipOffset = 0;
|
||||||
|
// in theory this wouldnt work if no corner was in screen, as min would be greater that max, however we verified that with view culling
|
||||||
|
while(screenCornerMax.x - screenCornerMin.x > 1 || screenCornerMax.y - screenCornerMin.y > 1)
|
||||||
|
{
|
||||||
|
mipOffset += mipDimensions.x * mipDimensions.y;
|
||||||
|
mipDimensions = uint2(mipDimensions.x + 1, mipDimensions.y + 1) / 2;
|
||||||
|
screenCornerMin /= 2;
|
||||||
|
screenCornerMax /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we sample 4 texels from the depth at the calculated mip level, this should give us the screen extent of the meshlet
|
||||||
|
float d1 = pDepthAttachment.buffer[mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMin.x];
|
||||||
|
float d2 = pDepthAttachment.buffer[mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMax.x];
|
||||||
|
float d3 = pDepthAttachment.buffer[mipOffset + (screenCornerMax.y * mipDimensions.x) + screenCornerMin.x];
|
||||||
|
float d4 = pDepthAttachment.buffer[mipOffset + (screenCornerMax.y * mipDimensions.x) + screenCornerMax.x];
|
||||||
|
|
||||||
|
// we want to check if the minimum depth (the value farthest away) is smaller than the maximum bounding box depth
|
||||||
|
// otherwise, there is no way for the meshlet to be visible
|
||||||
|
float d = min(min(d1, d2), min(d3, d4));
|
||||||
|
|
||||||
|
if(d < maxDepth)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
[numthreads(TASK_GROUP_SIZE, 1, 1)]
|
[numthreads(TASK_GROUP_SIZE, 1, 1)]
|
||||||
[shader("amplification")]
|
[shader("amplification")]
|
||||||
void taskMain(
|
void taskMain(
|
||||||
@@ -43,8 +99,13 @@ void taskMain(
|
|||||||
viewFrustum.sides[1] = computePlane(origin, corners[1], corners[3]);
|
viewFrustum.sides[1] = computePlane(origin, corners[1], corners[3]);
|
||||||
viewFrustum.sides[2] = computePlane(origin, corners[0], corners[1]);
|
viewFrustum.sides[2] = computePlane(origin, corners[0], corners[1]);
|
||||||
viewFrustum.sides[3] = computePlane(origin, corners[3], corners[2]);
|
viewFrustum.sides[3] = computePlane(origin, corners[3], corners[2]);
|
||||||
|
meshVisible = isBoxVisible(mesh.bounding);
|
||||||
}
|
}
|
||||||
GroupMemoryBarrierWithGroupSync();
|
GroupMemoryBarrierWithGroupSync();
|
||||||
|
if(!meshVisible)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE)
|
for (uint i = threadID; i < mesh.numMeshlets; i += TASK_GROUP_SIZE)
|
||||||
{
|
{
|
||||||
uint m = p.meshletOffset + i;
|
uint m = p.meshletOffset + i;
|
||||||
@@ -57,53 +118,8 @@ void taskMain(
|
|||||||
// if the meshlet is outside of the frustum, we skip it since we cant do depth culling anyways
|
// if the meshlet is outside of the frustum, we skip it since we cant do depth culling anyways
|
||||||
if(meshlet.bounding.insideFrustum(viewFrustum))
|
if(meshlet.bounding.insideFrustum(viewFrustum))
|
||||||
{
|
{
|
||||||
uint2 mipDimensions = uint2((uint(pViewParams.screenDimensions.x) + BLOCK_SIZE - 1) / BLOCK_SIZE, (uint(pViewParams.screenDimensions.y) + BLOCK_SIZE - 1) / BLOCK_SIZE);
|
// if the meshlet bounding box is behind the cached depth buffer, we skip
|
||||||
// now we calculate what mip level we need to only sample up to 4 texels covering the entire meshlet
|
if(isBoxVisible(meshlet.bounding))
|
||||||
uint2 screenCornerMin = mipDimensions;
|
|
||||||
uint2 screenCornerMax = uint2(0, 0);
|
|
||||||
// we use reverse depth, so higher values are closer
|
|
||||||
float maxDepth = 0;
|
|
||||||
{
|
|
||||||
float4 corners[8];
|
|
||||||
corners[0] = float4(meshlet.bounding.min.x, meshlet.bounding.min.y, meshlet.bounding.min.z, 1.0f);
|
|
||||||
corners[1] = float4(meshlet.bounding.min.x, meshlet.bounding.min.y, meshlet.bounding.max.z, 1.0f);
|
|
||||||
corners[2] = float4(meshlet.bounding.min.x, meshlet.bounding.max.y, meshlet.bounding.min.z, 1.0f);
|
|
||||||
corners[3] = float4(meshlet.bounding.min.x, meshlet.bounding.max.y, meshlet.bounding.max.z, 1.0f);
|
|
||||||
corners[4] = float4(meshlet.bounding.max.x, meshlet.bounding.min.y, meshlet.bounding.min.z, 1.0f);
|
|
||||||
corners[5] = float4(meshlet.bounding.max.x, meshlet.bounding.min.y, meshlet.bounding.max.z, 1.0f);
|
|
||||||
corners[6] = float4(meshlet.bounding.max.x, meshlet.bounding.max.y, meshlet.bounding.min.z, 1.0f);
|
|
||||||
corners[7] = float4(meshlet.bounding.max.x, meshlet.bounding.max.y, meshlet.bounding.max.z, 1.0f);
|
|
||||||
for(uint i = 0; i < 8; ++i)
|
|
||||||
{
|
|
||||||
float4 clipCorner = mul(modelViewProjection, corners[i]);
|
|
||||||
float4 screenCorner = clipToScreen(clipCorner) / BLOCK_SIZE;
|
|
||||||
screenCornerMin = uint2(min(screenCornerMin.x, uint(screenCorner.x)), min(screenCornerMin.y, uint(screenCorner.y)));
|
|
||||||
screenCornerMax = uint2(max(screenCornerMax.x, uint(screenCorner.x)), max(screenCornerMax.y, uint(screenCorner.y)));
|
|
||||||
maxDepth = max(maxDepth, screenCorner.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint mipOffset = 0;
|
|
||||||
// in theory this wouldnt work if no corner was in screen, as min would be greater that max, however we verified that with view culling
|
|
||||||
while(screenCornerMax.x - screenCornerMin.x > 1 || screenCornerMax.y - screenCornerMin.y > 1)
|
|
||||||
{
|
|
||||||
mipOffset += mipDimensions.x * mipDimensions.y;
|
|
||||||
mipDimensions = uint2(mipDimensions.x + 1, mipDimensions.y + 1) / 2;
|
|
||||||
screenCornerMin /= 2;
|
|
||||||
screenCornerMax /= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now we sample 4 texels from the depth at the calculated mip level, this should give us the screen extent of the meshlet
|
|
||||||
float d1 = pDepthAttachment.buffer[mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMin.x];
|
|
||||||
float d2 = pDepthAttachment.buffer[mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMax.x];
|
|
||||||
float d3 = pDepthAttachment.buffer[mipOffset + (screenCornerMax.y * mipDimensions.x) + screenCornerMin.x];
|
|
||||||
float d4 = pDepthAttachment.buffer[mipOffset + (screenCornerMax.y * mipDimensions.x) + screenCornerMax.x];
|
|
||||||
|
|
||||||
// we want to check if the minimum depth (the value farthest away) is smaller than the maximum bounding box depth
|
|
||||||
// otherwise, there is no way for the meshlet to be visible
|
|
||||||
float d = min(min(d1, d2), min(d3, d4));
|
|
||||||
|
|
||||||
// this is technically not correct, as the mipmap is generated with a linear filter, but we actually would need a min filter, but whatever
|
|
||||||
if(d < maxDepth)
|
|
||||||
{
|
{
|
||||||
uint index;
|
uint index;
|
||||||
InterlockedAdd(head, 1, index);
|
InterlockedAdd(head, 1, index);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ struct MipParam
|
|||||||
uint2 srcMipDim;
|
uint2 srcMipDim;
|
||||||
uint2 dstMipDim;
|
uint2 dstMipDim;
|
||||||
}
|
}
|
||||||
layout(push_constants)
|
layout(push_constant)
|
||||||
ConstantBuffer<MipParam> pMipParam;
|
ConstantBuffer<MipParam> pMipParam;
|
||||||
|
|
||||||
float getSrcDepth(uint2 pos)
|
float getSrcDepth(uint2 pos)
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ void MaterialLoader::import(MaterialImportArgs args, PMaterialAsset asset) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
asset->material = new Material(graphics, numTextures, numSamplers, numFloats, materialName, std::move(expressions),
|
asset->material = new Material(graphics, numTextures, numSamplers, numFloats, false, 1, materialName, std::move(expressions),
|
||||||
std::move(parameters), std::move(mat));
|
std::move(parameters), std::move(mat));
|
||||||
|
|
||||||
asset->material->compile();
|
asset->material->compile();
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <stb_image_write.h>
|
#include <stb_image_write.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
MeshLoader::MeshLoader(Gfx::PGraphics graphics) : graphics(graphics) {}
|
MeshLoader::MeshLoader(Gfx::PGraphics graphics) : graphics(graphics) {}
|
||||||
@@ -372,10 +371,13 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array<PTextureAsset>&
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
bool twoSided = true;
|
||||||
|
material->Get(AI_MATKEY_TWOSIDED, twoSided);
|
||||||
|
float opacity = 1.0f;
|
||||||
|
material->Get(AI_MATKEY_OPACITY, opacity);
|
||||||
OMaterialAsset baseMat = new MaterialAsset(importPath, materialName);
|
OMaterialAsset baseMat = new MaterialAsset(importPath, materialName);
|
||||||
baseMat->material = new Material(graphics, numTextures, numSamplers, numFloats, materialName, std::move(expressions),
|
baseMat->material = new Material(graphics, numTextures, numSamplers, numFloats, twoSided, opacity, materialName,
|
||||||
std::move(parameters), std::move(brdf));
|
std::move(expressions), std::move(parameters), std::move(brdf));
|
||||||
baseMat->material->compile();
|
baseMat->material->compile();
|
||||||
graphics->getShaderCompiler()->registerMaterial(baseMat->material);
|
graphics->getShaderCompiler()->registerMaterial(baseMat->material);
|
||||||
globalMaterials[m] = baseMat->instantiate(InstantiationParameter{
|
globalMaterials[m] = baseMat->instantiate(InstantiationParameter{
|
||||||
@@ -473,8 +475,6 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array<PMaterialIns
|
|||||||
globalMeshes[meshIndex]->meshlets = std::move(meshlets);
|
globalMeshes[meshIndex]->meshlets = std::move(meshlets);
|
||||||
globalMeshes[meshIndex]->indices = std::move(indices);
|
globalMeshes[meshIndex]->indices = std::move(indices);
|
||||||
globalMeshes[meshIndex]->vertexCount = mesh->mNumVertices;
|
globalMeshes[meshIndex]->vertexCount = mesh->mNumVertices;
|
||||||
globalMeshes[meshIndex]->blas =
|
|
||||||
graphics->createBottomLevelAccelerationStructure(Gfx::BottomLevelASCreateInfo(globalMeshes[meshIndex]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-8
@@ -63,16 +63,13 @@ int main() {
|
|||||||
.filePath = sourcePath / "import/textures/skyboxsun5deg_tn.jpg",
|
.filePath = sourcePath / "import/textures/skyboxsun5deg_tn.jpg",
|
||||||
.type = TextureImportType::TEXTURE_CUBEMAP,
|
.type = TextureImportType::TEXTURE_CUBEMAP,
|
||||||
});
|
});
|
||||||
// AssetImporter::importMesh(MeshImportArgs{
|
|
||||||
// .filePath = sourcePath / "import/models/greek-temple/source/greek-temple.fbx",
|
|
||||||
// .importPath = "temple"
|
|
||||||
// });
|
|
||||||
AssetImporter::importMesh(MeshImportArgs{.filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.fbx",
|
AssetImporter::importMesh(MeshImportArgs{.filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.fbx",
|
||||||
.importPath = "Whitechapel"});
|
.importPath = "Whitechapel"});
|
||||||
// AssetImporter::importMesh(MeshImportArgs{
|
//AssetImporter::importMesh(MeshImportArgs{
|
||||||
// .filePath = sourcePath / "import/models/nitra-castle-rawscan/source/Nitriansky.obj",
|
// .filePath = sourcePath / "import/models/city-suburbs/city-suburbs.gltf",
|
||||||
// .importPath = "Nitriansky"
|
// .importPath = "suburbs",
|
||||||
// });
|
//});
|
||||||
|
vd->commitMeshes();
|
||||||
WindowCreateInfo mainWindowInfo;
|
WindowCreateInfo mainWindowInfo;
|
||||||
mainWindowInfo.title = "SeeleEngine";
|
mainWindowInfo.title = "SeeleEngine";
|
||||||
mainWindowInfo.width = 1920;
|
mainWindowInfo.width = 1920;
|
||||||
|
|||||||
@@ -43,5 +43,6 @@ void Camera::buildViewMatrix() {
|
|||||||
Vector lookAt = eyePos + getTransform().getForward();
|
Vector lookAt = eyePos + getTransform().getForward();
|
||||||
viewMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
|
viewMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
|
||||||
cameraPos = eyePos;
|
cameraPos = eyePos;
|
||||||
|
cameraForward = getTransform().getForward();
|
||||||
bNeedsViewBuild = false;
|
bNeedsViewBuild = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ struct Camera {
|
|||||||
return viewMatrix;
|
return viewMatrix;
|
||||||
}
|
}
|
||||||
Vector getCameraPosition() const { return cameraPos; }
|
Vector getCameraPosition() const { return cameraPos; }
|
||||||
|
Vector getCameraForward() const { return cameraForward; }
|
||||||
void mouseMove(float deltaX, float deltaY);
|
void mouseMove(float deltaX, float deltaY);
|
||||||
void mouseScroll(float x);
|
void mouseScroll(float x);
|
||||||
void moveX(float amount);
|
void moveX(float amount);
|
||||||
@@ -29,6 +30,7 @@ struct Camera {
|
|||||||
float pitch;
|
float pitch;
|
||||||
Matrix4 viewMatrix;
|
Matrix4 viewMatrix;
|
||||||
Vector cameraPos;
|
Vector cameraPos;
|
||||||
|
Vector cameraForward;
|
||||||
bool bNeedsViewBuild;
|
bool bNeedsViewBuild;
|
||||||
};
|
};
|
||||||
} // namespace Component
|
} // namespace Component
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ DEFINE_REF(DescriptorPool)
|
|||||||
DECLARE_REF(UniformBuffer)
|
DECLARE_REF(UniformBuffer)
|
||||||
DECLARE_REF(ShaderBuffer)
|
DECLARE_REF(ShaderBuffer)
|
||||||
DECLARE_REF(Texture)
|
DECLARE_REF(Texture)
|
||||||
|
DECLARE_REF(Texture2D)
|
||||||
DECLARE_REF(Sampler)
|
DECLARE_REF(Sampler)
|
||||||
class DescriptorSet {
|
class DescriptorSet {
|
||||||
public:
|
public:
|
||||||
@@ -67,7 +68,8 @@ class DescriptorSet {
|
|||||||
virtual void updateSampler(uint32_t binding, uint32 dstArrayIndex, Gfx::PSampler samplerState) = 0;
|
virtual void updateSampler(uint32_t binding, uint32 dstArrayIndex, Gfx::PSampler samplerState) = 0;
|
||||||
virtual void updateTexture(uint32 binding, PTexture texture, PSampler samplerState = nullptr) = 0;
|
virtual void updateTexture(uint32 binding, PTexture texture, PSampler samplerState = nullptr) = 0;
|
||||||
virtual void updateTexture(uint32 binding, uint32 dstArrayIndex, PTexture texture) = 0;
|
virtual void updateTexture(uint32 binding, uint32 dstArrayIndex, PTexture texture) = 0;
|
||||||
virtual void updateTextureArray(uint32_t binding, Array<PTexture> texture) = 0;
|
virtual void updateTextureArray(uint32_t binding, Array<PTexture2D> texture) = 0;
|
||||||
|
virtual void updateSamplerArray(uint32_t binding, Array<PSampler> samplers) = 0;
|
||||||
bool operator<(PDescriptorSet other);
|
bool operator<(PDescriptorSet other);
|
||||||
|
|
||||||
constexpr PDescriptorLayout getLayout() const { return layout; }
|
constexpr PDescriptorLayout getLayout() const { return layout; }
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ struct ShaderBufferCreateInfo {
|
|||||||
DataSource sourceData = DataSource();
|
DataSource sourceData = DataSource();
|
||||||
uint64 numElements = 1;
|
uint64 numElements = 1;
|
||||||
uint32 clearValue = 0;
|
uint32 clearValue = 0;
|
||||||
|
uint8 createCleared = 0;
|
||||||
uint8 dynamic = 0;
|
uint8 dynamic = 0;
|
||||||
uint8 vertexBuffer = 0;
|
uint8 vertexBuffer = 0;
|
||||||
std::string name = "Unnamed";
|
std::string name = "Unnamed";
|
||||||
@@ -169,10 +170,10 @@ struct ColorBlendState {
|
|||||||
struct BlendAttachment {
|
struct BlendAttachment {
|
||||||
uint32 blendEnable = 0;
|
uint32 blendEnable = 0;
|
||||||
SeBlendFactor srcColorBlendFactor = Gfx::SE_BLEND_FACTOR_SRC_ALPHA;
|
SeBlendFactor srcColorBlendFactor = Gfx::SE_BLEND_FACTOR_SRC_ALPHA;
|
||||||
SeBlendFactor dstColorBlendFactor = Gfx::SE_BLEND_FACTOR_SRC_ALPHA;
|
SeBlendFactor dstColorBlendFactor = Gfx::SE_BLEND_FACTOR_DST_ALPHA;
|
||||||
SeBlendOp colorBlendOp = Gfx::SE_BLEND_OP_ADD;
|
SeBlendOp colorBlendOp = Gfx::SE_BLEND_OP_ADD;
|
||||||
SeBlendFactor srcAlphaBlendFactor = Gfx::SE_BLEND_FACTOR_SRC_ALPHA;
|
SeBlendFactor srcAlphaBlendFactor = Gfx::SE_BLEND_FACTOR_ONE;
|
||||||
SeBlendFactor dstAlphaBlendFactor = Gfx::SE_BLEND_FACTOR_SRC_ALPHA;
|
SeBlendFactor dstAlphaBlendFactor = Gfx::SE_BLEND_FACTOR_ONE;
|
||||||
SeBlendOp alphaBlendOp = Gfx::SE_BLEND_OP_ADD;
|
SeBlendOp alphaBlendOp = Gfx::SE_BLEND_OP_ADD;
|
||||||
SeColorComponentFlags colorWriteMask =
|
SeColorComponentFlags colorWriteMask =
|
||||||
Gfx::SE_COLOR_COMPONENT_R_BIT | Gfx::SE_COLOR_COMPONENT_G_BIT | Gfx::SE_COLOR_COMPONENT_B_BIT | Gfx::SE_COLOR_COMPONENT_A_BIT;
|
Gfx::SE_COLOR_COMPONENT_R_BIT | Gfx::SE_COLOR_COMPONENT_G_BIT | Gfx::SE_COLOR_COMPONENT_B_BIT | Gfx::SE_COLOR_COMPONENT_A_BIT;
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ BasePass::~BasePass() {}
|
|||||||
void BasePass::beginFrame(const Component::Camera& cam) {
|
void BasePass::beginFrame(const Component::Camera& cam) {
|
||||||
RenderPass::beginFrame(cam);
|
RenderPass::beginFrame(cam);
|
||||||
|
|
||||||
|
cameraPos = cam.getCameraPosition();
|
||||||
|
cameraForward = cam.getCameraForward();
|
||||||
|
|
||||||
lightCullingLayout->reset();
|
lightCullingLayout->reset();
|
||||||
opaqueCulling = lightCullingLayout->allocateDescriptorSet();
|
opaqueCulling = lightCullingLayout->allocateDescriptorSet();
|
||||||
transparentCulling = lightCullingLayout->allocateDescriptorSet();
|
transparentCulling = lightCullingLayout->allocateDescriptorSet();
|
||||||
@@ -95,7 +98,9 @@ void BasePass::render() {
|
|||||||
Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("BasePass");
|
Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("BasePass");
|
||||||
permutation.setDepthCulling(true); // always use the culling info
|
permutation.setDepthCulling(true); // always use the culling info
|
||||||
permutation.setPositionOnly(false);
|
permutation.setPositionOnly(false);
|
||||||
|
Array<VertexData::TransparentDraw> transparentData;
|
||||||
for (VertexData* vertexData : VertexData::getList()) {
|
for (VertexData* vertexData : VertexData::getList()) {
|
||||||
|
transparentData.addAll(vertexData->getTransparentData());
|
||||||
vertexData->getInstanceDataSet()->updateBuffer(6, cullingBuffer);
|
vertexData->getInstanceDataSet()->updateBuffer(6, cullingBuffer);
|
||||||
vertexData->getInstanceDataSet()->writeChanges();
|
vertexData->getInstanceDataSet()->writeChanges();
|
||||||
permutation.setVertexData(vertexData->getTypeName());
|
permutation.setVertexData(vertexData->getTypeName());
|
||||||
@@ -120,6 +125,9 @@ void BasePass::render() {
|
|||||||
|
|
||||||
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
|
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
|
||||||
assert(collection != nullptr);
|
assert(collection != nullptr);
|
||||||
|
|
||||||
|
bool twoSided = materialData.material->isTwoSided();
|
||||||
|
|
||||||
if (graphics->supportMeshShading()) {
|
if (graphics->supportMeshShading()) {
|
||||||
Gfx::MeshPipelineCreateInfo pipelineInfo = {
|
Gfx::MeshPipelineCreateInfo pipelineInfo = {
|
||||||
.taskShader = collection->taskShader,
|
.taskShader = collection->taskShader,
|
||||||
@@ -131,6 +139,10 @@ void BasePass::render() {
|
|||||||
{
|
{
|
||||||
.samples = viewport->getSamples(),
|
.samples = viewport->getSamples(),
|
||||||
},
|
},
|
||||||
|
.rasterizationState =
|
||||||
|
{
|
||||||
|
.cullMode = Gfx::SeCullModeFlags(twoSided ? Gfx::SE_CULL_MODE_NONE : Gfx::SE_CULL_MODE_BACK_BIT),
|
||||||
|
},
|
||||||
.depthStencilState =
|
.depthStencilState =
|
||||||
{
|
{
|
||||||
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL,
|
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL,
|
||||||
@@ -152,6 +164,10 @@ void BasePass::render() {
|
|||||||
{
|
{
|
||||||
.samples = viewport->getSamples(),
|
.samples = viewport->getSamples(),
|
||||||
},
|
},
|
||||||
|
.rasterizationState =
|
||||||
|
{
|
||||||
|
.cullMode = Gfx::SeCullModeFlags(twoSided ? Gfx::SE_CULL_MODE_NONE : Gfx::SE_CULL_MODE_BACK_BIT),
|
||||||
|
},
|
||||||
.depthStencilState =
|
.depthStencilState =
|
||||||
{
|
{
|
||||||
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL,
|
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL,
|
||||||
@@ -184,8 +200,106 @@ void BasePass::render() {
|
|||||||
commands.add(std::move(command));
|
commands.add(std::move(command));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics->executeCommands(std::move(commands));
|
graphics->executeCommands(std::move(commands));
|
||||||
|
|
||||||
|
Map<float, VertexData::TransparentDraw> sortedDraws;
|
||||||
|
for (const auto& t : transparentData) {
|
||||||
|
Vector toCenter = Vector(t.worldPosition) - cameraPos;
|
||||||
|
float dist = glm::length(toCenter) * glm::dot(glm::normalize(toCenter), cameraForward);
|
||||||
|
sortedDraws[dist] = t;
|
||||||
|
}
|
||||||
|
Gfx::ORenderCommand command = graphics->createRenderCommand("TransparentDraw");
|
||||||
|
command->setViewport(viewport);
|
||||||
|
for (const auto& [_, t] : sortedDraws) {
|
||||||
|
permutation.setVertexData(t.vertexData->getTypeName());
|
||||||
|
permutation.setMaterial(t.matInst->getBaseMaterial()->getName());
|
||||||
|
Gfx::PermutationId id(permutation);
|
||||||
|
|
||||||
|
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
|
||||||
|
assert(collection != nullptr);
|
||||||
|
|
||||||
|
bool twoSided = t.matInst->getBaseMaterial()->isTwoSided();
|
||||||
|
|
||||||
|
if (graphics->supportMeshShading()) {
|
||||||
|
Gfx::MeshPipelineCreateInfo pipelineInfo = {
|
||||||
|
.taskShader = collection->taskShader,
|
||||||
|
.meshShader = collection->meshShader,
|
||||||
|
.fragmentShader = collection->fragmentShader,
|
||||||
|
.renderPass = renderPass,
|
||||||
|
.pipelineLayout = collection->pipelineLayout,
|
||||||
|
.multisampleState =
|
||||||
|
{
|
||||||
|
.samples = viewport->getSamples(),
|
||||||
|
},
|
||||||
|
.rasterizationState =
|
||||||
|
{
|
||||||
|
.cullMode = Gfx::SeCullModeFlags(twoSided ? Gfx::SE_CULL_MODE_NONE : Gfx::SE_CULL_MODE_BACK_BIT),
|
||||||
|
},
|
||||||
|
.depthStencilState =
|
||||||
|
{
|
||||||
|
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL,
|
||||||
|
},
|
||||||
|
.colorBlend =
|
||||||
|
{
|
||||||
|
.attachmentCount = 1,
|
||||||
|
.blendAttachments =
|
||||||
|
{
|
||||||
|
Gfx::ColorBlendState::BlendAttachment{
|
||||||
|
.blendEnable = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||||
|
command->bindPipeline(pipeline);
|
||||||
|
} else {
|
||||||
|
Gfx::LegacyPipelineCreateInfo pipelineInfo = {
|
||||||
|
.vertexShader = collection->vertexShader,
|
||||||
|
.fragmentShader = collection->fragmentShader,
|
||||||
|
.renderPass = renderPass,
|
||||||
|
.pipelineLayout = collection->pipelineLayout,
|
||||||
|
.multisampleState =
|
||||||
|
{
|
||||||
|
.samples = viewport->getSamples(),
|
||||||
|
},
|
||||||
|
.rasterizationState =
|
||||||
|
{
|
||||||
|
.cullMode = Gfx::SeCullModeFlags(twoSided ? Gfx::SE_CULL_MODE_NONE : Gfx::SE_CULL_MODE_BACK_BIT),
|
||||||
|
},
|
||||||
|
.depthStencilState =
|
||||||
|
{
|
||||||
|
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL,
|
||||||
|
},
|
||||||
|
.colorBlend =
|
||||||
|
{
|
||||||
|
.attachmentCount = 1,
|
||||||
|
.blendAttachments =
|
||||||
|
{
|
||||||
|
Gfx::ColorBlendState::BlendAttachment{
|
||||||
|
.blendEnable = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||||
|
command->bindPipeline(pipeline);
|
||||||
|
}
|
||||||
|
command->bindDescriptor({viewParamsSet, t.vertexData->getVertexDataSet(), t.vertexData->getInstanceDataSet(),
|
||||||
|
scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), transparentCulling});
|
||||||
|
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0,
|
||||||
|
sizeof(VertexData::DrawCallOffsets), &t.offsets);
|
||||||
|
if (graphics->supportMeshShading()) {
|
||||||
|
command->drawMesh(1, 1, 1);
|
||||||
|
} else {
|
||||||
|
// command->bindIndexBuffer(t.vertexData->getIndexBuffer());
|
||||||
|
// for (const auto& meshData : drawCall.instanceMeshData) {
|
||||||
|
// // all meshlets of a mesh share the same indices offset
|
||||||
|
// command->drawIndexed(meshData.numIndices, 1, meshData.firstIndex, vertexData->getIndicesOffset(meshData.meshletOffset),
|
||||||
|
// 0);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
graphics->endRenderPass();
|
graphics->endRenderPass();
|
||||||
query->endQuery();
|
query->endQuery();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ class BasePass : public RenderPass {
|
|||||||
// use a different texture here so we can do multisampling
|
// use a different texture here so we can do multisampling
|
||||||
Gfx::OTexture2D basePassDepth;
|
Gfx::OTexture2D basePassDepth;
|
||||||
|
|
||||||
|
// used for transparency sorting
|
||||||
|
Vector cameraPos;
|
||||||
|
Vector cameraForward;
|
||||||
|
|
||||||
PCameraActor source;
|
PCameraActor source;
|
||||||
Gfx::OPipelineLayout basePassLayout;
|
Gfx::OPipelineLayout basePassLayout;
|
||||||
Gfx::ODescriptorLayout lightCullingLayout;
|
Gfx::ODescriptorLayout lightCullingLayout;
|
||||||
|
|||||||
@@ -105,7 +105,9 @@ void DepthCullingPass::render() {
|
|||||||
UVector2 threadGroups = (((mipDims[i] + UVector2(1, 1)) / 2u) + UVector2(BLOCK_SIZE - 1, BLOCK_SIZE - 1)) / uint32(BLOCK_SIZE);
|
UVector2 threadGroups = (((mipDims[i] + UVector2(1, 1)) / 2u) + UVector2(BLOCK_SIZE - 1, BLOCK_SIZE - 1)) / uint32(BLOCK_SIZE);
|
||||||
computeCommand->dispatch(threadGroups.x, threadGroups.y, 1);
|
computeCommand->dispatch(threadGroups.x, threadGroups.y, 1);
|
||||||
}
|
}
|
||||||
|
Array<Gfx::OComputeCommand> computeCommands;
|
||||||
|
computeCommands.add(std::move(computeCommand));
|
||||||
|
graphics->executeCommands(std::move(computeCommands));
|
||||||
depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT);
|
||||||
|
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ TextPass::FontData& TextPass::getFontData(PFontAsset font) {
|
|||||||
const auto& fontGlyphs = font->getGlyphData();
|
const auto& fontGlyphs = font->getGlyphData();
|
||||||
FontData& fd = fontData[font];
|
FontData& fd = fontData[font];
|
||||||
Array<GlyphData> glyphData;
|
Array<GlyphData> glyphData;
|
||||||
Array<Gfx::PTexture> textures;
|
Array<Gfx::PTexture2D> textures;
|
||||||
glyphData.reserve(fontGlyphs.size());
|
glyphData.reserve(fontGlyphs.size());
|
||||||
for (const auto& [key, value] : fontGlyphs) {
|
for (const auto& [key, value] : fontGlyphs) {
|
||||||
fd.characterToGlyphIndex[key] = static_cast<uint32>(glyphData.size());
|
fd.characterToGlyphIndex[key] = static_cast<uint32>(glyphData.size());
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class UIPass : public RenderPass {
|
|||||||
Gfx::OPipelineLayout pipelineLayout;
|
Gfx::OPipelineLayout pipelineLayout;
|
||||||
|
|
||||||
Array<UI::RenderElementStyle> renderElements;
|
Array<UI::RenderElementStyle> renderElements;
|
||||||
Array<Gfx::PTexture> usedTextures;
|
Array<Gfx::PTexture2D> usedTextures;
|
||||||
};
|
};
|
||||||
DEFINE_REF(UIPass);
|
DEFINE_REF(UIPass);
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ void VisibilityPass::publishOutputs() {
|
|||||||
|
|
||||||
cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
.clearValue = 0xffffffff,
|
.clearValue = 0xffffffff,
|
||||||
|
.createCleared = true,
|
||||||
.dynamic = true,
|
.dynamic = true,
|
||||||
.name = "CullingBuffer",
|
.name = "CullingBuffer",
|
||||||
});
|
});
|
||||||
|
|||||||
+213
-150
@@ -17,6 +17,8 @@ uint64 VertexData::meshletCount = 0;
|
|||||||
|
|
||||||
void VertexData::resetMeshData() {
|
void VertexData::resetMeshData() {
|
||||||
std::unique_lock l(materialDataLock);
|
std::unique_lock l(materialDataLock);
|
||||||
|
transparentInstanceData.clear();
|
||||||
|
transparentMeshData.clear();
|
||||||
for (auto& mat : materialData) {
|
for (auto& mat : materialData) {
|
||||||
for (auto& inst : mat.instances) {
|
for (auto& inst : mat.instances) {
|
||||||
inst.instanceData.clear();
|
inst.instanceData.clear();
|
||||||
@@ -36,6 +38,32 @@ void VertexData::updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Compo
|
|||||||
std::unique_lock l(materialDataLock);
|
std::unique_lock l(materialDataLock);
|
||||||
PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle();
|
PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle();
|
||||||
PMaterial mat = referencedInstance->getBaseMaterial();
|
PMaterial mat = referencedInstance->getBaseMaterial();
|
||||||
|
const auto& data = meshData[mesh->id];
|
||||||
|
|
||||||
|
Matrix4 transformMatrix = transform.toMatrix() * mesh->transform;
|
||||||
|
InstanceData inst = InstanceData{
|
||||||
|
.transformMatrix = transformMatrix,
|
||||||
|
.inverseTransformMatrix = glm::inverse(transformMatrix),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (mat->hasTransparency()) {
|
||||||
|
auto params = referencedInstance->getMaterialOffsets();
|
||||||
|
transparentData.add(TransparentDraw{
|
||||||
|
.matInst = referencedInstance,
|
||||||
|
.vertexData = this,
|
||||||
|
.offsets =
|
||||||
|
{
|
||||||
|
.instanceOffset = static_cast<uint32>(transparentInstanceData.size()),
|
||||||
|
.textureOffset = params.textureOffset,
|
||||||
|
.samplerOffset = params.samplerOffset,
|
||||||
|
.floatOffset = params.floatOffset,
|
||||||
|
},
|
||||||
|
.worldPosition = Vector(inst.transformMatrix[3]),
|
||||||
|
});
|
||||||
|
transparentInstanceData.add(inst);
|
||||||
|
transparentMeshData.add(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (materialData.size() <= mat->getId()) {
|
if (materialData.size() <= mat->getId()) {
|
||||||
materialData.resize(mat->getId() + 1);
|
materialData.resize(mat->getId() + 1);
|
||||||
}
|
}
|
||||||
@@ -47,12 +75,7 @@ void VertexData::updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Compo
|
|||||||
BatchedDrawCall& matInstanceData = matData.instances[referencedInstance->getId()];
|
BatchedDrawCall& matInstanceData = matData.instances[referencedInstance->getId()];
|
||||||
matInstanceData.materialInstance = referencedInstance;
|
matInstanceData.materialInstance = referencedInstance;
|
||||||
|
|
||||||
Matrix4 transformMatrix = transform.toMatrix() * mesh->transform;
|
matInstanceData.instanceData.add(inst);
|
||||||
matInstanceData.instanceData.add(InstanceData{
|
|
||||||
.transformMatrix = transformMatrix,
|
|
||||||
.inverseTransformMatrix = glm::inverse(transformMatrix),
|
|
||||||
});
|
|
||||||
const auto& data = meshData[mesh->id];
|
|
||||||
auto [instanceId, meshletOffset] = getCullingMapping(id, meshIndex, data.numMeshlets);
|
auto [instanceId, meshletOffset] = getCullingMapping(id, meshIndex, data.numMeshlets);
|
||||||
matInstanceData.instanceMeshData.add(data);
|
matInstanceData.instanceMeshData.add(data);
|
||||||
matInstanceData.cullingOffsets.add(meshletOffset);
|
matInstanceData.cullingOffsets.add(meshletOffset);
|
||||||
@@ -157,6 +180,25 @@ void VertexData::createDescriptors() {
|
|||||||
});
|
});
|
||||||
instanceMeshDataBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
instanceMeshDataBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
Gfx::SE_ACCESS_MEMORY_READ_BIT, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
Gfx::SE_ACCESS_MEMORY_READ_BIT, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
||||||
|
|
||||||
|
transparentInstanceDataBuffer->rotateBuffer(sizeof(InstanceData) * transparentInstanceData.size());
|
||||||
|
transparentInstanceDataBuffer->updateContents(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = sizeof(InstanceData) * transparentInstanceData.size(),
|
||||||
|
.data = (uint8*)transparentInstanceData.data(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
transparentMeshDataBuffer->rotateBuffer(sizeof(MeshData) * transparentMeshData.size());
|
||||||
|
transparentMeshDataBuffer->updateContents(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = sizeof(MeshData) * transparentMeshData.size(),
|
||||||
|
.data = (uint8*)transparentMeshData.data(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
instanceDataLayout->reset();
|
instanceDataLayout->reset();
|
||||||
descriptorSet = instanceDataLayout->allocateDescriptorSet();
|
descriptorSet = instanceDataLayout->allocateDescriptorSet();
|
||||||
descriptorSet->updateBuffer(0, instanceBuffer);
|
descriptorSet->updateBuffer(0, instanceBuffer);
|
||||||
@@ -169,176 +211,197 @@ void VertexData::createDescriptors() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets) {
|
void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets) {
|
||||||
assert(loadedMeshlets.size() < 2048);
|
std::unique_lock l(vertexDataLock);
|
||||||
std::unique_lock l(vertexDataLock);
|
meshlets.reserve(meshlets.size() + loadedMeshlets.size());
|
||||||
meshlets.reserve(meshlets.size() + loadedMeshlets.size());
|
vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet);
|
||||||
vertexIndices.reserve(vertexIndices.size() + loadedMeshlets.size() * Gfx::numVerticesPerMeshlet);
|
primitiveIndices.reserve(primitiveIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3);
|
||||||
primitiveIndices.reserve(primitiveIndices.size() + loadedMeshlets.size() * Gfx::numPrimitivesPerMeshlet * 3);
|
uint32 meshletOffset = meshlets.size();
|
||||||
uint32 meshletOffset = meshlets.size();
|
AABB meshAABB;
|
||||||
AABB meshAABB;
|
for (uint32 i = 0; i < loadedMeshlets.size(); ++i) {
|
||||||
for (uint32 i = 0; i < loadedMeshlets.size(); ++i) {
|
Meshlet& m = loadedMeshlets[i];
|
||||||
Meshlet& m = loadedMeshlets[i];
|
meshAABB = meshAABB.combine(m.boundingBox);
|
||||||
meshAABB = meshAABB.combine(m.boundingBox);
|
uint32 vertexOffset = vertexIndices.size();
|
||||||
uint32 vertexOffset = vertexIndices.size();
|
vertexIndices.resize(vertexOffset + m.numVertices);
|
||||||
vertexIndices.resize(vertexOffset + m.numVertices);
|
std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32));
|
||||||
std::memcpy(vertexIndices.data() + vertexOffset, m.uniqueVertices, m.numVertices * sizeof(uint32));
|
uint32 primitiveOffset = primitiveIndices.size();
|
||||||
uint32 primitiveOffset = primitiveIndices.size();
|
primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3));
|
||||||
primitiveIndices.resize(primitiveOffset + (m.numPrimitives * 3));
|
std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8));
|
||||||
std::memcpy(primitiveIndices.data() + primitiveOffset, m.primitiveLayout, m.numPrimitives * 3 * sizeof(uint8));
|
meshlets.add(MeshletDescription{
|
||||||
meshlets.add(MeshletDescription{
|
.bounding = m.boundingBox, //.toSphere(),
|
||||||
.bounding = m.boundingBox, //.toSphere(),
|
.vertexCount = m.numVertices,
|
||||||
.vertexCount = m.numVertices,
|
.primitiveCount = m.numPrimitives,
|
||||||
.primitiveCount = m.numPrimitives,
|
.vertexOffset = vertexOffset,
|
||||||
.vertexOffset = vertexOffset,
|
.primitiveOffset = primitiveOffset,
|
||||||
.primitiveOffset = primitiveOffset,
|
.color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX),
|
||||||
.color = Vector((float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX),
|
.indicesOffset = (uint32)meshOffsets[id],
|
||||||
.indicesOffset = (uint32)meshOffsets[id],
|
});
|
||||||
|
}
|
||||||
|
meshData[id] = MeshData{
|
||||||
|
.bounding = meshAABB, //.toSphere(),
|
||||||
|
.numMeshlets = (uint32)loadedMeshlets.size(),
|
||||||
|
.meshletOffset = meshletOffset,
|
||||||
|
.firstIndex = (uint32)indices.size(),
|
||||||
|
.numIndices = (uint32)loadedIndices.size(),
|
||||||
|
};
|
||||||
|
|
||||||
|
indices.resize(indices.size() + loadedIndices.size());
|
||||||
|
std::memcpy(indices.data() + meshData[id].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32));
|
||||||
|
}
|
||||||
|
|
||||||
|
void VertexData::commitMeshes() {
|
||||||
|
indexBuffer = graphics->createIndexBuffer(IndexBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = sizeof(uint32) * indices.size(),
|
||||||
|
.data = (uint8*)indices.data(),
|
||||||
|
},
|
||||||
|
.indexType = Gfx::SE_INDEX_TYPE_UINT32,
|
||||||
|
.name = "IndexBuffer",
|
||||||
|
});
|
||||||
|
meshletBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = sizeof(MeshletDescription) * meshlets.size(),
|
||||||
|
.data = (uint8*)meshlets.data(),
|
||||||
|
},
|
||||||
|
.numElements = meshlets.size(),
|
||||||
|
.dynamic = false,
|
||||||
|
.name = "MeshletBuffer",
|
||||||
|
});
|
||||||
|
vertexIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = sizeof(uint32) * vertexIndices.size(),
|
||||||
|
.data = (uint8*)vertexIndices.data(),
|
||||||
|
},
|
||||||
|
.numElements = vertexIndices.size(),
|
||||||
|
.dynamic = false,
|
||||||
|
.name = "VertexIndicesBuffer",
|
||||||
});
|
});
|
||||||
}
|
|
||||||
meshData[id] = MeshData{
|
|
||||||
.bounding = meshAABB, //.toSphere(),
|
|
||||||
.numMeshlets = (uint32)loadedMeshlets.size(),
|
|
||||||
.meshletOffset = meshletOffset,
|
|
||||||
.firstIndex = (uint32)indices.size(),
|
|
||||||
.numIndices = (uint32)loadedIndices.size(),
|
|
||||||
};
|
|
||||||
|
|
||||||
indices.resize(indices.size() + loadedIndices.size());
|
primitiveIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
std::memcpy(indices.data() + meshData[id].firstIndex, loadedIndices.data(), loadedIndices.size() * sizeof(uint32));
|
.sourceData =
|
||||||
indexBuffer = graphics->createIndexBuffer(IndexBufferCreateInfo{
|
{
|
||||||
.sourceData =
|
.size = sizeof(uint8) * primitiveIndices.size(),
|
||||||
{
|
.data = (uint8*)primitiveIndices.data(),
|
||||||
.size = sizeof(uint32) * indices.size(),
|
},
|
||||||
.data = (uint8*)indices.data(),
|
.numElements = primitiveIndices.size(),
|
||||||
},
|
.dynamic = false,
|
||||||
.indexType = Gfx::SE_INDEX_TYPE_UINT32,
|
.name = "PrimitiveIndicesBuffer",
|
||||||
.name = "IndexBuffer",
|
});
|
||||||
});
|
|
||||||
meshletBuffer = graphics->createShaderBuffer(
|
|
||||||
ShaderBufferCreateInfo{.sourceData = {.size = sizeof(MeshletDescription) * meshlets.size(), .data = (uint8*)meshlets.data()},
|
|
||||||
.numElements = meshlets.size(),
|
|
||||||
.dynamic = false,
|
|
||||||
.name = "MeshletBuffer"});
|
|
||||||
|
|
||||||
vertexIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{.sourceData =
|
|
||||||
{
|
|
||||||
.size = sizeof(uint32) * vertexIndices.size(),
|
|
||||||
.data = (uint8*)vertexIndices.data(),
|
|
||||||
},
|
|
||||||
.numElements = vertexIndices.size(),
|
|
||||||
.dynamic = false,
|
|
||||||
.name = "VertexIndicesBuffer"});
|
|
||||||
|
|
||||||
primitiveIndicesBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
|
||||||
.sourceData =
|
|
||||||
{
|
|
||||||
.size = sizeof(uint8) * primitiveIndices.size(),
|
|
||||||
.data = (uint8*)primitiveIndices.data(),
|
|
||||||
},
|
|
||||||
.numElements = primitiveIndices.size(),
|
|
||||||
.dynamic = false,
|
|
||||||
.name = "PrimitiveIndicesBuffer",
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MeshId VertexData::allocateVertexData(uint64 numVertices) {
|
MeshId VertexData::allocateVertexData(uint64 numVertices) {
|
||||||
std::unique_lock l(vertexDataLock);
|
std::unique_lock l(vertexDataLock);
|
||||||
MeshId res{idCounter++};
|
MeshId res{idCounter++};
|
||||||
meshOffsets[res] = head;
|
meshOffsets[res] = head;
|
||||||
meshVertexCounts[res] = numVertices;
|
meshVertexCounts[res] = numVertices;
|
||||||
head += numVertices;
|
head += numVertices;
|
||||||
if (head > verticesAllocated) {
|
if (head > verticesAllocated) {
|
||||||
verticesAllocated = std::max(head, verticesAllocated + NUM_DEFAULT_ELEMENTS);
|
verticesAllocated = std::max(head, verticesAllocated + NUM_DEFAULT_ELEMENTS);
|
||||||
resizeBuffers();
|
resizeBuffers();
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 VertexData::getMeshOffset(MeshId id) { return meshOffsets[id]; }
|
uint64 VertexData::getMeshOffset(MeshId id) {
|
||||||
|
return meshOffsets[id]; }
|
||||||
|
|
||||||
uint64 VertexData::getMeshVertexCount(MeshId id) { return meshVertexCounts[id]; }
|
uint64 VertexData::getMeshVertexCount(MeshId id) {
|
||||||
|
return meshVertexCounts[id]; }
|
||||||
|
|
||||||
List<VertexData*> vertexDataList;
|
List<VertexData*> vertexDataList;
|
||||||
|
|
||||||
List<VertexData*> VertexData::getList() { return vertexDataList; }
|
List<VertexData*> VertexData::getList() {
|
||||||
|
return vertexDataList; }
|
||||||
|
|
||||||
VertexData* VertexData::findByTypeName(std::string name) {
|
VertexData* VertexData::findByTypeName(std::string name) {
|
||||||
for (auto vd : vertexDataList) {
|
for (auto vd : vertexDataList) {
|
||||||
if (vd->getTypeName() == name) {
|
if (vd->getTypeName() == name) {
|
||||||
return vd;
|
return vd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return nullptr;
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexData::init(Gfx::PGraphics _graphics) {
|
void VertexData::init(Gfx::PGraphics _graphics) {
|
||||||
graphics = _graphics;
|
graphics = _graphics;
|
||||||
verticesAllocated = NUM_DEFAULT_ELEMENTS;
|
verticesAllocated = NUM_DEFAULT_ELEMENTS;
|
||||||
instanceDataLayout = graphics->createDescriptorLayout("pScene");
|
instanceDataLayout = graphics->createDescriptorLayout("pScene");
|
||||||
|
|
||||||
// instanceData
|
// instanceData
|
||||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
});
|
});
|
||||||
// meshData
|
// meshData
|
||||||
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
.binding = 1,
|
.binding = 1,
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
});
|
});
|
||||||
// meshletData
|
// meshletData
|
||||||
instanceDataLayout->addDescriptorBinding(
|
instanceDataLayout->addDescriptorBinding(
|
||||||
Gfx::DescriptorBinding{.binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
Gfx::DescriptorBinding{.binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
||||||
// primitiveIndices
|
// primitiveIndices
|
||||||
instanceDataLayout->addDescriptorBinding(
|
instanceDataLayout->addDescriptorBinding(
|
||||||
Gfx::DescriptorBinding{.binding = 3, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
Gfx::DescriptorBinding{.binding = 3, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
||||||
// vertexIndices
|
// vertexIndices
|
||||||
instanceDataLayout->addDescriptorBinding(
|
instanceDataLayout->addDescriptorBinding(
|
||||||
Gfx::DescriptorBinding{.binding = 4, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
Gfx::DescriptorBinding{.binding = 4, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
||||||
// cullingOffset
|
// cullingOffset
|
||||||
instanceDataLayout->addDescriptorBinding(
|
instanceDataLayout->addDescriptorBinding(
|
||||||
Gfx::DescriptorBinding{.binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
Gfx::DescriptorBinding{.binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
||||||
// cullingInfos
|
// cullingInfos
|
||||||
instanceDataLayout->addDescriptorBinding(
|
instanceDataLayout->addDescriptorBinding(
|
||||||
Gfx::DescriptorBinding{.binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
Gfx::DescriptorBinding{.binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER});
|
||||||
|
|
||||||
instanceDataLayout->create();
|
instanceDataLayout->create();
|
||||||
|
|
||||||
cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
.dynamic = true,
|
.dynamic = true,
|
||||||
.name = "MeshletOffset",
|
.name = "MeshletOffset",
|
||||||
});
|
});
|
||||||
instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
.dynamic = true,
|
.dynamic = true,
|
||||||
.name = "InstanceBuffer",
|
.name = "InstanceBuffer",
|
||||||
});
|
});
|
||||||
instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
.dynamic = true,
|
.dynamic = true,
|
||||||
.name = "MeshDataBuffer",
|
.name = "MeshDataBuffer",
|
||||||
});
|
});
|
||||||
resizeBuffers();
|
|
||||||
graphics->getShaderCompiler()->registerVertexData(this);
|
transparentInstanceDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.dynamic = true,
|
||||||
|
.name = "TransparentInstanceBuffer",
|
||||||
|
});
|
||||||
|
transparentMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.dynamic = true,
|
||||||
|
.name = "TransparentMeshBuffer",
|
||||||
|
});
|
||||||
|
|
||||||
|
resizeBuffers();
|
||||||
|
graphics->getShaderCompiler()->registerVertexData(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexData::destroy() {
|
void VertexData::destroy() {
|
||||||
instanceBuffer = nullptr;
|
instanceBuffer = nullptr;
|
||||||
instanceMeshDataBuffer = nullptr;
|
instanceMeshDataBuffer = nullptr;
|
||||||
instanceDataLayout = nullptr;
|
instanceDataLayout = nullptr;
|
||||||
meshletBuffer = nullptr;
|
meshletBuffer = nullptr;
|
||||||
vertexIndicesBuffer = nullptr;
|
vertexIndicesBuffer = nullptr;
|
||||||
primitiveIndicesBuffer = nullptr;
|
primitiveIndicesBuffer = nullptr;
|
||||||
indexBuffer = nullptr;
|
indexBuffer = nullptr;
|
||||||
meshData.clear();
|
meshData.clear();
|
||||||
materialData.clear();
|
materialData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexData::CullingMapping VertexData::getCullingMapping(entt::entity id, uint32 meshIndex, uint32 numMeshlets) {
|
VertexData::CullingMapping VertexData::getCullingMapping(entt::entity id, uint32 meshIndex, uint32 numMeshlets) {
|
||||||
MeshMapping key = MeshMapping{.id = id, .meshId = meshIndex};
|
MeshMapping key = MeshMapping{.id = id, .meshId = meshIndex};
|
||||||
if (!instanceIdMap.contains(key)) {
|
if (!instanceIdMap.contains(key)) {
|
||||||
instanceIdMap[key] = CullingMapping{.instanceId = instanceCount++, .cullingOffset = uint32(meshletCount)};
|
instanceIdMap[key] = CullingMapping{.instanceId = instanceCount++, .cullingOffset = uint32(meshletCount)};
|
||||||
meshletCount += numMeshlets;
|
meshletCount += numMeshlets;
|
||||||
}
|
}
|
||||||
return instanceIdMap[key];
|
return instanceIdMap[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexData::VertexData() : idCounter(0), head(0), verticesAllocated(0), dirty(false) {}
|
VertexData::VertexData() : idCounter(0), head(0), verticesAllocated(0), dirty(false) {}
|
||||||
|
|||||||
@@ -41,10 +41,17 @@ class VertexData {
|
|||||||
PMaterial material;
|
PMaterial material;
|
||||||
Array<BatchedDrawCall> instances;
|
Array<BatchedDrawCall> instances;
|
||||||
};
|
};
|
||||||
|
struct TransparentDraw {
|
||||||
|
PMaterialInstance matInst;
|
||||||
|
VertexData* vertexData;
|
||||||
|
DrawCallOffsets offsets;
|
||||||
|
Vector worldPosition;
|
||||||
|
};
|
||||||
void resetMeshData();
|
void resetMeshData();
|
||||||
void updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Component::Transform& transform);
|
void updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Component::Transform& transform);
|
||||||
void createDescriptors();
|
void createDescriptors();
|
||||||
void loadMesh(MeshId id, Array<uint32> indices, Array<Meshlet> meshlets);
|
void loadMesh(MeshId id, Array<uint32> indices, Array<Meshlet> meshlets);
|
||||||
|
void commitMeshes();
|
||||||
MeshId allocateVertexData(uint64 numVertices);
|
MeshId allocateVertexData(uint64 numVertices);
|
||||||
uint64 getMeshOffset(MeshId id);
|
uint64 getMeshOffset(MeshId id);
|
||||||
uint64 getMeshVertexCount(MeshId id);
|
uint64 getMeshVertexCount(MeshId id);
|
||||||
@@ -60,6 +67,7 @@ class VertexData {
|
|||||||
Gfx::PDescriptorLayout getInstanceDataLayout() { return instanceDataLayout; }
|
Gfx::PDescriptorLayout getInstanceDataLayout() { return instanceDataLayout; }
|
||||||
Gfx::PDescriptorSet getInstanceDataSet() { return descriptorSet; }
|
Gfx::PDescriptorSet getInstanceDataSet() { return descriptorSet; }
|
||||||
const Array<MaterialData>& getMaterialData() const { return materialData; }
|
const Array<MaterialData>& getMaterialData() const { return materialData; }
|
||||||
|
const Array<TransparentDraw>& getTransparentData() const { return transparentData; }
|
||||||
const MeshData& getMeshData(MeshId id) { return meshData[id]; }
|
const MeshData& getMeshData(MeshId id) { return meshData[id]; }
|
||||||
uint64 getIndicesOffset(uint32 meshletIndex) { return meshlets[meshletIndex].indicesOffset; }
|
uint64 getIndicesOffset(uint32 meshletIndex) { return meshlets[meshletIndex].indicesOffset; }
|
||||||
uint64 getNumInstances() const { return instanceData.size(); }
|
uint64 getNumInstances() const { return instanceData.size(); }
|
||||||
@@ -91,10 +99,13 @@ class VertexData {
|
|||||||
};
|
};
|
||||||
std::mutex materialDataLock;
|
std::mutex materialDataLock;
|
||||||
Array<MaterialData> materialData;
|
Array<MaterialData> materialData;
|
||||||
|
Array<TransparentDraw> transparentData;
|
||||||
|
|
||||||
std::mutex vertexDataLock;
|
std::mutex vertexDataLock;
|
||||||
Map<MeshId, MeshData> meshData;
|
Map<MeshId, MeshData> meshData;
|
||||||
Map<MeshId, uint64> meshOffsets;
|
Map<MeshId, uint64> meshOffsets;
|
||||||
Map<MeshId, uint64> meshVertexCounts;
|
Map<MeshId, uint64> meshVertexCounts;
|
||||||
|
|
||||||
Array<MeshletDescription> meshlets;
|
Array<MeshletDescription> meshlets;
|
||||||
Array<uint8> primitiveIndices;
|
Array<uint8> primitiveIndices;
|
||||||
Array<uint32> vertexIndices;
|
Array<uint32> vertexIndices;
|
||||||
@@ -121,8 +132,15 @@ class VertexData {
|
|||||||
// Material data
|
// Material data
|
||||||
Array<InstanceData> instanceData;
|
Array<InstanceData> instanceData;
|
||||||
Gfx::OShaderBuffer instanceBuffer;
|
Gfx::OShaderBuffer instanceBuffer;
|
||||||
|
|
||||||
Array<MeshData> instanceMeshData;
|
Array<MeshData> instanceMeshData;
|
||||||
Gfx::OShaderBuffer instanceMeshDataBuffer;
|
Gfx::OShaderBuffer instanceMeshDataBuffer;
|
||||||
|
|
||||||
|
Array<InstanceData> transparentInstanceData;
|
||||||
|
Gfx::OShaderBuffer transparentInstanceDataBuffer;
|
||||||
|
Array<MeshData> transparentMeshData;
|
||||||
|
Gfx::OShaderBuffer transparentMeshDataBuffer;
|
||||||
|
|
||||||
Gfx::PDescriptorSet descriptorSet;
|
Gfx::PDescriptorSet descriptorSet;
|
||||||
uint64 idCounter;
|
uint64 idCounter;
|
||||||
uint64 head;
|
uint64 head;
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ using namespace Seele::Vulkan;
|
|||||||
|
|
||||||
BufferAllocation::BufferAllocation(PGraphics graphics, const std::string& name, VkBufferCreateInfo bufferInfo,
|
BufferAllocation::BufferAllocation(PGraphics graphics, const std::string& name, VkBufferCreateInfo bufferInfo,
|
||||||
VmaAllocationCreateInfo allocInfo, Gfx::QueueType owner, uint64 alignment)
|
VmaAllocationCreateInfo allocInfo, Gfx::QueueType owner, uint64 alignment)
|
||||||
: CommandBoundResource(graphics), size(bufferInfo.size), owner(owner) {
|
: CommandBoundResource(graphics), size(bufferInfo.size), name(name), owner(owner) {
|
||||||
VK_CHECK(vmaCreateBufferWithAlignment(graphics->getAllocator(), &bufferInfo, &allocInfo, alignment, &buffer, &allocation, nullptr));
|
VK_CHECK(vmaCreateBufferWithAlignment(graphics->getAllocator(), &bufferInfo, &allocInfo, alignment, &buffer, &allocation, &info));
|
||||||
vmaGetAllocationMemoryProperties(graphics->getAllocator(), allocation, &properties);
|
vmaGetAllocationMemoryProperties(graphics->getAllocator(), allocation, &properties);
|
||||||
VkDebugUtilsObjectNameInfoEXT nameInfo = {
|
VkDebugUtilsObjectNameInfoEXT nameInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
|
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
|
||||||
@@ -167,10 +167,10 @@ void BufferAllocation::readContents(uint64 regionOffset, uint64 regionSize, void
|
|||||||
}
|
}
|
||||||
|
|
||||||
Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType queueType, bool dynamic, std::string name,
|
Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType queueType, bool dynamic, std::string name,
|
||||||
uint32 clearValue)
|
bool createCleared, uint32 clearValue)
|
||||||
: graphics(graphics), currentBuffer(0), initialOwner(queueType),
|
: graphics(graphics), currentBuffer(0), initialOwner(queueType),
|
||||||
usage(usage | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
|
usage(usage | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
|
||||||
dynamic(dynamic), name(name), clearValue(clearValue) {
|
dynamic(dynamic), createCleared(createCleared), name(name), clearValue(clearValue) {
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
buffers.add(nullptr);
|
buffers.add(nullptr);
|
||||||
createBuffer(size, 0);
|
createBuffer(size, 0);
|
||||||
@@ -235,10 +235,13 @@ void Buffer::createBuffer(uint64 size, uint32 destIndex) {
|
|||||||
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
|
.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
|
||||||
};
|
};
|
||||||
buffers[destIndex] = new BufferAllocation(graphics, name, info, allocInfo, initialOwner);
|
buffers[destIndex] = new BufferAllocation(graphics, name, info, allocInfo, initialOwner);
|
||||||
PCommand command = graphics->getQueueCommands(initialOwner)->getCommands();
|
if (createCleared)
|
||||||
vkCmdFillBuffer(command->getHandle(), buffers[destIndex]->buffer, 0, VK_WHOLE_SIZE, clearValue);
|
{
|
||||||
pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
PCommand command = graphics->getQueueCommands(initialOwner)->getCommands();
|
||||||
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
vkCmdFillBuffer(command->getHandle(), buffers[destIndex]->buffer, 0, VK_WHOLE_SIZE, clearValue);
|
||||||
|
pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +324,7 @@ ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& cre
|
|||||||
(createInfo.vertexBuffer ? VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR |
|
(createInfo.vertexBuffer ? VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR |
|
||||||
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
|
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
|
||||||
: 0),
|
: 0),
|
||||||
createInfo.sourceData.owner, createInfo.dynamic, createInfo.name) {
|
createInfo.sourceData.owner, createInfo.dynamic, createInfo.name, createInfo.createCleared, createInfo.clearValue) {
|
||||||
if (createInfo.sourceData.size > 0 && createInfo.sourceData.data != nullptr) {
|
if (createInfo.sourceData.size > 0 && createInfo.sourceData.data != nullptr) {
|
||||||
getAlloc()->updateContents(createInfo.sourceData.offset, createInfo.sourceData.size, createInfo.sourceData.data);
|
getAlloc()->updateContents(createInfo.sourceData.offset, createInfo.sourceData.size, createInfo.sourceData.data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,15 @@ class BufferAllocation : public CommandBoundResource {
|
|||||||
VmaAllocationInfo info = VmaAllocationInfo();
|
VmaAllocationInfo info = VmaAllocationInfo();
|
||||||
VkMemoryPropertyFlags properties = 0;
|
VkMemoryPropertyFlags properties = 0;
|
||||||
uint64 size = 0;
|
uint64 size = 0;
|
||||||
|
std::string name;
|
||||||
VkDeviceAddress deviceAddress;
|
VkDeviceAddress deviceAddress;
|
||||||
Gfx::QueueType owner;
|
Gfx::QueueType owner;
|
||||||
};
|
};
|
||||||
DEFINE_REF(BufferAllocation);
|
DEFINE_REF(BufferAllocation);
|
||||||
class Buffer {
|
class Buffer {
|
||||||
public:
|
public:
|
||||||
Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType initialOwner, bool dynamic, std::string name, uint32 clearValue = 0);
|
Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType initialOwner, bool dynamic, std::string name,
|
||||||
|
bool createCleared = false, uint32 clearValue = 0);
|
||||||
virtual ~Buffer();
|
virtual ~Buffer();
|
||||||
VkBuffer getHandle() const { return buffers[currentBuffer]->buffer; }
|
VkBuffer getHandle() const { return buffers[currentBuffer]->buffer; }
|
||||||
VkDeviceAddress getDeviceAddress() const { return buffers[currentBuffer]->deviceAddress; }
|
VkDeviceAddress getDeviceAddress() const { return buffers[currentBuffer]->deviceAddress; }
|
||||||
@@ -44,6 +46,7 @@ class Buffer {
|
|||||||
Array<OBufferAllocation> buffers;
|
Array<OBufferAllocation> buffers;
|
||||||
VkBufferUsageFlags usage;
|
VkBufferUsageFlags usage;
|
||||||
bool dynamic;
|
bool dynamic;
|
||||||
|
bool createCleared;
|
||||||
std::string name;
|
std::string name;
|
||||||
uint32 clearValue;
|
uint32 clearValue;
|
||||||
void rotateBuffer(uint64 size, bool preserveContents = false);
|
void rotateBuffer(uint64 size, bool preserveContents = false);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#include "RenderPass.h"
|
#include "RenderPass.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
|
|
||||||
@@ -151,8 +150,7 @@ void Command::waitForCommand(uint32 timeout) {
|
|||||||
checkFence();
|
checkFence();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Command::setPipelineStatisticsFlags(VkQueryPipelineStatisticFlags flags)
|
void Command::setPipelineStatisticsFlags(VkQueryPipelineStatisticFlags flags) { statisticsFlags = flags; }
|
||||||
{ statisticsFlags = flags; }
|
|
||||||
|
|
||||||
void Command::bindResource(PCommandBoundResource resource) {
|
void Command::bindResource(PCommandBoundResource resource) {
|
||||||
resource->bind();
|
resource->bind();
|
||||||
@@ -239,8 +237,10 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array<uint
|
|||||||
descriptor->bind();
|
descriptor->bind();
|
||||||
boundResources.add(descriptor.getHandle());
|
boundResources.add(descriptor.getHandle());
|
||||||
for (auto binding : descriptor->boundResources) {
|
for (auto binding : descriptor->boundResources) {
|
||||||
binding->bind();
|
for (auto res : binding) {
|
||||||
boundResources.add(binding);
|
res->bind();
|
||||||
|
boundResources.add(res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDescriptorSet setHandle = descriptor->getHandle();
|
VkDescriptorSet setHandle = descriptor->getHandle();
|
||||||
@@ -260,8 +260,13 @@ void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorS
|
|||||||
boundResources.add(descriptorSet.getHandle());
|
boundResources.add(descriptorSet.getHandle());
|
||||||
|
|
||||||
for (auto binding : descriptorSet->boundResources) {
|
for (auto binding : descriptorSet->boundResources) {
|
||||||
binding->bind();
|
for (auto res : binding) {
|
||||||
boundResources.add(binding);
|
// partially bound descriptors can include nulls
|
||||||
|
if (res != nullptr) {
|
||||||
|
res->bind();
|
||||||
|
boundResources.add(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle();
|
sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle();
|
||||||
}
|
}
|
||||||
@@ -316,7 +321,7 @@ void RenderCommand::drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, u
|
|||||||
vkCmdDrawMeshTasksIndirectEXT(handle, buffer.cast<ShaderBuffer>()->getHandle(), offset, drawCount, stride);
|
vkCmdDrawMeshTasksIndirectEXT(handle, buffer.cast<ShaderBuffer>()->getHandle(), offset, drawCount, stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderCommand::traceRays() { }
|
void RenderCommand::traceRays() {}
|
||||||
|
|
||||||
ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool) : graphics(graphics), owner(cmdPool) {
|
ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool) : graphics(graphics), owner(cmdPool) {
|
||||||
VkCommandBufferAllocateInfo allocInfo = {
|
VkCommandBufferAllocateInfo allocInfo = {
|
||||||
@@ -378,8 +383,10 @@ void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array<uin
|
|||||||
boundResources.add(descriptor.getHandle());
|
boundResources.add(descriptor.getHandle());
|
||||||
|
|
||||||
for (auto binding : descriptor->boundResources) {
|
for (auto binding : descriptor->boundResources) {
|
||||||
binding->bind();
|
for (auto res : binding) {
|
||||||
boundResources.add(binding);
|
res->bind();
|
||||||
|
boundResources.add(res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDescriptorSet setHandle = descriptor->getHandle();
|
VkDescriptorSet setHandle = descriptor->getHandle();
|
||||||
@@ -398,9 +405,12 @@ void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptor
|
|||||||
boundResources.add(descriptorSet.getHandle());
|
boundResources.add(descriptorSet.getHandle());
|
||||||
|
|
||||||
// std::cout << "Binding descriptor " << descriptorSet->getHandle() << " to cmd " << handle << std::endl;
|
// std::cout << "Binding descriptor " << descriptorSet->getHandle() << " to cmd " << handle << std::endl;
|
||||||
|
|
||||||
for (auto binding : descriptorSet->boundResources) {
|
for (auto binding : descriptorSet->boundResources) {
|
||||||
binding->bind();
|
for (auto res : binding) {
|
||||||
boundResources.add(binding);
|
res->bind();
|
||||||
|
boundResources.add(res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle();
|
sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,13 +168,17 @@ DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner)
|
|||||||
: Gfx::DescriptorSet(owner->getLayout()), CommandBoundResource(graphics), setHandle(VK_NULL_HANDLE), graphics(graphics), owner(owner),
|
: Gfx::DescriptorSet(owner->getLayout()), CommandBoundResource(graphics), setHandle(VK_NULL_HANDLE), graphics(graphics), owner(owner),
|
||||||
bindCount(0), currentlyInUse(false) {
|
bindCount(0), currentlyInUse(false) {
|
||||||
boundResources.resize(owner->getLayout()->getBindings().size());
|
boundResources.resize(owner->getLayout()->getBindings().size());
|
||||||
|
for (uint32 i = 0; i < boundResources.size(); ++i)
|
||||||
|
{
|
||||||
|
boundResources[i].resize(owner->getLayout()->getBindings()[i].descriptorCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DescriptorSet::~DescriptorSet() {}
|
DescriptorSet::~DescriptorSet() {}
|
||||||
|
|
||||||
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) {
|
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) {
|
||||||
PUniformBuffer vulkanBuffer = uniformBuffer.cast<UniformBuffer>();
|
PUniformBuffer vulkanBuffer = uniformBuffer.cast<UniformBuffer>();
|
||||||
if (boundResources[binding] == vulkanBuffer->getAlloc()) {
|
if (boundResources[binding][0] == vulkanBuffer->getAlloc()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,12 +199,12 @@ void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBu
|
|||||||
.pBufferInfo = &bufferInfos.back(),
|
.pBufferInfo = &bufferInfos.back(),
|
||||||
});
|
});
|
||||||
|
|
||||||
boundResources[binding] = vulkanBuffer->getAlloc();
|
boundResources[binding][0] = vulkanBuffer->getAlloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer shaderBuffer) {
|
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer shaderBuffer) {
|
||||||
PShaderBuffer vulkanBuffer = shaderBuffer.cast<ShaderBuffer>();
|
PShaderBuffer vulkanBuffer = shaderBuffer.cast<ShaderBuffer>();
|
||||||
if (boundResources[binding] == vulkanBuffer->getAlloc()) {
|
if (boundResources[binding][0] == vulkanBuffer->getAlloc()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,12 +224,12 @@ void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer shaderBuff
|
|||||||
.pBufferInfo = &bufferInfos.back(),
|
.pBufferInfo = &bufferInfos.back(),
|
||||||
});
|
});
|
||||||
|
|
||||||
boundResources[binding] = vulkanBuffer->getAlloc();
|
boundResources[binding][0] = vulkanBuffer->getAlloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptorSet::updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuffer shaderBuffer) {
|
void DescriptorSet::updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuffer shaderBuffer) {
|
||||||
PShaderBuffer vulkanBuffer = shaderBuffer.cast<ShaderBuffer>();
|
PShaderBuffer vulkanBuffer = shaderBuffer.cast<ShaderBuffer>();
|
||||||
if (boundResources[binding] == vulkanBuffer->getAlloc()) {
|
if (boundResources[binding][index] == vulkanBuffer->getAlloc()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,12 +250,12 @@ void DescriptorSet::updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuf
|
|||||||
.pBufferInfo = &bufferInfos.back(),
|
.pBufferInfo = &bufferInfos.back(),
|
||||||
});
|
});
|
||||||
|
|
||||||
boundResources[binding] = vulkanBuffer->getAlloc();
|
boundResources[binding][index] = vulkanBuffer->getAlloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState) {
|
void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState) {
|
||||||
PSampler vulkanSampler = samplerState.cast<Sampler>();
|
PSampler vulkanSampler = samplerState.cast<Sampler>();
|
||||||
if (boundResources[binding] == vulkanSampler->getHandle()) {
|
if (boundResources[binding][0] == vulkanSampler->getHandle()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,13 +276,13 @@ void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState)
|
|||||||
.pImageInfo = &imageInfos.back(),
|
.pImageInfo = &imageInfos.back(),
|
||||||
});
|
});
|
||||||
|
|
||||||
boundResources[binding] = vulkanSampler->getHandle();
|
boundResources[binding][0] = vulkanSampler->getHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptorSet::updateSampler(uint32_t binding, uint32 dstArrayIndex, Gfx::PSampler samplerState)
|
void DescriptorSet::updateSampler(uint32_t binding, uint32 dstArrayIndex, Gfx::PSampler samplerState)
|
||||||
{
|
{
|
||||||
PSampler vulkanSampler = samplerState.cast<Sampler>();
|
PSampler vulkanSampler = samplerState.cast<Sampler>();
|
||||||
if (boundResources[binding] == vulkanSampler->getHandle()) {
|
if (boundResources[binding][dstArrayIndex] == vulkanSampler->getHandle()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,13 +303,13 @@ void DescriptorSet::updateSampler(uint32_t binding, uint32 dstArrayIndex, Gfx::P
|
|||||||
.pImageInfo = &imageInfos.back(),
|
.pImageInfo = &imageInfos.back(),
|
||||||
});
|
});
|
||||||
|
|
||||||
boundResources[binding] = vulkanSampler->getHandle();
|
boundResources[binding][dstArrayIndex] = vulkanSampler->getHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler samplerState) {
|
void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler samplerState) {
|
||||||
TextureBase* vulkanTexture = texture.cast<TextureBase>().getHandle();
|
TextureBase* vulkanTexture = texture.cast<TextureBase>().getHandle();
|
||||||
if (boundResources[binding] == vulkanTexture->getHandle()) {
|
if (boundResources[binding][0] == vulkanTexture->getHandle()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,13 +336,13 @@ void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::
|
|||||||
.pImageInfo = &imageInfos.back(),
|
.pImageInfo = &imageInfos.back(),
|
||||||
});
|
});
|
||||||
|
|
||||||
boundResources[binding] = vulkanTexture->getHandle();
|
boundResources[binding][0] = vulkanTexture->getHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptorSet::updateTexture(uint32 binding, uint32 dstArrayIndex, Gfx::PTexture texture)
|
void DescriptorSet::updateTexture(uint32 binding, uint32 dstArrayIndex, Gfx::PTexture texture)
|
||||||
{
|
{
|
||||||
TextureBase* vulkanTexture = texture.cast<TextureBase>().getHandle();
|
TextureBase* vulkanTexture = texture.cast<TextureBase>().getHandle();
|
||||||
if (boundResources[binding] == vulkanTexture->getHandle()) {
|
if (boundResources[binding][dstArrayIndex] == vulkanTexture->getHandle()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,17 +363,16 @@ void DescriptorSet::updateTexture(uint32 binding, uint32 dstArrayIndex, Gfx::PTe
|
|||||||
.pImageInfo = &imageInfos.back(),
|
.pImageInfo = &imageInfos.back(),
|
||||||
});
|
});
|
||||||
|
|
||||||
boundResources[binding] = vulkanTexture->getHandle();
|
boundResources[binding][dstArrayIndex] = vulkanTexture->getHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DescriptorSet::updateTextureArray(uint32_t binding, Array<Gfx::PTexture> textures) {
|
void DescriptorSet::updateTextureArray(uint32_t binding, Array<Gfx::PTexture2D> textures) {
|
||||||
// maybe make this a parameter?
|
// maybe make this a parameter?
|
||||||
uint32 arrayElement = 0;
|
uint32 arrayElement = 0;
|
||||||
boundResources.resize(binding + textures.size());
|
|
||||||
for (auto& gfxTexture : textures) {
|
for (auto& gfxTexture : textures) {
|
||||||
TextureBase* vulkanTexture = gfxTexture.cast<TextureBase>().getHandle();
|
TextureBase* vulkanTexture = gfxTexture.cast<TextureBase>().getHandle();
|
||||||
if (boundResources[binding + arrayElement] == vulkanTexture->getHandle()) {
|
if (boundResources[binding][arrayElement] == vulkanTexture->getHandle()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
imageInfos.add(VkDescriptorImageInfo{
|
imageInfos.add(VkDescriptorImageInfo{
|
||||||
@@ -382,7 +385,7 @@ void DescriptorSet::updateTextureArray(uint32_t binding, Array<Gfx::PTexture> te
|
|||||||
if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT) {
|
if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT) {
|
||||||
descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||||
}
|
}
|
||||||
boundResources[binding + arrayElement] = vulkanTexture->getHandle();
|
boundResources[binding][arrayElement] = vulkanTexture->getHandle();
|
||||||
writeDescriptors.add(VkWriteDescriptorSet{
|
writeDescriptors.add(VkWriteDescriptorSet{
|
||||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
@@ -393,10 +396,40 @@ void DescriptorSet::updateTextureArray(uint32_t binding, Array<Gfx::PTexture> te
|
|||||||
.descriptorType = descriptorType,
|
.descriptorType = descriptorType,
|
||||||
.pImageInfo = &imageInfos.back(),
|
.pImageInfo = &imageInfos.back(),
|
||||||
});
|
});
|
||||||
vulkanTexture->getHandle()->bind();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DescriptorSet::updateSamplerArray(uint32_t binding, Array<Gfx::PSampler> samplers) {
|
||||||
|
// maybe make this a parameter?
|
||||||
|
uint32 arrayElement = 0;
|
||||||
|
for (auto& gfxSampler : samplers) {
|
||||||
|
PSampler vulkanSampler = gfxSampler.cast<Sampler>();
|
||||||
|
if (boundResources[binding][arrayElement] == vulkanSampler->getHandle()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
imageInfos.add(VkDescriptorImageInfo{
|
||||||
|
.sampler = vulkanSampler->getHandle()->sampler,
|
||||||
|
.imageView = VK_NULL_HANDLE,
|
||||||
|
.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
});
|
||||||
|
|
||||||
|
VkDescriptorType descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||||
|
boundResources[binding][arrayElement] = vulkanSampler->getHandle();
|
||||||
|
writeDescriptors.add(VkWriteDescriptorSet{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.dstSet = setHandle,
|
||||||
|
.dstBinding = binding,
|
||||||
|
.dstArrayElement = arrayElement++,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||||
|
.pImageInfo = &imageInfos.back(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DescriptorSet::writeChanges() {
|
void DescriptorSet::writeChanges() {
|
||||||
if (writeDescriptors.size() > 0) {
|
if (writeDescriptors.size() > 0) {
|
||||||
if (isCurrentlyBound()) {
|
if (isCurrentlyBound()) {
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource {
|
|||||||
virtual void updateSampler(uint32_t binding, uint32 dstArrayIndex, Gfx::PSampler samplerState) override;
|
virtual void updateSampler(uint32_t binding, uint32 dstArrayIndex, Gfx::PSampler samplerState) override;
|
||||||
virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler sampler = nullptr) override;
|
virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler sampler = nullptr) override;
|
||||||
virtual void updateTexture(uint32 binding, uint32 dstArrayIndex, Gfx::PTexture texture) override;
|
virtual void updateTexture(uint32 binding, uint32 dstArrayIndex, Gfx::PTexture texture) override;
|
||||||
virtual void updateTextureArray(uint32_t binding, Array<Gfx::PTexture> texture) override;
|
virtual void updateTextureArray(uint32_t binding, Array<Gfx::PTexture2D> texture) override;
|
||||||
|
virtual void updateSamplerArray(uint32_t binding, Array<Gfx::PSampler> samplers) override;
|
||||||
|
|
||||||
constexpr bool isCurrentlyInUse() const { return currentlyInUse; }
|
constexpr bool isCurrentlyInUse() const { return currentlyInUse; }
|
||||||
constexpr void allocate() { currentlyInUse = true; }
|
constexpr void allocate() { currentlyInUse = true; }
|
||||||
@@ -70,7 +71,7 @@ class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource {
|
|||||||
// since the layout is fixed, trying to bind a texture to a buffer
|
// since the layout is fixed, trying to bind a texture to a buffer
|
||||||
// would not work anyways, so casts should be safe
|
// would not work anyways, so casts should be safe
|
||||||
// Array<void*> cachedData;
|
// Array<void*> cachedData;
|
||||||
Array<PCommandBoundResource> boundResources;
|
Array<Array<PCommandBoundResource>> boundResources;
|
||||||
VkDescriptorSet setHandle;
|
VkDescriptorSet setHandle;
|
||||||
PGraphics graphics;
|
PGraphics graphics;
|
||||||
PDescriptorPool owner;
|
PDescriptorPool owner;
|
||||||
|
|||||||
@@ -51,13 +51,18 @@ void QueryPool::end() {
|
|||||||
// sizeof(uint64) * currentQuery, resultsStride + sizeof(uint64),
|
// sizeof(uint64) * currentQuery, resultsStride + sizeof(uint64),
|
||||||
// VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
|
// VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
|
||||||
graphics->getGraphicsCommands()->submitCommands();
|
graphics->getGraphicsCommands()->submitCommands();
|
||||||
|
std::unique_lock l(queryMutex);
|
||||||
currentQuery = (currentQuery + 1) % numQueries;
|
currentQuery = (currentQuery + 1) % numQueries;
|
||||||
|
queryCV.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueryPool::getQueryResults(Array<uint64>& results) {
|
void QueryPool::getQueryResults(Array<uint64>& results) {
|
||||||
//uint64 numInts = resultsStride / sizeof(uint64);
|
//uint64 numInts = resultsStride / sizeof(uint64);
|
||||||
while (currentQuery == pendingQuery)
|
while (currentQuery == pendingQuery)
|
||||||
;
|
{
|
||||||
|
std::unique_lock l(queryMutex);
|
||||||
|
queryCV.wait(l);
|
||||||
|
}
|
||||||
results.resize(resultsStride/ sizeof(uint64));
|
results.resize(resultsStride/ sizeof(uint64));
|
||||||
vkGetQueryPoolResults(graphics->getDevice(), handle, pendingQuery, 1, resultsStride, results.data(), resultsStride,
|
vkGetQueryPoolResults(graphics->getDevice(), handle, pendingQuery, 1, resultsStride, results.data(), resultsStride,
|
||||||
VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT);
|
VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT);
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ class QueryPool {
|
|||||||
uint32 currentQuery = 0;
|
uint32 currentQuery = 0;
|
||||||
uint32 numQueries;
|
uint32 numQueries;
|
||||||
uint32 resultsStride;
|
uint32 resultsStride;
|
||||||
|
std::mutex queryMutex;
|
||||||
|
std::condition_variable queryCV;
|
||||||
};
|
};
|
||||||
class OcclusionQuery : public Gfx::OcclusionQuery, public QueryPool {
|
class OcclusionQuery : public Gfx::OcclusionQuery, public QueryPool {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
|
|
||||||
@@ -76,7 +75,11 @@ DestructionManager::DestructionManager(PGraphics graphics) : graphics(graphics)
|
|||||||
|
|
||||||
DestructionManager::~DestructionManager() {}
|
DestructionManager::~DestructionManager() {}
|
||||||
|
|
||||||
void DestructionManager::queueResourceForDestruction(OCommandBoundResource resource) { resources.add(std::move(resource)); }
|
void DestructionManager::queueResourceForDestruction(OCommandBoundResource resource) {
|
||||||
|
if (resource->isCurrentlyBound()) {
|
||||||
|
resources.add(std::move(resource));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DestructionManager::notifyCommandComplete() {
|
void DestructionManager::notifyCommandComplete() {
|
||||||
for (size_t i = 0; i < resources.size(); ++i) {
|
for (size_t i = 0; i < resources.size(); ++i) {
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ Array<PMaterial> Material::materials;
|
|||||||
|
|
||||||
Material::Material() {}
|
Material::Material() {}
|
||||||
|
|
||||||
Material::Material(Gfx::PGraphics graphics, uint32 numTextures, uint32 numSamplers, uint32 numFloats, std::string materialName,
|
Material::Material(Gfx::PGraphics graphics, uint32 numTextures, uint32 numSamplers, uint32 numFloats, bool twoSided, float opacity,
|
||||||
Array<OShaderExpression> expressions, Array<std::string> parameter, MaterialNode brdf)
|
std::string materialName, Array<OShaderExpression> expressions, Array<std::string> parameter, MaterialNode brdf)
|
||||||
: graphics(graphics), numTextures(numTextures), numSamplers(numSamplers), numFloats(numFloats), instanceId(0),
|
: graphics(graphics), numTextures(numTextures), numSamplers(numSamplers), numFloats(numFloats), twoSided(twoSided), opacity(opacity),
|
||||||
materialName(materialName), codeExpressions(std::move(expressions)), parameters(std::move(parameter)), brdf(std::move(brdf)),
|
instanceId(0), materialName(materialName), codeExpressions(std::move(expressions)), parameters(std::move(parameter)),
|
||||||
materialId(materialIdCounter++) {
|
brdf(std::move(brdf)), materialId(materialIdCounter++) {
|
||||||
if (layout == nullptr) {
|
if (layout == nullptr) {
|
||||||
init(graphics);
|
init(graphics);
|
||||||
}
|
}
|
||||||
@@ -75,13 +75,15 @@ void Material::updateDescriptor() {
|
|||||||
Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||||
layout->reset();
|
layout->reset();
|
||||||
set = layout->allocateDescriptorSet();
|
set = layout->allocateDescriptorSet();
|
||||||
for (uint32 i = 0; i < textures.size(); ++i)
|
for (uint32 i = 0; i < textures.size(); ++i) {
|
||||||
{
|
if (textures[i] != nullptr) {
|
||||||
set->updateTexture(0, i, textures[i]);
|
set->updateTexture(0, i, textures[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (uint32 i = 0; i < samplers.size(); ++i)
|
for (uint32 i = 0; i < samplers.size(); ++i) {
|
||||||
{
|
if (samplers[i] != nullptr) {
|
||||||
set->updateSampler(1, i, samplers[i]);
|
set->updateSampler(1, i, samplers[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
set->updateBuffer(2, floatBuffer);
|
set->updateBuffer(2, floatBuffer);
|
||||||
set->writeChanges();
|
set->writeChanges();
|
||||||
@@ -116,11 +118,16 @@ uint32 Material::addFloats(uint32 numFloats) {
|
|||||||
OMaterialInstance Material::instantiate() {
|
OMaterialInstance Material::instantiate() {
|
||||||
return new MaterialInstance(instanceId++, graphics, codeExpressions, parameters, numTextures, numSamplers, numFloats);
|
return new MaterialInstance(instanceId++, graphics, codeExpressions, parameters, numTextures, numSamplers, numFloats);
|
||||||
}
|
}
|
||||||
|
bool Material::isTwoSided() const { return twoSided; }
|
||||||
|
bool Material::hasTransparency() const { return opacity != 1.0f; }
|
||||||
|
float Material::getOpacity() const { return opacity; }
|
||||||
|
|
||||||
void Material::save(ArchiveBuffer& buffer) const {
|
void Material::save(ArchiveBuffer& buffer) const {
|
||||||
Serialization::save(buffer, numTextures);
|
Serialization::save(buffer, numTextures);
|
||||||
Serialization::save(buffer, numSamplers);
|
Serialization::save(buffer, numSamplers);
|
||||||
Serialization::save(buffer, numFloats);
|
Serialization::save(buffer, numFloats);
|
||||||
|
Serialization::save(buffer, twoSided);
|
||||||
|
Serialization::save(buffer, opacity);
|
||||||
Serialization::save(buffer, instanceId);
|
Serialization::save(buffer, instanceId);
|
||||||
Serialization::save(buffer, materialName);
|
Serialization::save(buffer, materialName);
|
||||||
Serialization::save(buffer, codeExpressions);
|
Serialization::save(buffer, codeExpressions);
|
||||||
@@ -130,13 +137,14 @@ void Material::save(ArchiveBuffer& buffer) const {
|
|||||||
|
|
||||||
void Material::load(ArchiveBuffer& buffer) {
|
void Material::load(ArchiveBuffer& buffer) {
|
||||||
graphics = buffer.getGraphics();
|
graphics = buffer.getGraphics();
|
||||||
if (layout == nullptr)
|
if (layout == nullptr) {
|
||||||
{
|
|
||||||
init(graphics);
|
init(graphics);
|
||||||
}
|
}
|
||||||
Serialization::load(buffer, numTextures);
|
Serialization::load(buffer, numTextures);
|
||||||
Serialization::load(buffer, numSamplers);
|
Serialization::load(buffer, numSamplers);
|
||||||
Serialization::load(buffer, numFloats);
|
Serialization::load(buffer, numFloats);
|
||||||
|
Serialization::load(buffer, twoSided);
|
||||||
|
Serialization::load(buffer, opacity);
|
||||||
Serialization::load(buffer, instanceId);
|
Serialization::load(buffer, instanceId);
|
||||||
Serialization::load(buffer, materialName);
|
Serialization::load(buffer, materialName);
|
||||||
Serialization::load(buffer, codeExpressions);
|
Serialization::load(buffer, codeExpressions);
|
||||||
@@ -167,4 +175,3 @@ void Material::compile() {
|
|||||||
codeStream << "};\n";
|
codeStream << "};\n";
|
||||||
graphics->getShaderCompiler()->registerMaterial(this);
|
graphics->getShaderCompiler()->registerMaterial(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ DECLARE_NAME_REF(Gfx, Sampler)
|
|||||||
class Material {
|
class Material {
|
||||||
public:
|
public:
|
||||||
Material();
|
Material();
|
||||||
Material(Gfx::PGraphics graphics, uint32 numTextures, uint32 numSamplers, uint32 numFloats,
|
Material(Gfx::PGraphics graphics, uint32 numTextures, uint32 numSamplers, uint32 numFloats, bool twoSided, float opacity,
|
||||||
std::string materialName, Array<OShaderExpression> expressions, Array<std::string> parameter, MaterialNode brdf);
|
std::string materialName, Array<OShaderExpression> expressions, Array<std::string> parameter, MaterialNode brdf);
|
||||||
~Material();
|
~Material();
|
||||||
static void init(Gfx::PGraphics graphics);
|
static void init(Gfx::PGraphics graphics);
|
||||||
@@ -23,8 +23,14 @@ class Material {
|
|||||||
static uint32 addTextures(uint32 numTextures);
|
static uint32 addTextures(uint32 numTextures);
|
||||||
static uint32 addSamplers(uint32 numSamplers);
|
static uint32 addSamplers(uint32 numSamplers);
|
||||||
static uint32 addFloats(uint32 numFloats);
|
static uint32 addFloats(uint32 numFloats);
|
||||||
|
|
||||||
OMaterialInstance instantiate();
|
OMaterialInstance instantiate();
|
||||||
const std::string& getName() const { return materialName; }
|
const std::string& getName() const { return materialName; }
|
||||||
|
|
||||||
|
bool isTwoSided() const;
|
||||||
|
bool hasTransparency() const;
|
||||||
|
float getOpacity() const;
|
||||||
|
|
||||||
constexpr uint64 getId() const { return materialId; }
|
constexpr uint64 getId() const { return materialId; }
|
||||||
static constexpr const PMaterial findMaterialById(uint64 id) { return materials[id]; }
|
static constexpr const PMaterial findMaterialById(uint64 id) { return materials[id]; }
|
||||||
|
|
||||||
@@ -41,6 +47,8 @@ class Material {
|
|||||||
uint64 instanceId;
|
uint64 instanceId;
|
||||||
uint64 materialId;
|
uint64 materialId;
|
||||||
std::string materialName;
|
std::string materialName;
|
||||||
|
bool twoSided;
|
||||||
|
float opacity;
|
||||||
Array<OShaderExpression> codeExpressions;
|
Array<OShaderExpression> codeExpressions;
|
||||||
Array<std::string> parameters;
|
Array<std::string> parameters;
|
||||||
MaterialNode brdf;
|
MaterialNode brdf;
|
||||||
|
|||||||
Reference in New Issue
Block a user