Implementing ECS SystemBase and updating slang

This commit is contained in:
Dynamitos
2022-11-15 12:19:11 +01:00
parent 05bc31a2b4
commit f635ee2100
106 changed files with 1083 additions and 1675 deletions
@@ -95,7 +95,7 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
VkDeviceSize allocatedOffset = it.first;
PSubAllocation freeAllocation = it.second;
assert(allocatedOffset == freeAllocation->allocatedOffset);
VkDeviceSize alignedOffset = align(allocatedOffset, alignment);
VkDeviceSize alignedOffset = Math::align(allocatedOffset, alignment);
VkDeviceSize alignmentAdjustment = alignedOffset - allocatedOffset;
VkDeviceSize size = alignmentAdjustment + requestedSize;
if (freeAllocation->size == size)
@@ -171,6 +171,8 @@ void Allocation::markFree(SubAllocation *allocation)
allocHandle = foundAlloc->second;
allocHandle->allocatedOffset -= allocation->allocatedSize;
allocHandle->alignedOffset -= allocation->allocatedSize;
allocHandle->size += allocation->allocatedSize;
allocHandle->allocatedSize += allocation->allocatedSize;
// place back at correct offset
freeRanges[allocHandle->allocatedOffset] = allocHandle;
// remove from offset map since key changes
@@ -310,7 +312,7 @@ void StagingManager::clearPending()
{
}
PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead)
PStagingBuffer StagingManager::allocateStagingBuffer(uint64 size, VkBufferUsageFlags usage, bool bCPURead)
{
std::scoped_lock l(lock);
for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it)
+3 -3
View File
@@ -191,7 +191,7 @@ public:
{
return allocation->getOffset();
}
uint32 getSize() const
uint64 getSize() const
{
return size;
}
@@ -203,7 +203,7 @@ public:
private:
PSubAllocation allocation;
VkBuffer buffer;
uint32 size;
uint64 size;
VkBufferUsageFlags usage;
uint8 bReadable;
friend class StagingManager;
@@ -215,7 +215,7 @@ class StagingManager
public:
StagingManager(PGraphics graphics, PAllocator allocator);
~StagingManager();
PStagingBuffer allocateStagingBuffer(uint32 size, VkBufferUsageFlags usageFlags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, bool bCPURead = false);
PStagingBuffer allocateStagingBuffer(uint64 size, VkBufferUsageFlags usageFlags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, bool bCPURead = false);
void releaseStagingBuffer(PStagingBuffer buffer);
void clearPending();
+22 -4
View File
@@ -9,6 +9,8 @@ using namespace Seele::Vulkan;
struct PendingBuffer
{
uint64 offset;
uint64 size;
PStagingBuffer stagingBuffer;
Gfx::QueueType prevQueue;
bool bWriteOnly;
@@ -16,7 +18,7 @@ struct PendingBuffer
static std::map<ShaderBuffer *, PendingBuffer> pendingBuffers;
ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic)
ShaderBuffer::ShaderBuffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic)
: graphics(graphics)
, currentBuffer(0)
, size(size)
@@ -63,7 +65,7 @@ ShaderBuffer::~ShaderBuffer()
{
PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands();
VkDevice device = graphics->getDevice();
auto deletionLambda = [cmdBuffer, device](VkBuffer buffer) -> void
auto deletionLambda = [cmdBuffer, device](VkBuffer) -> void
{
//co_await cmdBuffer->asyncWait();
//vkDestroyBuffer(device, buffer, nullptr);
@@ -169,6 +171,11 @@ void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineSta
}
void *ShaderBuffer::lock(bool bWriteOnly)
{
return lockRegion(0, size, bWriteOnly);
}
void *ShaderBuffer::lockRegion(uint64 regionOffset, uint64 regionSize, bool bWriteOnly)
{
void *data = nullptr;
@@ -189,10 +196,12 @@ void *ShaderBuffer::lock(bool bWriteOnly)
PendingBuffer pending;
pending.bWriteOnly = bWriteOnly;
pending.prevQueue = owner;
pending.offset = regionOffset;
pending.size = regionSize;
if (bWriteOnly)
{
//requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(regionSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
data = stagingBuffer->getMappedPointer();
pending.stagingBuffer = stagingBuffer;
}
@@ -255,7 +264,8 @@ void ShaderBuffer::unlock()
VkBufferCopy region;
std::memset(&region, 0, sizeof(VkBufferCopy));
region.size = size;
region.size = pending.size;
region.dstOffset = pending.offset;
vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region);
graphics->getQueueCommands(owner)->submitCommands();
}
@@ -448,6 +458,14 @@ VertexBuffer::~VertexBuffer()
{
}
void VertexBuffer::updateRegion(BulkResourceData update)
{
void* data = lockRegion(update.offset, update.size);
std::memcpy(data, update.data, update.size);
unlock();
}
void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
{
Gfx::QueueOwnedResource::transferOwnership(newOwner);
@@ -302,7 +302,7 @@ void RenderCommand::pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStag
void RenderCommand::draw(const MeshBatchElement& data)
{
assert(threadId == std::this_thread::get_id());
vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, 0);
vkCmdDrawIndexed(handle, static_cast<uint32>(data.indexBuffer->getNumIndices()), data.numInstances, data.minVertexIndex, data.baseVertexIndex, 0);
}
void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance)
@@ -67,6 +67,7 @@ public:
virtual Gfx::PPipelineLayout createPipelineLayout(Gfx::PPipelineLayout baseLayout = nullptr) override;
virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) override;
protected:
Array<const char *> getRequiredExtensions();
void initInstance(GraphicsInitializer initInfo);
@@ -1390,7 +1390,7 @@ Gfx::SeCompareOp Seele::Vulkan::cast(const VkCompareOp &op)
VkClearValue Seele::Vulkan::cast(const Gfx::SeClearValue& clear)
{
VkClearValue result;
if(sizeof(clear) == sizeof(Gfx::SeClearColorValue))
if constexpr (sizeof(clear) == sizeof(Gfx::SeClearColorValue))
{
result.color.float32[0] = clear.color.float32[0];
result.color.float32[1] = clear.color.float32[1];
@@ -1408,7 +1408,7 @@ VkClearValue Seele::Vulkan::cast(const Gfx::SeClearValue& clear)
Gfx::SeClearValue Seele::Vulkan::cast(const VkClearValue& clear)
{
Gfx::SeClearValue result;
if(sizeof(clear) == sizeof(VkClearColorValue))
if constexpr (sizeof(clear) == sizeof(VkClearColorValue))
{
result.color.float32[0] = clear.color.float32[0];
result.color.float32[1] = clear.color.float32[1];
@@ -72,13 +72,13 @@ DEFINE_REF(VertexDeclaration)
class ShaderBuffer
{
public:
ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic = false);
ShaderBuffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic = false);
virtual ~ShaderBuffer();
VkBuffer getHandle() const
{
return buffers[currentBuffer].buffer;
}
uint32 getSize() const
uint64 getSize() const
{
return size;
}
@@ -88,6 +88,7 @@ public:
currentBuffer = (currentBuffer + 1) % numBuffers;
}
virtual void *lock(bool bWriteOnly = true);
virtual void *lockRegion(uint64 regionOffset, uint64 regionSize, bool bWriteOnly = true);
virtual void unlock();
protected:
@@ -98,7 +99,7 @@ protected:
};
PGraphics graphics;
uint32 currentBuffer;
uint32 size;
uint64 size;
Gfx::QueueType& owner;
BufferAllocation buffers[Gfx::numFramesBuffered];
uint32 numBuffers;
@@ -168,6 +169,8 @@ public:
VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData);
virtual ~VertexBuffer();
virtual void updateRegion(BulkResourceData update) override;
protected:
// Inherited via Vulkan::Buffer
virtual VkAccessFlags getSourceAccessMask();
+103 -58
View File
@@ -2,9 +2,9 @@
#include "VulkanGraphics.h"
#include "VulkanDescriptorSets.h"
#include "slang.h"
#include "slang-com-ptr.h"
#include "stdlib.h"
using namespace slang;
using namespace Seele;
using namespace Seele::Vulkan;
@@ -33,85 +33,130 @@ uint32 Seele::Vulkan::Shader::getShaderHash() const
return hash;
}
static SlangStage getStageFromShaderType(ShaderType type)
{
switch (type)
{
case ShaderType::VERTEX:
return SLANG_STAGE_VERTEX;
case ShaderType::CONTROL:
return SLANG_STAGE_HULL;
case ShaderType::EVALUATION:
return SLANG_STAGE_DOMAIN;
case ShaderType::GEOMETRY:
return SLANG_STAGE_GEOMETRY;
case ShaderType::FRAGMENT:
return SLANG_STAGE_PIXEL;
default:
return SLANG_STAGE_NONE;
}
}
void Shader::create(const ShaderCreateInfo& createInfo)
{
entryPointName = createInfo.entryPoint;
static SlangSession* session = spCreateSession(nullptr);
SlangCompileRequest* request = spCreateCompileRequest(session);
int targetIndex = spAddCodeGenTarget(request, SLANG_SPIRV);
spSetTargetProfile(request, targetIndex, spFindProfile(session, "glsl_vk"));
spSetDumpIntermediates(request, true);
int translationUnitIndex = spAddTranslationUnit(request, SLANG_SOURCE_LANGUAGE_SLANG, "");
for(auto code : createInfo.shaderCode)
thread_local Slang::ComPtr<slang::IGlobalSession> globalSession;
if(!globalSession)
{
spAddTranslationUnitSourceString(
request,
translationUnitIndex,
entryPointName.c_str(),
code.data()
);
slang::createGlobalSession(globalSession.writeRef());
}
slang::SessionDesc sessionDesc;
sessionDesc.flags = 0;
sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR;
Array<slang::PreprocessorMacroDesc> macros;
for(auto define : createInfo.defines)
{
spAddPreprocessorDefine(request, define.key, define.value);
macros.add(slang::PreprocessorMacroDesc{
.name = define.key,
.value = define.value
});
}
spAddSearchPath(request, "shaders/lib/");
spAddSearchPath(request, "shaders/generated/");
sessionDesc.preprocessorMacroCount = macros.size();
sessionDesc.preprocessorMacros = macros.data();
slang::TargetDesc vulkan;
vulkan.profile = globalSession->findProfile("glsl_vk");
vulkan.format = SLANG_SPIRV;
sessionDesc.targetCount = 1;
sessionDesc.targets = &vulkan;
StaticArray<const char*, 3> searchPaths = {"shaders/", "shaders/lib/", "shaders/generated/"};
sessionDesc.searchPaths = searchPaths.data();
sessionDesc.searchPathCount = searchPaths.size();
spSetGlobalGenericArgs(request, (int)createInfo.typeParameter.size(), createInfo.typeParameter.data());
Slang::ComPtr<slang::ISession> session;
globalSession->createSession(sessionDesc, session.writeRef());
Slang::ComPtr<slang::IBlob> diagnostics;
Array<slang::IComponentType*> modules;
Slang::ComPtr<slang::IEntryPoint> entrypoint;
int entryPointIndex = spAddEntryPoint(request, translationUnitIndex, entryPointName.c_str(), getStageFromShaderType(type));
if(spCompile(request))
for (auto moduleName : createInfo.additionalModules)
{
char const* diagnostics = spGetDiagnosticOutput(request);
std::cout << "Compile error for shader " << createInfo.name << std::endl;
std::cout << diagnostics << std::endl;
std::cout << "Defines: " << std::endl;
for(auto define : createInfo.defines)
modules.add(session->loadModule(moduleName.c_str(), diagnostics.writeRef()));
if(diagnostics)
{
std::cout << define.key << ": " << define.value << std::endl;
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
std::cout << "For shader code: " << std::endl;
for(auto code : createInfo.shaderCode)
{
std::cout << code << std::endl;
}
return;
}
size_t dataSize = 0;
const uint32* data = reinterpret_cast<const uint32*>(spGetEntryPointCode(request, entryPointIndex, &dataSize));
slang::IModule* mainModule = session->loadModule(createInfo.mainModule.c_str(), diagnostics.writeRef());
modules.add(mainModule);
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
mainModule->findEntryPointByName(createInfo.entryPoint.c_str(), entrypoint.writeRef());
modules.add(entrypoint);
slang::IComponentType* moduleComposition;
session->createCompositeComponentType(modules.data(), modules.size(), &moduleComposition, diagnostics.writeRef());
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
/*for(auto typeParam : createInfo.typeParameter)
{
Slang::ComPtr<slang::ITypeConformance> typeConformance;
session->createTypeConformanceComponentType(moduleComposition->getLayout()->findTypeByName(typeParam), moduleComposition->getLayout()->findTypeByName("IMaterial"), typeConformance.writeRef(), -1, diagnostics.writeRef());
modules.add(typeConformance);
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
}
Slang::ComPtr<slang::IComponentType> conformingModule;
session->createCompositeComponentType(modules.data(), modules.size(), conformingModule.writeRef(), diagnostics.writeRef());
*/
Slang::ComPtr<slang::IComponentType> linkedProgram;
moduleComposition->link(linkedProgram.writeRef(), diagnostics.writeRef());
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
slang::ProgramLayout* reflection = linkedProgram->getLayout(0, diagnostics.writeRef());
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
Array<slang::SpecializationArg> specialization;
for(auto typeArg : createInfo.typeParameter)
{
specialization.add(slang::SpecializationArg::fromType(reflection->findTypeByName(typeArg)));
}
Slang::ComPtr<slang::IComponentType> specializedComponent;
linkedProgram->specialize(specialization.data(), specialization.size(), specializedComponent.writeRef(), diagnostics.writeRef());
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
Slang::ComPtr<slang::IBlob> kernelBlob;
specializedComponent->getEntryPointCode(
0,
0,
kernelBlob.writeRef(),
diagnostics.writeRef()
);
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
VkShaderModuleCreateInfo moduleInfo;
moduleInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
moduleInfo.pNext = nullptr;
moduleInfo.flags = 0;
moduleInfo.codeSize = dataSize;
moduleInfo.pCode = data;
moduleInfo.codeSize = kernelBlob->getBufferSize();
moduleInfo.pCode = (uint32_t*)kernelBlob->getBufferPointer();
VK_CHECK(vkCreateShaderModule(graphics->getDevice(), &moduleInfo, nullptr, &module));
boost::crc_32_type result;
result.process_bytes(entryPointName.data(), entryPointName.size());
result.process_bytes(data, dataSize);
result.process_bytes(kernelBlob->getBufferPointer(), kernelBlob->getBufferSize());
hash = result.checksum();
}