Add initial support for compute pipelines
This commit is contained in:
parent
e4064997d8
commit
9578ba3ef5
|
|
@ -151,7 +151,7 @@ int main()
|
||||||
textureBinding.setIndex = 0;
|
textureBinding.setIndex = 0;
|
||||||
textureBinding.bindingIndex = 1;
|
textureBinding.bindingIndex = 1;
|
||||||
textureBinding.shaderStageFlags = nzsl::ShaderStageType::Fragment;
|
textureBinding.shaderStageFlags = nzsl::ShaderStageType::Fragment;
|
||||||
textureBinding.type = Nz::ShaderBindingType::Texture;
|
textureBinding.type = Nz::ShaderBindingType::Sampler;
|
||||||
|
|
||||||
std::shared_ptr<Nz::RenderPipelineLayout> skyboxPipelineLayout = device->InstantiateRenderPipelineLayout(std::move(skyboxPipelineLayoutInfo));
|
std::shared_ptr<Nz::RenderPipelineLayout> skyboxPipelineLayout = device->InstantiateRenderPipelineLayout(std::move(skyboxPipelineLayoutInfo));
|
||||||
|
|
||||||
|
|
@ -275,7 +275,7 @@ int main()
|
||||||
0,
|
0,
|
||||||
i + 1,
|
i + 1,
|
||||||
1,
|
1,
|
||||||
Nz::ShaderBindingType::Texture,
|
Nz::ShaderBindingType::Sampler,
|
||||||
nzsl::ShaderStageType::Fragment,
|
nzsl::ShaderStageType::Fragment,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -367,7 +367,7 @@ int main()
|
||||||
|
|
||||||
fullscreenPipelineLayoutInfoViewer.bindings.push_back({
|
fullscreenPipelineLayoutInfoViewer.bindings.push_back({
|
||||||
0, 1, 1,
|
0, 1, 1,
|
||||||
Nz::ShaderBindingType::Texture,
|
Nz::ShaderBindingType::Sampler,
|
||||||
nzsl::ShaderStageType::Fragment,
|
nzsl::ShaderStageType::Fragment,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -452,7 +452,7 @@ int main()
|
||||||
|
|
||||||
bloomBlendPipelineLayoutInfo.bindings.push_back({
|
bloomBlendPipelineLayoutInfo.bindings.push_back({
|
||||||
0, 2, 1,
|
0, 2, 1,
|
||||||
Nz::ShaderBindingType::Texture,
|
Nz::ShaderBindingType::Sampler,
|
||||||
nzsl::ShaderStageType::Fragment,
|
nzsl::ShaderStageType::Fragment,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -476,7 +476,7 @@ int main()
|
||||||
|
|
||||||
fullscreenPipelineLayoutInfo.bindings.push_back({
|
fullscreenPipelineLayoutInfo.bindings.push_back({
|
||||||
0, 0, 1,
|
0, 0, 1,
|
||||||
Nz::ShaderBindingType::Texture,
|
Nz::ShaderBindingType::Sampler,
|
||||||
nzsl::ShaderStageType::Fragment,
|
nzsl::ShaderStageType::Fragment,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -504,7 +504,7 @@ int main()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
0, 2, 1,
|
0, 2, 1,
|
||||||
Nz::ShaderBindingType::Texture,
|
Nz::ShaderBindingType::Sampler,
|
||||||
nzsl::ShaderStageType::Fragment,
|
nzsl::ShaderStageType::Fragment,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -613,7 +613,7 @@ int main()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
1,
|
1,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::SampledTextureBinding {
|
||||||
skyboxTexture.get(),
|
skyboxTexture.get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
|
|
@ -837,10 +837,10 @@ int main()
|
||||||
{
|
{
|
||||||
builder.BindShaderBinding(1, *lightingShaderBindings[i]);
|
builder.BindShaderBinding(1, *lightingShaderBindings[i]);
|
||||||
|
|
||||||
builder.BindPipeline(*stencilPipeline);
|
builder.BindRenderPipeline(*stencilPipeline);
|
||||||
builder.DrawIndexed(coneMeshGfx->GetIndexCount(0));
|
builder.DrawIndexed(coneMeshGfx->GetIndexCount(0));
|
||||||
|
|
||||||
builder.BindPipeline(*lightingPipeline);
|
builder.BindRenderPipeline(*lightingPipeline);
|
||||||
builder.DrawIndexed(coneMeshGfx->GetIndexCount(0));
|
builder.DrawIndexed(coneMeshGfx->GetIndexCount(0));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -862,7 +862,7 @@ int main()
|
||||||
|
|
||||||
builder.BindIndexBuffer(*cubeMeshGfx->GetIndexBuffer(0), Nz::IndexType::U16);
|
builder.BindIndexBuffer(*cubeMeshGfx->GetIndexBuffer(0), Nz::IndexType::U16);
|
||||||
builder.BindVertexBuffer(0, *cubeMeshGfx->GetVertexBuffer(0));
|
builder.BindVertexBuffer(0, *cubeMeshGfx->GetVertexBuffer(0));
|
||||||
builder.BindPipeline(*skyboxPipeline);
|
builder.BindRenderPipeline(*skyboxPipeline);
|
||||||
|
|
||||||
builder.DrawIndexed(Nz::SafeCast<Nz::UInt32>(cubeMeshGfx->GetIndexCount(0)));
|
builder.DrawIndexed(Nz::SafeCast<Nz::UInt32>(cubeMeshGfx->GetIndexCount(0)));
|
||||||
|
|
||||||
|
|
@ -932,7 +932,7 @@ int main()
|
||||||
|
|
||||||
builder.BindShaderBinding(0, *godRaysShaderBinding);
|
builder.BindShaderBinding(0, *godRaysShaderBinding);
|
||||||
|
|
||||||
builder.BindPipeline(*godraysPipeline);
|
builder.BindRenderPipeline(*godraysPipeline);
|
||||||
|
|
||||||
builder.Draw(3);
|
builder.Draw(3);
|
||||||
});
|
});
|
||||||
|
|
@ -948,7 +948,7 @@ int main()
|
||||||
|
|
||||||
builder.BindShaderBinding(0, *bloomBrightShaderBinding);
|
builder.BindShaderBinding(0, *bloomBrightShaderBinding);
|
||||||
|
|
||||||
builder.BindPipeline(*bloomBrightPipeline);
|
builder.BindRenderPipeline(*bloomBrightPipeline);
|
||||||
|
|
||||||
builder.Draw(3);
|
builder.Draw(3);
|
||||||
});
|
});
|
||||||
|
|
@ -970,7 +970,7 @@ int main()
|
||||||
builder.SetViewport(env.renderRect);
|
builder.SetViewport(env.renderRect);
|
||||||
|
|
||||||
builder.BindShaderBinding(0, *gaussianBlurShaderBinding[i * 2 + 0]);
|
builder.BindShaderBinding(0, *gaussianBlurShaderBinding[i * 2 + 0]);
|
||||||
builder.BindPipeline(*gaussianBlurPipeline);
|
builder.BindRenderPipeline(*gaussianBlurPipeline);
|
||||||
|
|
||||||
builder.Draw(3);
|
builder.Draw(3);
|
||||||
});
|
});
|
||||||
|
|
@ -990,7 +990,7 @@ int main()
|
||||||
builder.SetViewport(env.renderRect);
|
builder.SetViewport(env.renderRect);
|
||||||
|
|
||||||
builder.BindShaderBinding(0, *gaussianBlurShaderBinding[i * 2 + 1]);
|
builder.BindShaderBinding(0, *gaussianBlurShaderBinding[i * 2 + 1]);
|
||||||
builder.BindPipeline(*gaussianBlurPipeline);
|
builder.BindRenderPipeline(*gaussianBlurPipeline);
|
||||||
|
|
||||||
builder.Draw(3);
|
builder.Draw(3);
|
||||||
});
|
});
|
||||||
|
|
@ -1011,7 +1011,7 @@ int main()
|
||||||
builder.SetViewport(env.renderRect);
|
builder.SetViewport(env.renderRect);
|
||||||
|
|
||||||
// Blend bloom
|
// Blend bloom
|
||||||
builder.BindPipeline(*bloomBlendPipeline);
|
builder.BindRenderPipeline(*bloomBlendPipeline);
|
||||||
for (std::size_t i = 0; i < BloomSubdivisionCount; ++i)
|
for (std::size_t i = 0; i < BloomSubdivisionCount; ++i)
|
||||||
{
|
{
|
||||||
builder.BindShaderBinding(0, *bloomBlendShaderBinding[i]);
|
builder.BindShaderBinding(0, *bloomBlendShaderBinding[i]);
|
||||||
|
|
@ -1046,7 +1046,7 @@ int main()
|
||||||
builder.SetViewport(env.renderRect);
|
builder.SetViewport(env.renderRect);
|
||||||
|
|
||||||
builder.BindShaderBinding(0, *toneMappingShaderBinding);
|
builder.BindShaderBinding(0, *toneMappingShaderBinding);
|
||||||
builder.BindPipeline(*toneMappingPipeline);
|
builder.BindRenderPipeline(*toneMappingPipeline);
|
||||||
|
|
||||||
builder.Draw(3);
|
builder.Draw(3);
|
||||||
});
|
});
|
||||||
|
|
@ -1218,21 +1218,21 @@ int main()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
1,
|
1,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::SampledTextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(colorTexture).get(),
|
bakedGraph.GetAttachmentTexture(colorTexture).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
2,
|
2,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::SampledTextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(normalTexture).get(),
|
bakedGraph.GetAttachmentTexture(normalTexture).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
3,
|
3,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::SampledTextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(positionTexture).get(),
|
bakedGraph.GetAttachmentTexture(positionTexture).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
|
|
@ -1271,7 +1271,7 @@ int main()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
1,
|
1,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::SampledTextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(lightOutput).get(),
|
bakedGraph.GetAttachmentTexture(lightOutput).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
|
|
@ -1296,7 +1296,7 @@ int main()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
1,
|
1,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::SampledTextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture((i == 0 && j == 0) ? bloomBrightOutput : bloomTextures[bloomTextureIndex++]).get(),
|
bakedGraph.GetAttachmentTexture((i == 0 && j == 0) ? bloomBrightOutput : bloomTextures[bloomTextureIndex++]).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
|
|
@ -1331,7 +1331,7 @@ int main()
|
||||||
},*/
|
},*/
|
||||||
{
|
{
|
||||||
2,
|
2,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::SampledTextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(bloomTextures[i * 2 + 1]).get(),
|
bakedGraph.GetAttachmentTexture(bloomTextures[i * 2 + 1]).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
|
|
@ -1345,7 +1345,7 @@ int main()
|
||||||
bloomBlitBinding->Update({
|
bloomBlitBinding->Update({
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::SampledTextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(lightOutput).get(),
|
bakedGraph.GetAttachmentTexture(lightOutput).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
|
|
@ -1358,7 +1358,7 @@ int main()
|
||||||
bloomSkipBlit->Update({
|
bloomSkipBlit->Update({
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::SampledTextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(lightOutput).get(),
|
bakedGraph.GetAttachmentTexture(lightOutput).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
|
|
@ -1385,7 +1385,7 @@ int main()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
2,
|
2,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::SampledTextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(occluderTexture).get(),
|
bakedGraph.GetAttachmentTexture(occluderTexture).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
|
|
@ -1405,7 +1405,7 @@ int main()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
1,
|
1,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::SampledTextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(bloomOutput).get(),
|
bakedGraph.GetAttachmentTexture(bloomOutput).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
|
|
@ -1432,7 +1432,7 @@ int main()
|
||||||
},*/
|
},*/
|
||||||
{
|
{
|
||||||
2,
|
2,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::SampledTextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(godRaysTexture).get(),
|
bakedGraph.GetAttachmentTexture(godRaysTexture).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
|
|
@ -1445,7 +1445,7 @@ int main()
|
||||||
finalBlitBinding->Update({
|
finalBlitBinding->Update({
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
Nz::ShaderBinding::TextureBinding {
|
Nz::ShaderBinding::SampledTextureBinding {
|
||||||
bakedGraph.GetAttachmentTexture(toneMappingOutput).get(),
|
bakedGraph.GetAttachmentTexture(toneMappingOutput).get(),
|
||||||
textureSampler.get()
|
textureSampler.get()
|
||||||
}
|
}
|
||||||
|
|
@ -1548,7 +1548,7 @@ int main()
|
||||||
builder.SetViewport(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) });
|
builder.SetViewport(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) });
|
||||||
|
|
||||||
builder.BindShaderBinding(0, *finalBlitBinding);
|
builder.BindShaderBinding(0, *finalBlitBinding);
|
||||||
builder.BindPipeline(*fullscreenPipeline);
|
builder.BindRenderPipeline(*fullscreenPipeline);
|
||||||
|
|
||||||
builder.Draw(3);
|
builder.Draw(3);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ int main()
|
||||||
pipelineTextureBinding.setIndex = 1;
|
pipelineTextureBinding.setIndex = 1;
|
||||||
pipelineTextureBinding.bindingIndex = 0;
|
pipelineTextureBinding.bindingIndex = 0;
|
||||||
pipelineTextureBinding.shaderStageFlags = nzsl::ShaderStageType::Fragment;
|
pipelineTextureBinding.shaderStageFlags = nzsl::ShaderStageType::Fragment;
|
||||||
pipelineTextureBinding.type = Nz::ShaderBindingType::Texture;
|
pipelineTextureBinding.type = Nz::ShaderBindingType::Sampler;
|
||||||
|
|
||||||
std::shared_ptr<Nz::RenderPipelineLayout> renderPipelineLayout = device->InstantiateRenderPipelineLayout(std::move(pipelineLayoutInfo));
|
std::shared_ptr<Nz::RenderPipelineLayout> renderPipelineLayout = device->InstantiateRenderPipelineLayout(std::move(pipelineLayoutInfo));
|
||||||
|
|
||||||
|
|
@ -218,14 +218,14 @@ int main()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Nz::ShaderBinding::TextureBinding textureBinding {
|
Nz::ShaderBinding::SampledTextureBinding textureBinding {
|
||||||
texture.get(), textureSampler.get()
|
texture.get(), textureSampler.get()
|
||||||
};
|
};
|
||||||
|
|
||||||
textureShaderBinding->Update({
|
textureShaderBinding->Update({
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
Nz::ShaderBinding::TextureBindings {
|
Nz::ShaderBinding::SampledTextureBindings {
|
||||||
1, &textureBinding
|
1, &textureBinding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -389,7 +389,7 @@ int main()
|
||||||
builder.BeginRenderPass(windowRT->GetFramebuffer(frame.GetFramebufferIndex()), windowRT->GetRenderPass(), renderRect, { clearValues[0], clearValues[1] });
|
builder.BeginRenderPass(windowRT->GetFramebuffer(frame.GetFramebufferIndex()), windowRT->GetRenderPass(), renderRect, { clearValues[0], clearValues[1] });
|
||||||
{
|
{
|
||||||
builder.BindIndexBuffer(*renderBufferIB, Nz::IndexType::U16);
|
builder.BindIndexBuffer(*renderBufferIB, Nz::IndexType::U16);
|
||||||
builder.BindPipeline(*pipeline);
|
builder.BindRenderPipeline(*pipeline);
|
||||||
builder.BindVertexBuffer(0, *renderBufferVB);
|
builder.BindVertexBuffer(0, *renderBufferVB);
|
||||||
builder.BindShaderBinding(0, *viewerShaderBinding);
|
builder.BindShaderBinding(0, *viewerShaderBinding);
|
||||||
builder.BindShaderBinding(1, *textureShaderBinding);
|
builder.BindShaderBinding(1, *textureShaderBinding);
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,13 @@ namespace Nz
|
||||||
UInt32 bindingIndex;
|
UInt32 bindingIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ExternalSampler : ExternalData
|
||||||
|
{
|
||||||
|
UInt32 arraySize;
|
||||||
|
nzsl::ImageType imageType;
|
||||||
|
nzsl::Ast::PrimitiveType sampledType;
|
||||||
|
};
|
||||||
|
|
||||||
struct ExternalStorageBlock : ExternalData
|
struct ExternalStorageBlock : ExternalData
|
||||||
{
|
{
|
||||||
std::size_t structIndex;
|
std::size_t structIndex;
|
||||||
|
|
@ -53,8 +60,10 @@ namespace Nz
|
||||||
struct ExternalTexture : ExternalData
|
struct ExternalTexture : ExternalData
|
||||||
{
|
{
|
||||||
UInt32 arraySize;
|
UInt32 arraySize;
|
||||||
|
nzsl::AccessPolicy accessPolicy;
|
||||||
|
nzsl::ImageFormat imageFormat;
|
||||||
nzsl::ImageType imageType;
|
nzsl::ImageType imageType;
|
||||||
nzsl::Ast::PrimitiveType sampledType;
|
nzsl::Ast::PrimitiveType baseType;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExternalUniformBlock : ExternalData
|
struct ExternalUniformBlock : ExternalData
|
||||||
|
|
@ -64,8 +73,9 @@ namespace Nz
|
||||||
|
|
||||||
struct ExternalBlockData
|
struct ExternalBlockData
|
||||||
{
|
{
|
||||||
|
std::unordered_map<std::string /*tag*/, ExternalSampler> samplers;
|
||||||
std::unordered_map<std::string /*tag*/, ExternalStorageBlock> storageBlocks;
|
std::unordered_map<std::string /*tag*/, ExternalStorageBlock> storageBlocks;
|
||||||
std::unordered_map<std::string /*tag*/, ExternalTexture> samplers;
|
std::unordered_map<std::string /*tag*/, ExternalTexture> textures;
|
||||||
std::unordered_map<std::string /*tag*/, ExternalUniformBlock> uniformBlocks;
|
std::unordered_map<std::string /*tag*/, ExternalUniformBlock> uniformBlocks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace Nz
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<ShaderBinding::Binding> m_bindingCache;
|
std::vector<ShaderBinding::Binding> m_bindingCache;
|
||||||
std::vector<ShaderBinding::TextureBinding> m_textureBindingCache;
|
std::vector<ShaderBinding::SampledTextureBinding> m_textureBindingCache;
|
||||||
RenderElementPool<RenderSubmesh> m_submeshPool;
|
RenderElementPool<RenderSubmesh> m_submeshPool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@
|
||||||
#include <Nazara/Core/Color.hpp>
|
#include <Nazara/Core/Color.hpp>
|
||||||
#include <Nazara/Graphics/Config.hpp>
|
#include <Nazara/Graphics/Config.hpp>
|
||||||
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
||||||
#include <Nazara/Utils/Bitset.hpp>
|
|
||||||
#include <Nazara/Utility/VertexStruct.hpp>
|
#include <Nazara/Utility/VertexStruct.hpp>
|
||||||
|
#include <Nazara/Utils/Bitset.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
class OpenGLCommandPool;
|
class OpenGLCommandPool;
|
||||||
|
class OpenGLComputePipeline;
|
||||||
class OpenGLFramebuffer;
|
class OpenGLFramebuffer;
|
||||||
class OpenGLRenderPass;
|
class OpenGLRenderPass;
|
||||||
class OpenGLTexture;
|
class OpenGLTexture;
|
||||||
|
|
@ -38,8 +39,9 @@ namespace Nz
|
||||||
|
|
||||||
inline void BeginDebugRegion(const std::string_view& regionName, const Color& color);
|
inline void BeginDebugRegion(const std::string_view& regionName, const Color& color);
|
||||||
|
|
||||||
|
inline void BindComputePipeline(const OpenGLComputePipeline* pipeline);
|
||||||
inline void BindIndexBuffer(GLuint indexBuffer, IndexType indexType, UInt64 offset = 0);
|
inline void BindIndexBuffer(GLuint indexBuffer, IndexType indexType, UInt64 offset = 0);
|
||||||
inline void BindPipeline(const OpenGLRenderPipeline* pipeline);
|
inline void BindRenderPipeline(const OpenGLRenderPipeline* pipeline);
|
||||||
inline void BindShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding);
|
inline void BindShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding);
|
||||||
inline void BindVertexBuffer(UInt32 binding, GLuint vertexBuffer, UInt64 offset = 0);
|
inline void BindVertexBuffer(UInt32 binding, GLuint vertexBuffer, UInt64 offset = 0);
|
||||||
inline void BlitTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Boxui& targetBox, SamplerFilter filter = SamplerFilter::Nearest);
|
inline void BlitTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Boxui& targetBox, SamplerFilter filter = SamplerFilter::Nearest);
|
||||||
|
|
@ -48,6 +50,8 @@ namespace Nz
|
||||||
inline void CopyBuffer(const UploadPool::Allocation& allocation, GLuint target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0);
|
inline void CopyBuffer(const UploadPool::Allocation& allocation, GLuint target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0);
|
||||||
inline void CopyTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Vector3ui& targetPoint);
|
inline void CopyTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Vector3ui& targetPoint);
|
||||||
|
|
||||||
|
inline void Dispatch(UInt32 numGroupsX, UInt32 numGroupsY, UInt32 numGroupsZ);
|
||||||
|
|
||||||
inline void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0);
|
inline void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0);
|
||||||
inline void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstIndex = 0, UInt32 firstInstance = 0);
|
inline void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstIndex = 0, UInt32 firstInstance = 0);
|
||||||
|
|
||||||
|
|
@ -89,6 +93,11 @@ namespace Nz
|
||||||
SamplerFilter filter;
|
SamplerFilter filter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ComputeStates
|
||||||
|
{
|
||||||
|
const OpenGLComputePipeline* pipeline = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
struct CopyBufferData
|
struct CopyBufferData
|
||||||
{
|
{
|
||||||
GLuint source;
|
GLuint source;
|
||||||
|
|
@ -114,6 +123,14 @@ namespace Nz
|
||||||
UInt64 targetOffset;
|
UInt64 targetOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DispatchData
|
||||||
|
{
|
||||||
|
ComputeStates states;
|
||||||
|
UInt32 numGroupsX;
|
||||||
|
UInt32 numGroupsY;
|
||||||
|
UInt32 numGroupsZ;
|
||||||
|
};
|
||||||
|
|
||||||
struct DrawStates
|
struct DrawStates
|
||||||
{
|
{
|
||||||
struct VertexBuffer
|
struct VertexBuffer
|
||||||
|
|
@ -168,13 +185,15 @@ namespace Nz
|
||||||
CopyBufferData,
|
CopyBufferData,
|
||||||
CopyBufferFromMemoryData,
|
CopyBufferFromMemoryData,
|
||||||
CopyTextureData,
|
CopyTextureData,
|
||||||
|
DispatchData,
|
||||||
DrawData,
|
DrawData,
|
||||||
DrawIndexedData,
|
DrawIndexedData,
|
||||||
EndDebugRegionData,
|
EndDebugRegionData,
|
||||||
SetFrameBufferData
|
SetFrameBufferData
|
||||||
>;
|
>;
|
||||||
|
|
||||||
DrawStates m_currentStates;
|
ComputeStates m_currentComputeStates;
|
||||||
|
DrawStates m_currentDrawStates;
|
||||||
std::size_t m_bindingIndex;
|
std::size_t m_bindingIndex;
|
||||||
std::size_t m_maxColorBufferCount;
|
std::size_t m_maxColorBufferCount;
|
||||||
std::size_t m_poolIndex;
|
std::size_t m_poolIndex;
|
||||||
|
|
|
||||||
|
|
@ -33,32 +33,37 @@ namespace Nz
|
||||||
m_commands.emplace_back(std::move(beginDebugRegion));
|
m_commands.emplace_back(std::move(beginDebugRegion));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::BindIndexBuffer(GLuint indexBuffer, IndexType indexType, UInt64 offset)
|
inline void OpenGLCommandBuffer::BindComputePipeline(const OpenGLComputePipeline* pipeline)
|
||||||
{
|
{
|
||||||
m_currentStates.indexBuffer = indexBuffer;
|
m_currentComputeStates.pipeline = pipeline;
|
||||||
m_currentStates.indexBufferOffset = offset;
|
|
||||||
m_currentStates.indexBufferType = indexType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::BindPipeline(const OpenGLRenderPipeline* pipeline)
|
inline void OpenGLCommandBuffer::BindIndexBuffer(GLuint indexBuffer, IndexType indexType, UInt64 offset)
|
||||||
{
|
{
|
||||||
m_currentStates.pipeline = pipeline;
|
m_currentDrawStates.indexBuffer = indexBuffer;
|
||||||
|
m_currentDrawStates.indexBufferOffset = offset;
|
||||||
|
m_currentDrawStates.indexBufferType = indexType;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OpenGLCommandBuffer::BindRenderPipeline(const OpenGLRenderPipeline* pipeline)
|
||||||
|
{
|
||||||
|
m_currentDrawStates.pipeline = pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::BindShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding)
|
inline void OpenGLCommandBuffer::BindShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding)
|
||||||
{
|
{
|
||||||
if (set >= m_currentStates.shaderBindings.size())
|
if (set >= m_currentDrawStates.shaderBindings.size())
|
||||||
m_currentStates.shaderBindings.resize(set + 1);
|
m_currentDrawStates.shaderBindings.resize(set + 1);
|
||||||
|
|
||||||
m_currentStates.shaderBindings[set] = std::make_pair(&pipelineLayout, binding);
|
m_currentDrawStates.shaderBindings[set] = std::make_pair(&pipelineLayout, binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::BindVertexBuffer(UInt32 binding, GLuint vertexBuffer, UInt64 offset)
|
inline void OpenGLCommandBuffer::BindVertexBuffer(UInt32 binding, GLuint vertexBuffer, UInt64 offset)
|
||||||
{
|
{
|
||||||
if (binding >= m_currentStates.vertexBuffers.size())
|
if (binding >= m_currentDrawStates.vertexBuffers.size())
|
||||||
m_currentStates.vertexBuffers.resize(binding + 1);
|
m_currentDrawStates.vertexBuffers.resize(binding + 1);
|
||||||
|
|
||||||
auto& vertexBufferData = m_currentStates.vertexBuffers[binding];
|
auto& vertexBufferData = m_currentDrawStates.vertexBuffers[binding];
|
||||||
vertexBufferData.offset = offset;
|
vertexBufferData.offset = offset;
|
||||||
vertexBufferData.vertexBuffer = vertexBuffer;
|
vertexBufferData.vertexBuffer = vertexBuffer;
|
||||||
}
|
}
|
||||||
|
|
@ -113,13 +118,27 @@ namespace Nz
|
||||||
m_commands.emplace_back(std::move(copyTexture));
|
m_commands.emplace_back(std::move(copyTexture));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void OpenGLCommandBuffer::Dispatch(UInt32 numGroupsX, UInt32 numGroupsY, UInt32 numGroupsZ)
|
||||||
|
{
|
||||||
|
if (!m_currentComputeStates.pipeline)
|
||||||
|
throw std::runtime_error("no pipeline bound");
|
||||||
|
|
||||||
|
DispatchData dispatch;
|
||||||
|
dispatch.states = m_currentComputeStates;
|
||||||
|
dispatch.numGroupsX = numGroupsX;
|
||||||
|
dispatch.numGroupsY = numGroupsY;
|
||||||
|
dispatch.numGroupsZ = numGroupsZ;
|
||||||
|
|
||||||
|
m_commands.emplace_back(std::move(dispatch));
|
||||||
|
}
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance)
|
inline void OpenGLCommandBuffer::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance)
|
||||||
{
|
{
|
||||||
if (!m_currentStates.pipeline)
|
if (!m_currentDrawStates.pipeline)
|
||||||
throw std::runtime_error("no pipeline bound");
|
throw std::runtime_error("no pipeline bound");
|
||||||
|
|
||||||
DrawData draw;
|
DrawData draw;
|
||||||
draw.states = m_currentStates;
|
draw.states = m_currentDrawStates;
|
||||||
draw.firstInstance = firstInstance;
|
draw.firstInstance = firstInstance;
|
||||||
draw.firstVertex = firstVertex;
|
draw.firstVertex = firstVertex;
|
||||||
draw.instanceCount = instanceCount;
|
draw.instanceCount = instanceCount;
|
||||||
|
|
@ -130,11 +149,11 @@ namespace Nz
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::DrawIndexed(UInt32 indexCount, UInt32 instanceCount, UInt32 firstIndex, UInt32 firstInstance)
|
inline void OpenGLCommandBuffer::DrawIndexed(UInt32 indexCount, UInt32 instanceCount, UInt32 firstIndex, UInt32 firstInstance)
|
||||||
{
|
{
|
||||||
if (!m_currentStates.pipeline)
|
if (!m_currentDrawStates.pipeline)
|
||||||
throw std::runtime_error("no pipeline bound");
|
throw std::runtime_error("no pipeline bound");
|
||||||
|
|
||||||
DrawIndexedData draw;
|
DrawIndexedData draw;
|
||||||
draw.states = m_currentStates;
|
draw.states = m_currentDrawStates;
|
||||||
draw.firstIndex = firstIndex;
|
draw.firstIndex = firstIndex;
|
||||||
draw.firstInstance = firstInstance;
|
draw.firstInstance = firstInstance;
|
||||||
draw.indexCount = indexCount;
|
draw.indexCount = indexCount;
|
||||||
|
|
@ -177,17 +196,17 @@ namespace Nz
|
||||||
|
|
||||||
m_commands.emplace_back(std::move(setFramebuffer));
|
m_commands.emplace_back(std::move(setFramebuffer));
|
||||||
|
|
||||||
m_currentStates.shouldFlipY = (framebuffer.GetType() == FramebufferType::Window);
|
m_currentDrawStates.shouldFlipY = (framebuffer.GetType() == FramebufferType::Window);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::SetScissor(const Recti& scissorRegion)
|
inline void OpenGLCommandBuffer::SetScissor(const Recti& scissorRegion)
|
||||||
{
|
{
|
||||||
m_currentStates.scissorRegion = scissorRegion;
|
m_currentDrawStates.scissorRegion = scissorRegion;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::SetViewport(const Recti& viewportRegion)
|
inline void OpenGLCommandBuffer::SetViewport(const Recti& viewportRegion)
|
||||||
{
|
{
|
||||||
m_currentStates.viewportRegion = viewportRegion;
|
m_currentDrawStates.viewportRegion = viewportRegion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,9 @@ namespace Nz
|
||||||
void BeginDebugRegion(const std::string_view& regionName, const Color& color) override;
|
void BeginDebugRegion(const std::string_view& regionName, const Color& color) override;
|
||||||
void BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, const Recti& renderRect, const ClearValues* clearValues, std::size_t clearValueCount) override;
|
void BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, const Recti& renderRect, const ClearValues* clearValues, std::size_t clearValueCount) override;
|
||||||
|
|
||||||
|
void BindComputePipeline(const ComputePipeline& pipeline) override;
|
||||||
void BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset = 0) override;
|
void BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset = 0) override;
|
||||||
void BindPipeline(const RenderPipeline& pipeline) override;
|
void BindRenderPipeline(const RenderPipeline& pipeline) override;
|
||||||
void BindShaderBinding(UInt32 set, const ShaderBinding& binding) override;
|
void BindShaderBinding(UInt32 set, const ShaderBinding& binding) override;
|
||||||
void BindShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) override;
|
void BindShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) override;
|
||||||
void BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset = 0) override;
|
void BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset = 0) override;
|
||||||
|
|
@ -39,6 +40,8 @@ namespace Nz
|
||||||
void CopyBuffer(const UploadPool::Allocation& allocation, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
|
void CopyBuffer(const UploadPool::Allocation& allocation, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
|
||||||
void CopyTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Vector3ui& toPos, TextureLayout toLayout) override;
|
void CopyTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Vector3ui& toPos, TextureLayout toLayout) override;
|
||||||
|
|
||||||
|
void Dispatch(UInt32 workgroupX, UInt32 workgroupY, UInt32 workgroupZ) override;
|
||||||
|
|
||||||
void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0) override;
|
void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0) override;
|
||||||
void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstIndex = 0, UInt32 firstInstance = 0) override;
|
void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstIndex = 0, UInt32 firstInstance = 0) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - OpenGL renderer"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_OPENGLRENDERER_OPENGLCOMPUTEPIPELINE_HPP
|
||||||
|
#define NAZARA_OPENGLRENDERER_OPENGLCOMPUTEPIPELINE_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/OpenGLRenderer/Config.hpp>
|
||||||
|
#include <Nazara/OpenGLRenderer/Wrapper/Program.hpp>
|
||||||
|
#include <Nazara/Renderer/ComputePipeline.hpp>
|
||||||
|
#include <Nazara/Utils/MovablePtr.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class NAZARA_OPENGLRENDERER_API OpenGLComputePipeline : public ComputePipeline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpenGLComputePipeline(OpenGLDevice& device, ComputePipelineInfo pipelineInfo);
|
||||||
|
~OpenGLComputePipeline() = default;
|
||||||
|
|
||||||
|
void Apply(const GL::Context& context) const;
|
||||||
|
|
||||||
|
inline const ComputePipelineInfo& GetPipelineInfo() const override;
|
||||||
|
|
||||||
|
void UpdateDebugName(std::string_view name) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ComputePipelineInfo m_pipelineInfo;
|
||||||
|
GL::Program m_program;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/OpenGLRenderer/OpenGLComputePipeline.inl>
|
||||||
|
|
||||||
|
#endif // NAZARA_OPENGLRENDERER_OPENGLCOMPUTEPIPELINE_HPP
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - OpenGL renderer"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/OpenGLRenderer/OpenGLComputePipeline.hpp>
|
||||||
|
#include <Nazara/OpenGLRenderer/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
inline const ComputePipelineInfo& OpenGLComputePipeline::GetPipelineInfo() const
|
||||||
|
{
|
||||||
|
return m_pipelineInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/OpenGLRenderer/DebugOff.hpp>
|
||||||
|
|
@ -38,6 +38,7 @@ namespace Nz
|
||||||
|
|
||||||
std::shared_ptr<RenderBuffer> InstantiateBuffer(BufferType type, UInt64 size, BufferUsageFlags usageFlags, const void* initialData = nullptr) override;
|
std::shared_ptr<RenderBuffer> InstantiateBuffer(BufferType type, UInt64 size, BufferUsageFlags usageFlags, const void* initialData = nullptr) override;
|
||||||
std::shared_ptr<CommandPool> InstantiateCommandPool(QueueType queueType) override;
|
std::shared_ptr<CommandPool> InstantiateCommandPool(QueueType queueType) override;
|
||||||
|
std::shared_ptr<ComputePipeline> InstantiateComputePipeline(ComputePipelineInfo pipelineInfo) override;
|
||||||
std::shared_ptr<Framebuffer> InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr<RenderPass>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments) override;
|
std::shared_ptr<Framebuffer> InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr<RenderPass>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments) override;
|
||||||
std::shared_ptr<RenderPass> InstantiateRenderPass(std::vector<RenderPass::Attachment> attachments, std::vector<RenderPass::SubpassDescription> subpassDescriptions, std::vector<RenderPass::SubpassDependency> subpassDependencies) override;
|
std::shared_ptr<RenderPass> InstantiateRenderPass(std::vector<RenderPass::Attachment> attachments, std::vector<RenderPass::SubpassDescription> subpassDescriptions, std::vector<RenderPass::SubpassDependency> subpassDependencies) override;
|
||||||
std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override;
|
std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override;
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ namespace Nz
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct DescriptorPool;
|
struct DescriptorPool;
|
||||||
|
struct SampledTextureDescriptor;
|
||||||
struct StorageBufferDescriptor;
|
struct StorageBufferDescriptor;
|
||||||
struct TextureDescriptor;
|
struct TextureDescriptor;
|
||||||
struct UniformBufferDescriptor;
|
struct UniformBufferDescriptor;
|
||||||
|
|
@ -50,12 +51,20 @@ namespace Nz
|
||||||
DescriptorPool& AllocatePool();
|
DescriptorPool& AllocatePool();
|
||||||
ShaderBindingPtr AllocateFromPool(std::size_t poolIndex, UInt32 setIndex);
|
ShaderBindingPtr AllocateFromPool(std::size_t poolIndex, UInt32 setIndex);
|
||||||
template<typename F> void ForEachDescriptor(std::size_t poolIndex, std::size_t bindingIndex, F&& functor);
|
template<typename F> void ForEachDescriptor(std::size_t poolIndex, std::size_t bindingIndex, F&& functor);
|
||||||
|
SampledTextureDescriptor& GetSampledTextureDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t descriptorIndex);
|
||||||
StorageBufferDescriptor& GetStorageBufferDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t descriptorIndex);
|
StorageBufferDescriptor& GetStorageBufferDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t descriptorIndex);
|
||||||
TextureDescriptor& GetTextureDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t descriptorIndex);
|
TextureDescriptor& GetTextureDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t descriptorIndex);
|
||||||
UniformBufferDescriptor& GetUniformBufferDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t descriptorIndex);
|
UniformBufferDescriptor& GetUniformBufferDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t descriptorIndex);
|
||||||
void Release(ShaderBinding& binding);
|
void Release(ShaderBinding& binding);
|
||||||
inline void TryToShrink();
|
inline void TryToShrink();
|
||||||
|
|
||||||
|
struct SampledTextureDescriptor
|
||||||
|
{
|
||||||
|
GLuint texture;
|
||||||
|
GLuint sampler;
|
||||||
|
GL::TextureTarget textureTarget;
|
||||||
|
};
|
||||||
|
|
||||||
struct StorageBufferDescriptor
|
struct StorageBufferDescriptor
|
||||||
{
|
{
|
||||||
GLuint buffer;
|
GLuint buffer;
|
||||||
|
|
@ -65,9 +74,12 @@ namespace Nz
|
||||||
|
|
||||||
struct TextureDescriptor
|
struct TextureDescriptor
|
||||||
{
|
{
|
||||||
|
GLboolean layered;
|
||||||
|
GLenum access;
|
||||||
|
GLenum format;
|
||||||
|
GLint layer;
|
||||||
|
GLint level;
|
||||||
GLuint texture;
|
GLuint texture;
|
||||||
GLuint sampler;
|
|
||||||
GL::TextureTarget textureTarget;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UniformBufferDescriptor
|
struct UniformBufferDescriptor
|
||||||
|
|
@ -77,7 +89,7 @@ namespace Nz
|
||||||
GLsizeiptr size;
|
GLsizeiptr size;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Descriptor = std::variant<std::monostate, StorageBufferDescriptor, TextureDescriptor, UniformBufferDescriptor>;
|
using Descriptor = std::variant<std::monostate, SampledTextureDescriptor, StorageBufferDescriptor, TextureDescriptor, UniformBufferDescriptor>;
|
||||||
|
|
||||||
struct DescriptorPool
|
struct DescriptorPool
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ namespace Nz
|
||||||
OpenGLShaderBinding& operator=(OpenGLShaderBinding&&) = delete;
|
OpenGLShaderBinding& operator=(OpenGLShaderBinding&&) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void HandleTextureBinding(UInt32 bindingIndex, const TextureBinding& textureBinding);
|
void HandleTextureBinding(UInt32 bindingIndex, const SampledTextureBinding& textureBinding);
|
||||||
void Release() override;
|
void Release() override;
|
||||||
|
|
||||||
OpenGLRenderPipelineLayout& m_owner;
|
OpenGLRenderPipelineLayout& m_owner;
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ namespace Nz
|
||||||
inline GLenum ToOpenGL(SamplerWrap wrapMode);
|
inline GLenum ToOpenGL(SamplerWrap wrapMode);
|
||||||
inline GLenum ToOpenGL(nzsl::ShaderStageType stageType);
|
inline GLenum ToOpenGL(nzsl::ShaderStageType stageType);
|
||||||
inline GLenum ToOpenGL(StencilOperation stencilOp);
|
inline GLenum ToOpenGL(StencilOperation stencilOp);
|
||||||
|
inline GLenum ToOpenGL(TextureAccess textureAccess);
|
||||||
inline GLenum ToOpenGL(GL::BufferTarget bufferTarget);
|
inline GLenum ToOpenGL(GL::BufferTarget bufferTarget);
|
||||||
inline GLenum ToOpenGL(GL::TextureTarget bufferTarget);
|
inline GLenum ToOpenGL(GL::TextureTarget bufferTarget);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
switch (stageType)
|
switch (stageType)
|
||||||
{
|
{
|
||||||
|
case nzsl::ShaderStageType::Compute: return GL_COMPUTE_SHADER;
|
||||||
case nzsl::ShaderStageType::Fragment: return GL_FRAGMENT_SHADER;
|
case nzsl::ShaderStageType::Fragment: return GL_FRAGMENT_SHADER;
|
||||||
case nzsl::ShaderStageType::Vertex: return GL_VERTEX_SHADER;
|
case nzsl::ShaderStageType::Vertex: return GL_VERTEX_SHADER;
|
||||||
}
|
}
|
||||||
|
|
@ -255,6 +256,19 @@ namespace Nz
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline GLenum ToOpenGL(TextureAccess textureAccess)
|
||||||
|
{
|
||||||
|
switch (textureAccess)
|
||||||
|
{
|
||||||
|
case TextureAccess::ReadOnly: return GL_READ_ONLY;
|
||||||
|
case TextureAccess::ReadWrite: return GL_READ_WRITE;
|
||||||
|
case TextureAccess::WriteOnly: return GL_WRITE_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
NazaraError("Unhandled TextureAccess 0x" + NumberToString(UnderlyingCast(textureAccess), 16));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
inline GLenum ToOpenGL(GL::BufferTarget bufferTarget)
|
inline GLenum ToOpenGL(GL::BufferTarget bufferTarget)
|
||||||
{
|
{
|
||||||
switch (bufferTarget)
|
switch (bufferTarget)
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,12 @@ namespace Nz::GL
|
||||||
enum class Extension
|
enum class Extension
|
||||||
{
|
{
|
||||||
ClipControl,
|
ClipControl,
|
||||||
|
ComputeShader,
|
||||||
DebugOutput,
|
DebugOutput,
|
||||||
DepthClamp,
|
DepthClamp,
|
||||||
PolygonMode,
|
PolygonMode,
|
||||||
|
ShaderImageLoadFormatted,
|
||||||
|
ShaderImageLoadStore,
|
||||||
SpirV,
|
SpirV,
|
||||||
StorageBuffers,
|
StorageBuffers,
|
||||||
TextureCompressionS3tc,
|
TextureCompressionS3tc,
|
||||||
|
|
@ -127,6 +130,7 @@ namespace Nz::GL
|
||||||
void BindBuffer(BufferTarget target, GLuint buffer, bool force = false) const;
|
void BindBuffer(BufferTarget target, GLuint buffer, bool force = false) const;
|
||||||
[[nodiscard]] GLenum BindFramebuffer(GLuint fbo) const;
|
[[nodiscard]] GLenum BindFramebuffer(GLuint fbo) const;
|
||||||
void BindFramebuffer(FramebufferTarget target, GLuint fbo) const;
|
void BindFramebuffer(FramebufferTarget target, GLuint fbo) const;
|
||||||
|
void BindImageTexture(GLuint imageUnit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) const;
|
||||||
void BindProgram(GLuint program) const;
|
void BindProgram(GLuint program) const;
|
||||||
void BindSampler(UInt32 textureUnit, GLuint sampler) const;
|
void BindSampler(UInt32 textureUnit, GLuint sampler) const;
|
||||||
void BindStorageBuffer(UInt32 storageUnit, GLuint buffer, GLintptr offset, GLsizeiptr size) const;
|
void BindStorageBuffer(UInt32 storageUnit, GLuint buffer, GLintptr offset, GLsizeiptr size) const;
|
||||||
|
|
@ -145,11 +149,16 @@ namespace Nz::GL
|
||||||
|
|
||||||
virtual void EnableVerticalSync(bool enabled) = 0;
|
virtual void EnableVerticalSync(bool enabled) = 0;
|
||||||
|
|
||||||
|
inline bool GetBoolean(GLenum name) const;
|
||||||
|
inline bool GetBoolean(GLenum name, GLuint index) const;
|
||||||
inline const OpenGLDevice* GetDevice() const;
|
inline const OpenGLDevice* GetDevice() const;
|
||||||
inline ExtensionStatus GetExtensionStatus(Extension extension) const;
|
inline ExtensionStatus GetExtensionStatus(Extension extension) const;
|
||||||
|
inline float GetFloat(GLenum name) const;
|
||||||
inline GLFunction GetFunctionByIndex(std::size_t funcIndex) const;
|
inline GLFunction GetFunctionByIndex(std::size_t funcIndex) const;
|
||||||
inline const OpenGLVaoCache& GetVaoCache() const;
|
template<typename T> T GetInteger(GLenum name) const;
|
||||||
|
template<typename T> T GetInteger(GLenum name, GLuint index) const;
|
||||||
inline const ContextParams& GetParams() const;
|
inline const ContextParams& GetParams() const;
|
||||||
|
inline const OpenGLVaoCache& GetVaoCache() const;
|
||||||
|
|
||||||
inline bool IsExtensionSupported(Extension extension) const;
|
inline bool IsExtensionSupported(Extension extension) const;
|
||||||
inline bool IsExtensionSupported(const std::string& extension) const;
|
inline bool IsExtensionSupported(const std::string& extension) const;
|
||||||
|
|
@ -232,6 +241,16 @@ namespace Nz::GL
|
||||||
GLsizeiptr size = 0;
|
GLsizeiptr size = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ImageUnits
|
||||||
|
{
|
||||||
|
GLboolean layered = GL_FALSE;
|
||||||
|
GLenum access = GL_READ_ONLY;
|
||||||
|
GLenum format = GL_RGBA8;
|
||||||
|
GLint layer = 0;
|
||||||
|
GLint level = 0;
|
||||||
|
GLuint texture = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct TextureUnit
|
struct TextureUnit
|
||||||
{
|
{
|
||||||
GLuint sampler = 0;
|
GLuint sampler = 0;
|
||||||
|
|
@ -239,9 +258,10 @@ namespace Nz::GL
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<GLuint, UnderlyingCast(BufferTarget::Max) + 1> bufferTargets = { 0 };
|
std::array<GLuint, UnderlyingCast(BufferTarget::Max) + 1> bufferTargets = { 0 };
|
||||||
std::vector<TextureUnit> textureUnits;
|
|
||||||
std::vector<BufferBinding> storageUnits;
|
std::vector<BufferBinding> storageUnits;
|
||||||
std::vector<BufferBinding> uboUnits;
|
std::vector<BufferBinding> uboUnits;
|
||||||
|
std::vector<ImageUnits> imageUnits;
|
||||||
|
std::vector<TextureUnit> textureUnits;
|
||||||
Box scissorBox;
|
Box scissorBox;
|
||||||
Box viewport;
|
Box viewport;
|
||||||
GLuint boundProgram = 0;
|
GLuint boundProgram = 0;
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,22 @@ namespace Nz::GL
|
||||||
return !m_hadAnyError;
|
return !m_hadAnyError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool Context::GetBoolean(GLenum name) const
|
||||||
|
{
|
||||||
|
GLboolean value;
|
||||||
|
glGetBooleanv(name, &value);
|
||||||
|
|
||||||
|
return value != GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Context::GetBoolean(GLenum name, GLuint index) const
|
||||||
|
{
|
||||||
|
GLboolean value;
|
||||||
|
glGetBooleani_v(name, index, &value);
|
||||||
|
|
||||||
|
return value != GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
inline const OpenGLDevice* Context::GetDevice() const
|
inline const OpenGLDevice* Context::GetDevice() const
|
||||||
{
|
{
|
||||||
return m_device;
|
return m_device;
|
||||||
|
|
@ -25,15 +41,56 @@ namespace Nz::GL
|
||||||
return m_extensionStatus[UnderlyingCast(extension)];
|
return m_extensionStatus[UnderlyingCast(extension)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline float Context::GetFloat(GLenum name) const
|
||||||
|
{
|
||||||
|
GLfloat value;
|
||||||
|
glGetFloatv(name, &value);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
inline GLFunction Context::GetFunctionByIndex(std::size_t funcIndex) const
|
inline GLFunction Context::GetFunctionByIndex(std::size_t funcIndex) const
|
||||||
{
|
{
|
||||||
assert(funcIndex < m_originalFunctionPointer.size());
|
assert(funcIndex < m_originalFunctionPointer.size());
|
||||||
return m_originalFunctionPointer[funcIndex];
|
return m_originalFunctionPointer[funcIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const OpenGLVaoCache& Context::GetVaoCache() const
|
template<typename T>
|
||||||
|
T Context::GetInteger(GLenum name) const
|
||||||
{
|
{
|
||||||
return m_vaoCache;
|
if constexpr (std::is_same_v<T, Int64> || std::is_same_v<T, UInt64>)
|
||||||
|
{
|
||||||
|
GLint64 value;
|
||||||
|
glGetInteger64v(name, &value);
|
||||||
|
|
||||||
|
return SafeCast<T>(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLint value;
|
||||||
|
glGetIntegerv(name, &value);
|
||||||
|
|
||||||
|
return SafeCast<T>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T Context::GetInteger(GLenum name, GLuint index) const
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<T, Int64> || std::is_same_v<T, UInt64>)
|
||||||
|
{
|
||||||
|
GLint64 value;
|
||||||
|
glGetInteger64i_v(name, index, &value);
|
||||||
|
|
||||||
|
return SafeCast<T>(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLint value;
|
||||||
|
glGetIntegeri_v(name, index, &value);
|
||||||
|
|
||||||
|
return SafeCast<T>(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const ContextParams& Context::GetParams() const
|
inline const ContextParams& Context::GetParams() const
|
||||||
|
|
@ -41,6 +98,11 @@ namespace Nz::GL
|
||||||
return m_params;
|
return m_params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const OpenGLVaoCache& Context::GetVaoCache() const
|
||||||
|
{
|
||||||
|
return m_vaoCache;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool Context::IsExtensionSupported(Extension extension) const
|
inline bool Context::IsExtensionSupported(Extension extension) const
|
||||||
{
|
{
|
||||||
return GetExtensionStatus(extension) != ExtensionStatus::NotSupported;
|
return GetExtensionStatus(extension) != ExtensionStatus::NotSupported;
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ namespace Nz::GL
|
||||||
EnsureContext();
|
EnsureContext();
|
||||||
|
|
||||||
if (m_context->glObjectLabel)
|
if (m_context->glObjectLabel)
|
||||||
m_context->glObjectLabel(ObjectType, m_objectId, name.size(), name.data());
|
m_context->glObjectLabel(ObjectType, m_objectId, SafeCast<GLsizei>(name.size()), name.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,9 +118,13 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERPROC) (GLuint shader, const GLch
|
||||||
cb(glGetActiveUniformBlockiv, PFNGLGETACTIVEUNIFORMBLOCKIVPROC) \
|
cb(glGetActiveUniformBlockiv, PFNGLGETACTIVEUNIFORMBLOCKIVPROC) \
|
||||||
cb(glGetActiveUniformBlockName, PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) \
|
cb(glGetActiveUniformBlockName, PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) \
|
||||||
cb(glGetBooleanv, PFNGLGETBOOLEANVPROC) \
|
cb(glGetBooleanv, PFNGLGETBOOLEANVPROC) \
|
||||||
|
cb(glGetBooleani_v, PFNGLGETBOOLEANI_VPROC) \
|
||||||
cb(glGetBufferParameteriv, PFNGLGETBUFFERPARAMETERIVPROC) \
|
cb(glGetBufferParameteriv, PFNGLGETBUFFERPARAMETERIVPROC) \
|
||||||
cb(glGetError, PFNGLGETERRORPROC) \
|
cb(glGetError, PFNGLGETERRORPROC) \
|
||||||
cb(glGetFloatv, PFNGLGETFLOATVPROC) \
|
cb(glGetFloatv, PFNGLGETFLOATVPROC) \
|
||||||
|
cb(glGetInteger64i_v, PFNGLGETINTEGER64I_VPROC) \
|
||||||
|
cb(glGetInteger64v, PFNGLGETINTEGER64VPROC) \
|
||||||
|
cb(glGetIntegeri_v, PFNGLGETINTEGERI_VPROC) \
|
||||||
cb(glGetIntegerv, PFNGLGETINTEGERVPROC) \
|
cb(glGetIntegerv, PFNGLGETINTEGERVPROC) \
|
||||||
cb(glGetProgramBinary, PFNGLGETPROGRAMBINARYPROC) \
|
cb(glGetProgramBinary, PFNGLGETPROGRAMBINARYPROC) \
|
||||||
cb(glGetProgramInfoLog, PFNGLGETPROGRAMINFOLOGPROC) \
|
cb(glGetProgramInfoLog, PFNGLGETPROGRAMINFOLOGPROC) \
|
||||||
|
|
@ -195,8 +199,11 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERPROC) (GLuint shader, const GLch
|
||||||
extCb(glDrawBuffer, PFNGLDRAWBUFFERPROC) \
|
extCb(glDrawBuffer, PFNGLDRAWBUFFERPROC) \
|
||||||
extCb(glPolygonMode, PFNGLPOLYGONMODEPROC) \
|
extCb(glPolygonMode, PFNGLPOLYGONMODEPROC) \
|
||||||
/* OpenGL 4.2 - OpenGL ES 3.1 */\
|
/* OpenGL 4.2 - OpenGL ES 3.1 */\
|
||||||
|
extCb(glBindImageTexture, PFNGLBINDIMAGETEXTUREPROC) \
|
||||||
extCb(glMemoryBarrier, PFNGLMEMORYBARRIERPROC) \
|
extCb(glMemoryBarrier, PFNGLMEMORYBARRIERPROC) \
|
||||||
extCb(glMemoryBarrierByRegion, PFNGLMEMORYBARRIERBYREGIONPROC) \
|
extCb(glMemoryBarrierByRegion, PFNGLMEMORYBARRIERBYREGIONPROC) \
|
||||||
|
/* OpenGL 4.3 - OpenGL ES 3.1 */\
|
||||||
|
extCb(glDispatchCompute, PFNGLDISPATCHCOMPUTEPROC) \
|
||||||
/* OpenGL 4.3 - OpenGL ES 3.2 */\
|
/* OpenGL 4.3 - OpenGL ES 3.2 */\
|
||||||
extCb(glCopyImageSubData, PFNGLCOPYIMAGESUBDATAPROC) \
|
extCb(glCopyImageSubData, PFNGLCOPYIMAGESUBDATAPROC) \
|
||||||
extCb(glDebugMessageCallback, PFNGLDEBUGMESSAGECALLBACKPROC) \
|
extCb(glDebugMessageCallback, PFNGLDEBUGMESSAGECALLBACKPROC) \
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
class ComputePipeline;
|
||||||
class Framebuffer;
|
class Framebuffer;
|
||||||
class RenderPass;
|
class RenderPass;
|
||||||
class RenderPipeline;
|
class RenderPipeline;
|
||||||
|
|
@ -42,8 +43,9 @@ namespace Nz
|
||||||
inline void BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, const Recti& renderRect);
|
inline void BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, const Recti& renderRect);
|
||||||
inline void BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, const Recti& renderRect, std::initializer_list<ClearValues> clearValues);
|
inline void BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, const Recti& renderRect, std::initializer_list<ClearValues> clearValues);
|
||||||
|
|
||||||
|
virtual void BindComputePipeline(const ComputePipeline& pipeline) = 0;
|
||||||
virtual void BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset = 0) = 0;
|
virtual void BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset = 0) = 0;
|
||||||
virtual void BindPipeline(const RenderPipeline& pipeline) = 0;
|
virtual void BindRenderPipeline(const RenderPipeline& pipeline) = 0;
|
||||||
virtual void BindShaderBinding(UInt32 set, const ShaderBinding& binding) = 0;
|
virtual void BindShaderBinding(UInt32 set, const ShaderBinding& binding) = 0;
|
||||||
virtual void BindShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) = 0;
|
virtual void BindShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) = 0;
|
||||||
virtual void BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset = 0) = 0;
|
virtual void BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset = 0) = 0;
|
||||||
|
|
@ -59,6 +61,8 @@ namespace Nz
|
||||||
virtual void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0) = 0;
|
virtual void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0) = 0;
|
||||||
virtual void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstIndex = 0, UInt32 firstInstance = 0) = 0;
|
virtual void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstIndex = 0, UInt32 firstInstance = 0) = 0;
|
||||||
|
|
||||||
|
virtual void Dispatch(UInt32 workgroupX, UInt32 workgroupY, UInt32 workgroupZ) = 0;
|
||||||
|
|
||||||
virtual void EndDebugRegion() = 0;
|
virtual void EndDebugRegion() = 0;
|
||||||
virtual void EndRenderPass() = 0;
|
virtual void EndRenderPass() = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - Renderer module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_RENDERER_COMPUTEPIPELINE_HPP
|
||||||
|
#define NAZARA_RENDERER_COMPUTEPIPELINE_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Renderer/RenderPipelineLayout.hpp>
|
||||||
|
#include <Nazara/Renderer/ShaderModule.hpp>
|
||||||
|
#include <Nazara/Utility/Enums.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class RenderPipelineLayout;
|
||||||
|
class ShaderModule;
|
||||||
|
|
||||||
|
struct ComputePipelineInfo
|
||||||
|
{
|
||||||
|
std::shared_ptr<RenderPipelineLayout> pipelineLayout;
|
||||||
|
std::shared_ptr<ShaderModule> shaderModule;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NAZARA_RENDERER_API ComputePipeline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ComputePipeline() = default;
|
||||||
|
virtual ~ComputePipeline();
|
||||||
|
|
||||||
|
virtual const ComputePipelineInfo& GetPipelineInfo() const = 0;
|
||||||
|
|
||||||
|
virtual void UpdateDebugName(std::string_view name) = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Renderer/ComputePipeline.inl>
|
||||||
|
|
||||||
|
#endif // NAZARA_RENDERER_COMPUTEPIPELINE_HPP
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - Renderer module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Renderer/ComputePipeline.hpp>
|
||||||
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Renderer/DebugOff.hpp>
|
||||||
|
|
@ -165,6 +165,7 @@ namespace Nz
|
||||||
|
|
||||||
enum class ShaderBindingType
|
enum class ShaderBindingType
|
||||||
{
|
{
|
||||||
|
Sampler,
|
||||||
StorageBuffer,
|
StorageBuffer,
|
||||||
Texture,
|
Texture,
|
||||||
UniformBuffer,
|
UniformBuffer,
|
||||||
|
|
@ -182,6 +183,13 @@ namespace Nz
|
||||||
SpirV
|
SpirV
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class TextureAccess
|
||||||
|
{
|
||||||
|
ReadOnly,
|
||||||
|
ReadWrite,
|
||||||
|
WriteOnly
|
||||||
|
};
|
||||||
|
|
||||||
enum class TextureLayout
|
enum class TextureLayout
|
||||||
{
|
{
|
||||||
ColorInput,
|
ColorInput,
|
||||||
|
|
@ -199,6 +207,7 @@ namespace Nz
|
||||||
ColorAttachment,
|
ColorAttachment,
|
||||||
DepthStencilAttachment,
|
DepthStencilAttachment,
|
||||||
InputAttachment,
|
InputAttachment,
|
||||||
|
ShaderReadWrite,
|
||||||
ShaderSampling,
|
ShaderSampling,
|
||||||
TransferSource,
|
TransferSource,
|
||||||
TransferDestination,
|
TransferDestination,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#define NAZARA_RENDERER_RENDERDEVICE_HPP
|
#define NAZARA_RENDERER_RENDERDEVICE_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Renderer/ComputePipeline.hpp>
|
||||||
#include <Nazara/Renderer/Config.hpp>
|
#include <Nazara/Renderer/Config.hpp>
|
||||||
#include <Nazara/Renderer/Enums.hpp>
|
#include <Nazara/Renderer/Enums.hpp>
|
||||||
#include <Nazara/Renderer/Framebuffer.hpp>
|
#include <Nazara/Renderer/Framebuffer.hpp>
|
||||||
|
|
@ -40,6 +41,7 @@ namespace Nz
|
||||||
|
|
||||||
virtual std::shared_ptr<RenderBuffer> InstantiateBuffer(BufferType type, UInt64 size, BufferUsageFlags usageFlags, const void* initialData = nullptr) = 0;
|
virtual std::shared_ptr<RenderBuffer> InstantiateBuffer(BufferType type, UInt64 size, BufferUsageFlags usageFlags, const void* initialData = nullptr) = 0;
|
||||||
virtual std::shared_ptr<CommandPool> InstantiateCommandPool(QueueType queueType) = 0;
|
virtual std::shared_ptr<CommandPool> InstantiateCommandPool(QueueType queueType) = 0;
|
||||||
|
virtual std::shared_ptr<ComputePipeline> InstantiateComputePipeline(ComputePipelineInfo pipelineInfo) = 0;
|
||||||
virtual std::shared_ptr<Framebuffer> InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr<RenderPass>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments) = 0;
|
virtual std::shared_ptr<Framebuffer> InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr<RenderPass>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments) = 0;
|
||||||
virtual std::shared_ptr<RenderPass> InstantiateRenderPass(std::vector<RenderPass::Attachment> attachments, std::vector<RenderPass::SubpassDescription> subpassDescriptions, std::vector<RenderPass::SubpassDependency> subpassDependencies) = 0;
|
virtual std::shared_ptr<RenderPass> InstantiateRenderPass(std::vector<RenderPass::Attachment> attachments, std::vector<RenderPass::SubpassDescription> subpassDescriptions, std::vector<RenderPass::SubpassDependency> subpassDependencies) = 0;
|
||||||
virtual std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0;
|
virtual std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#define NAZARA_RENDERER_RENDERDEVICEINFO_HPP
|
#define NAZARA_RENDERER_RENDERDEVICEINFO_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Math/Vector3.hpp>
|
||||||
#include <Nazara/Renderer/Enums.hpp>
|
#include <Nazara/Renderer/Enums.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -16,18 +17,27 @@ namespace Nz
|
||||||
struct RenderDeviceFeatures
|
struct RenderDeviceFeatures
|
||||||
{
|
{
|
||||||
bool anisotropicFiltering = false;
|
bool anisotropicFiltering = false;
|
||||||
|
bool computeShaders = false;
|
||||||
bool depthClamping = false;
|
bool depthClamping = false;
|
||||||
bool nonSolidFaceFilling = false;
|
bool nonSolidFaceFilling = false;
|
||||||
bool storageBuffers = false;
|
bool storageBuffers = false;
|
||||||
|
bool textureRead = false;
|
||||||
|
bool textureReadWithoutFormat = false;
|
||||||
|
bool textureWrite = false;
|
||||||
|
bool textureWriteWithoutFormat = false;
|
||||||
bool unrestrictedTextureViews = false;
|
bool unrestrictedTextureViews = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RenderDeviceLimits
|
struct RenderDeviceLimits
|
||||||
{
|
{
|
||||||
UInt64 minStorageBufferOffsetAlignment;
|
UInt64 maxComputeSharedMemorySize;
|
||||||
UInt64 minUniformBufferOffsetAlignment;
|
UInt32 maxComputeWorkGroupInvocations;
|
||||||
|
Vector3ui32 maxComputeWorkGroupCount;
|
||||||
|
Vector3ui32 maxComputeWorkGroupSize;
|
||||||
UInt64 maxStorageBufferSize;
|
UInt64 maxStorageBufferSize;
|
||||||
UInt64 maxUniformBufferSize;
|
UInt64 maxUniformBufferSize;
|
||||||
|
UInt64 minStorageBufferOffsetAlignment;
|
||||||
|
UInt64 minUniformBufferOffsetAlignment;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RenderDeviceInfo
|
struct RenderDeviceInfo
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <Nazara/Prerequisites.hpp>
|
#include <Nazara/Prerequisites.hpp>
|
||||||
#include <Nazara/Renderer/Config.hpp>
|
#include <Nazara/Renderer/Config.hpp>
|
||||||
|
#include <Nazara/Renderer/Enums.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
@ -43,6 +44,18 @@ namespace Nz
|
||||||
ShaderBinding& operator=(const ShaderBinding&) = delete;
|
ShaderBinding& operator=(const ShaderBinding&) = delete;
|
||||||
ShaderBinding& operator=(ShaderBinding&&) = delete;
|
ShaderBinding& operator=(ShaderBinding&&) = delete;
|
||||||
|
|
||||||
|
struct SampledTextureBinding
|
||||||
|
{
|
||||||
|
const Texture* texture;
|
||||||
|
const TextureSampler* sampler;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SampledTextureBindings
|
||||||
|
{
|
||||||
|
UInt32 arraySize;
|
||||||
|
const SampledTextureBinding* textureBindings;
|
||||||
|
};
|
||||||
|
|
||||||
struct StorageBufferBinding
|
struct StorageBufferBinding
|
||||||
{
|
{
|
||||||
RenderBuffer* buffer;
|
RenderBuffer* buffer;
|
||||||
|
|
@ -53,13 +66,7 @@ namespace Nz
|
||||||
struct TextureBinding
|
struct TextureBinding
|
||||||
{
|
{
|
||||||
const Texture* texture;
|
const Texture* texture;
|
||||||
const TextureSampler* sampler;
|
TextureAccess access;
|
||||||
};
|
|
||||||
|
|
||||||
struct TextureBindings
|
|
||||||
{
|
|
||||||
UInt32 arraySize;
|
|
||||||
const TextureBinding* textureBindings;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UniformBufferBinding
|
struct UniformBufferBinding
|
||||||
|
|
@ -72,7 +79,7 @@ namespace Nz
|
||||||
struct Binding
|
struct Binding
|
||||||
{
|
{
|
||||||
UInt32 bindingIndex;
|
UInt32 bindingIndex;
|
||||||
std::variant<StorageBufferBinding, TextureBinding, TextureBindings, UniformBufferBinding> content;
|
std::variant<SampledTextureBinding, SampledTextureBindings, StorageBufferBinding, TextureBinding, UniformBufferBinding> content;
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ namespace Nz
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Mutex;
|
|
||||||
class ImageStream;
|
class ImageStream;
|
||||||
|
|
||||||
using ImageStreamLoader = ResourceLoader<ImageStream, ImageStreamParams>;
|
using ImageStreamLoader = ResourceLoader<ImageStream, ImageStreamParams>;
|
||||||
|
|
|
||||||
|
|
@ -382,8 +382,9 @@ namespace Nz
|
||||||
{
|
{
|
||||||
switch (bindingType)
|
switch (bindingType)
|
||||||
{
|
{
|
||||||
|
case ShaderBindingType::Sampler: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
case ShaderBindingType::StorageBuffer: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
case ShaderBindingType::StorageBuffer: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||||
case ShaderBindingType::Texture: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
case ShaderBindingType::Texture: return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||||
case ShaderBindingType::UniformBuffer: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
case ShaderBindingType::UniformBuffer: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -395,6 +396,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
switch (stageType)
|
switch (stageType)
|
||||||
{
|
{
|
||||||
|
case nzsl::ShaderStageType::Compute: return VK_SHADER_STAGE_COMPUTE_BIT;
|
||||||
case nzsl::ShaderStageType::Fragment: return VK_SHADER_STAGE_FRAGMENT_BIT;
|
case nzsl::ShaderStageType::Fragment: return VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
case nzsl::ShaderStageType::Vertex: return VK_SHADER_STAGE_VERTEX_BIT;
|
case nzsl::ShaderStageType::Vertex: return VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
}
|
}
|
||||||
|
|
@ -459,6 +461,7 @@ namespace Nz
|
||||||
case TextureUsage::ColorAttachment: return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
case TextureUsage::ColorAttachment: return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
case TextureUsage::DepthStencilAttachment: return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
case TextureUsage::DepthStencilAttachment: return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||||
case TextureUsage::InputAttachment: return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
case TextureUsage::InputAttachment: return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||||
|
case TextureUsage::ShaderReadWrite: return VK_IMAGE_USAGE_STORAGE_BIT;
|
||||||
case TextureUsage::ShaderSampling: return VK_IMAGE_USAGE_SAMPLED_BIT;
|
case TextureUsage::ShaderSampling: return VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
case TextureUsage::TransferSource: return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
case TextureUsage::TransferSource: return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
case TextureUsage::TransferDestination: return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
case TextureUsage::TransferDestination: return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,9 @@ namespace Nz
|
||||||
void BeginDebugRegion(const std::string_view& regionName, const Color& color) override;
|
void BeginDebugRegion(const std::string_view& regionName, const Color& color) override;
|
||||||
void BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, const Recti& renderRect, const ClearValues* clearValues, std::size_t clearValueCount) override;
|
void BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, const Recti& renderRect, const ClearValues* clearValues, std::size_t clearValueCount) override;
|
||||||
|
|
||||||
|
void BindComputePipeline(const ComputePipeline& pipeline) override;
|
||||||
void BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset = 0) override;
|
void BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset = 0) override;
|
||||||
void BindPipeline(const RenderPipeline& pipeline) override;
|
void BindRenderPipeline(const RenderPipeline& pipeline) override;
|
||||||
void BindShaderBinding(UInt32 set, const ShaderBinding& binding) override;
|
void BindShaderBinding(UInt32 set, const ShaderBinding& binding) override;
|
||||||
void BindShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) override;
|
void BindShaderBinding(const RenderPipelineLayout& pipelineLayout, UInt32 set, const ShaderBinding& binding) override;
|
||||||
void BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset = 0) override;
|
void BindVertexBuffer(UInt32 binding, const RenderBuffer& vertexBuffer, UInt64 offset = 0) override;
|
||||||
|
|
@ -39,6 +40,8 @@ namespace Nz
|
||||||
void CopyBuffer(const UploadPool::Allocation& allocation, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
|
void CopyBuffer(const UploadPool::Allocation& allocation, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
|
||||||
void CopyTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Vector3ui& toPos, TextureLayout toLayout) override;
|
void CopyTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Vector3ui& toPos, TextureLayout toLayout) override;
|
||||||
|
|
||||||
|
void Dispatch(UInt32 workgroupX, UInt32 workgroupY, UInt32 workgroupZ) override;
|
||||||
|
|
||||||
void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0) override;
|
void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0) override;
|
||||||
void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstIndex = 0, UInt32 firstInstance = 0) override;
|
void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstIndex = 0, UInt32 firstInstance = 0) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - Vulkan renderer"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_VULKANRENDERER_VULKANCOMPUTEPIPELINE_HPP
|
||||||
|
#define NAZARA_VULKANRENDERER_VULKANCOMPUTEPIPELINE_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Core/Algorithm.hpp>
|
||||||
|
#include <Nazara/Renderer/ComputePipeline.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/Config.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/Wrapper/Device.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/Wrapper/Pipeline.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class VulkanDevice;
|
||||||
|
|
||||||
|
class NAZARA_VULKANRENDERER_API VulkanComputePipeline : public ComputePipeline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VulkanComputePipeline(VulkanDevice& device, ComputePipelineInfo pipelineInfo);
|
||||||
|
VulkanComputePipeline(const VulkanComputePipeline&) = delete;
|
||||||
|
VulkanComputePipeline(VulkanComputePipeline&&) = delete;
|
||||||
|
~VulkanComputePipeline() = default;
|
||||||
|
|
||||||
|
inline const Vk::Pipeline& GetPipeline() const;
|
||||||
|
inline const ComputePipelineInfo& GetPipelineInfo() const override;
|
||||||
|
|
||||||
|
void UpdateDebugName(std::string_view name) override;
|
||||||
|
|
||||||
|
VulkanComputePipeline& operator=(const VulkanComputePipeline&) = delete;
|
||||||
|
VulkanComputePipeline& operator=(VulkanComputePipeline&&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vk::Pipeline m_pipeline;
|
||||||
|
ComputePipelineInfo m_pipelineInfo;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/VulkanRenderer/VulkanComputePipeline.inl>
|
||||||
|
|
||||||
|
#endif // NAZARA_VULKANRENDERER_VULKANCOMPUTEPIPELINE_HPP
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - Vulkan renderer"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/VulkanRenderer/VulkanComputePipeline.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
inline const Vk::Pipeline& VulkanComputePipeline::GetPipeline() const
|
||||||
|
{
|
||||||
|
return m_pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const ComputePipelineInfo& VulkanComputePipeline::GetPipelineInfo() const
|
||||||
|
{
|
||||||
|
return m_pipelineInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/VulkanRenderer/DebugOff.hpp>
|
||||||
|
|
@ -28,6 +28,7 @@ namespace Nz
|
||||||
|
|
||||||
std::shared_ptr<RenderBuffer> InstantiateBuffer(BufferType type, UInt64 size, BufferUsageFlags usageFlags, const void* initialData = nullptr) override;
|
std::shared_ptr<RenderBuffer> InstantiateBuffer(BufferType type, UInt64 size, BufferUsageFlags usageFlags, const void* initialData = nullptr) override;
|
||||||
std::shared_ptr<CommandPool> InstantiateCommandPool(QueueType queueType) override;
|
std::shared_ptr<CommandPool> InstantiateCommandPool(QueueType queueType) override;
|
||||||
|
std::shared_ptr<ComputePipeline> InstantiateComputePipeline(ComputePipelineInfo pipelineInfo) override;
|
||||||
std::shared_ptr<Framebuffer> InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr<RenderPass>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments) override;
|
std::shared_ptr<Framebuffer> InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr<RenderPass>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments) override;
|
||||||
std::shared_ptr<RenderPass> InstantiateRenderPass(std::vector<RenderPass::Attachment> attachments, std::vector<RenderPass::SubpassDescription> subpassDescriptions, std::vector<RenderPass::SubpassDependency> subpassDependencies) override;
|
std::shared_ptr<RenderPass> InstantiateRenderPass(std::vector<RenderPass::Attachment> attachments, std::vector<RenderPass::SubpassDescription> subpassDescriptions, std::vector<RenderPass::SubpassDependency> subpassDependencies) override;
|
||||||
std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override;
|
std::shared_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override;
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,8 @@ namespace Nz
|
||||||
inline void CopyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, const VkImageCopy& region);
|
inline void CopyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, const VkImageCopy& region);
|
||||||
inline void CopyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, UInt32 regionCount, const VkImageCopy* regions);
|
inline void CopyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, UInt32 regionCount, const VkImageCopy* regions);
|
||||||
|
|
||||||
|
inline void Dispatch(UInt32 groupCountX, UInt32 groupCountY, UInt32 groupCountZ);
|
||||||
|
|
||||||
inline void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0);
|
inline void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0);
|
||||||
inline void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, Int32 vertexOffset = 0, UInt32 firstInstance = 0);
|
inline void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, Int32 vertexOffset = 0, UInt32 firstInstance = 0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,11 @@ namespace Nz
|
||||||
return m_pool->GetDevice()->vkCmdCopyImage(m_handle, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, regions);
|
return m_pool->GetDevice()->vkCmdCopyImage(m_handle, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, regions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void CommandBuffer::Dispatch(UInt32 groupCountX, UInt32 groupCountY, UInt32 groupCountZ)
|
||||||
|
{
|
||||||
|
return m_pool->GetDevice()->vkCmdDispatch(m_handle, groupCountX, groupCountY, groupCountZ);
|
||||||
|
}
|
||||||
|
|
||||||
inline void CommandBuffer::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance)
|
inline void CommandBuffer::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance)
|
||||||
{
|
{
|
||||||
return m_pool->GetDevice()->vkCmdDraw(m_handle, vertexCount, instanceCount, firstVertex, firstInstance);
|
return m_pool->GetDevice()->vkCmdDraw(m_handle, vertexCount, instanceCount, firstVertex, firstInstance);
|
||||||
|
|
|
||||||
|
|
@ -402,7 +402,7 @@ namespace Nz
|
||||||
viewerData.blitShaderBinding->Update({
|
viewerData.blitShaderBinding->Update({
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
ShaderBinding::TextureBinding {
|
ShaderBinding::SampledTextureBinding {
|
||||||
m_bakedFrameGraph.GetAttachmentTexture(viewerData.debugColorAttachment).get(),
|
m_bakedFrameGraph.GetAttachmentTexture(viewerData.debugColorAttachment).get(),
|
||||||
sampler.get()
|
sampler.get()
|
||||||
}
|
}
|
||||||
|
|
@ -419,7 +419,7 @@ namespace Nz
|
||||||
renderTargetData.blitShaderBinding->Update({
|
renderTargetData.blitShaderBinding->Update({
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
ShaderBinding::TextureBinding {
|
ShaderBinding::SampledTextureBinding {
|
||||||
m_bakedFrameGraph.GetAttachmentTexture(renderTargetData.finalAttachment).get(),
|
m_bakedFrameGraph.GetAttachmentTexture(renderTargetData.finalAttachment).get(),
|
||||||
sampler.get()
|
sampler.get()
|
||||||
}
|
}
|
||||||
|
|
@ -456,7 +456,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
builder.SetScissor(renderRegion);
|
builder.SetScissor(renderRegion);
|
||||||
builder.SetViewport(renderRegion);
|
builder.SetViewport(renderRegion);
|
||||||
builder.BindPipeline(*graphics->GetBlitPipeline(false));
|
builder.BindRenderPipeline(*graphics->GetBlitPipeline(false));
|
||||||
|
|
||||||
builder.BindShaderBinding(0, *data.blitShaderBinding);
|
builder.BindShaderBinding(0, *data.blitShaderBinding);
|
||||||
builder.Draw(3);
|
builder.Draw(3);
|
||||||
|
|
@ -644,7 +644,7 @@ namespace Nz
|
||||||
builder.SetViewport(env.renderRect);
|
builder.SetViewport(env.renderRect);
|
||||||
|
|
||||||
Graphics* graphics = Graphics::Instance();
|
Graphics* graphics = Graphics::Instance();
|
||||||
builder.BindPipeline(*graphics->GetBlitPipeline(false));
|
builder.BindRenderPipeline(*graphics->GetBlitPipeline(false));
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
|
|
@ -657,7 +657,7 @@ namespace Nz
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
builder.BindPipeline(*graphics->GetBlitPipeline(true));
|
builder.BindRenderPipeline(*graphics->GetBlitPipeline(true));
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,9 +108,14 @@ namespace Nz
|
||||||
|
|
||||||
RenderDeviceFeatures enabledFeatures;
|
RenderDeviceFeatures enabledFeatures;
|
||||||
enabledFeatures.anisotropicFiltering = !config.forceDisableFeatures.anisotropicFiltering && renderDeviceInfo[bestRenderDeviceIndex].features.anisotropicFiltering;
|
enabledFeatures.anisotropicFiltering = !config.forceDisableFeatures.anisotropicFiltering && renderDeviceInfo[bestRenderDeviceIndex].features.anisotropicFiltering;
|
||||||
|
enabledFeatures.computeShaders = !config.forceDisableFeatures.computeShaders && renderDeviceInfo[bestRenderDeviceIndex].features.computeShaders;
|
||||||
enabledFeatures.depthClamping = !config.forceDisableFeatures.depthClamping && renderDeviceInfo[bestRenderDeviceIndex].features.depthClamping;
|
enabledFeatures.depthClamping = !config.forceDisableFeatures.depthClamping && renderDeviceInfo[bestRenderDeviceIndex].features.depthClamping;
|
||||||
enabledFeatures.nonSolidFaceFilling = !config.forceDisableFeatures.nonSolidFaceFilling && renderDeviceInfo[bestRenderDeviceIndex].features.nonSolidFaceFilling;
|
enabledFeatures.nonSolidFaceFilling = !config.forceDisableFeatures.nonSolidFaceFilling && renderDeviceInfo[bestRenderDeviceIndex].features.nonSolidFaceFilling;
|
||||||
enabledFeatures.storageBuffers = !config.forceDisableFeatures.storageBuffers && renderDeviceInfo[bestRenderDeviceIndex].features.storageBuffers;
|
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.textureWriteWithoutFormat = !config.forceDisableFeatures.textureWriteWithoutFormat && renderDeviceInfo[bestRenderDeviceIndex].features.textureWriteWithoutFormat;
|
||||||
enabledFeatures.unrestrictedTextureViews = !config.forceDisableFeatures.unrestrictedTextureViews && renderDeviceInfo[bestRenderDeviceIndex].features.unrestrictedTextureViews;
|
enabledFeatures.unrestrictedTextureViews = !config.forceDisableFeatures.unrestrictedTextureViews && renderDeviceInfo[bestRenderDeviceIndex].features.unrestrictedTextureViews;
|
||||||
|
|
||||||
m_renderDevice = renderer->InstanciateRenderDevice(bestRenderDeviceIndex, enabledFeatures);
|
m_renderDevice = renderer->InstanciateRenderDevice(bestRenderDeviceIndex, enabledFeatures);
|
||||||
|
|
@ -176,7 +181,7 @@ namespace Nz
|
||||||
layoutInfo.bindings.assign({
|
layoutInfo.bindings.assign({
|
||||||
{
|
{
|
||||||
0, 0, 1,
|
0, 0, 1,
|
||||||
ShaderBindingType::Texture,
|
ShaderBindingType::Sampler,
|
||||||
nzsl::ShaderStageType::Fragment
|
nzsl::ShaderStageType::Fragment
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ namespace Nz
|
||||||
|
|
||||||
bindings.push_back({
|
bindings.push_back({
|
||||||
textureSlot.bindingIndex,
|
textureSlot.bindingIndex,
|
||||||
ShaderBinding::TextureBinding {
|
ShaderBinding::SampledTextureBinding {
|
||||||
texture.get(), sampler.get()
|
texture.get(), sampler.get()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@ namespace Nz
|
||||||
if (IsStorageType(*varType))
|
if (IsStorageType(*varType))
|
||||||
bindingType = ShaderBindingType::StorageBuffer;
|
bindingType = ShaderBindingType::StorageBuffer;
|
||||||
else if (IsSamplerType(*varType))
|
else if (IsSamplerType(*varType))
|
||||||
|
bindingType = ShaderBindingType::Sampler;
|
||||||
|
else if (IsTextureType(*varType))
|
||||||
bindingType = ShaderBindingType::Texture;
|
bindingType = ShaderBindingType::Texture;
|
||||||
else if (IsUniformType(*varType))
|
else if (IsUniformType(*varType))
|
||||||
bindingType = ShaderBindingType::UniformBuffer;
|
bindingType = ShaderBindingType::UniformBuffer;
|
||||||
|
|
@ -67,7 +69,7 @@ namespace Nz
|
||||||
throw std::runtime_error("unexpected type " + ToString(innerType) + " in array " + ToString(arrayType));
|
throw std::runtime_error("unexpected type " + ToString(innerType) + " in array " + ToString(arrayType));
|
||||||
|
|
||||||
arraySize = arrayType.length;
|
arraySize = arrayType.length;
|
||||||
bindingType = ShaderBindingType::Texture;
|
bindingType = ShaderBindingType::Sampler;
|
||||||
varType = &innerType;
|
varType = &innerType;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -86,6 +88,21 @@ namespace Nz
|
||||||
{
|
{
|
||||||
switch (bindingType)
|
switch (bindingType)
|
||||||
{
|
{
|
||||||
|
case ShaderBindingType::Sampler:
|
||||||
|
{
|
||||||
|
if (externalBlock->samplers.find(externalVar.tag) != externalBlock->samplers.end())
|
||||||
|
throw std::runtime_error("duplicate sampler tag " + externalVar.tag + " in external block " + node.tag);
|
||||||
|
|
||||||
|
const auto& samplerType = std::get<nzsl::Ast::SamplerType>(*varType);
|
||||||
|
|
||||||
|
ExternalSampler& texture = externalBlock->samplers[externalVar.tag];
|
||||||
|
texture.bindingIndex = bindingIndex;
|
||||||
|
texture.bindingSet = bindingSet;
|
||||||
|
texture.imageType = samplerType.dim;
|
||||||
|
texture.sampledType = samplerType.sampledType;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case ShaderBindingType::StorageBuffer:
|
case ShaderBindingType::StorageBuffer:
|
||||||
{
|
{
|
||||||
if (externalBlock->storageBlocks.find(externalVar.tag) != externalBlock->storageBlocks.end())
|
if (externalBlock->storageBlocks.find(externalVar.tag) != externalBlock->storageBlocks.end())
|
||||||
|
|
@ -100,16 +117,18 @@ namespace Nz
|
||||||
|
|
||||||
case ShaderBindingType::Texture:
|
case ShaderBindingType::Texture:
|
||||||
{
|
{
|
||||||
if (externalBlock->samplers.find(externalVar.tag) != externalBlock->samplers.end())
|
if (externalBlock->textures.find(externalVar.tag) != externalBlock->textures.end())
|
||||||
throw std::runtime_error("duplicate textures tag " + externalVar.tag + " in external block " + node.tag);
|
throw std::runtime_error("duplicate textures tag " + externalVar.tag + " in external block " + node.tag);
|
||||||
|
|
||||||
const auto& samplerType = std::get<nzsl::Ast::SamplerType>(*varType);
|
const auto& textureType = std::get<nzsl::Ast::TextureType>(*varType);
|
||||||
|
|
||||||
ExternalTexture& texture = externalBlock->samplers[externalVar.tag];
|
ExternalTexture& texture = externalBlock->textures[externalVar.tag];
|
||||||
texture.bindingIndex = bindingIndex;
|
texture.bindingIndex = bindingIndex;
|
||||||
texture.bindingSet = bindingSet;
|
texture.bindingSet = bindingSet;
|
||||||
texture.imageType = samplerType.dim;
|
texture.accessPolicy = textureType.accessPolicy;
|
||||||
texture.sampledType = samplerType.sampledType;
|
texture.baseType = textureType.baseType;
|
||||||
|
texture.imageFormat = textureType.format;
|
||||||
|
texture.imageType = textureType.dim;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
auto& bindingEntry = m_bindingCache.emplace_back();
|
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||||
bindingEntry.bindingIndex = bindingIndex;
|
bindingEntry.bindingIndex = bindingIndex;
|
||||||
bindingEntry.content = ShaderBinding::TextureBinding{
|
bindingEntry.content = ShaderBinding::SampledTextureBinding{
|
||||||
m_pendingData.currentTextureOverlay, defaultSampler.get()
|
m_pendingData.currentTextureOverlay, defaultSampler.get()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -310,7 +310,7 @@ namespace Nz
|
||||||
|
|
||||||
if (currentPipeline != drawData.renderPipeline)
|
if (currentPipeline != drawData.renderPipeline)
|
||||||
{
|
{
|
||||||
commandBuffer.BindPipeline(*drawData.renderPipeline);
|
commandBuffer.BindRenderPipeline(*drawData.renderPipeline);
|
||||||
currentPipeline = drawData.renderPipeline;
|
currentPipeline = drawData.renderPipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ namespace Nz
|
||||||
|
|
||||||
auto& bindingEntry = m_bindingCache.emplace_back();
|
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||||
bindingEntry.bindingIndex = bindingIndex;
|
bindingEntry.bindingIndex = bindingIndex;
|
||||||
bindingEntry.content = ShaderBinding::TextureBindings {
|
bindingEntry.content = ShaderBinding::SampledTextureBindings {
|
||||||
SafeCast<UInt32>(renderState.shadowMaps2D.size()), &m_textureBindingCache[textureBindingBaseIndex]
|
SafeCast<UInt32>(renderState.shadowMaps2D.size()), &m_textureBindingCache[textureBindingBaseIndex]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -197,7 +197,7 @@ namespace Nz
|
||||||
|
|
||||||
auto& bindingEntry = m_bindingCache.emplace_back();
|
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||||
bindingEntry.bindingIndex = bindingIndex;
|
bindingEntry.bindingIndex = bindingIndex;
|
||||||
bindingEntry.content = ShaderBinding::TextureBindings {
|
bindingEntry.content = ShaderBinding::SampledTextureBindings {
|
||||||
SafeCast<UInt32>(renderState.shadowMapsCube.size()), &m_textureBindingCache[textureBindingBaseIndex]
|
SafeCast<UInt32>(renderState.shadowMapsCube.size()), &m_textureBindingCache[textureBindingBaseIndex]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -230,7 +230,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
auto& bindingEntry = m_bindingCache.emplace_back();
|
auto& bindingEntry = m_bindingCache.emplace_back();
|
||||||
bindingEntry.bindingIndex = bindingIndex;
|
bindingEntry.bindingIndex = bindingIndex;
|
||||||
bindingEntry.content = ShaderBinding::TextureBinding{
|
bindingEntry.content = ShaderBinding::SampledTextureBinding{
|
||||||
whiteTexture2D.get(), defaultSampler.get()
|
whiteTexture2D.get(), defaultSampler.get()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -285,7 +285,7 @@ namespace Nz
|
||||||
|
|
||||||
if (currentPipeline != drawData.renderPipeline)
|
if (currentPipeline != drawData.renderPipeline)
|
||||||
{
|
{
|
||||||
commandBuffer.BindPipeline(*drawData.renderPipeline);
|
commandBuffer.BindRenderPipeline(*drawData.renderPipeline);
|
||||||
currentPipeline = drawData.renderPipeline;
|
currentPipeline = drawData.renderPipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp>
|
||||||
|
#include <Nazara/OpenGLRenderer/OpenGLComputePipeline.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLRenderPass.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLRenderPass.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp>
|
||||||
|
|
@ -93,6 +94,14 @@ namespace Nz
|
||||||
{
|
{
|
||||||
context->CopyTexture(*command.source, *command.target, command.sourceBox, command.targetPoint);
|
context->CopyTexture(*command.source, *command.target, command.sourceBox, command.targetPoint);
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, DispatchData>)
|
||||||
|
{
|
||||||
|
if (!context->glDispatchCompute)
|
||||||
|
throw std::runtime_error("compute shaders are not supported on this device");
|
||||||
|
|
||||||
|
command.states.pipeline->Apply(*context);
|
||||||
|
context->glDispatchCompute(command.numGroupsX, command.numGroupsY, command.numGroupsZ);
|
||||||
|
}
|
||||||
else if constexpr (std::is_same_v<T, DrawData>)
|
else if constexpr (std::is_same_v<T, DrawData>)
|
||||||
{
|
{
|
||||||
ApplyStates(*context, command.states);
|
ApplyStates(*context, command.states);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp>
|
||||||
|
#include <Nazara/OpenGLRenderer/OpenGLComputePipeline.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLRenderPass.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLRenderPass.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp>
|
||||||
|
|
@ -26,6 +27,13 @@ namespace Nz
|
||||||
m_commandBuffer.SetFramebuffer(static_cast<const OpenGLFramebuffer&>(framebuffer), static_cast<const OpenGLRenderPass&>(renderPass), clearValues, clearValueCount);
|
m_commandBuffer.SetFramebuffer(static_cast<const OpenGLFramebuffer&>(framebuffer), static_cast<const OpenGLRenderPass&>(renderPass), clearValues, clearValueCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLCommandBufferBuilder::BindComputePipeline(const ComputePipeline& pipeline)
|
||||||
|
{
|
||||||
|
const OpenGLComputePipeline& glPipeline = static_cast<const OpenGLComputePipeline&>(pipeline);
|
||||||
|
|
||||||
|
m_commandBuffer.BindComputePipeline(&glPipeline);
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLCommandBufferBuilder::BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset)
|
void OpenGLCommandBufferBuilder::BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset)
|
||||||
{
|
{
|
||||||
const OpenGLBuffer& glBuffer = static_cast<const OpenGLBuffer&>(indexBuffer);
|
const OpenGLBuffer& glBuffer = static_cast<const OpenGLBuffer&>(indexBuffer);
|
||||||
|
|
@ -33,11 +41,11 @@ namespace Nz
|
||||||
m_commandBuffer.BindIndexBuffer(glBuffer.GetBuffer().GetObjectId(), indexType, offset);
|
m_commandBuffer.BindIndexBuffer(glBuffer.GetBuffer().GetObjectId(), indexType, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLCommandBufferBuilder::BindPipeline(const RenderPipeline& pipeline)
|
void OpenGLCommandBufferBuilder::BindRenderPipeline(const RenderPipeline& pipeline)
|
||||||
{
|
{
|
||||||
const OpenGLRenderPipeline& glPipeline = static_cast<const OpenGLRenderPipeline&>(pipeline);
|
const OpenGLRenderPipeline& glPipeline = static_cast<const OpenGLRenderPipeline&>(pipeline);
|
||||||
|
|
||||||
m_commandBuffer.BindPipeline(&glPipeline);
|
m_commandBuffer.BindRenderPipeline(&glPipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLCommandBufferBuilder::BindShaderBinding(UInt32 set, const ShaderBinding& binding)
|
void OpenGLCommandBufferBuilder::BindShaderBinding(UInt32 set, const ShaderBinding& binding)
|
||||||
|
|
@ -93,6 +101,11 @@ namespace Nz
|
||||||
m_commandBuffer.CopyTexture(sourceTexture, fromBox, targetTexture, toPos);
|
m_commandBuffer.CopyTexture(sourceTexture, fromBox, targetTexture, toPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLCommandBufferBuilder::Dispatch(UInt32 workgroupX, UInt32 workgroupY, UInt32 workgroupZ)
|
||||||
|
{
|
||||||
|
m_commandBuffer.Dispatch(workgroupX, workgroupY, workgroupZ);
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLCommandBufferBuilder::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance)
|
void OpenGLCommandBufferBuilder::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance)
|
||||||
{
|
{
|
||||||
m_commandBuffer.Draw(vertexCount, instanceCount, firstVertex, firstInstance);
|
m_commandBuffer.Draw(vertexCount, instanceCount, firstVertex, firstInstance);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - OpenGL renderer"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/OpenGLRenderer/OpenGLComputePipeline.hpp>
|
||||||
|
#include <Nazara/Core/ErrorFlags.hpp>
|
||||||
|
#include <Nazara/OpenGLRenderer/OpenGLRenderPipelineLayout.hpp>
|
||||||
|
#include <Nazara/OpenGLRenderer/OpenGLShaderModule.hpp>
|
||||||
|
#include <Nazara/OpenGLRenderer/Utils.hpp>
|
||||||
|
#include <NZSL/GlslWriter.hpp>
|
||||||
|
#include <NZSL/ShaderBuilder.hpp>
|
||||||
|
#include <NZSL/Ast/Module.hpp>
|
||||||
|
#include <cassert>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <Nazara/OpenGLRenderer/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
OpenGLComputePipeline::OpenGLComputePipeline(OpenGLDevice& device, ComputePipelineInfo pipelineInfo) :
|
||||||
|
m_pipelineInfo(std::move(pipelineInfo))
|
||||||
|
{
|
||||||
|
if (device.GetEnabledFeatures().computeShaders)
|
||||||
|
throw std::runtime_error("compute shaders are not enabled on the device");
|
||||||
|
|
||||||
|
OpenGLRenderPipelineLayout& pipelineLayout = static_cast<OpenGLRenderPipelineLayout&>(*m_pipelineInfo.pipelineLayout);
|
||||||
|
|
||||||
|
if (!m_program.Create(device))
|
||||||
|
throw std::runtime_error("failed to create program");
|
||||||
|
|
||||||
|
NazaraAssert(pipelineInfo.shaderModule, "invalid shader module");
|
||||||
|
|
||||||
|
OpenGLShaderModule& shaderModule = static_cast<OpenGLShaderModule&>(*pipelineInfo.shaderModule);
|
||||||
|
|
||||||
|
std::vector<OpenGLShaderModule::ExplicitBinding> explicitBindings;
|
||||||
|
nzsl::ShaderStageTypeFlags stageFlags = shaderModule.Attach(m_program, pipelineLayout.GetBindingMapping(), &explicitBindings);
|
||||||
|
if (!stageFlags.Test(nzsl::ShaderStageType::Compute))
|
||||||
|
throw std::runtime_error("shader module has no compute stage");
|
||||||
|
|
||||||
|
m_program.Link();
|
||||||
|
|
||||||
|
std::string errLog;
|
||||||
|
if (!m_program.GetLinkStatus(&errLog))
|
||||||
|
throw std::runtime_error("failed to link program: " + errLog);
|
||||||
|
|
||||||
|
for (const auto& explicitBinding : explicitBindings)
|
||||||
|
{
|
||||||
|
if (explicitBinding.isBlock)
|
||||||
|
{
|
||||||
|
GLuint blockIndex = m_program.GetUniformBlockIndex(explicitBinding.name);
|
||||||
|
if (blockIndex == GL_INVALID_INDEX)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m_program.UniformBlockBinding(blockIndex, explicitBinding.binding);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int location = m_program.GetUniformLocation(explicitBinding.name);
|
||||||
|
if (location == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m_program.Uniform(location, SafeCast<int>(explicitBinding.binding));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLComputePipeline::Apply(const GL::Context& context) const
|
||||||
|
{
|
||||||
|
context.BindProgram(m_program.GetObjectId());
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLComputePipeline::UpdateDebugName(std::string_view name)
|
||||||
|
{
|
||||||
|
m_program.SetDebugName(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLDevice.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLDevice.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLBuffer.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLBuffer.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp>
|
||||||
|
#include <Nazara/OpenGLRenderer/OpenGLComputePipeline.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLRenderPass.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLRenderPass.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLRenderPipeline.hpp>
|
||||||
|
|
@ -62,47 +63,58 @@ namespace Nz
|
||||||
if (m_referenceContext->IsExtensionSupported(GL::Extension::TextureFilterAnisotropic))
|
if (m_referenceContext->IsExtensionSupported(GL::Extension::TextureFilterAnisotropic))
|
||||||
m_deviceInfo.features.anisotropicFiltering = true;
|
m_deviceInfo.features.anisotropicFiltering = true;
|
||||||
|
|
||||||
|
if (m_referenceContext->IsExtensionSupported(GL::Extension::ComputeShader))
|
||||||
|
m_deviceInfo.features.computeShaders = true;
|
||||||
|
|
||||||
if (m_referenceContext->IsExtensionSupported(GL::Extension::DepthClamp))
|
if (m_referenceContext->IsExtensionSupported(GL::Extension::DepthClamp))
|
||||||
m_deviceInfo.features.depthClamping = true;
|
m_deviceInfo.features.depthClamping = true;
|
||||||
|
|
||||||
|
if (m_referenceContext->glPolygonMode) //< not supported in core OpenGL ES, but supported in OpenGL or with GL_NV_polygon_mode extension
|
||||||
|
m_deviceInfo.features.nonSolidFaceFilling = true;
|
||||||
|
|
||||||
if (m_referenceContext->IsExtensionSupported(GL::Extension::StorageBuffers))
|
if (m_referenceContext->IsExtensionSupported(GL::Extension::StorageBuffers))
|
||||||
m_deviceInfo.features.storageBuffers = true;
|
m_deviceInfo.features.storageBuffers = true;
|
||||||
|
|
||||||
if (m_referenceContext->glPolygonMode) //< not supported in core OpenGL ES, but supported in OpenGL or with GL_NV_polygon_mode extension
|
if (m_referenceContext->IsExtensionSupported(GL::Extension::ShaderImageLoadStore))
|
||||||
m_deviceInfo.features.nonSolidFaceFilling = true;
|
{
|
||||||
|
m_deviceInfo.features.textureRead = true;
|
||||||
|
m_deviceInfo.features.textureWrite = true;
|
||||||
|
m_deviceInfo.features.textureWriteWithoutFormat = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_referenceContext->IsExtensionSupported(GL::Extension::ShaderImageLoadFormatted))
|
||||||
|
m_deviceInfo.features.textureReadWithoutFormat = true;
|
||||||
|
|
||||||
if (m_referenceContext->IsExtensionSupported(GL::Extension::TextureView))
|
if (m_referenceContext->IsExtensionSupported(GL::Extension::TextureView))
|
||||||
m_deviceInfo.features.unrestrictedTextureViews = true;
|
m_deviceInfo.features.unrestrictedTextureViews = true;
|
||||||
|
|
||||||
// Limits
|
// Limits
|
||||||
GLint minUboOffsetAlignment;
|
m_deviceInfo.limits.maxUniformBufferSize = m_referenceContext->GetInteger<UInt64>(GL_MAX_UNIFORM_BLOCK_SIZE);
|
||||||
m_referenceContext->glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &minUboOffsetAlignment);
|
m_deviceInfo.limits.minUniformBufferOffsetAlignment = m_referenceContext->GetInteger<UInt64>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
|
||||||
|
|
||||||
assert(minUboOffsetAlignment >= 1);
|
|
||||||
m_deviceInfo.limits.minUniformBufferOffsetAlignment = static_cast<UInt64>(minUboOffsetAlignment);
|
|
||||||
|
|
||||||
GLint maxUboBlockSize;
|
|
||||||
m_referenceContext->glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUboBlockSize);
|
|
||||||
|
|
||||||
assert(maxUboBlockSize >= 1);
|
|
||||||
m_deviceInfo.limits.maxUniformBufferSize = static_cast<UInt64>(maxUboBlockSize);
|
|
||||||
|
|
||||||
if (m_deviceInfo.features.storageBuffers)
|
if (m_deviceInfo.features.storageBuffers)
|
||||||
{
|
{
|
||||||
GLint minStorageOffsetAlignment;
|
m_deviceInfo.limits.maxStorageBufferSize = m_referenceContext->GetInteger<UInt64>(GL_MAX_SHADER_STORAGE_BLOCK_SIZE);
|
||||||
m_referenceContext->glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &minStorageOffsetAlignment);
|
m_deviceInfo.limits.minStorageBufferOffsetAlignment = m_referenceContext->GetInteger<UInt64>(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT);
|
||||||
|
}
|
||||||
assert(minStorageOffsetAlignment >= 1);
|
|
||||||
m_deviceInfo.limits.minStorageBufferOffsetAlignment = static_cast<UInt64>(minStorageOffsetAlignment);
|
if (m_deviceInfo.features.computeShaders)
|
||||||
|
{
|
||||||
GLint maxStorageBlockSize;
|
m_deviceInfo.limits.maxComputeSharedMemorySize = m_referenceContext->GetInteger<UInt64>(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE);
|
||||||
m_referenceContext->glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxStorageBlockSize);
|
m_deviceInfo.limits.maxComputeWorkGroupInvocations = m_referenceContext->GetInteger<UInt32>(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS);
|
||||||
|
|
||||||
assert(maxStorageBlockSize >= 1);
|
m_deviceInfo.limits.maxComputeWorkGroupCount = {
|
||||||
m_deviceInfo.limits.maxStorageBufferSize = static_cast<UInt64>(maxStorageBlockSize);
|
m_referenceContext->GetInteger<UInt32>(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0),
|
||||||
|
m_referenceContext->GetInteger<UInt32>(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1),
|
||||||
|
m_referenceContext->GetInteger<UInt32>(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
m_deviceInfo.limits.maxComputeWorkGroupSize = {
|
||||||
|
m_referenceContext->GetInteger<UInt32>(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0),
|
||||||
|
m_referenceContext->GetInteger<UInt32>(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1),
|
||||||
|
m_referenceContext->GetInteger<UInt32>(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
else
|
|
||||||
m_deviceInfo.limits.maxStorageBufferSize = 0;
|
|
||||||
|
|
||||||
m_contexts.insert(m_referenceContext.get());
|
m_contexts.insert(m_referenceContext.get());
|
||||||
}
|
}
|
||||||
|
|
@ -154,6 +166,11 @@ namespace Nz
|
||||||
return std::make_shared<OpenGLCommandPool>();
|
return std::make_shared<OpenGLCommandPool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ComputePipeline> OpenGLDevice::InstantiateComputePipeline(ComputePipelineInfo pipelineInfo)
|
||||||
|
{
|
||||||
|
return std::make_shared<OpenGLComputePipeline>(*this, std::move(pipelineInfo));
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<Framebuffer> OpenGLDevice::InstantiateFramebuffer(unsigned int /*width*/, unsigned int /*height*/, const std::shared_ptr<RenderPass>& /*renderPass*/, const std::vector<std::shared_ptr<Texture>>& attachments)
|
std::shared_ptr<Framebuffer> OpenGLDevice::InstantiateFramebuffer(unsigned int /*width*/, unsigned int /*height*/, const std::shared_ptr<RenderPass>& /*renderPass*/, const std::vector<std::shared_ptr<Texture>>& attachments)
|
||||||
{
|
{
|
||||||
return std::make_shared<OpenGLFboFramebuffer>(*this, attachments);
|
return std::make_shared<OpenGLFboFramebuffer>(*this, attachments);
|
||||||
|
|
@ -246,7 +263,7 @@ namespace Nz
|
||||||
case PixelFormat::RGBA32F:
|
case PixelFormat::RGBA32F:
|
||||||
case PixelFormat::RGBA32I:
|
case PixelFormat::RGBA32I:
|
||||||
case PixelFormat::RGBA32UI:
|
case PixelFormat::RGBA32UI:
|
||||||
return usage == TextureUsage::ColorAttachment || usage == TextureUsage::InputAttachment || usage == TextureUsage::ShaderSampling || usage == TextureUsage::TransferDestination || usage == TextureUsage::TransferSource;
|
return usage == TextureUsage::ColorAttachment || usage == TextureUsage::InputAttachment || usage == TextureUsage::ShaderSampling || usage == TextureUsage::ShaderReadWrite || usage == TextureUsage::TransferDestination || usage == TextureUsage::TransferSource;
|
||||||
|
|
||||||
case PixelFormat::DXT1:
|
case PixelFormat::DXT1:
|
||||||
case PixelFormat::DXT3:
|
case PixelFormat::DXT3:
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ namespace Nz
|
||||||
if (location == -1)
|
if (location == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
m_program.Uniform(location, static_cast<int>(explicitBinding.binding)); //< FIXME: Use SafeCast
|
m_program.Uniform(location, SafeCast<int>(explicitBinding.binding));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,16 @@ namespace Nz
|
||||||
return ShaderBindingPtr(PlacementNew(freeBindingMemory, *this, poolIndex, freeBindingId));
|
return ShaderBindingPtr(PlacementNew(freeBindingMemory, *this, poolIndex, freeBindingId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto OpenGLRenderPipelineLayout::GetSampledTextureDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t descriptorIndex) -> SampledTextureDescriptor&
|
||||||
|
{
|
||||||
|
assert(poolIndex < m_descriptorPools.size());
|
||||||
|
auto& pool = m_descriptorPools[poolIndex];
|
||||||
|
assert(!pool.freeBindings.Test(bindingIndex));
|
||||||
|
assert(descriptorIndex < m_maxDescriptorCount);
|
||||||
|
|
||||||
|
return pool.descriptors[bindingIndex * m_maxDescriptorCount + descriptorIndex].emplace<SampledTextureDescriptor>();
|
||||||
|
}
|
||||||
|
|
||||||
auto OpenGLRenderPipelineLayout::GetStorageBufferDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t descriptorIndex) -> StorageBufferDescriptor&
|
auto OpenGLRenderPipelineLayout::GetStorageBufferDescriptor(std::size_t poolIndex, std::size_t bindingIndex, std::size_t descriptorIndex) -> StorageBufferDescriptor&
|
||||||
{
|
{
|
||||||
assert(poolIndex < m_descriptorPools.size());
|
assert(poolIndex < m_descriptorPools.size());
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,15 @@ namespace Nz
|
||||||
|
|
||||||
UInt32 bindingPoint = bindingMappingIt->second;
|
UInt32 bindingPoint = bindingMappingIt->second;
|
||||||
|
|
||||||
if constexpr (std::is_same_v<DescriptorType, OpenGLRenderPipelineLayout::StorageBufferDescriptor>)
|
if constexpr (std::is_same_v<DescriptorType, OpenGLRenderPipelineLayout::SampledTextureDescriptor>)
|
||||||
|
{
|
||||||
|
if (bindingInfo.type != ShaderBindingType::Sampler)
|
||||||
|
throw std::runtime_error("descriptor (set=" + std::to_string(setIndex) + ", binding=" + std::to_string(bindingIndex) + ") is not a sampler");
|
||||||
|
|
||||||
|
context.BindSampler(bindingPoint, descriptor.sampler);
|
||||||
|
context.BindTexture(bindingPoint, descriptor.textureTarget, descriptor.texture);
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<DescriptorType, OpenGLRenderPipelineLayout::StorageBufferDescriptor>)
|
||||||
{
|
{
|
||||||
if (bindingInfo.type != ShaderBindingType::StorageBuffer)
|
if (bindingInfo.type != ShaderBindingType::StorageBuffer)
|
||||||
throw std::runtime_error("descriptor (set=" + std::to_string(setIndex) + ", binding=" + std::to_string(bindingIndex) + ") is not a storage buffer");
|
throw std::runtime_error("descriptor (set=" + std::to_string(setIndex) + ", binding=" + std::to_string(bindingIndex) + ") is not a storage buffer");
|
||||||
|
|
@ -57,8 +65,7 @@ namespace Nz
|
||||||
if (bindingInfo.type != ShaderBindingType::Texture)
|
if (bindingInfo.type != ShaderBindingType::Texture)
|
||||||
throw std::runtime_error("descriptor (set=" + std::to_string(setIndex) + ", binding=" + std::to_string(bindingIndex) + ") is not a texture");
|
throw std::runtime_error("descriptor (set=" + std::to_string(setIndex) + ", binding=" + std::to_string(bindingIndex) + ") is not a texture");
|
||||||
|
|
||||||
context.BindSampler(bindingPoint, descriptor.sampler);
|
context.BindImageTexture(bindingPoint, descriptor.texture, descriptor.level, descriptor.layered, descriptor.layer, descriptor.access, descriptor.format);
|
||||||
context.BindTexture(bindingPoint, descriptor.textureTarget, descriptor.texture);
|
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<DescriptorType, OpenGLRenderPipelineLayout::UniformBufferDescriptor>)
|
else if constexpr (std::is_same_v<DescriptorType, OpenGLRenderPipelineLayout::UniformBufferDescriptor>)
|
||||||
{
|
{
|
||||||
|
|
@ -82,7 +89,14 @@ namespace Nz
|
||||||
{
|
{
|
||||||
using T = std::decay_t<decltype(arg)>;
|
using T = std::decay_t<decltype(arg)>;
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, StorageBufferBinding>)
|
if constexpr (std::is_same_v<T, SampledTextureBinding>)
|
||||||
|
HandleTextureBinding(binding.bindingIndex, arg);
|
||||||
|
else if constexpr (std::is_same_v<T, SampledTextureBindings>)
|
||||||
|
{
|
||||||
|
for (UInt32 i = 0; i < arg.arraySize; ++i)
|
||||||
|
HandleTextureBinding(binding.bindingIndex + i, arg.textureBindings[i]);
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, StorageBufferBinding>)
|
||||||
{
|
{
|
||||||
auto& storageDescriptor = m_owner.GetStorageBufferDescriptor(m_poolIndex, m_bindingIndex, binding.bindingIndex);
|
auto& storageDescriptor = m_owner.GetStorageBufferDescriptor(m_poolIndex, m_bindingIndex, binding.bindingIndex);
|
||||||
storageDescriptor.offset = arg.offset;
|
storageDescriptor.offset = arg.offset;
|
||||||
|
|
@ -99,11 +113,41 @@ namespace Nz
|
||||||
storageDescriptor.buffer = 0;
|
storageDescriptor.buffer = 0;
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<T, TextureBinding>)
|
else if constexpr (std::is_same_v<T, TextureBinding>)
|
||||||
HandleTextureBinding(binding.bindingIndex, arg);
|
|
||||||
else if constexpr (std::is_same_v<T, TextureBindings>)
|
|
||||||
{
|
{
|
||||||
for (UInt32 i = 0; i < arg.arraySize; ++i)
|
auto& textureDescriptor = m_owner.GetTextureDescriptor(m_poolIndex, m_bindingIndex, binding.bindingIndex);
|
||||||
HandleTextureBinding(binding.bindingIndex + i, arg.textureBindings[i]);
|
if (const OpenGLTexture* glTexture = static_cast<const OpenGLTexture*>(arg.texture))
|
||||||
|
{
|
||||||
|
const TextureViewInfo& viewInfo = glTexture->GetTextureViewInfo();
|
||||||
|
|
||||||
|
std::optional<GLTextureFormat> format = DescribeTextureFormat(viewInfo.reinterpretFormat);
|
||||||
|
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;
|
||||||
|
textureDescriptor.texture = glTexture->GetTexture().GetObjectId();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
textureDescriptor.access = GL_READ_ONLY;
|
||||||
|
textureDescriptor.format = GL_RGBA8;
|
||||||
|
textureDescriptor.layer = 0;
|
||||||
|
textureDescriptor.layered = GL_FALSE;
|
||||||
|
textureDescriptor.level = 0;
|
||||||
|
textureDescriptor.texture = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<T, UniformBufferBinding>)
|
else if constexpr (std::is_same_v<T, UniformBufferBinding>)
|
||||||
{
|
{
|
||||||
|
|
@ -133,9 +177,9 @@ namespace Nz
|
||||||
// No OpenGL object to name
|
// No OpenGL object to name
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLShaderBinding::HandleTextureBinding(UInt32 bindingIndex, const TextureBinding& textureBinding)
|
void OpenGLShaderBinding::HandleTextureBinding(UInt32 bindingIndex, const SampledTextureBinding& textureBinding)
|
||||||
{
|
{
|
||||||
auto& textureDescriptor = m_owner.GetTextureDescriptor(m_poolIndex, m_bindingIndex, bindingIndex);
|
auto& textureDescriptor = m_owner.GetSampledTextureDescriptor(m_poolIndex, m_bindingIndex, bindingIndex);
|
||||||
|
|
||||||
if (const OpenGLTexture* glTexture = static_cast<const OpenGLTexture*>(textureBinding.texture))
|
if (const OpenGLTexture* glTexture = static_cast<const OpenGLTexture*>(textureBinding.texture))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,32 @@ namespace Nz::GL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Context::BindImageTexture(GLuint imageUnit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) const
|
||||||
|
{
|
||||||
|
if (imageUnit >= m_state.imageUnits.size())
|
||||||
|
throw std::runtime_error("unsupported image unit #" + std::to_string(imageUnit));
|
||||||
|
|
||||||
|
layer = (layered == GL_TRUE) ? layer : 0;
|
||||||
|
|
||||||
|
auto& unit = m_state.imageUnits[imageUnit];
|
||||||
|
if (unit.texture != texture || unit.level != level || unit.layered != layered || unit.layer != layer || unit.access != access || unit.format != format)
|
||||||
|
{
|
||||||
|
if (!SetCurrentContext(this))
|
||||||
|
throw std::runtime_error("failed to activate context");
|
||||||
|
|
||||||
|
if (!glBindImageTexture)
|
||||||
|
throw std::runtime_error("image binding is not supported");
|
||||||
|
|
||||||
|
glBindImageTexture(imageUnit, texture, level, layered, layer, access, format);
|
||||||
|
unit.access = access;
|
||||||
|
unit.format = format;
|
||||||
|
unit.layer = layer;
|
||||||
|
unit.layered = layered;
|
||||||
|
unit.level = level;
|
||||||
|
unit.texture = texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Context::BindProgram(GLuint program) const
|
void Context::BindProgram(GLuint program) const
|
||||||
{
|
{
|
||||||
if (m_state.boundProgram != program)
|
if (m_state.boundProgram != program)
|
||||||
|
|
@ -413,21 +439,13 @@ namespace Nz::GL
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLint majorVersion = 0;
|
m_params.glMajorVersion = GetInteger<unsigned int>(GL_MAJOR_VERSION);
|
||||||
glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
|
m_params.glMinorVersion = GetInteger<unsigned int>(GL_MINOR_VERSION);
|
||||||
|
|
||||||
GLint minorVersion = 0;
|
unsigned int glVersion = m_params.glMajorVersion * 100 + m_params.glMinorVersion * 10;
|
||||||
glGetIntegerv(GL_MINOR_VERSION, &minorVersion);
|
|
||||||
|
|
||||||
m_params.glMajorVersion = majorVersion;
|
|
||||||
m_params.glMinorVersion = minorVersion;
|
|
||||||
|
|
||||||
unsigned int glVersion = majorVersion * 100 + minorVersion * 10;
|
|
||||||
|
|
||||||
// Load extensions
|
// Load extensions
|
||||||
GLint extensionCount = 0;
|
GLint extensionCount = GetInteger<GLint>(GL_NUM_EXTENSIONS);
|
||||||
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
|
|
||||||
|
|
||||||
for (GLint i = 0; i < extensionCount; ++i)
|
for (GLint i = 0; i < extensionCount; ++i)
|
||||||
m_supportedExtensions.emplace(reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i)));
|
m_supportedExtensions.emplace(reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i)));
|
||||||
|
|
||||||
|
|
@ -441,6 +459,12 @@ namespace Nz::GL
|
||||||
else if (m_supportedExtensions.count("GL_EXT_clip_control"))
|
else if (m_supportedExtensions.count("GL_EXT_clip_control"))
|
||||||
m_extensionStatus[UnderlyingCast(Extension::ClipControl)] = ExtensionStatus::EXT;
|
m_extensionStatus[UnderlyingCast(Extension::ClipControl)] = ExtensionStatus::EXT;
|
||||||
|
|
||||||
|
// Compute shaders
|
||||||
|
if ((m_params.type == ContextType::OpenGL && glVersion >= 430) || (m_params.type == ContextType::OpenGL_ES && glVersion >= 310))
|
||||||
|
m_extensionStatus[UnderlyingCast(Extension::ComputeShader)] = ExtensionStatus::Core;
|
||||||
|
else if (m_supportedExtensions.count("GL_ARB_compute_shader"))
|
||||||
|
m_extensionStatus[UnderlyingCast(Extension::ComputeShader)] = ExtensionStatus::ARB;
|
||||||
|
|
||||||
// Debug output
|
// Debug output
|
||||||
if ((m_params.type == ContextType::OpenGL && glVersion >= 430) || (m_params.type == ContextType::OpenGL_ES && glVersion >= 320))
|
if ((m_params.type == ContextType::OpenGL && glVersion >= 430) || (m_params.type == ContextType::OpenGL_ES && glVersion >= 320))
|
||||||
m_extensionStatus[UnderlyingCast(Extension::DebugOutput)] = ExtensionStatus::Core;
|
m_extensionStatus[UnderlyingCast(Extension::DebugOutput)] = ExtensionStatus::Core;
|
||||||
|
|
@ -465,6 +489,18 @@ namespace Nz::GL
|
||||||
else if (m_supportedExtensions.count("GL_NV_polygon_mode"))
|
else if (m_supportedExtensions.count("GL_NV_polygon_mode"))
|
||||||
m_extensionStatus[UnderlyingCast(Extension::DepthClamp)] = ExtensionStatus::Vendor;
|
m_extensionStatus[UnderlyingCast(Extension::DepthClamp)] = ExtensionStatus::Vendor;
|
||||||
|
|
||||||
|
// Shader image load formatted
|
||||||
|
if (m_supportedExtensions.count("GL_EXT_shader_image_load_formatted"))
|
||||||
|
m_extensionStatus[UnderlyingCast(Extension::ShaderImageLoadFormatted)] = ExtensionStatus::EXT;
|
||||||
|
|
||||||
|
// Shader image load/store
|
||||||
|
if ((m_params.type == ContextType::OpenGL && glVersion >= 420) || (m_params.type == ContextType::OpenGL_ES && glVersion >= 310))
|
||||||
|
m_extensionStatus[UnderlyingCast(Extension::ShaderImageLoadStore)] = ExtensionStatus::Core;
|
||||||
|
else if (m_supportedExtensions.count("GL_ARB_shader_image_load_store"))
|
||||||
|
m_extensionStatus[UnderlyingCast(Extension::ShaderImageLoadStore)] = ExtensionStatus::ARB;
|
||||||
|
else if (m_supportedExtensions.count("GL_EXT_shader_image_load_store"))
|
||||||
|
m_extensionStatus[UnderlyingCast(Extension::ShaderImageLoadStore)] = ExtensionStatus::EXT;
|
||||||
|
|
||||||
// SPIR-V support
|
// SPIR-V support
|
||||||
if (m_params.type == ContextType::OpenGL && glVersion >= 460)
|
if (m_params.type == ContextType::OpenGL && glVersion >= 460)
|
||||||
m_extensionStatus[UnderlyingCast(Extension::SpirV)] = ExtensionStatus::Core;
|
m_extensionStatus[UnderlyingCast(Extension::SpirV)] = ExtensionStatus::Core;
|
||||||
|
|
@ -583,16 +619,14 @@ namespace Nz::GL
|
||||||
else
|
else
|
||||||
m_params.validationLevel = m_params.validationLevel;
|
m_params.validationLevel = m_params.validationLevel;
|
||||||
|
|
||||||
GLint maxTextureUnits = -1;
|
unsigned int maxTextureUnits = GetInteger<unsigned int>(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
|
||||||
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
|
|
||||||
if (maxTextureUnits < 32) //< OpenGL ES 3.0 requires at least 32 textures units
|
if (maxTextureUnits < 32) //< OpenGL ES 3.0 requires at least 32 textures units
|
||||||
NazaraWarning("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is " + std::to_string(maxTextureUnits) + ", expected >= 32");
|
NazaraWarning("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is " + std::to_string(maxTextureUnits) + ", expected >= 32");
|
||||||
|
|
||||||
assert(maxTextureUnits > 0);
|
assert(maxTextureUnits > 0);
|
||||||
m_state.textureUnits.resize(maxTextureUnits);
|
m_state.textureUnits.resize(maxTextureUnits);
|
||||||
|
|
||||||
GLint maxUniformBufferUnits = -1;
|
unsigned int maxUniformBufferUnits = GetInteger<unsigned int>(GL_MAX_UNIFORM_BUFFER_BINDINGS);
|
||||||
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxUniformBufferUnits);
|
|
||||||
if (maxUniformBufferUnits < 24) //< OpenGL ES 3.0 requires at least 24 uniform buffers units
|
if (maxUniformBufferUnits < 24) //< OpenGL ES 3.0 requires at least 24 uniform buffers units
|
||||||
NazaraWarning("GL_MAX_UNIFORM_BUFFER_BINDINGS is " + std::to_string(maxUniformBufferUnits) + ", expected >= 24");
|
NazaraWarning("GL_MAX_UNIFORM_BUFFER_BINDINGS is " + std::to_string(maxUniformBufferUnits) + ", expected >= 24");
|
||||||
|
|
||||||
|
|
@ -601,8 +635,7 @@ namespace Nz::GL
|
||||||
|
|
||||||
if (IsExtensionSupported(Extension::StorageBuffers))
|
if (IsExtensionSupported(Extension::StorageBuffers))
|
||||||
{
|
{
|
||||||
GLint maxStorageBufferUnits = -1;
|
unsigned int maxStorageBufferUnits = GetInteger<unsigned int>(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
|
||||||
glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxStorageBufferUnits);
|
|
||||||
if (maxStorageBufferUnits < 8) //< OpenGL ES 3.1 requires at least 8 storage buffers units
|
if (maxStorageBufferUnits < 8) //< OpenGL ES 3.1 requires at least 8 storage buffers units
|
||||||
NazaraWarning("GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS is " + std::to_string(maxUniformBufferUnits) + ", expected >= 8");
|
NazaraWarning("GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS is " + std::to_string(maxUniformBufferUnits) + ", expected >= 8");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - Renderer module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Renderer/ComputePipeline.hpp>
|
||||||
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
ComputePipeline::~ComputePipeline() = default;
|
||||||
|
}
|
||||||
|
|
@ -83,7 +83,7 @@ namespace Nz
|
||||||
return;
|
return;
|
||||||
|
|
||||||
builder.BindShaderBinding(0, *m_currentViewerData.binding);
|
builder.BindShaderBinding(0, *m_currentViewerData.binding);
|
||||||
builder.BindPipeline(*m_renderPipeline);
|
builder.BindRenderPipeline(*m_renderPipeline);
|
||||||
|
|
||||||
for (auto& drawCall : m_drawCalls)
|
for (auto& drawCall : m_drawCalls)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,14 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
NzValidateFeature(anisotropicFiltering, "anistropic filtering feature")
|
NzValidateFeature(anisotropicFiltering, "anistropic filtering feature")
|
||||||
|
NzValidateFeature(computeShaders, "compute shaders feature")
|
||||||
NzValidateFeature(depthClamping, "depth clamping feature")
|
NzValidateFeature(depthClamping, "depth clamping feature")
|
||||||
NzValidateFeature(nonSolidFaceFilling, "non-solid face filling feature")
|
NzValidateFeature(nonSolidFaceFilling, "non-solid face filling feature")
|
||||||
NzValidateFeature(storageBuffers, "storage buffers support")
|
NzValidateFeature(storageBuffers, "storage buffers support")
|
||||||
|
NzValidateFeature(textureRead, "texture read")
|
||||||
|
NzValidateFeature(textureReadWithoutFormat, "texture read without format")
|
||||||
|
NzValidateFeature(textureWrite, "texture write")
|
||||||
|
NzValidateFeature(textureWriteWithoutFormat, "texture write without format")
|
||||||
NzValidateFeature(unrestrictedTextureViews, "unrestricted texture view support")
|
NzValidateFeature(unrestrictedTextureViews, "unrestricted texture view support")
|
||||||
|
|
||||||
#undef NzValidateFeature
|
#undef NzValidateFeature
|
||||||
|
|
|
||||||
|
|
@ -243,7 +243,7 @@ namespace Nz
|
||||||
|
|
||||||
void Seek(UInt64 frameIndex) override
|
void Seek(UInt64 frameIndex) override
|
||||||
{
|
{
|
||||||
assert(frameIndex < m_frames.size());
|
assert(frameIndex <= m_frames.size());
|
||||||
|
|
||||||
if (m_requiresFrameHistory)
|
if (m_requiresFrameHistory)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,20 @@ namespace Nz
|
||||||
deviceInfo.name = physDevice.properties.deviceName;
|
deviceInfo.name = physDevice.properties.deviceName;
|
||||||
|
|
||||||
deviceInfo.features.anisotropicFiltering = physDevice.features.samplerAnisotropy;
|
deviceInfo.features.anisotropicFiltering = physDevice.features.samplerAnisotropy;
|
||||||
|
deviceInfo.features.computeShaders = true;
|
||||||
deviceInfo.features.depthClamping = physDevice.features.depthClamp;
|
deviceInfo.features.depthClamping = physDevice.features.depthClamp;
|
||||||
deviceInfo.features.nonSolidFaceFilling = physDevice.features.fillModeNonSolid;
|
deviceInfo.features.nonSolidFaceFilling = physDevice.features.fillModeNonSolid;
|
||||||
deviceInfo.features.storageBuffers = true;
|
deviceInfo.features.storageBuffers = true;
|
||||||
|
deviceInfo.features.textureRead = true;
|
||||||
|
deviceInfo.features.textureReadWithoutFormat = physDevice.features.shaderStorageImageReadWithoutFormat;
|
||||||
|
deviceInfo.features.textureWrite = true;
|
||||||
|
deviceInfo.features.textureWriteWithoutFormat = physDevice.features.shaderStorageImageWriteWithoutFormat;
|
||||||
deviceInfo.features.unrestrictedTextureViews = true;
|
deviceInfo.features.unrestrictedTextureViews = true;
|
||||||
|
|
||||||
|
deviceInfo.limits.maxComputeSharedMemorySize = physDevice.properties.limits.maxComputeSharedMemorySize;
|
||||||
|
deviceInfo.limits.maxComputeWorkGroupCount = { physDevice.properties.limits.maxComputeWorkGroupCount[0], physDevice.properties.limits.maxComputeWorkGroupCount[1], physDevice.properties.limits.maxComputeWorkGroupCount[2] };
|
||||||
|
deviceInfo.limits.maxComputeWorkGroupSize = { physDevice.properties.limits.maxComputeWorkGroupSize[0], physDevice.properties.limits.maxComputeWorkGroupSize[1], physDevice.properties.limits.maxComputeWorkGroupSize[2] };
|
||||||
|
deviceInfo.limits.maxComputeWorkGroupInvocations = physDevice.properties.limits.maxComputeWorkGroupInvocations;
|
||||||
deviceInfo.limits.maxStorageBufferSize = physDevice.properties.limits.maxStorageBufferRange;
|
deviceInfo.limits.maxStorageBufferSize = physDevice.properties.limits.maxStorageBufferRange;
|
||||||
deviceInfo.limits.maxUniformBufferSize = physDevice.properties.limits.maxUniformBufferRange;
|
deviceInfo.limits.maxUniformBufferSize = physDevice.properties.limits.maxUniformBufferRange;
|
||||||
deviceInfo.limits.minStorageBufferOffsetAlignment = physDevice.properties.limits.minStorageBufferOffsetAlignment;
|
deviceInfo.limits.minStorageBufferOffsetAlignment = physDevice.properties.limits.minStorageBufferOffsetAlignment;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <Nazara/VulkanRenderer/VulkanCommandBufferBuilder.hpp>
|
#include <Nazara/VulkanRenderer/VulkanCommandBufferBuilder.hpp>
|
||||||
#include <Nazara/Utility/PixelFormat.hpp>
|
#include <Nazara/Utility/PixelFormat.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanBuffer.hpp>
|
#include <Nazara/VulkanRenderer/VulkanBuffer.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/VulkanComputePipeline.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanRenderPass.hpp>
|
#include <Nazara/VulkanRenderer/VulkanRenderPass.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanRenderPipeline.hpp>
|
#include <Nazara/VulkanRenderer/VulkanRenderPipeline.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp>
|
#include <Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp>
|
||||||
|
|
@ -72,6 +73,13 @@ namespace Nz
|
||||||
m_currentSubpassIndex = 0;
|
m_currentSubpassIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VulkanCommandBufferBuilder::BindComputePipeline(const ComputePipeline& pipeline)
|
||||||
|
{
|
||||||
|
const VulkanComputePipeline& vkPipeline = static_cast<const VulkanComputePipeline&>(pipeline);
|
||||||
|
|
||||||
|
m_commandBuffer.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vkPipeline.GetPipeline());
|
||||||
|
}
|
||||||
|
|
||||||
void VulkanCommandBufferBuilder::BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset)
|
void VulkanCommandBufferBuilder::BindIndexBuffer(const RenderBuffer& indexBuffer, IndexType indexType, UInt64 offset)
|
||||||
{
|
{
|
||||||
const VulkanBuffer& vkBuffer = static_cast<const VulkanBuffer&>(indexBuffer);
|
const VulkanBuffer& vkBuffer = static_cast<const VulkanBuffer&>(indexBuffer);
|
||||||
|
|
@ -79,14 +87,14 @@ namespace Nz
|
||||||
m_commandBuffer.BindIndexBuffer(vkBuffer.GetBuffer(), offset, ToVulkan(indexType));
|
m_commandBuffer.BindIndexBuffer(vkBuffer.GetBuffer(), offset, ToVulkan(indexType));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanCommandBufferBuilder::BindPipeline(const RenderPipeline& pipeline)
|
void VulkanCommandBufferBuilder::BindRenderPipeline(const RenderPipeline& pipeline)
|
||||||
{
|
{
|
||||||
if (!m_currentRenderPass)
|
if (!m_currentRenderPass)
|
||||||
throw std::runtime_error("BindPipeline must be called in a RenderPass");
|
throw std::runtime_error("BindPipeline must be called in a RenderPass");
|
||||||
|
|
||||||
const VulkanRenderPipeline& vkBinding = static_cast<const VulkanRenderPipeline&>(pipeline);
|
const VulkanRenderPipeline& vkPipeline = static_cast<const VulkanRenderPipeline&>(pipeline);
|
||||||
|
|
||||||
m_commandBuffer.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, vkBinding.Get(*m_currentRenderPass, m_currentSubpassIndex));
|
m_commandBuffer.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, vkPipeline.Get(*m_currentRenderPass, m_currentSubpassIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanCommandBufferBuilder::BindShaderBinding(UInt32 set, const ShaderBinding& binding)
|
void VulkanCommandBufferBuilder::BindShaderBinding(UInt32 set, const ShaderBinding& binding)
|
||||||
|
|
@ -207,6 +215,11 @@ namespace Nz
|
||||||
m_commandBuffer.CopyImage(vkFromTexture.GetImage(), ToVulkan(fromLayout), vkToTexture.GetImage(), ToVulkan(toLayout), region);
|
m_commandBuffer.CopyImage(vkFromTexture.GetImage(), ToVulkan(fromLayout), vkToTexture.GetImage(), ToVulkan(toLayout), region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VulkanCommandBufferBuilder::Dispatch(UInt32 workgroupX, UInt32 workgroupY, UInt32 workgroupZ)
|
||||||
|
{
|
||||||
|
m_commandBuffer.Dispatch(workgroupX, workgroupY, workgroupZ);
|
||||||
|
}
|
||||||
|
|
||||||
void VulkanCommandBufferBuilder::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance)
|
void VulkanCommandBufferBuilder::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance)
|
||||||
{
|
{
|
||||||
m_commandBuffer.Draw(vertexCount, instanceCount, firstVertex, firstInstance);
|
m_commandBuffer.Draw(vertexCount, instanceCount, firstVertex, firstInstance);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - Vulkan renderer"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/VulkanRenderer/VulkanComputePipeline.hpp>
|
||||||
|
#include <Nazara/Core/ErrorFlags.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/Utils.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/VulkanComputePipeline.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/VulkanShaderModule.hpp>
|
||||||
|
#include <cassert>
|
||||||
|
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
VulkanComputePipeline::VulkanComputePipeline(VulkanDevice& device, ComputePipelineInfo pipelineInfo) :
|
||||||
|
m_pipelineInfo(std::move(pipelineInfo))
|
||||||
|
{
|
||||||
|
if (device.GetEnabledFeatures().computeShaders)
|
||||||
|
throw std::runtime_error("compute shaders are not enabled on the device");
|
||||||
|
|
||||||
|
VulkanShaderModule& vulkanModule = static_cast<VulkanShaderModule&>(*m_pipelineInfo.shaderModule);
|
||||||
|
const VulkanShaderModule::Stage* computeStage = nullptr;
|
||||||
|
for (const auto& stage : vulkanModule.GetStages())
|
||||||
|
{
|
||||||
|
if (stage.stage != nzsl::ShaderStageType::Compute)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (computeStage)
|
||||||
|
throw std::runtime_error("multiple compute stages found in shader module");
|
||||||
|
|
||||||
|
computeStage = &stage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!computeStage)
|
||||||
|
throw std::runtime_error("no compute stages found in shader module");
|
||||||
|
|
||||||
|
VkComputePipelineCreateInfo createInfo = {};
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
||||||
|
createInfo.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
|
createInfo.stage.module = vulkanModule.GetHandle();
|
||||||
|
createInfo.stage.pName = computeStage->name.data();
|
||||||
|
createInfo.stage.stage = ToVulkan(computeStage->stage);
|
||||||
|
|
||||||
|
VulkanRenderPipelineLayout& pipelineLayout = *static_cast<VulkanRenderPipelineLayout*>(m_pipelineInfo.pipelineLayout.get());
|
||||||
|
createInfo.layout = pipelineLayout.GetPipelineLayout();
|
||||||
|
|
||||||
|
if (!m_pipeline.CreateCompute(device, createInfo))
|
||||||
|
throw std::runtime_error("failed to create compute pipeline: " + TranslateVulkanError(m_pipeline.GetLastErrorCode()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanComputePipeline::UpdateDebugName(std::string_view name)
|
||||||
|
{
|
||||||
|
m_pipeline.SetDebugName(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
|
#include <Nazara/Core/AntiWindows.hpp>
|
||||||
|
#endif
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
|
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanCommandPool.hpp>
|
#include <Nazara/VulkanRenderer/VulkanCommandPool.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/VulkanComputePipeline.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanRenderPass.hpp>
|
#include <Nazara/VulkanRenderer/VulkanRenderPass.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanRenderPipeline.hpp>
|
#include <Nazara/VulkanRenderer/VulkanRenderPipeline.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp>
|
#include <Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp>
|
||||||
|
|
@ -37,6 +38,11 @@ namespace Nz
|
||||||
return std::make_shared<VulkanCommandPool>(*this, queueType);
|
return std::make_shared<VulkanCommandPool>(*this, queueType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ComputePipeline> VulkanDevice::InstantiateComputePipeline(ComputePipelineInfo pipelineInfo)
|
||||||
|
{
|
||||||
|
return std::make_shared<VulkanComputePipeline>(*this, std::move(pipelineInfo));
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<Framebuffer> VulkanDevice::InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr<RenderPass>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments)
|
std::shared_ptr<Framebuffer> VulkanDevice::InstantiateFramebuffer(unsigned int width, unsigned int height, const std::shared_ptr<RenderPass>& renderPass, const std::vector<std::shared_ptr<Texture>>& attachments)
|
||||||
{
|
{
|
||||||
return std::make_shared<VulkanTextureFramebuffer>(*this, width, height, renderPass, attachments);
|
return std::make_shared<VulkanTextureFramebuffer>(*this, width, height, renderPass, attachments);
|
||||||
|
|
@ -111,6 +117,10 @@ namespace Nz
|
||||||
flags = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
|
flags = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TextureUsage::ShaderReadWrite:
|
||||||
|
flags = VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
|
||||||
|
break;
|
||||||
|
|
||||||
case TextureUsage::TransferSource:
|
case TextureUsage::TransferSource:
|
||||||
flags = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT;
|
flags = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@ namespace Nz
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, StorageBufferBinding> || std::is_same_v<T, UniformBufferBinding>)
|
if constexpr (std::is_same_v<T, StorageBufferBinding> || std::is_same_v<T, UniformBufferBinding>)
|
||||||
bufferBindingCount++;
|
bufferBindingCount++;
|
||||||
else if constexpr (std::is_same_v<T, TextureBinding>)
|
else if constexpr (std::is_same_v<T, SampledTextureBinding> || std::is_same_v<T, TextureBinding>)
|
||||||
imageBindingCount++;
|
imageBindingCount++;
|
||||||
else if constexpr (std::is_same_v<T, TextureBindings>)
|
else if constexpr (std::is_same_v<T, SampledTextureBindings>)
|
||||||
imageBindingCount += arg.arraySize;
|
imageBindingCount += arg.arraySize;
|
||||||
else
|
else
|
||||||
static_assert(AlwaysFalse<T>(), "non-exhaustive visitor");
|
static_assert(AlwaysFalse<T>(), "non-exhaustive visitor");
|
||||||
|
|
@ -58,20 +58,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
using T = std::decay_t<decltype(arg)>;
|
using T = std::decay_t<decltype(arg)>;
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, StorageBufferBinding>)
|
if constexpr (std::is_same_v<T, SampledTextureBinding>)
|
||||||
{
|
|
||||||
VulkanBuffer* vkBuffer = SafeCast<VulkanBuffer*>(arg.buffer);
|
|
||||||
|
|
||||||
VkDescriptorBufferInfo& bufferInfo = bufferBinding.emplace_back();
|
|
||||||
bufferInfo.buffer = (vkBuffer) ? vkBuffer->GetBuffer() : VK_NULL_HANDLE;
|
|
||||||
bufferInfo.offset = arg.offset;
|
|
||||||
bufferInfo.range = arg.range;
|
|
||||||
|
|
||||||
writeOp.descriptorCount = 1;
|
|
||||||
writeOp.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
||||||
writeOp.pBufferInfo = &bufferInfo;
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, TextureBinding>)
|
|
||||||
{
|
{
|
||||||
const VulkanTexture* vkTexture = SafeCast<const VulkanTexture*>(arg.texture);
|
const VulkanTexture* vkTexture = SafeCast<const VulkanTexture*>(arg.texture);
|
||||||
const VulkanTextureSampler* vkSampler = SafeCast<const VulkanTextureSampler*>(arg.sampler);
|
const VulkanTextureSampler* vkSampler = SafeCast<const VulkanTextureSampler*>(arg.sampler);
|
||||||
|
|
@ -85,7 +72,7 @@ namespace Nz
|
||||||
writeOp.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
writeOp.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
writeOp.pImageInfo = &imageInfo;
|
writeOp.pImageInfo = &imageInfo;
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<T, TextureBindings>)
|
else if constexpr (std::is_same_v<T, SampledTextureBindings>)
|
||||||
{
|
{
|
||||||
for (UInt32 i = 0; i < arg.arraySize; ++i)
|
for (UInt32 i = 0; i < arg.arraySize; ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -102,6 +89,32 @@ namespace Nz
|
||||||
writeOp.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
writeOp.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
writeOp.pImageInfo = &imageBinding[imageBinding.size() - arg.arraySize];
|
writeOp.pImageInfo = &imageBinding[imageBinding.size() - arg.arraySize];
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, StorageBufferBinding>)
|
||||||
|
{
|
||||||
|
VulkanBuffer* vkBuffer = SafeCast<VulkanBuffer*>(arg.buffer);
|
||||||
|
|
||||||
|
VkDescriptorBufferInfo& bufferInfo = bufferBinding.emplace_back();
|
||||||
|
bufferInfo.buffer = (vkBuffer) ? vkBuffer->GetBuffer() : VK_NULL_HANDLE;
|
||||||
|
bufferInfo.offset = arg.offset;
|
||||||
|
bufferInfo.range = arg.range;
|
||||||
|
|
||||||
|
writeOp.descriptorCount = 1;
|
||||||
|
writeOp.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||||
|
writeOp.pBufferInfo = &bufferInfo;
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, TextureBinding>)
|
||||||
|
{
|
||||||
|
const VulkanTexture* vkTexture = SafeCast<const VulkanTexture*>(arg.texture);
|
||||||
|
|
||||||
|
VkDescriptorImageInfo& imageInfo = imageBinding.emplace_back();
|
||||||
|
imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
imageInfo.imageView = (vkTexture) ? vkTexture->GetImageView() : VK_NULL_HANDLE;
|
||||||
|
imageInfo.sampler = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
writeOp.descriptorCount = 1;
|
||||||
|
writeOp.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||||
|
writeOp.pImageInfo = &imageInfo;
|
||||||
|
}
|
||||||
else if constexpr (std::is_same_v<T, UniformBufferBinding>)
|
else if constexpr (std::is_same_v<T, UniformBufferBinding>)
|
||||||
{
|
{
|
||||||
VulkanBuffer* vkBuffer = static_cast<VulkanBuffer*>(arg.buffer);
|
VulkanBuffer* vkBuffer = static_cast<VulkanBuffer*>(arg.buffer);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue