diff --git a/res/shaders/LightCulling.slang b/res/shaders/LightCulling.slang index bcc1b48..ca2ca6f 100644 --- a/res/shaders/LightCulling.slang +++ b/res/shaders/LightCulling.slang @@ -24,9 +24,6 @@ struct CullingParams }; ParameterBlock pCullingParams; -// Debug -//Texture2D lightCountHeatMap; -//RWTexture2D debugTexture; groupshared uint uMinDepth; groupshared uint uMaxDepth; diff --git a/res/shaders/lib/BRDF.slang b/res/shaders/lib/BRDF.slang index f7c2e4a..7feceb5 100644 --- a/res/shaders/lib/BRDF.slang +++ b/res/shaders/lib/BRDF.slang @@ -2,7 +2,7 @@ import Common; interface IBRDF { - float3 evaluate(float3x3 tbn, float3 viewDir_WS, float3 lightDir_WS, float3 lightColor); + float3 evaluate(float3x3 tbn, float3 viewDir_WS, float3 lightDir_WS, float3 normal_WS, float3 lightColor); float3 evaluateAmbient(); }; @@ -19,14 +19,15 @@ struct Phong : IBRDF normal = float3(0, 0, 1); } - float3 evaluate(float3x3 tbn, float3 viewDir_TS, float3 lightDir_TS, float3 lightColor) + float3 evaluate(float3x3 tbn, float3 viewDir_WS, float3 lightDir_WS, float3 n, float3 lightColor) { - float3 normal_TS = normalize(normal); - float3 nDotL = dot(normal_TS, lightDir_TS); - float3 r = 2 * (nDotL) * normal_TS - lightDir_TS; - float rDotV = dot(r, viewDir_TS); + float3 normal_TS = normal; + float3 normal_WS = n;//normalize(mul(tbn, normal_TS)); + float3 nDotL = dot(normal_WS, lightDir_WS); + float3 r = 2 * (nDotL) * normal_WS - lightDir_WS; + float rDotV = dot(r, viewDir_WS); - return baseColor * max(nDotL, 0.0) * lightColor + specular * pow(max(rDotV, 0.0), shininess); + return lightColor * (baseColor * max(nDotL, 0.0));// + specular * pow(max(rDotV, 0.0), max(shininess, 1))); } float3 evaluateAmbient() @@ -48,11 +49,12 @@ struct BlinnPhong : IBRDF normal = float3(0, 0, 1); } - float3 evaluate(float3x3 tbn, float3 viewDir_TS, float3 lightDir_TS, float3 lightColor) + float3 evaluate(float3x3 tbn, float3 viewDir_WS, float3 lightDir_WS, float3 normal_WS, float3 lightColor) { float3 normal_TS = normalize(normal); - float diffuse = max(dot(normal_TS, lightDir_TS), 0); - float3 h = normalize(lightDir_TS + viewDir_TS); + //float3 normal_WS = normalize(mul(tbn, normal_TS)); + float diffuse = max(dot(normal_WS, lightDir_WS), 0); + float3 h = normalize(lightDir_WS + viewDir_WS); float specular = pow(saturate(dot(normal_TS, h)), shininess); return (baseColor * diffuse * lightColor) + (specularColor * specular); @@ -74,10 +76,11 @@ struct CelShading : IBRDF normal = float3(0, 0, 1); } - float3 evaluate(float3x3 tbn, float3 viewDir_TS, float3 lightDir_TS, float3 lightColor) + float3 evaluate(float3x3 tbn, float3 viewDir_WS, float3 lightDir_WS, float3 n, float3 lightColor) { float3 normal_TS = normalize(normal); - float nDotL = dot(normal_TS, lightDir_TS); + float3 normal_WS = normalize(mul(tbn, normal_TS)); + float nDotL = dot(normal_WS, lightDir_WS); float diffuse = max(nDotL, 0); float3 darkenedBase = baseColor * 0.8; @@ -145,21 +148,21 @@ struct CookTorrance : IBRDF return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); } - float3 evaluate(float3x3 tbn, float3 viewDir_TS, float3 lightDir_TS, float3 lightColor) + float3 evaluate(float3x3 tbn, float3 viewDir_WS, float3 lightDir_WS, float3 normal_WS, float3 lightColor) { - float3 n = normalize(normal); - float3 h = normalize(lightDir_TS + viewDir_TS); + float3 n = normal_WS;//normalize(mul(tbn, normal)); + float3 h = normalize(lightDir_WS + viewDir_WS); float3 F0 = float3(0.04); F0 = lerp(F0, baseColor, metallic); - float3 F = FresnelSchlick(max(dot(h, viewDir_TS), 0.0), F0); + float3 F = FresnelSchlick(max(dot(h, viewDir_WS), 0.0), F0); float NDF = TrowbridgeReitzGGX(n, h); - float G = Smith(n, viewDir_TS, lightDir_TS); + float G = Smith(n, viewDir_WS, lightDir_WS); float3 num = NDF * G * F; - float denom = 4.0 * max(dot(n, viewDir_TS), 0.0) * max(dot(n, lightDir_TS), 0.0) + 0.000001; + float denom = 4.0 * max(dot(n, viewDir_WS), 0.0) * max(dot(n, lightDir_WS), 0.0) + 0.000001; float3 specular = num / denom; float3 k_s = F; @@ -167,7 +170,7 @@ struct CookTorrance : IBRDF k_d *= 1.0 - metallic; - float nDotL = max(dot(n, lightDir_TS), 0.0); + float nDotL = max(dot(n, lightDir_WS), 0.0); float3 result = (k_d * baseColor / PI + specular) * nDotL * lightColor; return result * ambientOcclusion; diff --git a/res/shaders/lib/LightEnv.slang b/res/shaders/lib/LightEnv.slang index 4ddfb4d..75813c5 100644 --- a/res/shaders/lib/LightEnv.slang +++ b/res/shaders/lib/LightEnv.slang @@ -14,8 +14,7 @@ struct DirectionalLight : ILightEnv float3 illuminate(LightingParameter params, B brdf) { - float3 lightDir_TS = mul(params.tbn, direction.xyz); - return brdf.evaluate(params.tbn, params.viewDir_TS, -normalize(lightDir_TS), color.xyz); + return brdf.evaluate(params.tbn, params.viewDir_WS, -normalize(direction.xyz), params.normal_WS, color.xyz); } }; @@ -26,11 +25,10 @@ struct PointLight : ILightEnv float3 illuminate(LightingParameter params, B brdf) { - float3 lightDir_WS = params.position_WS - position_WS.xyz; - float3 lightDir_TS = mul(params.tbn, lightDir_WS); - float d = length(lightDir_TS); + float3 lightDir_WS = position_WS.xyz - params.position_WS; + float d = length(lightDir_WS); float illuminance = max(1 - d / colorRange.w, 0); - return illuminance * brdf.evaluate(params.tbn, params.viewDir_TS, -normalize(lightDir_TS), colorRange.xyz); + return illuminance * brdf.evaluate(params.tbn, params.viewDir_WS, normalize(lightDir_WS), normalize(params.normal_WS), colorRange.xyz); } bool insidePlane(Plane plane, float3 position) diff --git a/res/shaders/lib/MaterialParameter.slang b/res/shaders/lib/MaterialParameter.slang index b35d01a..2449f8e 100644 --- a/res/shaders/lib/MaterialParameter.slang +++ b/res/shaders/lib/MaterialParameter.slang @@ -10,16 +10,17 @@ struct MaterialParameter // data used by light environment struct LightingParameter { - float3x3 tbn; + float3x3 tbn; + float3 normal_WS; float3 position_WS; - float3 viewDir_TS; + float3 viewDir_WS; }; // data passed to fragment shader struct FragmentParameter { - float4 position_CS : SV_Position; - float3 viewDir_WS : POSITION1; + float4 position_CS : SV_Position; + float3 cameraPos_WS: POSITION0; float3 normal_WS : NORMAL0; float3 tangent_WS : TANGENT0; float3 biTangent_WS : TANGENT1; @@ -43,7 +44,8 @@ struct FragmentParameter LightingParameter result; result.tbn = float3x3(normalize(tangent_WS), normalize(biTangent_WS), normalize(normal_WS)); result.position_WS = position_WS; - result.viewDir_TS = normalize(mul(result.tbn, viewDir_WS)); + result.viewDir_WS = normalize(cameraPos_WS - position_WS); + result.normal_WS = normal_WS; return result; } }; @@ -64,16 +66,17 @@ struct VertexAttributes float4 worldPos = mul(transformMatrix, modelPos); float4 viewPos = mul(pViewParams.viewMatrix, worldPos); float4 clipPos = mul(pViewParams.projectionMatrix, viewPos); - float3 tangent_WS = normalize(mul(transformMatrix, float4(tangent_MS, 0.0)).xyz); - float3 biTangent_WS = normalize(mul(transformMatrix, float4(biTangent_MS, 0.0)).xyz); - float3 normal_WS = normalize(mul(transformMatrix, float4(normal_MS, 0.0)).xyz); + float3x3 normalMatrix = float3x3(transformMatrix); + float3 T = mul(normalMatrix, tangent_MS); + float3 N = mul(normalMatrix, normal_MS); + float3 B = mul(normalMatrix, biTangent_MS); FragmentParameter result; - result.viewDir_WS = pViewParams.cameraPos_WS.xyz - worldPos.xyz; - result.normal_WS = normal_WS; - result.tangent_WS = tangent_WS; - result.biTangent_WS = biTangent_WS; - result.position_WS = worldPos.xyz; result.position_CS = clipPos; + result.cameraPos_WS = pViewParams.cameraPos_WS.xyz; + result.normal_WS = N; + result.tangent_WS = T; + result.biTangent_WS = B; + result.position_WS = worldPos.xyz; result.vertexColor = vertexColor; result.meshletId = meshletId; for(uint i = 0; i < MAX_TEXCOORDS; ++i) diff --git a/src/Editor/Asset/MeshLoader.cpp b/src/Editor/Asset/MeshLoader.cpp index a7f06b2..d1f02b4 100644 --- a/src/Editor/Asset/MeshLoader.cpp +++ b/src/Editor/Asset/MeshLoader.cpp @@ -112,11 +112,11 @@ constexpr const char* KEY_AMBIENT_OCCLUSION_TEXTURE = "tex_ao"; void MeshLoader::loadMaterials(const aiScene* scene, const Array& textures, const std::string& baseName, const std::filesystem::path& meshDirectory, const std::string& importPath, Array& globalMaterials) { - for(uint32 i = 0; i < scene->mNumMaterials; ++i) + for(uint32 m = 0; m < scene->mNumMaterials; ++m) { - aiMaterial* material = scene->mMaterials[i]; + aiMaterial* material = scene->mMaterials[m]; aiString texPath; - std::string materialName = fmt::format("M{0}{1}{2}", baseName, material->GetName().C_Str(), i); + std::string materialName = fmt::format("M{0}{1}{2}", baseName, material->GetName().C_Str(), m); materialName.erase(std::remove(materialName.begin(), materialName.end(), '.'), materialName.end()); // dots break adding the .asset extension later materialName.erase(std::remove(materialName.begin(), materialName.end(), '-'), materialName.end()); // dots break adding the .asset extension later materialName.erase(std::remove(materialName.begin(), materialName.end(), ' '), materialName.end()); // dots break adding the .asset extension later @@ -158,10 +158,10 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array& aiString texPath; aiTextureMapping mapping; uint32 uvIndex = 0; + aiTextureMapMode mapMode = aiTextureMapMode_Clamp; float blend = std::numeric_limits::max(); aiTextureOp op; - aiTextureMapMode mapMode; - if (material->GetTexture(type, index, &texPath, &mapping, &uvIndex, &blend, &op, &mapMode) != AI_SUCCESS) + if (material->GetTexture(type, index, &texPath, &mapping, &uvIndex, nullptr, nullptr, nullptr) != AI_SUCCESS) { std::cout << "fuck" << std::endl; } @@ -438,7 +438,7 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array& ); baseMat->material->compile(); graphics->getShaderCompiler()->registerMaterial(baseMat->material); - globalMaterials[i] = baseMat->instantiate(InstantiationParameter{ + globalMaterials[m] = baseMat->instantiate(InstantiationParameter{ .name = fmt::format("{0}_Inst_0", baseMat->getName()), .folderPath = baseMat->getFolderPath(), }); @@ -462,8 +462,7 @@ void findMeshRoots(aiNode *node, List &meshNodes) void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array& materials, Array& globalMeshes, Component::Collider& collider) { -//#pragma omp parallel for - for (uint32 meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex) + for (int32 meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex) { aiMesh* mesh = scene->mMeshes[meshIndex]; if (!(mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)) @@ -484,7 +483,6 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array colors(mesh->mNumVertices); StaticMeshVertexData* vertexData = StaticMeshVertexData::getInstance(); -//#pragma omp parallel for for (int32 i = 0; i < mesh->mNumVertices; ++i) { positions[i] = Vector(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z); @@ -532,8 +530,7 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const ArrayloadColors(id, colors); Array indices(mesh->mNumFaces * 3); -//#pragma omp parallel for - for (size_t faceIndex = 0; faceIndex < mesh->mNumFaces; ++faceIndex) + for (int32 faceIndex = 0; faceIndex < mesh->mNumFaces; ++faceIndex) { indices[faceIndex * 3 + 0] = mesh->mFaces[faceIndex].mIndices[0]; indices[faceIndex * 3 + 1] = mesh->mFaces[faceIndex].mIndices[1]; diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index ad267c4..0457b47 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -63,8 +63,8 @@ int main() { .importPath = "Whitechapel" }); //AssetImporter::importMesh(MeshImportArgs{ - // .filePath = sourcePath / "import/models/Volvo S90/Volvo S90.blend", - // .importPath = "Volvo", + // .filePath = sourcePath / "import/models/nitra-castle-rawscan/source/Nitriansky.obj", + // .importPath = "Nitriansky" // }); WindowCreateInfo mainWindowInfo; mainWindowInfo.title = "SeeleEngine"; diff --git a/src/Engine/Graphics/Buffer.cpp b/src/Engine/Graphics/Buffer.cpp index 79ccf24..f35b2cb 100644 --- a/src/Engine/Graphics/Buffer.cpp +++ b/src/Engine/Graphics/Buffer.cpp @@ -1,4 +1,5 @@ #include "Buffer.h" +#include "Buffer.h" using namespace Seele; using namespace Seele::Gfx; @@ -81,13 +82,13 @@ ShaderBuffer::~ShaderBuffer() { } -bool ShaderBuffer::updateContents(const DataSource& sourceData) +void ShaderBuffer::updateContents(const ShaderBufferCreateInfo& createInfo) { - assert(contents.size() >= sourceData.size); - if (std::memcmp(contents.data(), sourceData.data, sourceData.size) == 0) + contents.resize(createInfo.sourceData.size); + numElements = createInfo.numElements; + if (createInfo.sourceData.data != nullptr) { - return false; + std::memcpy(contents.data(), createInfo.sourceData.data, createInfo.sourceData.size); } - std::memcpy(contents.data(), sourceData.data, sourceData.size); - return true; } + diff --git a/src/Engine/Graphics/Buffer.h b/src/Engine/Graphics/Buffer.h index 480c7e9..0416e82 100644 --- a/src/Engine/Graphics/Buffer.h +++ b/src/Engine/Graphics/Buffer.h @@ -7,7 +7,6 @@ class Buffer : public QueueOwnedResource { public: Buffer(QueueFamilyMapping mapping, QueueType startQueueType); virtual ~Buffer(); - protected: // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(QueueType newOwner) = 0; @@ -85,20 +84,11 @@ class ShaderBuffer : public Buffer { public: ShaderBuffer(QueueFamilyMapping mapping, uint32 numElements, const DataSource& bulkResourceData); virtual ~ShaderBuffer(); - virtual bool updateContents(const DataSource& sourceData); - bool isDataEquals(ShaderBuffer* other) { - if (other == nullptr) { - return false; - } - if (contents.size() != other->contents.size()) { - return false; - } - if (std::memcmp(contents.data(), other->contents.data(), contents.size()) != 0) { - return false; - } - return true; - } + virtual void rotateBuffer(uint64 size) = 0; + virtual void updateContents(const ShaderBufferCreateInfo& sourceData); constexpr uint32 getNumElements() const { return numElements; } + virtual void* mapRegion(uint64 offset = 0, uint64 size = -1, bool writeOnly = true) = 0; + virtual void unmap() = 0; protected: // Inherited via QueueOwnedResource diff --git a/src/Engine/Graphics/Initializer.h b/src/Engine/Graphics/Initializer.h index a7da9a7..b8778dc 100644 --- a/src/Engine/Graphics/Initializer.h +++ b/src/Engine/Graphics/Initializer.h @@ -94,26 +94,26 @@ namespace Seele // bytes per vertex uint32 vertexSize = 0; uint32 numVertices = 0; - std::string name = ""; + std::string name = "Unnamed"; }; struct IndexBufferCreateInfo { DataSource sourceData = DataSource(); Gfx::SeIndexType indexType = Gfx::SeIndexType::SE_INDEX_TYPE_UINT16; - std::string name = ""; + std::string name = "Unnamed"; }; struct UniformBufferCreateInfo { DataSource sourceData = DataSource(); uint8 dynamic = 0; - std::string name = ""; + std::string name = "Unnamed"; }; struct ShaderBufferCreateInfo { DataSource sourceData = DataSource(); uint64 numElements = 1; uint8 dynamic = 0; - std::string name = ""; + std::string name = "Unnamed"; }; DECLARE_NAME_REF(Gfx, PipelineLayout) struct ShaderCreateInfo diff --git a/src/Engine/Graphics/RenderPass/DebugPass.cpp b/src/Engine/Graphics/RenderPass/DebugPass.cpp index ee7da1b..919e4df 100644 --- a/src/Engine/Graphics/RenderPass/DebugPass.cpp +++ b/src/Engine/Graphics/RenderPass/DebugPass.cpp @@ -40,6 +40,7 @@ void DebugPass::beginFrame(const Component::Camera& cam) }, .vertexSize = sizeof(DebugVertex), .numVertices = (uint32)gDebugVertices.size(), + .name = "DebugVertices", }; debugVertices = graphics->createVertexBuffer(vertexBufferInfo); @@ -48,15 +49,18 @@ void DebugPass::beginFrame(const Component::Camera& cam) void DebugPass::render() { graphics->beginRenderPass(renderPass); - Gfx::ORenderCommand renderCommand = graphics->createRenderCommand("DebugRender"); - renderCommand->setViewport(viewport); - renderCommand->bindPipeline(pipeline); - renderCommand->bindDescriptor(viewParamsSet); - renderCommand->bindVertexBuffer({ debugVertices }); - renderCommand->draw((uint32)gDebugVertices.size(), 1, 0, 0); - Array commands; - commands.add(std::move(renderCommand)); - graphics->executeCommands({std::move(commands)}); + if (gDebugVertices.size() > 0) + { + Gfx::ORenderCommand renderCommand = graphics->createRenderCommand("DebugRender"); + renderCommand->setViewport(viewport); + renderCommand->bindPipeline(pipeline); + renderCommand->bindDescriptor(viewParamsSet); + renderCommand->bindVertexBuffer({ debugVertices }); + renderCommand->draw((uint32)gDebugVertices.size(), 1, 0, 0); + Array commands; + commands.add(std::move(renderCommand)); + graphics->executeCommands({ std::move(commands) }); + } graphics->endRenderPass(); gDebugVertices.clear(); } @@ -75,9 +79,11 @@ void DebugPass::createRenderPass() Gfx::RenderTargetAttachment baseColorAttachment = resources->requestRenderTarget("BASEPASS_COLOR"); baseColorAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD); baseColorAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + baseColorAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); Gfx::RenderTargetAttachment depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH"); depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD); depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + depthAttachment.setFinalLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{ .colorAttachments = {baseColorAttachment}, .depthAttachment = depthAttachment, @@ -97,7 +103,7 @@ void DebugPass::createRenderPass() .dstSubpass = 0, .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - .srcAccess = Gfx::SE_ACCESS_NONE, + .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, }, { @@ -114,7 +120,7 @@ void DebugPass::createRenderPass() .srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - .dstAccess = Gfx::SE_ACCESS_NONE, + .dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, }, }; renderPass = graphics->createRenderPass(std::move(layout), dependency, viewport); diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp index 5bd5de3..1a38f06 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp @@ -13,12 +13,12 @@ LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene) { } -LightCullingPass::~LightCullingPass() +LightCullingPass::~LightCullingPass() { - + } -void LightCullingPass::beginFrame(const Component::Camera& cam) +void LightCullingPass::beginFrame(const Component::Camera& cam) { RenderPass::beginFrame(cam); @@ -31,10 +31,12 @@ void LightCullingPass::beginFrame(const Component::Camera& cam) Gfx::SE_ACCESS_MEMORY_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT ); uint32 reset = 0; - DataSource counterReset = { - .size = sizeof(uint32), - .data = (uint8*)&reset, - .owner = Gfx::QueueType::COMPUTE + ShaderBufferCreateInfo counterReset = { + .sourceData = { + .size = sizeof(uint32), + .data = (uint8*)&reset, + .owner = Gfx::QueueType::COMPUTE + } }; oLightIndexCounter->updateContents(counterReset); tLightIndexCounter->updateContents(counterReset); @@ -49,7 +51,7 @@ void LightCullingPass::beginFrame(const Component::Camera& cam) cullingDescriptorSet = cullingDescriptorLayout->allocateDescriptorSet(); } -void LightCullingPass::render() +void LightCullingPass::render() { depthAttachment->transferOwnership(Gfx::QueueType::COMPUTE); cullingDescriptorSet->updateTexture(0, depthAttachment); @@ -70,11 +72,11 @@ void LightCullingPass::render() graphics->executeCommands(std::move(commands)); } -void LightCullingPass::endFrame() +void LightCullingPass::endFrame() { } -void LightCullingPass::publishOutputs() +void LightCullingPass::publishOutputs() { setupFrustums(); uint32_t viewportWidth = viewport->getWidth(); @@ -100,22 +102,22 @@ void LightCullingPass::publishOutputs() cullingDescriptorLayout = graphics->createDescriptorLayout("pCullingParams"); //DepthTexture - cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,}); + cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, }); //o_lightIndexCounter - cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT}); + cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT }); //t_lightIndexCounter - cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT}); + cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 2, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT }); //o_lightIndexList - cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 3, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT}); + cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 3, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT }); //t_lightIndexList - cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 4, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT}); + cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 4, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT }); //o_lightGrid - cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT}); + cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT }); //t_lightGrid - cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT}); + cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT }); cullingDescriptorLayout->create(); - + lightEnv = scene->getLightEnvironment(); cullingLayout = graphics->createPipelineLayout("CullingLayout"); @@ -123,7 +125,7 @@ void LightCullingPass::publishOutputs() cullingLayout->addDescriptorLayout(dispatchParamsLayout); cullingLayout->addDescriptorLayout(cullingDescriptorLayout); cullingLayout->addDescriptorLayout(lightEnv->getDescriptorLayout()); - + ShaderCreateInfo createInfo = { .name = "Culling", .mainModule = "LightCulling", @@ -154,9 +156,9 @@ void LightCullingPass::publishOutputs() tLightIndexCounter = graphics->createShaderBuffer(structInfo); structInfo = { .sourceData = { - .size = (uint32)sizeof(uint32) - * dispatchParams.numThreadGroups.x - * dispatchParams.numThreadGroups.y + .size = (uint32)sizeof(uint32) + * dispatchParams.numThreadGroups.x + * dispatchParams.numThreadGroups.y * dispatchParams.numThreadGroups.z * 8192, .data = nullptr, .owner = Gfx::QueueType::COMPUTE @@ -169,7 +171,7 @@ void LightCullingPass::publishOutputs() tLightIndexList = graphics->createShaderBuffer(structInfo); resources->registerBufferOutput("LIGHTCULLING_OLIGHTLIST", oLightIndexList); resources->registerBufferOutput("LIGHTCULLING_TLIGHTLIST", tLightIndexList); - + TextureCreateInfo textureInfo = { .format = Gfx::SE_FORMAT_R32G32_UINT, .width = dispatchParams.numThreadGroups.x, @@ -178,7 +180,7 @@ void LightCullingPass::publishOutputs() }; oLightGrid = graphics->createTexture2D(textureInfo); tLightGrid = graphics->createTexture2D(textureInfo); - + resources->registerTextureOutput("LIGHTCULLING_OLIGHTGRID", Gfx::PTexture2D(oLightGrid)); resources->registerTextureOutput("LIGHTCULLING_TLIGHTGRID", Gfx::PTexture2D(tLightGrid)); } @@ -197,14 +199,14 @@ void LightCullingPass::setupFrustums() glm::uvec3 numThreads = glm::ceil(glm::vec3(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1)); glm::uvec3 numThreadGroups = glm::ceil(glm::vec3(numThreads.x / (float)BLOCK_SIZE, numThreads.y / (float)BLOCK_SIZE, 1)); - + RenderPass::beginFrame(Component::Camera()); dispatchParams.numThreads = numThreads; dispatchParams.numThreadGroups = numThreadGroups; dispatchParamsLayout = graphics->createDescriptorLayout("pDispatchParams"); - dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, }); - dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{.binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_WRITE_ONLY_BIT }); + dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 0, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, }); + dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 1, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_WRITE_ONLY_BIT }); frustumLayout = graphics->createPipelineLayout("FrustumLayout"); frustumLayout->addDescriptorLayout(viewParamsLayout); frustumLayout->addDescriptorLayout(dispatchParamsLayout); @@ -224,17 +226,17 @@ void LightCullingPass::setupFrustums() pipelineInfo.computeShader = frustumShader; pipelineInfo.pipelineLayout = frustumLayout; frustumPipeline = graphics->createComputePipeline(pipelineInfo); - + Gfx::OUniformBuffer frustumDispatchParamsBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{ .sourceData = { .size = sizeof(DispatchParams), - .data = (uint8*) & dispatchParams, + .data = (uint8*)&dispatchParams, .owner = Gfx::QueueType::COMPUTE }, .dynamic = false, .name = "FrustumDispatch" - }); - + }); + frustumBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .sourceData = { .size = sizeof(Frustum) * numThreads.x * numThreads.y * numThreads.z, @@ -244,13 +246,13 @@ void LightCullingPass::setupFrustums() .numElements = numThreads.x * numThreads.y * numThreads.z, .dynamic = false, .name = "FrustumBuffer" - }); - + }); + Gfx::PDescriptorSet dispatchParamsSet = dispatchParamsLayout->allocateDescriptorSet(); dispatchParamsSet->updateBuffer(0, frustumDispatchParamsBuffer); dispatchParamsSet->updateBuffer(1, frustumBuffer); dispatchParamsSet->writeChanges(); - + Gfx::OComputeCommand command = graphics->createComputeCommand("FrustumCommand"); command->bindPipeline(frustumPipeline); command->bindDescriptor({ viewParamsSet, dispatchParamsSet }); @@ -258,6 +260,6 @@ void LightCullingPass::setupFrustums() Array commands; commands.add(std::move(command)); graphics->executeCommands(std::move(commands)); - frustumBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + frustumBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); } diff --git a/src/Engine/Graphics/Resources.cpp b/src/Engine/Graphics/Resources.cpp index 8f9bb5b..5107bf6 100644 --- a/src/Engine/Graphics/Resources.cpp +++ b/src/Engine/Graphics/Resources.cpp @@ -3,6 +3,7 @@ #include "RenderPass/DepthPrepass.h" #include "RenderPass/BasePass.h" #include "Material/Material.h" +#include "Resources.h" using namespace Seele; using namespace Seele::Gfx; @@ -30,4 +31,5 @@ void QueueOwnedResource::pipelineBarrier(SeAccessFlags srcAccess, SePipelineStag { // maybe add some checks executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); -} \ No newline at end of file +} + diff --git a/src/Engine/Graphics/StaticMeshVertexData.cpp b/src/Engine/Graphics/StaticMeshVertexData.cpp index 6e3846b..e48ff4e 100644 --- a/src/Engine/Graphics/StaticMeshVertexData.cpp +++ b/src/Engine/Graphics/StaticMeshVertexData.cpp @@ -193,71 +193,6 @@ Gfx::PDescriptorSet StaticMeshVertexData::getVertexDataSet() return descriptorSet; } -void StaticMeshVertexData::registerStaticMesh(const Array& meshes, const Component::Transform& transform) -{ - for (auto& mesh : meshes) - { - uint64 numVertices = meshVertexCounts[mesh->id]; - uint64 offset = meshOffsets[mesh->id]; - // Create new mesh where transform is "embedded" - MeshId mapped = VertexData::allocateVertexData(numVertices); - Array 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 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 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); - - // Load meshlets again - VertexData::loadMesh(mapped, mesh->indices, mesh->meshlets); - - Array ids; - // Get references to loaded meshlets - const auto& meshData = VertexData::getMeshData(mapped); - - for (size_t i = 0; i < meshData.numMeshlets; ++i) - { - ids.add(meshData.meshletOffset + i); - } - - - // Get Static instance array - PMaterialInstance instance = mesh->referencedMaterial->getHandle(); - PMaterial baseMat = instance->getBaseMaterial(); - Array instances; - instances.add(StaticMatInstance{ - .instance = mesh->referencedMaterial->getHandle(), - .meshletIds = ids, - .culledMeshletBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ - .sourceData = { - .size = ids.size() * sizeof(uint32), - .data = (uint8*)ids.data(), - }, - .numElements = ids.size(), - .dynamic = true, - }), - }); - staticData.add(StaticMatData{ - .material = baseMat, - .staticInstance = std::move(instances), - }); - } -} - void StaticMeshVertexData::resizeBuffers() { ShaderBufferCreateInfo createInfo = { @@ -265,7 +200,7 @@ void StaticMeshVertexData::resizeBuffers() .size = verticesAllocated * sizeof(Vector), }, .numElements = verticesAllocated * 3, - .dynamic = true, + .dynamic = false, .name = "Positions", }; positions = graphics->createShaderBuffer(createInfo); @@ -295,32 +230,50 @@ void StaticMeshVertexData::resizeBuffers() void StaticMeshVertexData::updateBuffers() { - positions->updateContents(DataSource{ - .size = positionData.size() * sizeof(Vector), - .data = (uint8*)positionData.data(), + positions->updateContents(ShaderBufferCreateInfo{ + .sourceData{ + .size = positionData.size() * sizeof(Vector), + .data = (uint8*)positionData.data(), + }, + .numElements = positionData.size(), }); for (size_t i = 0; i < MAX_TEXCOORDS; ++i) { - texCoords[i]->updateContents(DataSource{ - .size = texCoordsData[i].size() * sizeof(Vector2), - .data = (uint8*)texCoordsData[i].data(), + texCoords[i]->updateContents(ShaderBufferCreateInfo { + .sourceData = { + .size = texCoordsData[i].size() * sizeof(Vector2), + .data = (uint8*)texCoordsData[i].data(), + }, + .numElements = texCoordsData[i].size(), }); } - normals->updateContents(DataSource{ - .size = normalData.size() * sizeof(Vector), - .data = (uint8*)normalData.data(), + normals->updateContents(ShaderBufferCreateInfo { + .sourceData = { + .size = normalData.size() * sizeof(Vector), + .data = (uint8*)normalData.data(), + }, + .numElements = normalData.size(), }); - tangents->updateContents(DataSource{ - .size = tangentData.size() * sizeof(Vector), - .data = (uint8*)tangentData.data(), + tangents->updateContents(ShaderBufferCreateInfo { + .sourceData = { + .size = tangentData.size() * sizeof(Vector), + .data = (uint8*)tangentData.data(), + }, + .numElements = tangentData.size() }); - biTangents->updateContents(DataSource{ - .size = biTangentData.size() * sizeof(Vector), - .data = (uint8*)biTangentData.data(), + biTangents->updateContents(ShaderBufferCreateInfo { + .sourceData = { + .size = biTangentData.size() * sizeof(Vector), + .data = (uint8*)biTangentData.data(), + }, + .numElements = biTangentData.size(), }); - colors->updateContents(DataSource{ - .size = colorData.size() * sizeof(Vector), - .data = (uint8*)colorData.data() + colors->updateContents(ShaderBufferCreateInfo { + .sourceData = { + .size = colorData.size() * sizeof(Vector), + .data = (uint8*)colorData.data() + }, + .numElements = colorData.size(), }); descriptorLayout->reset(); descriptorSet = descriptorLayout->allocateDescriptorSet(); diff --git a/src/Engine/Graphics/StaticMeshVertexData.h b/src/Engine/Graphics/StaticMeshVertexData.h index 76cfe2e..2382ff9 100644 --- a/src/Engine/Graphics/StaticMeshVertexData.h +++ b/src/Engine/Graphics/StaticMeshVertexData.h @@ -39,7 +39,6 @@ public: virtual Gfx::PDescriptorLayout getVertexDataLayout() override; virtual Gfx::PDescriptorSet getVertexDataSet() override; virtual std::string getTypeName() const override { return "StaticMeshVertexData"; } - void registerStaticMesh(const Array& meshes, const Component::Transform& transform); constexpr const Array& getStaticMeshes() const { return staticData; } private: virtual void resizeBuffers() override; diff --git a/src/Engine/Graphics/Texture.cpp b/src/Engine/Graphics/Texture.cpp index bbeebe3..9defc17 100644 --- a/src/Engine/Graphics/Texture.cpp +++ b/src/Engine/Graphics/Texture.cpp @@ -1,4 +1,5 @@ #include "Texture.h" +#include "Texture.h" using namespace Seele; using namespace Seele::Gfx; diff --git a/src/Engine/Graphics/VertexData.cpp b/src/Engine/Graphics/VertexData.cpp index eb5b471..a1cb878 100644 --- a/src/Engine/Graphics/VertexData.cpp +++ b/src/Engine/Graphics/VertexData.cpp @@ -127,7 +127,8 @@ void VertexData::createDescriptors() } } } - cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + cullingOffsetBuffer->rotateBuffer(cullingOffsets.size() * sizeof(uint32)); + cullingOffsetBuffer->updateContents(ShaderBufferCreateInfo{ .sourceData = { .size = cullingOffsets.size() * sizeof(uint32), .data = (uint8*)cullingOffsets.data(), @@ -135,48 +136,59 @@ void VertexData::createDescriptors() .numElements = cullingOffsets.size(), .name = "MeshletOffset" }); - cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + cullingOffsetBuffer->pipelineBarrier( + Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, + Gfx::SE_ACCESS_MEMORY_READ_BIT, + Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT + ); + cullingBuffer->rotateBuffer(numMeshlets * sizeof(uint32)); + cullingBuffer->updateContents(ShaderBufferCreateInfo{ .sourceData = { .size = numMeshlets * sizeof(uint32), }, .numElements = numMeshlets, .name = "MeshletCulling" }); - - - instanceDataLayout->reset(); - instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + cullingBuffer->pipelineBarrier( + Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, + Gfx::SE_ACCESS_MEMORY_WRITE_BIT, + Gfx::SE_PIPELINE_STAGE_MESH_SHADER_BIT_EXT + ); + instanceBuffer->rotateBuffer(instanceData.size() * sizeof(InstanceData)); + instanceBuffer->updateContents(ShaderBufferCreateInfo{ .sourceData = { - .size = sizeof(InstanceData) * instanceData.size(), + .size = instanceData.size() * sizeof(InstanceData), .data = (uint8*)instanceData.data(), }, .numElements = instanceData.size(), - .dynamic = false, .name = "InstanceBuffer" }); 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 + Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT | Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT ); - descriptorSet = instanceDataLayout->allocateDescriptorSet(); - instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ + instanceMeshDataBuffer->rotateBuffer(sizeof(MeshData) * instanceMeshData.size()); + instanceMeshDataBuffer->updateContents(ShaderBufferCreateInfo{ .sourceData = { .size = sizeof(MeshData) * instanceMeshData.size(), .data = (uint8*)instanceMeshData.data(), }, .numElements = instanceMeshData.size(), - .dynamic = false, .name = "MeshDataBuffer" }); 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 + Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT | Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT ); + instanceDataLayout->reset(); + descriptorSet = instanceDataLayout->allocateDescriptorSet(); descriptorSet->updateBuffer(0, instanceBuffer); descriptorSet->updateBuffer(1, instanceMeshDataBuffer); descriptorSet->updateBuffer(2, meshletBuffer); @@ -331,7 +343,10 @@ void VertexData::init(Gfx::PGraphics _graphics) instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 5, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER }); // cullingOffset instanceDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{ .binding = 6, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER }); - + cullingOffsetBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .dynamic = true }); + cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .dynamic = true }); + instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .dynamic = true }); + instanceMeshDataBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .dynamic = true }); instanceDataLayout->create(); resizeBuffers(); graphics->getShaderCompiler()->registerVertexData(this); diff --git a/src/Engine/Graphics/Vulkan/Buffer.cpp b/src/Engine/Graphics/Vulkan/Buffer.cpp index 0c5d4f4..21fd76b 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.cpp +++ b/src/Engine/Graphics/Vulkan/Buffer.cpp @@ -4,195 +4,255 @@ using namespace Seele; using namespace Seele::Vulkan; +BufferAllocation::BufferAllocation(PGraphics graphics) + : CommandBoundResource(graphics) +{ +} + +BufferAllocation::~BufferAllocation() +{ + if (buffer != VK_NULL_HANDLE) + { + vmaDestroyBuffer(graphics->getAllocator(), buffer, allocation); + } +} + struct PendingBuffer { - uint64 offset; - uint64 size; - VkBuffer stagingBuffer; - VmaAllocation allocation; - Gfx::QueueType prevQueue; - bool writeOnly; + OBufferAllocation allocation; + uint64 offset; + Gfx::QueueType prevQueue; + bool writeOnly; }; static Map pendingBuffers; Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool dynamic, - std::string name) - : graphics(graphics), currentBuffer(0), size(size), owner(queueType), usage(usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT), name(name) { - createBuffer(); + std::string name) + : graphics(graphics), currentBuffer(0), owner(queueType), usage(usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT), dynamic(dynamic), name(name) { + createBuffer(size); } Buffer::~Buffer() { - for (uint32 i = 0; i < buffers.size(); ++i) { - graphics->getDestructionManager()->queueBuffer(graphics->getQueueCommands(owner)->getCommands(), buffers[i].buffer, - buffers[i].allocation); - } + for (uint32 i = 0; i < buffers.size(); ++i) { + graphics->getDestructionManager()->queueResourceForDestruction(std::move(buffers[i])); + } } void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping(); - VkBufferMemoryBarrier barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .pNext = nullptr, - .srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(owner), - .dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner), - .offset = 0, - .size = size, - }; - PCommandPool sourcePool = graphics->getQueueCommands(owner); - PCommandPool dstPool = nullptr; - VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; - VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; - assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex); - if (owner == Gfx::QueueType::TRANSFER) { - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - } else if (owner == Gfx::QueueType::COMPUTE) { - barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - srcStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - } else if (owner == Gfx::QueueType::GRAPHICS) { - barrier.srcAccessMask = getSourceAccessMask(); - srcStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; - } - if (newOwner == Gfx::QueueType::TRANSFER) { - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - dstPool = graphics->getTransferCommands(); - } else if (newOwner == Gfx::QueueType::COMPUTE) { - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - dstStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - dstPool = graphics->getComputeCommands(); - } else if (newOwner == Gfx::QueueType::GRAPHICS) { - barrier.dstAccessMask = getDestAccessMask(); - dstStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; - dstPool = graphics->getGraphicsCommands(); - } - VkCommandBuffer srcCommand = sourcePool->getCommands()->getHandle(); - VkCommandBuffer dstCommand = dstPool->getCommands()->getHandle(); - VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered]; - for (uint32 i = 0; i < buffers.size(); ++i) { - dynamicBarriers[i] = barrier; - dynamicBarriers[i].buffer = buffers[i].buffer; - } - vkCmdPipelineBarrier(srcCommand, srcStage, srcStage, 0, 0, nullptr, buffers.size(), dynamicBarriers, 0, nullptr); - vkCmdPipelineBarrier(dstCommand, dstStage, dstStage, 0, 0, nullptr, buffers.size(), dynamicBarriers, 0, nullptr); - sourcePool->submitCommands(); + if (getSize() == 0) + return; + Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping(); + VkBufferMemoryBarrier barrier = { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + .pNext = nullptr, + .srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(owner), + .dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner), + .buffer = getHandle(), + .offset = 0, + .size = getSize(), + }; + PCommandPool sourcePool = graphics->getQueueCommands(owner); + PCommandPool dstPool = nullptr; + VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex); + if (owner == Gfx::QueueType::TRANSFER) { + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + } + else if (owner == Gfx::QueueType::COMPUTE) { + barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + srcStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + } + else if (owner == Gfx::QueueType::GRAPHICS) { + barrier.srcAccessMask = getSourceAccessMask(); + srcStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; + } + if (newOwner == Gfx::QueueType::TRANSFER) { + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + dstPool = graphics->getTransferCommands(); + } + else if (newOwner == Gfx::QueueType::COMPUTE) { + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + dstStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + dstPool = graphics->getComputeCommands(); + } + else if (newOwner == Gfx::QueueType::GRAPHICS) { + barrier.dstAccessMask = getDestAccessMask(); + dstStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; + dstPool = graphics->getGraphicsCommands(); + } + VkCommandBuffer srcCommand = sourcePool->getCommands()->getHandle(); + VkCommandBuffer dstCommand = dstPool->getCommands()->getHandle(); + vkCmdPipelineBarrier(srcCommand, srcStage, srcStage, 0, 0, nullptr, 1, &barrier, 0, nullptr); + vkCmdPipelineBarrier(dstCommand, dstStage, dstStage, 0, 0, nullptr, 1, &barrier, 0, nullptr); + sourcePool->submitCommands(); } void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, - VkPipelineStageFlags dstStage) { - PCommand commandBuffer = graphics->getQueueCommands(owner)->getCommands(); - VkBufferMemoryBarrier barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = srcAccess, - .dstAccessMask = dstAccess, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .offset = 0, - .size = size, - }; - VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered]; - for (uint32 i = 0; i < buffers.size(); ++i) { - dynamicBarriers[i] = barrier; - dynamicBarriers[i].buffer = buffers[i].buffer; - } - vkCmdPipelineBarrier(commandBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, buffers.size(), dynamicBarriers, 0, - nullptr); + VkPipelineStageFlags dstStage) { + if (getSize() == 0) + return; + PCommand commandBuffer = graphics->getQueueCommands(owner)->getCommands(); + VkBufferMemoryBarrier barrier = { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = srcAccess, + .dstAccessMask = dstAccess, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .buffer = getHandle(), + .offset = 0, + .size = getSize(), + }; + vkCmdPipelineBarrier(commandBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, 1, &barrier, 0, + nullptr); } -void* Buffer::map(bool writeOnly) { return mapRegion(0, size, writeOnly); } +void* Buffer::map(bool writeOnly) { return mapRegion(0, getSize(), writeOnly); } void* Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly) { - void* data = nullptr; + if (regionSize == 0) return nullptr; + void* data = nullptr; - PendingBuffer pending; - pending.writeOnly = writeOnly; - pending.prevQueue = owner; - pending.offset = regionOffset; - pending.size = regionSize; - if (writeOnly) { - if (buffers[currentBuffer].properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { - VK_CHECK(vmaMapMemory(graphics->getAllocator(), buffers[currentBuffer].allocation, &data)); - } else { - VkBufferCreateInfo stagingInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = regionSize, - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - }; - VmaAllocationCreateInfo allocInfo = { - .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT, - .usage = VMA_MEMORY_USAGE_AUTO, - .requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - }; - VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &allocInfo, &pending.stagingBuffer, - &pending.allocation, nullptr)); - vmaMapMemory(graphics->getAllocator(), pending.allocation, &data); + PendingBuffer pending; + pending.allocation = new BufferAllocation(graphics); + pending.allocation->size = regionSize; + pending.writeOnly = writeOnly; + pending.prevQueue = owner; + pending.offset = regionOffset; + if (writeOnly) { + if (buffers[currentBuffer]->properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { + VK_CHECK(vmaMapMemory(graphics->getAllocator(), buffers[currentBuffer]->allocation, &data)); + } + else { + VkBufferCreateInfo stagingInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = regionSize, + .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + }; + VmaAllocationCreateInfo allocInfo = { + .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT, + .usage = VMA_MEMORY_USAGE_AUTO, + .requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + }; + VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &allocInfo, &pending.allocation->buffer, + &pending.allocation->allocation, nullptr)); + vmaMapMemory(graphics->getAllocator(), pending.allocation->allocation, &data); + vmaSetAllocationName(graphics->getAllocator(), pending.allocation->allocation, "MappingStaging"); + } } - } else { - assert(false); - } - pendingBuffers[this] = std::move(pending); + else { + assert(false); + } + pendingBuffers[this] = std::move(pending); - assert(data); - return data; + assert(data); + return data; } void Buffer::unmap() { - auto found = pendingBuffers.find(this); - if (found != pendingBuffers.end()) { - PendingBuffer& pending = found->value; - if (pending.writeOnly) { - if (buffers[currentBuffer].properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { - vmaUnmapMemory(graphics->getAllocator(), buffers[currentBuffer].allocation); - } else { - vmaFlushAllocation(graphics->getAllocator(), pending.allocation, 0, VK_WHOLE_SIZE); - vmaUnmapMemory(graphics->getAllocator(), pending.allocation); - PCommand command = graphics->getQueueCommands(owner)->getCommands(); - VkCommandBuffer cmdHandle = command->getHandle(); + auto found = pendingBuffers.find(this); + if (found != pendingBuffers.end()) { + PendingBuffer& pending = found->value; + if (pending.writeOnly) { + if (buffers[currentBuffer]->properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { + vmaUnmapMemory(graphics->getAllocator(), buffers[currentBuffer]->allocation); + } + else { + vmaFlushAllocation(graphics->getAllocator(), pending.allocation->allocation, 0, VK_WHOLE_SIZE); + vmaUnmapMemory(graphics->getAllocator(), pending.allocation->allocation); + PCommand command = graphics->getQueueCommands(owner)->getCommands(); + command->bindResource(PBufferAllocation(pending.allocation)); + VkCommandBuffer cmdHandle = command->getHandle(); - VkBufferCopy region = { - .srcOffset = 0, - .dstOffset = pending.offset, - .size = pending.size, - }; - VkBufferMemoryBarrier barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT, - .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = buffers[currentBuffer].buffer, - .offset = 0, - .size = size, - }; - vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, - nullptr, 1, &barrier, 0, nullptr); - vkCmdCopyBuffer(cmdHandle, pending.stagingBuffer, buffers[currentBuffer].buffer, 1, ®ion); - barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = buffers[currentBuffer].buffer, - .offset = 0, - .size = size, - }; - vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, - nullptr, 1, &barrier, 0, nullptr); - graphics->getDestructionManager()->queueBuffer(command, pending.stagingBuffer, pending.allocation); - } + VkBufferCopy region = { + .srcOffset = 0, + .dstOffset = pending.offset, + .size = pending.allocation->size, + }; + VkBufferMemoryBarrier barrier = { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT, + .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .buffer = buffers[currentBuffer]->buffer, + .offset = 0, + .size = buffers[currentBuffer]->size, + }; + vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, + nullptr, 1, &barrier, 0, nullptr); + vkCmdCopyBuffer(cmdHandle, pending.allocation->buffer, buffers[currentBuffer]->buffer, 1, ®ion); + barrier = { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .buffer = buffers[currentBuffer]->buffer, + .offset = 0, + .size = buffers[currentBuffer]->size, + }; + vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, + nullptr, 1, &barrier, 0, nullptr); + graphics->getDestructionManager()->queueResourceForDestruction(std::move(pending.allocation)); + } + } + pendingBuffers.erase(this); } - pendingBuffers.erase(this); - } } -void Buffer::createBuffer() +void Buffer::rotateBuffer(uint64 size) +{ + size = std::max(getSize(), size); + for (size_t i = 0; i < buffers.size(); ++i) + { + if (buffers[i]->isCurrentlyBound()) + { + continue; + } + if (buffers[i]->size < size) + { + vmaDestroyBuffer(graphics->getAllocator(), buffers[i]->buffer, buffers[i]->allocation); + VkBufferCreateInfo info = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .size = size, + .usage = usage, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + }; + VmaAllocationCreateInfo allocInfo = { + .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | + VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + .usage = VMA_MEMORY_USAGE_AUTO, + }; + VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &info, &allocInfo, &buffers[i]->buffer, &buffers[i]->allocation, + &buffers[i]->info)); + vmaGetAllocationMemoryProperties(graphics->getAllocator(), buffers[i]->allocation, &buffers[i]->properties); + if (!name.empty()) { + VkDebugUtilsObjectNameInfoEXT nameInfo = { .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, + .pNext = nullptr, + .objectType = VK_OBJECT_TYPE_BUFFER, + .objectHandle = (uint64)buffers[i]->buffer, + .pObjectName = this->name.c_str() }; + graphics->vkSetDebugUtilsObjectNameEXT(&nameInfo); + } + buffers[i]->size = size; + } + currentBuffer = i; + return; + } + createBuffer(size); +} + +void Buffer::createBuffer(uint64 size) { VkBufferCreateInfo info = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, @@ -206,17 +266,18 @@ void Buffer::createBuffer() VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, .usage = VMA_MEMORY_USAGE_AUTO, }; - buffers.add(); + buffers.add(new BufferAllocation(graphics)); if (size > 0) { - VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &info, &allocInfo, &buffers.back().buffer, &buffers.back().allocation, - &buffers.back().info)); - vmaGetAllocationMemoryProperties(graphics->getAllocator(), buffers.back().allocation, &buffers.back().properties); + VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &info, &allocInfo, &buffers.back()->buffer, &buffers.back()->allocation, + &buffers.back()->info)); + buffers.back()->size = size; + vmaGetAllocationMemoryProperties(graphics->getAllocator(), buffers.back()->allocation, &buffers.back()->properties); if (!name.empty()) { VkDebugUtilsObjectNameInfoEXT nameInfo = { .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, .pNext = nullptr, .objectType = VK_OBJECT_TYPE_BUFFER, - .objectHandle = (uint64)buffers.back().buffer, + .objectHandle = (uint64)buffers.back()->buffer, .pObjectName = this->name.c_str() }; graphics->vkSetDebugUtilsObjectNameEXT(&nameInfo); } @@ -225,39 +286,39 @@ void Buffer::createBuffer() UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo& createInfo) : Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.sourceData), - Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, - createInfo.dynamic, createInfo.name) { - if (size > 0 && createInfo.sourceData.data != nullptr) { - void* data = map(); - std::memcpy(data, createInfo.sourceData.data, createInfo.sourceData.size); - unmap(); - } + Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, + createInfo.dynamic, createInfo.name) { + if (getSize() > 0 && createInfo.sourceData.data != nullptr) { + void* data = map(); + std::memcpy(data, createInfo.sourceData.data, createInfo.sourceData.size); + unmap(); + } } UniformBuffer::~UniformBuffer() {} bool UniformBuffer::updateContents(const DataSource& sourceData) { - if (!Gfx::UniformBuffer::updateContents(sourceData)) { - // no update was performed, skip - return false; - } - void* data = map(); - std::memcpy(data, sourceData.data, sourceData.size); - unmap(); - return true; + if (!Gfx::UniformBuffer::updateContents(sourceData)) { + // no update was performed, skip + return false; + } + void* data = map(); + std::memcpy(data, sourceData.data, sourceData.size); + unmap(); + return true; } void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { - Gfx::QueueOwnedResource::transferOwnership(newOwner); + Gfx::QueueOwnedResource::transferOwnership(newOwner); } void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Vulkan::Buffer::executeOwnershipBarrier(newOwner); + Vulkan::Buffer::executeOwnershipBarrier(newOwner); } void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { - Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { + Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } VkAccessFlags UniformBuffer::getSourceAccessMask() { return VK_ACCESS_MEMORY_WRITE_BIT; } @@ -266,38 +327,56 @@ VkAccessFlags UniformBuffer::getDestAccessMask() { return VK_ACCESS_UNIFORM_READ ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& sourceData) : Gfx::ShaderBuffer(graphics->getFamilyMapping(), sourceData.numElements, sourceData.sourceData), - Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, - sourceData.dynamic, sourceData.name) { - if (size > 0 && sourceData.sourceData.data != nullptr) { - void* data = map(); - std::memcpy(data, sourceData.sourceData.data, sourceData.sourceData.size); - unmap(); - } + Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, + sourceData.dynamic, sourceData.name) { + if (getSize() > 0 && sourceData.sourceData.data != nullptr) { + void* data = map(); + std::memcpy(data, sourceData.sourceData.data, sourceData.sourceData.size); + unmap(); + } } ShaderBuffer::~ShaderBuffer() {} -bool ShaderBuffer::updateContents(const DataSource& sourceData) { - assert(sourceData.size <= getSize()); - Gfx::ShaderBuffer::updateContents(sourceData); - // We always want to update, as the contents could be different on the GPU - void* data = map(); - std::memcpy(data, sourceData.data, sourceData.size); - unmap(); - return true; +void ShaderBuffer::updateContents(const ShaderBufferCreateInfo& createInfo) { + Gfx::ShaderBuffer::updateContents(createInfo); + // We always want to update, as the contents could be different on the GPU + if (createInfo.sourceData.data == nullptr) + { + return; + } + void* data = map(); + std::memcpy(data, createInfo.sourceData.data, createInfo.sourceData.size); + unmap(); +} + +void Seele::Vulkan::ShaderBuffer::rotateBuffer(uint64 size) +{ + assert(dynamic); + Vulkan::Buffer::rotateBuffer(size); +} + +void* ShaderBuffer::mapRegion(uint64 offset, uint64 size, bool writeOnly) +{ + return Vulkan::Buffer::mapRegion(offset, size, writeOnly); +} + +void ShaderBuffer::unmap() +{ + Vulkan::Buffer::unmap(); } void ShaderBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { - Gfx::QueueOwnedResource::transferOwnership(newOwner); + Gfx::QueueOwnedResource::transferOwnership(newOwner); } void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Vulkan::Buffer::executeOwnershipBarrier(newOwner); + Vulkan::Buffer::executeOwnershipBarrier(newOwner); } void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { - Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { + Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } VkAccessFlags ShaderBuffer::getSourceAccessMask() { return VK_ACCESS_MEMORY_WRITE_BIT; } @@ -306,42 +385,42 @@ VkAccessFlags ShaderBuffer::getDestAccessMask() { return VK_ACCESS_MEMORY_READ_B VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo& sourceData) : Gfx::VertexBuffer(graphics->getFamilyMapping(), sourceData.numVertices, sourceData.vertexSize, - sourceData.sourceData.owner), - Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner, false, - sourceData.name) { - if (sourceData.sourceData.data != nullptr) { - void* data = map(); - std::memcpy(data, sourceData.sourceData.data, sourceData.sourceData.size); - unmap(); - } + sourceData.sourceData.owner), + Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner, false, + sourceData.name) { + if (sourceData.sourceData.data != nullptr) { + void* data = map(); + std::memcpy(data, sourceData.sourceData.data, sourceData.sourceData.size); + unmap(); + } } VertexBuffer::~VertexBuffer() {} void VertexBuffer::updateRegion(DataSource update) { - void* data = mapRegion(update.offset, update.size); - std::memcpy(data, update.data, update.size); - unmap(); + void* data = mapRegion(update.offset, update.size); + std::memcpy(data, update.data, update.size); + unmap(); } void VertexBuffer::download(Array& buffer) { - void* data = map(false); - buffer.resize(size); - std::memcpy(buffer.data(), data, size); - unmap(); + void* data = map(false); + buffer.resize(getSize()); + std::memcpy(buffer.data(), data, getSize()); + unmap(); } void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { - Gfx::QueueOwnedResource::transferOwnership(newOwner); + Gfx::QueueOwnedResource::transferOwnership(newOwner); } void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Vulkan::Buffer::executeOwnershipBarrier(newOwner); + Vulkan::Buffer::executeOwnershipBarrier(newOwner); } void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { - Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { + Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } VkAccessFlags VertexBuffer::getSourceAccessMask() { return VK_ACCESS_MEMORY_WRITE_BIT; } @@ -350,36 +429,36 @@ VkAccessFlags VertexBuffer::getDestAccessMask() { return VK_ACCESS_VERTEX_ATTRIB IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo& sourceData) : Gfx::IndexBuffer(graphics->getFamilyMapping(), sourceData.sourceData.size, sourceData.indexType, - sourceData.sourceData.owner), - Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, currentOwner, false, - sourceData.name) { - if (sourceData.sourceData.data != nullptr) { - void* data = map(); - std::memcpy(data, sourceData.sourceData.data, sourceData.sourceData.size); - unmap(); - } + sourceData.sourceData.owner), + Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, currentOwner, false, + sourceData.name) { + if (sourceData.sourceData.data != nullptr) { + void* data = map(); + std::memcpy(data, sourceData.sourceData.data, sourceData.sourceData.size); + unmap(); + } } IndexBuffer::~IndexBuffer() {} void IndexBuffer::download(Array& buffer) { - void* data = map(false); - buffer.resize(size); - std::memcpy(buffer.data(), data, size); - unmap(); + void* data = map(false); + buffer.resize(getSize()); + std::memcpy(buffer.data(), data, getSize()); + unmap(); } void IndexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { - Gfx::QueueOwnedResource::transferOwnership(newOwner); + Gfx::QueueOwnedResource::transferOwnership(newOwner); } void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Vulkan::Buffer::executeOwnershipBarrier(newOwner); + Vulkan::Buffer::executeOwnershipBarrier(newOwner); } void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { - Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { + Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } VkAccessFlags IndexBuffer::getSourceAccessMask() { return VK_ACCESS_MEMORY_WRITE_BIT; } diff --git a/src/Engine/Graphics/Vulkan/Buffer.h b/src/Engine/Graphics/Vulkan/Buffer.h index 1cecb9e..2f2ed16 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.h +++ b/src/Engine/Graphics/Vulkan/Buffer.h @@ -1,38 +1,46 @@ #pragma once #include "Graphics.h" #include "Graphics/Buffer.h" +#include "Resources.h" namespace Seele { namespace Vulkan { DECLARE_REF(Command) DECLARE_REF(Fence) +class BufferAllocation : public CommandBoundResource { +public: + BufferAllocation(PGraphics graphics); + virtual ~BufferAllocation(); + VkBuffer buffer = VK_NULL_HANDLE; + VmaAllocation allocation = VmaAllocation(); + VmaAllocationInfo info = VmaAllocationInfo(); + VkMemoryPropertyFlags properties = 0; + uint64 size = 0; +}; +DEFINE_REF(BufferAllocation); class Buffer { public: Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType &queueType, bool dynamic, std::string name); virtual ~Buffer(); - VkBuffer getHandle() const { return buffers[currentBuffer].buffer; } - uint64 getSize() const { return size; } + VkBuffer getHandle() const { return buffers[currentBuffer]->buffer; } + PBufferAllocation getAlloc() const { return buffers[currentBuffer]; } + uint64 getSize() const { return buffers[currentBuffer]->size; } void *map(bool writeOnly = true); void *mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly = true); void unmap(); protected: - struct BufferAllocation { - VkBuffer buffer; - VmaAllocation allocation; - VmaAllocationInfo info; - VkMemoryPropertyFlags properties; - }; PGraphics graphics; uint32 currentBuffer; - uint64 size; Gfx::QueueType &owner; - Array buffers; + Array buffers; VkBufferUsageFlags usage; + bool dynamic; std::string name; - void createBuffer(); + void rotateBuffer(uint64 size); + void createBuffer(uint64 size); void executeOwnershipBarrier(Gfx::QueueType newOwner); void executePipelineBarrier(VkAccessFlags srcAccess, @@ -115,7 +123,10 @@ class ShaderBuffer : public Gfx::ShaderBuffer, public Buffer { public: ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &sourceData); virtual ~ShaderBuffer(); - virtual bool updateContents(const DataSource &sourceData) override; + virtual void updateContents(const ShaderBufferCreateInfo &createInfo) override; + virtual void rotateBuffer(uint64 size) override; + virtual void* mapRegion(uint64 offset, uint64 size, bool writeOnly) override; + virtual void unmap() override; protected: // Inherited via Vulkan::Buffer diff --git a/src/Engine/Graphics/Vulkan/Command.cpp b/src/Engine/Graphics/Vulkan/Command.cpp index 9255266..c9a2a73 100644 --- a/src/Engine/Graphics/Vulkan/Command.cpp +++ b/src/Engine/Graphics/Vulkan/Command.cpp @@ -95,9 +95,9 @@ void Command::executeCommands(Array commands) { auto command = Gfx::PRenderCommand(commands[i]).cast(); command->end(); - for(auto& descriptor : command->boundDescriptors) + for(auto& descriptor : command->boundResources) { - boundDescriptors.add(descriptor); + boundResources.add(descriptor); //std::cout << "Cmd " << handle << " bound descriptor " << descriptor->getHandle() << std::endl; } cmdBuffers[i] = command->getHandle(); @@ -117,9 +117,9 @@ void Command::executeCommands(Array commands) { auto command = Gfx::PComputeCommand(commands[i]).cast(); command->end(); - for(auto& descriptor : command->boundDescriptors) + for(auto& descriptor : command->boundResources) { - boundDescriptors.add(descriptor); + boundResources.add(descriptor); //std::cout << "Cmd " << handle << " bound descriptor " << descriptor->getHandle() << std::endl; } cmdBuffers[i] = command->getHandle(); @@ -153,18 +153,17 @@ void Command::checkFence() command->reset(); } executingRenders.clear(); - for(auto& descriptor : boundDescriptors) + for(auto& descriptor : boundResources) { descriptor->unbind(); //std::cout << "Cmd " << handle << " unbind " << descriptor->getHandle() << std::endl; } - boundDescriptors.clear(); - graphics->getDestructionManager()->notifyCmdComplete(this); + boundResources.clear(); + graphics->getDestructionManager()->notifyCommandComplete(); state = State::Init; } } - void Command::waitForCommand(uint32 timeout) { pool->submitCommands(); @@ -177,6 +176,12 @@ void Command::waitForCommand(uint32 timeout) checkFence(); } +void Command::bindResource(PCommandBoundResource resource) +{ + resource->bind(); + boundResources.add(resource); +} + PFence Command::getFence() { return fence; @@ -237,7 +242,7 @@ void RenderCommand::end() void RenderCommand::reset() { vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); - boundDescriptors.clear(); + boundResources.clear(); ready = true; } @@ -275,12 +280,15 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array(); assert(descriptor->writeDescriptors.size() == 0); - boundDescriptors.add(descriptor.getHandle()); + boundResources.add(descriptor.getHandle()); + descriptor->boundResources.clear(); + boundResources.addAll(descriptor->boundResources); descriptor->bind(); VkDescriptorSet setHandle = descriptor->getHandle(); 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& descriptorSets, Array dynamicOffsets) { assert(threadId == std::this_thread::get_id()); @@ -291,11 +299,14 @@ void RenderCommand::bindDescriptor(const Array& descriptorS assert(descriptorSet->writeDescriptors.size() == 0); descriptorSet->bind(); - boundDescriptors.add(descriptorSet.getHandle()); + boundResources.add(descriptorSet.getHandle()); + boundResources.addAll(descriptorSet->boundResources); + descriptorSet->boundResources.clear(); sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle(); } 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& streams) { @@ -307,6 +318,8 @@ void RenderCommand::bindVertexBuffer(const Array& streams) PVertexBuffer buf = streams[i].cast(); buffers[i] = buf->getHandle(); offsets[i] = 0; + buf->getAlloc()->bind(); + boundResources.add(buf->getAlloc()); }; vkCmdBindVertexBuffers(handle, 0, (uint32)streams.size(), buffers.data(), offsets.data()); } @@ -314,6 +327,8 @@ void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) { assert(threadId == std::this_thread::get_id()); PIndexBuffer buf = indexBuffer.cast(); + buf->getAlloc()->bind(); + boundResources.add(buf->getAlloc()); vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, cast(buf->getIndexType())); } @@ -398,7 +413,7 @@ void ComputeCommand::reset() { assert(threadId == std::this_thread::get_id()); vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); - boundDescriptors.clear(); + boundResources.clear(); ready = true; } bool ComputeCommand::isReady() @@ -418,7 +433,9 @@ void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet, Array(); assert(descriptor->writeDescriptors.size() == 0); - boundDescriptors.add(descriptor.getHandle()); + boundResources.add(descriptor.getHandle()); + boundResources.addAll(descriptor->boundResources); + descriptor->boundResources.clear(); descriptor->bind(); VkDescriptorSet setHandle = descriptor->getHandle(); @@ -436,7 +453,9 @@ void ComputeCommand::bindDescriptor(const Array& descriptor descriptorSet->bind(); //std::cout << "Binding descriptor " << descriptorSet->getHandle() << " to cmd " << handle << std::endl; - boundDescriptors.add(descriptorSet.getHandle()); + boundResources.add(descriptorSet.getHandle()); + boundResources.addAll(descriptorSet->boundResources); + descriptorSet->boundResources.clear(); sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle(); } vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, dynamicOffsets.size(), dynamicOffsets.data()); diff --git a/src/Engine/Graphics/Vulkan/Command.h b/src/Engine/Graphics/Vulkan/Command.h index 7cd8243..5310c2a 100644 --- a/src/Engine/Graphics/Vulkan/Command.h +++ b/src/Engine/Graphics/Vulkan/Command.h @@ -2,6 +2,7 @@ #include "Buffer.h" #include "Graphics/Command.h" #include "Queue.h" +#include "Resources.h" #include namespace Seele { @@ -25,6 +26,7 @@ public: void executeCommands(Array secondaryCommands); void executeCommands(Array secondaryCommands); void waitForSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore); + void bindResource(PCommandBoundResource resource); void checkFence(); void waitForCommand(uint32 timeToWait = 1000000u); PFence getFence(); @@ -52,7 +54,7 @@ private: Array waitFlags; Array executingRenders; Array executingComputes; - Array boundDescriptors; + Array boundResources; friend class RenderCommand; friend class CommandPool; friend class Queue; @@ -87,7 +89,7 @@ public: private: PGraphicsPipeline pipeline; bool ready; - Array boundDescriptors; + Array boundResources; VkViewport currentViewport; VkRect2D currentScissor; PGraphics graphics; @@ -117,7 +119,7 @@ public: private: PComputePipeline pipeline; bool ready; - Array boundDescriptors; + Array boundResources; VkViewport currentViewport; VkRect2D currentScissor; PGraphics graphics; diff --git a/src/Engine/Graphics/Vulkan/Descriptor.cpp b/src/Engine/Graphics/Vulkan/Descriptor.cpp index da506a0..9c1b727 100644 --- a/src/Engine/Graphics/Vulkan/Descriptor.cpp +++ b/src/Engine/Graphics/Vulkan/Descriptor.cpp @@ -11,6 +11,7 @@ DescriptorLayout::DescriptorLayout(PGraphics graphics, const std::string& name) : Gfx::DescriptorLayout(name), graphics(graphics), layoutHandle(VK_NULL_HANDLE) {} DescriptorLayout::~DescriptorLayout() { + graphics->getDestructionManager()->queueResourceForDestruction(std::move(pool)); if (layoutHandle != VK_NULL_HANDLE) { vkDestroyDescriptorSetLayout(graphics->getDevice(), layoutHandle, nullptr); } @@ -53,7 +54,10 @@ void DescriptorLayout::create() { hash = CRC::Calculate(bindings.data(), sizeof(VkDescriptorSetLayoutBinding) * bindings.size(), CRC::CRC_32()); } -DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout) : graphics(graphics), layout(layout) { +DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout) + : CommandBoundResource(graphics) + , graphics(graphics) + , layout(layout) { for (uint32 i = 0; i < cachedHandles.size(); ++i) { cachedHandles[i] = nullptr; } @@ -86,10 +90,17 @@ DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout) : g } DescriptorPool::~DescriptorPool() { - graphics->getDestructionManager()->queueDescriptorPool(graphics->getGraphicsCommands()->getCommands(), poolHandle); - if (nextAlloc) { - delete nextAlloc; - } + for (size_t i = 0; i < maxSets; ++i) + { + if (cachedHandles[i] != nullptr) + { + cachedHandles[i] = nullptr; + } + } + vkDestroyDescriptorPool(graphics->getDevice(), poolHandle, nullptr); + if (nextAlloc) { + delete nextAlloc; + } } Gfx::PDescriptorSet DescriptorPool::allocateDescriptorSet() { @@ -159,10 +170,19 @@ void DescriptorPool::reset() { } DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner) - : Gfx::DescriptorSet(owner->getLayout()), setHandle(VK_NULL_HANDLE), graphics(graphics), owner(owner), bindCount(0), - currentlyInUse(false) {} + : Gfx::DescriptorSet(owner->getLayout()) + , CommandBoundResource(graphics) + , setHandle(VK_NULL_HANDLE) + , graphics(graphics) + , owner(owner) + , bindCount(0) + , currentlyInUse(false) +{} -DescriptorSet::~DescriptorSet() {} +DescriptorSet::~DescriptorSet() +{ + vkFreeDescriptorSets(graphics->getDevice(), owner->getHandle(), 1, &setHandle); +} void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) { PUniformBuffer vulkanBuffer = uniformBuffer.cast(); @@ -189,6 +209,8 @@ void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBu }); cachedData[binding] = vulkanBuffer.getHandle(); + vulkanBuffer->getAlloc()->bind(); + boundResources.add(vulkanBuffer->getAlloc()); } void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer shaderBuffer) { @@ -215,6 +237,8 @@ void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer shaderBuff }); cachedData[binding] = vulkanBuffer.getHandle(); + vulkanBuffer->getAlloc()->bind(); + boundResources.add(vulkanBuffer->getAlloc()); } void DescriptorSet::updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuffer shaderBuffer) { @@ -242,6 +266,8 @@ void DescriptorSet::updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuf }); cachedData[binding] = vulkanBuffer.getHandle(); + vulkanBuffer->getAlloc()->bind(); + boundResources.add(vulkanBuffer->getAlloc()); } void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState) { @@ -300,6 +326,8 @@ void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx:: }); cachedData[binding] = vulkanTexture; + vulkanTexture->getHandle()->bind(); + boundResources.add(vulkanTexture->getHandle()); } void DescriptorSet::updateTextureArray(uint32_t binding, Array textures) { // maybe make this a parameter? @@ -326,6 +354,8 @@ void DescriptorSet::updateTextureArray(uint32_t binding, Array te .descriptorType = descriptorType, .pImageInfo = &imageInfos.back(), }); + vulkanTexture->getHandle()->bind(); + boundResources.add(vulkanTexture->getHandle()); } } @@ -366,7 +396,7 @@ void PipelineLayout::create() { for (size_t i = 0; i < pushConstants.size(); i++) { vkPushConstants[i].offset = pushConstants[i].offset; vkPushConstants[i].size = pushConstants[i].size; - vkPushConstants[i].stageFlags = (VkShaderStageFlagBits)pushConstants[i].stageFlags; + vkPushConstants[i].stageFlags = pushConstants[i].stageFlags; } VkPipelineLayoutCreateInfo createInfo = { diff --git a/src/Engine/Graphics/Vulkan/Descriptor.h b/src/Engine/Graphics/Vulkan/Descriptor.h index 9a8622c..3265f51 100644 --- a/src/Engine/Graphics/Vulkan/Descriptor.h +++ b/src/Engine/Graphics/Vulkan/Descriptor.h @@ -23,7 +23,7 @@ private: DEFINE_REF(DescriptorLayout) DECLARE_REF(DescriptorSet) -class DescriptorPool : public Gfx::DescriptorPool { +class DescriptorPool : public Gfx::DescriptorPool, public CommandBoundResource { public: DescriptorPool(PGraphics graphics, PDescriptorLayout layout); virtual ~DescriptorPool(); @@ -43,7 +43,7 @@ private: }; DEFINE_REF(DescriptorPool) -class DescriptorSet : public Gfx::DescriptorSet { +class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource { public: DescriptorSet(PGraphics graphics, PDescriptorPool owner); virtual ~DescriptorSet(); @@ -55,10 +55,7 @@ public: virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler sampler = nullptr) override; virtual void updateTextureArray(uint32_t binding, Array texture) override; - constexpr bool isCurrentlyBound() const { return bindCount > 0; } constexpr bool isCurrentlyInUse() const { return currentlyInUse; } - constexpr void bind() { bindCount++; } - constexpr void unbind() { bindCount--; } constexpr void allocate() { currentlyInUse = true; } constexpr void free() { currentlyInUse = false; } constexpr VkDescriptorSet getHandle() const { return setHandle; } @@ -71,6 +68,7 @@ private: // since the layout is fixed, trying to bind a texture to a buffer // would not work anyways, so casts should be safe Array cachedData; + Array boundResources; VkDescriptorSet setHandle; PGraphics graphics; PDescriptorPool owner; diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index 67ca28d..1844508 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -404,7 +404,6 @@ void Graphics::initInstance(GraphicsInitializer initInfo) .apiVersion = VK_API_VERSION_1_2, }; - Array extensions = getRequiredExtensions(); for (uint32 i = 0; i < initInfo.instanceExtensions.size(); ++i) { @@ -452,11 +451,16 @@ void Graphics::pickPhysicalDevice() VkPhysicalDevice bestDevice = VK_NULL_HANDLE; uint32 deviceRating = 0; features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - features.pNext = &features11; + features.pNext = &robustness; + robustness.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; + robustness.pNext = &features11; + robustness.nullDescriptor = true; features11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; features11.pNext = &features12; features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; - features12.pNext = nullptr; + features12.pNext = &features13; + features13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; + features13.pNext = nullptr; for (auto dev : physicalDevices) { uint32 currentRating = 0; diff --git a/src/Engine/Graphics/Vulkan/Graphics.h b/src/Engine/Graphics/Vulkan/Graphics.h index 4179449..afa33f1 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.h +++ b/src/Engine/Graphics/Vulkan/Graphics.h @@ -101,6 +101,8 @@ protected: VkPhysicalDeviceFeatures2 features; VkPhysicalDeviceVulkan11Features features11; VkPhysicalDeviceVulkan12Features features12; + VkPhysicalDeviceVulkan13Features features13; + VkPhysicalDeviceRobustness2FeaturesEXT robustness; VkDebugUtilsMessengerEXT callback; Map allocatedFramebuffers; VmaAllocator allocator; diff --git a/src/Engine/Graphics/Vulkan/RenderPass.cpp b/src/Engine/Graphics/Vulkan/RenderPass.cpp index bc4d056..38715b4 100644 --- a/src/Engine/Graphics/Vulkan/RenderPass.cpp +++ b/src/Engine/Graphics/Vulkan/RenderPass.cpp @@ -207,7 +207,8 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout _layout, Arra RenderPass::~RenderPass() { - graphics->getDestructionManager()->queueRenderPass(graphics->getGraphicsCommands()->getCommands(), renderPass); + vkDestroyRenderPass(graphics->getDevice(), renderPass, nullptr); + //graphics->getDestructionManager()->queueRenderPass(graphics->getGraphicsCommands()->getCommands(), renderPass); } uint32 RenderPass::getFramebufferHash() diff --git a/src/Engine/Graphics/Vulkan/Resources.cpp b/src/Engine/Graphics/Vulkan/Resources.cpp index 2119540..872f8cf 100644 --- a/src/Engine/Graphics/Vulkan/Resources.cpp +++ b/src/Engine/Graphics/Vulkan/Resources.cpp @@ -20,9 +20,10 @@ Semaphore::Semaphore(PGraphics graphics) Semaphore::~Semaphore() { - graphics->getDestructionManager()->queueSemaphore(graphics->getGraphicsCommands()->getCommands(), handle); + //graphics->getDestructionManager()->queueSemaphore(graphics->getGraphicsCommands()->getCommands(), handle); } + Fence::Fence(PGraphics graphics) : graphics(graphics) , signaled(false) @@ -100,66 +101,19 @@ DestructionManager::~DestructionManager() { } -void DestructionManager::queueBuffer(PCommand cmd, VkBuffer buffer, VmaAllocation alloc) +void DestructionManager::queueResourceForDestruction(OCommandBoundResource resource) { - buffers[cmd].add({buffer, alloc}); + resources.add(std::move(resource)); } -void DestructionManager::queueImage(PCommand cmd, VkImage image, VmaAllocation alloc) +void DestructionManager::notifyCommandComplete() { - images[cmd].add({image, alloc}); -} - -void DestructionManager::queueImageView(PCommand cmd, VkImageView image) -{ - views[cmd].add(image); -} - -void DestructionManager::queueSemaphore(PCommand cmd, VkSemaphore sem) -{ - sems[cmd].add(sem); -} - -void DestructionManager::queueRenderPass(PCommand cmd, VkRenderPass renderPass) -{ - renderPasses[cmd].add(renderPass); -} - -void DestructionManager::queueDescriptorPool(PCommand cmd, VkDescriptorPool pool) -{ - pools[cmd].add(pool); -} - -void DestructionManager::notifyCmdComplete(PCommand cmd) -{ - for(auto [buf, alloc] : buffers[cmd]) + for (size_t i = 0; i < resources.size(); ++i) { - vmaDestroyBuffer(graphics->getAllocator(), buf, alloc); + if(!resources[i]->isCurrentlyBound()) + { + resources.removeAt(i, false); + i--; + } } - for(auto view : views[cmd]) - { - vkDestroyImageView(graphics->getDevice(), view, nullptr); - } - for(auto [img, alloc] : images[cmd]) - { - vmaDestroyImage(graphics->getAllocator(), img, alloc); - } - for (auto sem : sems[cmd]) - { - vkDestroySemaphore(graphics->getDevice(), sem, nullptr); - } - for (auto pool : pools[cmd]) - { - vkDestroyDescriptorPool(graphics->getDevice(), pool, nullptr); - } - for (auto renderPass : renderPasses[cmd]) - { - vkDestroyRenderPass(graphics->getDevice(), renderPass, nullptr); - } - buffers[cmd].clear(); - images[cmd].clear(); - views[cmd].clear(); - sems[cmd].clear(); - pools[cmd].clear(); - renderPasses[cmd].clear(); } diff --git a/src/Engine/Graphics/Vulkan/Resources.h b/src/Engine/Graphics/Vulkan/Resources.h index 0dea544..fd222d7 100644 --- a/src/Engine/Graphics/Vulkan/Resources.h +++ b/src/Engine/Graphics/Vulkan/Resources.h @@ -50,30 +50,41 @@ private: VkFence fence; }; DEFINE_REF(Fence) - +DECLARE_REF(CommandBoundResource) class DestructionManager { public: DestructionManager(PGraphics graphics); ~DestructionManager(); - void queueBuffer(PCommand cmd, VkBuffer buffer, VmaAllocation alloc); - void queueImage(PCommand cmd, VkImage image, VmaAllocation alloc); - void queueImageView(PCommand cmd, VkImageView view); - void queueSemaphore(PCommand cmd, VkSemaphore sem); - void queueRenderPass(PCommand cmd, VkRenderPass renderPass); - void queueDescriptorPool(PCommand cmd, VkDescriptorPool pool); - void notifyCmdComplete(PCommand cmdbuffer); + void queueResourceForDestruction(OCommandBoundResource resource); + void notifyCommandComplete(); private: PGraphics graphics; - Map>> buffers; - Map>> images; - Map> views; - Map> sems; - Map> renderPasses; - Map> pools; + Array resources; }; DEFINE_REF(DestructionManager) +class CommandBoundResource +{ +public: + CommandBoundResource(PGraphics graphics) + : graphics(graphics) + { + } + virtual ~CommandBoundResource() + { + if (isCurrentlyBound()) + abort(); + } + constexpr bool isCurrentlyBound() const { return bindCount > 0; } + constexpr void bind() { bindCount++; } + constexpr void unbind() { bindCount--; } +protected: + PGraphics graphics; + uint64 bindCount = 0; +}; +DEFINE_REF(CommandBoundResource) + class Sampler : public Gfx::Sampler { public: diff --git a/src/Engine/Graphics/Vulkan/Texture.cpp b/src/Engine/Graphics/Vulkan/Texture.cpp index a471863..bf1cf22 100644 --- a/src/Engine/Graphics/Vulkan/Texture.cpp +++ b/src/Engine/Graphics/Vulkan/Texture.cpp @@ -25,6 +25,21 @@ VkImageAspectFlags getAspectFromFormat(Gfx::SeFormat format) } } + +TextureHandle::TextureHandle(PGraphics graphics) + : CommandBoundResource(graphics) +{ +} + +TextureHandle::~TextureHandle() +{ + vkDestroyImageView(graphics->getDevice(), imageView, nullptr); + if (ownsImage) + { + vmaDestroyImage(graphics->getAllocator(), image, allocation); + } +} + TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, const TextureCreateInfo& createInfo, Gfx::QueueType& owner, VkImage existingImage) : currentOwner(owner) @@ -38,14 +53,15 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, , samples(createInfo.samples) , format(createInfo.format) , usage(createInfo.usage) - , image(existingImage) + , handle(new TextureHandle(graphics)) , aspect(getAspectFromFormat(createInfo.format)) , layout(Gfx::SE_IMAGE_LAYOUT_UNDEFINED) - , ownsImage(false) { + handle->image = existingImage; + handle->ownsImage = false; if (existingImage == VK_NULL_HANDLE) { - ownsImage = true; + handle->ownsImage = true; VkImageType type = VK_IMAGE_TYPE_MAX_ENUM; VkImageCreateFlags flags = 0; switch (viewType) @@ -99,7 +115,7 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, VmaAllocationCreateInfo allocInfo = { .usage = VMA_MEMORY_USAGE_AUTO, }; - VK_CHECK(vmaCreateImage(graphics->getAllocator(), &info, &allocInfo, &image, &allocation, nullptr)); + VK_CHECK(vmaCreateImage(graphics->getAllocator(), &info, &allocInfo, &handle->image, &handle->allocation, nullptr)); } const DataSource& sourceData = createInfo.sourceData; @@ -109,9 +125,7 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, VK_ACCESS_NONE, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_ACCESS_MEMORY_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); void* data; - VkMemoryPropertyFlags memProps; - VkBuffer stagingBuffer = VK_NULL_HANDLE; - VmaAllocation stagingAlloc = VK_NULL_HANDLE; + OBufferAllocation stagingAlloc = new BufferAllocation(graphics); VkBufferCreateInfo stagingInfo = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, @@ -124,11 +138,12 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT, .usage = VMA_MEMORY_USAGE_AUTO, }; - VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &alloc, &stagingBuffer, &stagingAlloc, nullptr)); - vmaMapMemory(graphics->getAllocator(), stagingAlloc, &data); + VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &alloc, &stagingAlloc->buffer, &stagingAlloc->allocation, nullptr)); + vmaMapMemory(graphics->getAllocator(), stagingAlloc->allocation, &data); + vmaSetAllocationName(graphics->getAllocator(), stagingAlloc->allocation, "TextureStaging"); std::memcpy(data, sourceData.data, sourceData.size); - vmaUnmapMemory(graphics->getAllocator(), stagingAlloc); + vmaUnmapMemory(graphics->getAllocator(), stagingAlloc->allocation); PCommandPool commandPool = graphics->getQueueCommands(currentOwner); VkBufferImageCopy region = { @@ -154,14 +169,14 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, }; vkCmdCopyBufferToImage(commandPool->getCommands()->getHandle(), - stagingBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + stagingAlloc->buffer, handle->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + commandPool->getCommands()->bindResource(PBufferAllocation(stagingAlloc)); // When loading a texture from a file, we will almost always use it as a texture map for fragment shaders changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - - graphics->getDestructionManager()->queueBuffer(commandPool->getCommands(), stagingBuffer, stagingAlloc); + graphics->getDestructionManager()->queueResourceForDestruction(std::move(stagingAlloc)); } else { @@ -188,7 +203,7 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .pNext = nullptr, .flags = 0, - .image = image, + .image = handle->image, .viewType = viewType, .format = cast(format), .subresourceRange = { @@ -198,18 +213,23 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, }, }; - VK_CHECK(vkCreateImageView(graphics->getDevice(), &viewInfo, nullptr, &imageView)); + VK_CHECK(vkCreateImageView(graphics->getDevice(), &viewInfo, nullptr, &handle->imageView)); } TextureBase::~TextureBase() { - if (ownsImage) - { - graphics->getDestructionManager()->queueImage(graphics->getQueueCommands(currentOwner)->getCommands(), image, allocation); - } - graphics->getDestructionManager()->queueImageView(graphics->getQueueCommands(currentOwner)->getCommands(), imageView); + graphics->getDestructionManager()->queueResourceForDestruction(std::move(handle)); } +VkImage TextureBase::getImage() const +{ + return handle->image; +} + +VkImageView TextureBase::getView() const +{ + return handle->imageView; +} void TextureBase::changeLayout(Gfx::SeImageLayout newLayout, VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, @@ -224,7 +244,7 @@ void TextureBase::changeLayout(Gfx::SeImageLayout newLayout, .newLayout = cast(newLayout), .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image, + .image = handle->image, .subresourceRange = { .aspectMask = aspect, .baseMipLevel = 0, @@ -237,6 +257,7 @@ void TextureBase::changeLayout(Gfx::SeImageLayout newLayout, vkCmdPipelineBarrier(commandPool->getCommands()->getHandle(), srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier); + commandPool->getCommands()->bindResource(PTextureHandle(handle)); commandPool->submitCommands(); layout = newLayout; } @@ -250,8 +271,7 @@ void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra VK_ACCESS_MEMORY_WRITE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); void* data; - VkBuffer stagingBuffer = VK_NULL_HANDLE; - VmaAllocation stagingAlloc; + OBufferAllocation stagingAlloc = new BufferAllocation(graphics); // always create a staging buffer since we do buffer -> image copy and the image may be in any tiling format VkBufferCreateInfo stagingInfo = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, @@ -265,7 +285,8 @@ void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra .flags = VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT, .usage = VMA_MEMORY_USAGE_AUTO, }; - VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &alloc, &stagingBuffer, &stagingAlloc, nullptr)); + VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &alloc, &stagingAlloc->buffer, &stagingAlloc->allocation, nullptr)); + vmaSetAllocationName(graphics->getAllocator(), stagingAlloc->allocation, "DownloadBuffer"); PCommand cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); //Gfx::FormatCompatibilityInfo formatInfo = Gfx::getFormatInfo(format); @@ -290,15 +311,16 @@ void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra .depth = depth }, }; - vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer, 1, ®ion); + vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), handle->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingAlloc->buffer, 1, ®ion); + cmdBuffer->bindResource(PBufferAllocation(stagingAlloc)); changeLayout(prevLayout, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_MEMORY_READ_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - VK_CHECK(vmaMapMemory(graphics->getAllocator(), stagingAlloc, &data)); + VK_CHECK(vmaMapMemory(graphics->getAllocator(), stagingAlloc->allocation, &data)); buffer.resize(imageSize); std::memcpy(buffer.data(), data, buffer.size()); - vmaUnmapMemory(graphics->getAllocator(), stagingAlloc); - graphics->getDestructionManager()->queueBuffer(cmdBuffer, stagingBuffer, stagingAlloc); + vmaUnmapMemory(graphics->getAllocator(), stagingAlloc->allocation); + graphics->getDestructionManager()->queueResourceForDestruction(std::move(stagingAlloc)); } void TextureBase::executeOwnershipBarrier(Gfx::QueueType newOwner) @@ -311,7 +333,7 @@ void TextureBase::executeOwnershipBarrier(Gfx::QueueType newOwner) .newLayout = cast(layout), .srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(currentOwner), .dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner), - .image = image, + .image = handle->image, .subresourceRange = { .aspectMask = aspect, .baseMipLevel = 0, @@ -360,6 +382,8 @@ void TextureBase::executeOwnershipBarrier(Gfx::QueueType newOwner) VkCommandBuffer sourceCmd = sourcePool->getCommands()->getHandle(); VkCommandBuffer destCmd = dstPool->getCommands()->getHandle(); + sourcePool->getCommands()->bindResource(PTextureHandle(handle)); + dstPool->getCommands()->bindResource(PTextureHandle(handle)); vkCmdPipelineBarrier(sourceCmd, srcStage, srcStage, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier); vkCmdPipelineBarrier(destCmd, dstStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier); currentOwner = newOwner; @@ -378,7 +402,7 @@ void TextureBase::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStag .newLayout = cast(layout), .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image, + .image = handle->image, .subresourceRange = { .aspectMask = aspect, .baseMipLevel = 0, @@ -389,6 +413,7 @@ void TextureBase::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStag }; PCommand command = graphics->getQueueCommands(currentOwner)->getCommands(); vkCmdPipelineBarrier(command->getHandle(), srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier); + command->bindResource(PTextureHandle(handle)); } Texture2D::Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage) diff --git a/src/Engine/Graphics/Vulkan/Texture.h b/src/Engine/Graphics/Vulkan/Texture.h index 67adc64..8633cd0 100644 --- a/src/Engine/Graphics/Vulkan/Texture.h +++ b/src/Engine/Graphics/Vulkan/Texture.h @@ -1,11 +1,23 @@ #pragma once #include "Graphics/Texture.h" #include "Graphics.h" +#include "Resources.h" namespace Seele { namespace Vulkan { +class TextureHandle : public CommandBoundResource +{ +public: + TextureHandle(PGraphics graphics); + virtual ~TextureHandle(); + VkImage image; + VkImageView imageView; + VmaAllocation allocation; + uint8 ownsImage; +}; +DECLARE_REF(TextureHandle) class TextureBase { public: @@ -24,14 +36,12 @@ public: { return depth; } - constexpr VkImage getImage() const + PTextureHandle getHandle() const { - return image; - } - constexpr VkImageView getView() const - { - return imageView; + return handle; } + VkImage getImage() const; + VkImageView getView() const; constexpr Gfx::SeImageLayout getLayout() const { return layout; @@ -73,10 +83,10 @@ public: void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer); protected: + OTextureHandle handle; //Updates via reference Gfx::QueueType& currentOwner; PGraphics graphics; - VmaAllocation allocation; uint32 width; uint32 height; uint32 depth; @@ -86,11 +96,8 @@ protected: uint32 samples; Gfx::SeFormat format; Gfx::SeImageUsageFlags usage; - VkImage image; - VkImageView imageView; VkImageAspectFlags aspect; Gfx::SeImageLayout layout; - uint8 ownsImage; friend class Graphics; }; DEFINE_REF(TextureBase) diff --git a/src/Engine/Graphics/Vulkan/Window.cpp b/src/Engine/Graphics/Vulkan/Window.cpp index b38a51b..f3e97ad 100644 --- a/src/Engine/Graphics/Vulkan/Window.cpp +++ b/src/Engine/Graphics/Vulkan/Window.cpp @@ -14,6 +14,12 @@ double Gfx::getCurrentFrameDelta() return currentFrameDelta; } +uint32 currentFrameIndex = 0; +uint32 Gfx::getCurrentFrameIndex() +{ + return currentFrameIndex; +} + void glfwKeyCallback(GLFWwindow* handle, int key, int, int action, int modifier) { if (key == -1) @@ -143,7 +149,8 @@ void Window::endFrame() VK_CHECK(r); } currentSemaphoreIndex = (currentSemaphoreIndex + 1) % Gfx::numFramesBuffered; - graphics->waitDeviceIdle(); + currentFrameIndex = currentSemaphoreIndex; + //graphics->waitDeviceIdle(); } void Window::onWindowCloseEvent() diff --git a/src/Engine/Graphics/slang-compile.cpp b/src/Engine/Graphics/slang-compile.cpp index 6298bfb..33f846f 100644 --- a/src/Engine/Graphics/slang-compile.cpp +++ b/src/Engine/Graphics/slang-compile.cpp @@ -16,16 +16,19 @@ Slang::ComPtr Seele::generateShader(const ShaderCreateInfo& create } slang::SessionDesc sessionDesc; sessionDesc.flags = 0; - StaticArray option; + StaticArray option; option[0].name = slang::CompilerOptionName::IgnoreCapabilities; option[0].value.kind = slang::CompilerOptionValueKind::Int; option[0].value.intValue0 = 1; option[1].name = slang::CompilerOptionName::EmitSpirvViaGLSL; option[1].value.kind = slang::CompilerOptionValueKind::Int; option[1].value.intValue0 = 1; - option[2].name = slang::CompilerOptionName::DebugInformationFormat; + option[2].name = slang::CompilerOptionName::DebugInformation; option[2].value.kind = slang::CompilerOptionValueKind::Int; - option[2].value.intValue0 = 0; + option[2].value.intValue0 = SLANG_DEBUG_INFO_LEVEL_NONE; + option[3].name = slang::CompilerOptionName::DebugInformationFormat; + option[3].value.kind = slang::CompilerOptionValueKind::Int; + option[3].value.intValue0 = SLANG_DEBUG_INFO_FORMAT_C7; sessionDesc.compilerOptionEntries = option.data(); sessionDesc.compilerOptionEntryCount = option.size(); sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR; diff --git a/src/Engine/Scene/LightEnvironment.cpp b/src/Engine/Scene/LightEnvironment.cpp index b5cd04c..411719e 100644 --- a/src/Engine/Scene/LightEnvironment.cpp +++ b/src/Engine/Scene/LightEnvironment.cpp @@ -60,7 +60,6 @@ void LightEnvironment::addPointLight(Component::PointLight pointLight) void LightEnvironment::commit() { - lightEnvBuffer->pipelineBarrier( Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_ALL_COMMANDS_BIT, Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT @@ -79,42 +78,23 @@ void LightEnvironment::commit() .size = sizeof(LightEnv), .data = (uint8*) & lightEnv, }); - if(directionalLights->getNumElements() < dirs.size()) - { - directionalLights = graphics->createShaderBuffer({ - .sourceData = { - .size = sizeof(Component::DirectionalLight) * dirs.size(), - .data = (uint8*)dirs.data(), - }, - .numElements = dirs.size(), - .dynamic = true, - }); - } - else - { - directionalLights->updateContents(DataSource{ + directionalLights->rotateBuffer(sizeof(Component::DirectionalLight) * dirs.size()); + directionalLights->updateContents({ + .sourceData = { .size = sizeof(Component::DirectionalLight) * dirs.size(), .data = (uint8*)dirs.data(), - }); - } - if(pointLights->getNumElements() < points.size()) - { - pointLights = graphics->createShaderBuffer({ - .sourceData = { - .size = sizeof(Component::PointLight) * points.size(), - .data = (uint8*)points.data() - }, - .numElements = points.size(), - .dynamic = true - }); - } - else - { - pointLights->updateContents(DataSource{ + }, + .numElements = dirs.size(), + }); + pointLights->rotateBuffer(sizeof(Component::PointLight) * points.size()); + pointLights->updateContents({ + .sourceData = { .size = sizeof(Component::PointLight) * points.size(), - .data = (uint8*)points.data(), - }); - } + .data = (uint8*)points.data() + }, + .numElements = points.size(), + }); + lightEnvBuffer->pipelineBarrier( Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_ALL_COMMANDS_BIT @@ -133,12 +113,12 @@ void LightEnvironment::commit() set->writeChanges(); } -const Gfx::PDescriptorLayout Seele::LightEnvironment::getDescriptorLayout() const +const Gfx::PDescriptorLayout LightEnvironment::getDescriptorLayout() const { return layout; } -Gfx::PDescriptorSet Seele::LightEnvironment::getDescriptorSet() +Gfx::PDescriptorSet LightEnvironment::getDescriptorSet() { return set; } diff --git a/src/Engine/Window/GameView.cpp b/src/Engine/Window/GameView.cpp index ae74dc8..4ad8c53 100644 --- a/src/Engine/Window/GameView.cpp +++ b/src/Engine/Window/GameView.cpp @@ -23,7 +23,7 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate renderGraph.addPass(new LightCullingPass(graphics, scene)); //renderGraph.addPass(new StaticBasePass(graphics, scene)); renderGraph.addPass(new BasePass(graphics, scene)); - //renderGraph.addPass(new DebugPass(graphics, scene)); + renderGraph.addPass(new DebugPass(graphics, scene)); //renderGraph.addPass(new SkyboxRenderPass(graphics, scene)); renderGraph.setViewport(viewport); renderGraph.createRenderPass();