Renderer: Working compute implementation

This commit is contained in:
SirLynix
2022-12-25 16:08:35 +01:00
committed by Jérôme Leclercq
parent 4605eed0da
commit fe8715f1fb
31 changed files with 615 additions and 167 deletions

View File

@@ -458,7 +458,7 @@ namespace Nz
builder.SetViewport(renderRegion);
builder.BindRenderPipeline(*graphics->GetBlitPipeline(false));
builder.BindShaderBinding(0, *data.blitShaderBinding);
builder.BindRenderShaderBinding(0, *data.blitShaderBinding);
builder.Draw(3);
}
builder.EndDebugRegion();
@@ -652,7 +652,7 @@ namespace Nz
{
const ShaderBindingPtr& blitShaderBinding = viewerData->blitShaderBinding;
builder.BindShaderBinding(0, *blitShaderBinding);
builder.BindRenderShaderBinding(0, *blitShaderBinding);
builder.Draw(3);
if (first)

View File

@@ -112,9 +112,8 @@ namespace Nz
enabledFeatures.depthClamping = !config.forceDisableFeatures.depthClamping && renderDeviceInfo[bestRenderDeviceIndex].features.depthClamping;
enabledFeatures.nonSolidFaceFilling = !config.forceDisableFeatures.nonSolidFaceFilling && renderDeviceInfo[bestRenderDeviceIndex].features.nonSolidFaceFilling;
enabledFeatures.storageBuffers = !config.forceDisableFeatures.storageBuffers && renderDeviceInfo[bestRenderDeviceIndex].features.storageBuffers;
enabledFeatures.textureRead = !config.forceDisableFeatures.textureRead && renderDeviceInfo[bestRenderDeviceIndex].features.textureRead;
enabledFeatures.textureReadWithoutFormat = !config.forceDisableFeatures.textureReadWithoutFormat && renderDeviceInfo[bestRenderDeviceIndex].features.textureReadWithoutFormat;
enabledFeatures.textureWrite = !config.forceDisableFeatures.textureWrite && renderDeviceInfo[bestRenderDeviceIndex].features.textureWrite;
enabledFeatures.textureReadWrite = !config.forceDisableFeatures.textureReadWrite && renderDeviceInfo[bestRenderDeviceIndex].features.textureReadWrite;
enabledFeatures.textureWriteWithoutFormat = !config.forceDisableFeatures.textureWriteWithoutFormat && renderDeviceInfo[bestRenderDeviceIndex].features.textureWriteWithoutFormat;
enabledFeatures.unrestrictedTextureViews = !config.forceDisableFeatures.unrestrictedTextureViews && renderDeviceInfo[bestRenderDeviceIndex].features.unrestrictedTextureViews;

View File

@@ -316,7 +316,7 @@ namespace Nz
if (currentShaderBinding != drawData.shaderBinding)
{
commandBuffer.BindShaderBinding(0, *drawData.shaderBinding);
commandBuffer.BindRenderShaderBinding(0, *drawData.shaderBinding);
currentShaderBinding = drawData.shaderBinding;
}

View File

@@ -291,7 +291,7 @@ namespace Nz
if (currentShaderBinding != drawData.shaderBinding)
{
commandBuffer.BindShaderBinding(0, *drawData.shaderBinding);
commandBuffer.BindRenderShaderBinding(0, *drawData.shaderBinding);
currentShaderBinding = drawData.shaderBinding;
}

View File

@@ -100,11 +100,13 @@ namespace Nz
throw std::runtime_error("compute shaders are not supported on this device");
command.states.pipeline->Apply(*context);
ApplyBindings(*context, command.bindings);
context->glDispatchCompute(command.numGroupsX, command.numGroupsY, command.numGroupsZ);
}
else if constexpr (std::is_same_v<T, DrawData>)
{
ApplyStates(*context, command.states);
ApplyBindings(*context, command.bindings);
context->glDrawArraysInstanced(ToOpenGL(command.states.pipeline->GetPipelineInfo().primitiveMode), command.firstVertex, command.vertexCount, command.instanceCount);
}
else if constexpr (std::is_same_v<T, DrawIndexedData>)
@@ -120,6 +122,7 @@ namespace Nz
}
ApplyStates(*context, command.states);
ApplyBindings(*context, command.bindings);
context->glDrawElementsInstanced(ToOpenGL(command.states.pipeline->GetPipelineInfo().primitiveMode), command.indexCount, ToOpenGL(command.states.indexBufferType), origin, command.instanceCount);
}
else if constexpr (std::is_same_v<T, EndDebugRegionData>)
@@ -127,6 +130,11 @@ namespace Nz
if (context->glPopDebugGroup)
context->glPopDebugGroup();
}
else if constexpr (std::is_same_v<T, MemoryBarrier>)
{
if (context->glMemoryBarrier)
context->glMemoryBarrier(command.barriers);
}
else if constexpr (std::is_same_v<T, SetFrameBufferData>)
{
command.framebuffer->Activate();
@@ -329,10 +337,8 @@ namespace Nz
// No OpenGL object to name
}
void OpenGLCommandBuffer::ApplyStates(const GL::Context& context, const DrawStates& states)
void OpenGLCommandBuffer::ApplyBindings(const GL::Context& context, const ShaderBindings& states)
{
states.pipeline->Apply(context, states.shouldFlipY);
unsigned int setIndex = 0;
for (const auto& [pipelineLayout, shaderBinding] : states.shaderBindings)
{
@@ -343,6 +349,11 @@ namespace Nz
setIndex++;
}
}
void OpenGLCommandBuffer::ApplyStates(const GL::Context& context, const DrawStates& states)
{
states.pipeline->Apply(context, states.shouldFlipY);
if (states.scissorRegion)
context.SetScissorBox(states.scissorRegion->x, states.scissorRegion->y, states.scissorRegion->width, states.scissorRegion->height);

View File

@@ -34,6 +34,21 @@ namespace Nz
m_commandBuffer.BindComputePipeline(&glPipeline);
}
void OpenGLCommandBufferBuilder::BindComputeShaderBinding(UInt32 set, const ShaderBinding& binding)
{
const OpenGLShaderBinding& glBinding = static_cast<const OpenGLShaderBinding&>(binding);
m_commandBuffer.BindComputeShaderBinding(glBinding.GetOwner(), set, &glBinding);
}
void OpenGLCommandBufferBuilder::BindComputeShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding)
{
const OpenGLRenderPipelineLayout& glPipelineLayout = static_cast<const OpenGLRenderPipelineLayout&>(pipelineLayout);
const OpenGLShaderBinding& glBinding = static_cast<const OpenGLShaderBinding&>(binding);
m_commandBuffer.BindComputeShaderBinding(glPipelineLayout, set, &glBinding);
}
void OpenGLCommandBufferBuilder::BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset)
{
const OpenGLBuffer& glBuffer = static_cast<const OpenGLBuffer&>(indexBuffer);
@@ -48,19 +63,19 @@ namespace Nz
m_commandBuffer.BindRenderPipeline(&glPipeline);
}
void OpenGLCommandBufferBuilder::BindShaderBinding(UInt32 set, const ShaderBinding& binding)
void OpenGLCommandBufferBuilder::BindRenderShaderBinding(UInt32 set, const ShaderBinding& binding)
{
const OpenGLShaderBinding& glBinding = static_cast<const OpenGLShaderBinding&>(binding);
m_commandBuffer.BindShaderBinding(glBinding.GetOwner(), set, &glBinding);
m_commandBuffer.BindRenderShaderBinding(glBinding.GetOwner(), set, &glBinding);
}
void OpenGLCommandBufferBuilder::BindShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding)
void OpenGLCommandBufferBuilder::BindRenderShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding)
{
const OpenGLRenderPipelineLayout& glPipelineLayout = static_cast<const OpenGLRenderPipelineLayout&>(pipelineLayout);
const OpenGLShaderBinding& glBinding = static_cast<const OpenGLShaderBinding&>(binding);
m_commandBuffer.BindShaderBinding(glPipelineLayout, set, &glBinding);
m_commandBuffer.BindRenderShaderBinding(glPipelineLayout, set, &glBinding);
}
void OpenGLCommandBufferBuilder::BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset)
@@ -151,8 +166,23 @@ namespace Nz
m_commandBuffer.SetViewport(viewportRegion);
}
void OpenGLCommandBufferBuilder::TextureBarrier(PipelineStageFlags /*srcStageMask*/, PipelineStageFlags /*dstStageMask*/, MemoryAccessFlags /*srcAccessMask*/, MemoryAccessFlags /*dstAccessMask*/, TextureLayout /*oldLayout*/, TextureLayout /*newLayout*/, const Texture& /*texture*/)
void OpenGLCommandBufferBuilder::TextureBarrier(PipelineStageFlags /*srcStageMask*/, PipelineStageFlags /*dstStageMask*/, MemoryAccessFlags srcAccessMask, MemoryAccessFlags dstAccessMask, TextureLayout /*oldLayout*/, TextureLayout /*newLayout*/, const Texture& /*texture*/)
{
/* nothing to do */
if (srcAccessMask.Test(MemoryAccess::ShaderWrite))
{
GLbitfield barriers = 0;
if (dstAccessMask.Test(MemoryAccess::ColorRead))
barriers |= GL_TEXTURE_FETCH_BARRIER_BIT;
if (dstAccessMask.Test(MemoryAccess::ShaderRead))
barriers |= GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT;
if (dstAccessMask.Test(MemoryAccess::ShaderWrite))
barriers |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT;
if (barriers != 0)
m_commandBuffer.InsertMemoryBarrier(barriers);
}
}
}

View File

@@ -77,8 +77,7 @@ namespace Nz
if (m_referenceContext->IsExtensionSupported(GL::Extension::ShaderImageLoadStore))
{
m_deviceInfo.features.textureRead = true;
m_deviceInfo.features.textureWrite = true;
m_deviceInfo.features.textureReadWrite = true;
m_deviceInfo.features.textureWriteWithoutFormat = true;
}

View File

@@ -117,26 +117,22 @@ namespace Nz
auto& textureDescriptor = m_owner.GetTextureDescriptor(m_poolIndex, m_bindingIndex, binding.bindingIndex);
if (const OpenGLTexture* glTexture = static_cast<const OpenGLTexture*>(arg.texture))
{
const TextureViewInfo& viewInfo = glTexture->GetTextureViewInfo();
std::optional<GLTextureFormat> format = DescribeTextureFormat(viewInfo.reinterpretFormat);
std::optional<GLTextureFormat> format = DescribeTextureFormat(glTexture->GetFormat());
if (!format)
throw std::runtime_error("unexpected texture format");
textureDescriptor.access = ToOpenGL(arg.access);
textureDescriptor.format = format->internalFormat;
if (viewInfo.layerCount > 1)
{
textureDescriptor.layered = true;
textureDescriptor.layer = 0;
}
else
{
textureDescriptor.layered = false;
textureDescriptor.layer = viewInfo.baseArrayLayer;
}
textureDescriptor.level = viewInfo.baseMipLevel;
// Don't bother emulating texture views as their support is virtually guaranteed when compute shaders are available
if (Nz::ImageType imageType = glTexture->GetType(); imageType == ImageType::Cubemap || imageType == ImageType::E1D_Array || imageType == ImageType::E2D_Array)
textureDescriptor.layered = true;
else
textureDescriptor.layered = false;
textureDescriptor.level = 0;
textureDescriptor.layer = 0;
textureDescriptor.texture = glTexture->GetTexture().GetObjectId();
}
else

View File

@@ -117,31 +117,6 @@ namespace Nz
return std::make_shared<OpenGLTexture>(std::static_pointer_cast<OpenGLTexture>(shared_from_this()), viewInfo);
}
PixelFormat OpenGLTexture::GetFormat() const
{
return m_textureInfo.pixelFormat;
}
UInt8 OpenGLTexture::GetLevelCount() const
{
return m_textureInfo.levelCount;
}
OpenGLTexture* OpenGLTexture::GetParentTexture() const
{
return m_parentTexture.get();
}
Vector3ui OpenGLTexture::GetSize(UInt8 level) const
{
return Vector3ui(GetLevelSize(m_textureInfo.width, level), GetLevelSize(m_textureInfo.height, level), GetLevelSize(m_textureInfo.depth, level));
}
ImageType OpenGLTexture::GetType() const
{
return m_textureInfo.type;
}
bool OpenGLTexture::Update(const void* ptr, const Boxui& box, unsigned int srcWidth, unsigned int srcHeight, UInt8 level)
{
auto format = DescribeTextureFormat(m_textureInfo.pixelFormat);

View File

@@ -633,6 +633,13 @@ namespace Nz::GL
assert(maxUniformBufferUnits > 0);
m_state.uboUnits.resize(maxUniformBufferUnits);
if (IsExtensionSupported(Extension::ShaderImageLoadStore))
{
unsigned int maxImageUnits = GetInteger<unsigned int>(GL_MAX_IMAGE_UNITS);
assert(maxImageUnits > 0);
m_state.imageUnits.resize(maxImageUnits);
}
if (IsExtensionSupported(Extension::StorageBuffers))
{
unsigned int maxStorageBufferUnits = GetInteger<unsigned int>(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);

View File

@@ -82,7 +82,7 @@ namespace Nz
if (m_drawCalls.empty())
return;
builder.BindShaderBinding(0, *m_currentViewerData.binding);
builder.BindRenderShaderBinding(0, *m_currentViewerData.binding);
builder.BindRenderPipeline(*m_renderPipeline);
for (auto& drawCall : m_drawCalls)

View File

@@ -46,9 +46,8 @@ namespace Nz
NzValidateFeature(depthClamping, "depth clamping feature")
NzValidateFeature(nonSolidFaceFilling, "non-solid face filling feature")
NzValidateFeature(storageBuffers, "storage buffers support")
NzValidateFeature(textureRead, "texture read")
NzValidateFeature(textureReadWithoutFormat, "texture read without format")
NzValidateFeature(textureWrite, "texture write")
NzValidateFeature(textureReadWrite, "texture read/write")
NzValidateFeature(textureWriteWithoutFormat, "texture write without format")
NzValidateFeature(unrestrictedTextureViews, "unrestricted texture view support")

View File

@@ -58,9 +58,8 @@ namespace Nz
deviceInfo.features.depthClamping = physDevice.features.depthClamp;
deviceInfo.features.nonSolidFaceFilling = physDevice.features.fillModeNonSolid;
deviceInfo.features.storageBuffers = true;
deviceInfo.features.textureRead = true;
deviceInfo.features.textureReadWithoutFormat = physDevice.features.shaderStorageImageReadWithoutFormat;
deviceInfo.features.textureWrite = true;
deviceInfo.features.textureReadWrite = true;
deviceInfo.features.textureWriteWithoutFormat = physDevice.features.shaderStorageImageWriteWithoutFormat;
deviceInfo.features.unrestrictedTextureViews = true;

View File

@@ -80,6 +80,22 @@ namespace Nz
m_commandBuffer.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vkPipeline.GetPipeline());
}
void VulkanCommandBufferBuilder::BindComputeShaderBinding(UInt32 set, const ShaderBinding& binding)
{
const VulkanShaderBinding& vkBinding = static_cast<const VulkanShaderBinding&>(binding);
const VulkanRenderPipelineLayout& pipelineLayout = vkBinding.GetOwner();
m_commandBuffer.BindDescriptorSet(VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.GetPipelineLayout(), set, vkBinding.GetDescriptorSet());
}
void VulkanCommandBufferBuilder::BindComputeShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding)
{
const VulkanRenderPipelineLayout& vkPipelineLayout = static_cast<const VulkanRenderPipelineLayout&>(pipelineLayout);
const VulkanShaderBinding& vkBinding = static_cast<const VulkanShaderBinding&>(binding);
m_commandBuffer.BindDescriptorSet(VK_PIPELINE_BIND_POINT_COMPUTE, vkPipelineLayout.GetPipelineLayout(), set, vkBinding.GetDescriptorSet());
}
void VulkanCommandBufferBuilder::BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset)
{
const VulkanBuffer& vkBuffer = static_cast<const VulkanBuffer&>(indexBuffer);
@@ -97,7 +113,7 @@ namespace Nz
m_commandBuffer.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, vkPipeline.Get(*m_currentRenderPass, m_currentSubpassIndex));
}
void VulkanCommandBufferBuilder::BindShaderBinding(UInt32 set, const ShaderBinding& binding)
void VulkanCommandBufferBuilder::BindRenderShaderBinding(UInt32 set, const ShaderBinding& binding)
{
const VulkanShaderBinding& vkBinding = static_cast<const VulkanShaderBinding&>(binding);
const VulkanRenderPipelineLayout& pipelineLayout = vkBinding.GetOwner();
@@ -105,7 +121,7 @@ namespace Nz
m_commandBuffer.BindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.GetPipelineLayout(), set, vkBinding.GetDescriptorSet());
}
void VulkanCommandBufferBuilder::BindShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding)
void VulkanCommandBufferBuilder::BindRenderShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding)
{
const VulkanRenderPipelineLayout& vkPipelineLayout = static_cast<const VulkanRenderPipelineLayout&>(pipelineLayout);
const VulkanShaderBinding& vkBinding = static_cast<const VulkanShaderBinding&>(binding);

View File

@@ -294,31 +294,6 @@ namespace Nz
return std::make_shared<VulkanTexture>(std::static_pointer_cast<VulkanTexture>(shared_from_this()), viewInfo);
}
PixelFormat VulkanTexture::GetFormat() const
{
return m_textureInfo.pixelFormat;
}
UInt8 VulkanTexture::GetLevelCount() const
{
return m_textureInfo.levelCount;
}
VulkanTexture* VulkanTexture::GetParentTexture() const
{
return m_parentTexture.get();
}
Vector3ui VulkanTexture::GetSize(UInt8 level) const
{
return Vector3ui(GetLevelSize(m_textureInfo.width, level), GetLevelSize(m_textureInfo.height, level), GetLevelSize(m_textureInfo.depth, level));
}
ImageType VulkanTexture::GetType() const
{
return m_textureInfo.type;
}
bool VulkanTexture::Update(const void* ptr, const Boxui& box, unsigned int srcWidth, unsigned int srcHeight, UInt8 level)
{
std::size_t textureSize = box.width * box.height * box.depth * PixelFormatInfo::GetBytesPerPixel(m_textureInfo.pixelFormat);