Add compute demo (WIP) + fixes creation of compute pipelines
This commit is contained in:
parent
9578ba3ef5
commit
4605eed0da
|
|
@ -0,0 +1,132 @@
|
||||||
|
#include <Nazara/Core.hpp>
|
||||||
|
#include <Nazara/Math.hpp>
|
||||||
|
#include <Nazara/Platform.hpp>
|
||||||
|
#include <Nazara/Renderer.hpp>
|
||||||
|
#include <NZSL/LangWriter.hpp>
|
||||||
|
#include <NZSL/Parser.hpp>
|
||||||
|
#include <Nazara/Utility.hpp>
|
||||||
|
#include <array>
|
||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
NAZARA_REQUEST_DEDICATED_GPU()
|
||||||
|
|
||||||
|
const char shaderSource[] = R"(
|
||||||
|
[nzsl_version("1.0")]
|
||||||
|
module;
|
||||||
|
|
||||||
|
external
|
||||||
|
{
|
||||||
|
[binding(0)] input_tex: texture2D[f32, readonly, rgba8],
|
||||||
|
[binding(1)] output_tex: texture2D[f32, writeonly, rgba8]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Input
|
||||||
|
{
|
||||||
|
[builtin(global_invocation_indices)] global_invocation_id: vec3[u32]
|
||||||
|
}
|
||||||
|
|
||||||
|
[entry(compute)]
|
||||||
|
[workgroup(16, 16, 1)]
|
||||||
|
fn main(input: Input)
|
||||||
|
{
|
||||||
|
let indices = vec2[i32](input.global_invocation_id.xy);
|
||||||
|
let color = input_tex.Read(indices);
|
||||||
|
output_tex.Write(indices, color);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
struct ComputePipeline
|
||||||
|
{
|
||||||
|
std::shared_ptr<Nz::RenderPipelineLayout> layout;
|
||||||
|
std::shared_ptr<Nz::ComputePipeline> pipeline;
|
||||||
|
};
|
||||||
|
|
||||||
|
ComputePipeline BuildComputePipeline(Nz::RenderDevice& device)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
nzsl::Ast::ModulePtr shaderModule = nzsl::Parse(std::string_view(shaderSource, sizeof(shaderSource)));
|
||||||
|
if (!shaderModule)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to parse shader module" << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
nzsl::ShaderWriter::States states;
|
||||||
|
states.optimize = true;
|
||||||
|
|
||||||
|
auto computeShader = device.InstantiateShaderModule(nzsl::ShaderStageType::Compute, *shaderModule, states);
|
||||||
|
if (!computeShader)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to instantiate shader" << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
Nz::RenderPipelineLayoutInfo computePipelineLayoutInfo;
|
||||||
|
|
||||||
|
auto& inputBinding = computePipelineLayoutInfo.bindings.emplace_back();
|
||||||
|
inputBinding.setIndex = 0;
|
||||||
|
inputBinding.bindingIndex = 0;
|
||||||
|
inputBinding.shaderStageFlags = nzsl::ShaderStageType::Compute;
|
||||||
|
inputBinding.type = Nz::ShaderBindingType::Texture;
|
||||||
|
|
||||||
|
auto& outputBinding = computePipelineLayoutInfo.bindings.emplace_back();
|
||||||
|
outputBinding.setIndex = 0;
|
||||||
|
outputBinding.bindingIndex = 1;
|
||||||
|
outputBinding.shaderStageFlags = nzsl::ShaderStageType::Compute;
|
||||||
|
outputBinding.type = Nz::ShaderBindingType::Texture;
|
||||||
|
|
||||||
|
std::shared_ptr<Nz::RenderPipelineLayout> pipelineLayout = device.InstantiateRenderPipelineLayout(computePipelineLayoutInfo);
|
||||||
|
|
||||||
|
Nz::ComputePipelineInfo computePipelineInfo;
|
||||||
|
computePipelineInfo.pipelineLayout = pipelineLayout;
|
||||||
|
computePipelineInfo.shaderModule = computeShader;
|
||||||
|
|
||||||
|
std::shared_ptr<Nz::ComputePipeline> pipeline = device.InstantiateComputePipeline(computePipelineInfo);
|
||||||
|
if (!pipeline)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to instantiate compute pipeline" << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
ComputePipeline result;
|
||||||
|
result.layout = std::move(pipelineLayout);
|
||||||
|
result.pipeline = std::move(pipeline);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::filesystem::path resourceDir = "assets/examples";
|
||||||
|
if (!std::filesystem::is_directory(resourceDir) && std::filesystem::is_directory("../.." / resourceDir))
|
||||||
|
resourceDir = "../.." / resourceDir;
|
||||||
|
|
||||||
|
Nz::Renderer::Config rendererConfig;
|
||||||
|
std::cout << "Run using Vulkan? (y/n)" << std::endl;
|
||||||
|
if (std::getchar() == 'y')
|
||||||
|
rendererConfig.preferredAPI = Nz::RenderAPI::Vulkan;
|
||||||
|
else
|
||||||
|
rendererConfig.preferredAPI = Nz::RenderAPI::OpenGL;
|
||||||
|
|
||||||
|
Nz::Modules<Nz::Renderer> nazara(rendererConfig);
|
||||||
|
|
||||||
|
Nz::RenderDeviceFeatures enabledFeatures;
|
||||||
|
enabledFeatures.computeShaders = true;
|
||||||
|
enabledFeatures.textureRead = true;
|
||||||
|
enabledFeatures.textureWrite = true;
|
||||||
|
|
||||||
|
std::shared_ptr<Nz::RenderDevice> device = Nz::Renderer::Instance()->InstanciateRenderDevice(0, enabledFeatures);
|
||||||
|
|
||||||
|
ComputePipeline result = BuildComputePipeline(*device);
|
||||||
|
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
target("ComputeTest")
|
||||||
|
add_deps("NazaraRenderer")
|
||||||
|
add_files("main.cpp")
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLCommandPool.hpp>
|
||||||
|
#include <Nazara/OpenGLRenderer/OpenGLComputePipeline.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLDevice.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLDevice.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLFboFramebuffer.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLFramebuffer.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLFramebuffer.hpp>
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include <Nazara/Renderer/CommandBuffer.hpp>
|
#include <Nazara/Renderer/CommandBuffer.hpp>
|
||||||
#include <Nazara/Renderer/CommandBufferBuilder.hpp>
|
#include <Nazara/Renderer/CommandBufferBuilder.hpp>
|
||||||
#include <Nazara/Renderer/CommandPool.hpp>
|
#include <Nazara/Renderer/CommandPool.hpp>
|
||||||
|
#include <Nazara/Renderer/ComputePipeline.hpp>
|
||||||
#include <Nazara/Renderer/Config.hpp>
|
#include <Nazara/Renderer/Config.hpp>
|
||||||
#include <Nazara/Renderer/DebugDrawer.hpp>
|
#include <Nazara/Renderer/DebugDrawer.hpp>
|
||||||
#include <Nazara/Renderer/Enums.hpp>
|
#include <Nazara/Renderer/Enums.hpp>
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
#include <Nazara/VulkanRenderer/VulkanCommandBuffer.hpp>
|
#include <Nazara/VulkanRenderer/VulkanCommandBuffer.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanCommandBufferBuilder.hpp>
|
#include <Nazara/VulkanRenderer/VulkanCommandBufferBuilder.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanCommandPool.hpp>
|
#include <Nazara/VulkanRenderer/VulkanCommandPool.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/VulkanComputePipeline.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanDescriptorSetLayoutCache.hpp>
|
#include <Nazara/VulkanRenderer/VulkanDescriptorSetLayoutCache.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
|
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
|
||||||
#include <Nazara/VulkanRenderer/VulkanFramebuffer.hpp>
|
#include <Nazara/VulkanRenderer/VulkanFramebuffer.hpp>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Nz
|
||||||
OpenGLComputePipeline::OpenGLComputePipeline(OpenGLDevice& device, ComputePipelineInfo pipelineInfo) :
|
OpenGLComputePipeline::OpenGLComputePipeline(OpenGLDevice& device, ComputePipelineInfo pipelineInfo) :
|
||||||
m_pipelineInfo(std::move(pipelineInfo))
|
m_pipelineInfo(std::move(pipelineInfo))
|
||||||
{
|
{
|
||||||
if (device.GetEnabledFeatures().computeShaders)
|
if (!device.GetEnabledFeatures().computeShaders)
|
||||||
throw std::runtime_error("compute shaders are not enabled on the device");
|
throw std::runtime_error("compute shaders are not enabled on the device");
|
||||||
|
|
||||||
OpenGLRenderPipelineLayout& pipelineLayout = static_cast<OpenGLRenderPipelineLayout&>(*m_pipelineInfo.pipelineLayout);
|
OpenGLRenderPipelineLayout& pipelineLayout = static_cast<OpenGLRenderPipelineLayout&>(*m_pipelineInfo.pipelineLayout);
|
||||||
|
|
@ -27,9 +27,9 @@ namespace Nz
|
||||||
if (!m_program.Create(device))
|
if (!m_program.Create(device))
|
||||||
throw std::runtime_error("failed to create program");
|
throw std::runtime_error("failed to create program");
|
||||||
|
|
||||||
NazaraAssert(pipelineInfo.shaderModule, "invalid shader module");
|
NazaraAssert(m_pipelineInfo.shaderModule, "invalid shader module");
|
||||||
|
|
||||||
OpenGLShaderModule& shaderModule = static_cast<OpenGLShaderModule&>(*pipelineInfo.shaderModule);
|
OpenGLShaderModule& shaderModule = static_cast<OpenGLShaderModule&>(*m_pipelineInfo.shaderModule);
|
||||||
|
|
||||||
std::vector<OpenGLShaderModule::ExplicitBinding> explicitBindings;
|
std::vector<OpenGLShaderModule::ExplicitBinding> explicitBindings;
|
||||||
nzsl::ShaderStageTypeFlags stageFlags = shaderModule.Attach(m_program, pipelineLayout.GetBindingMapping(), &explicitBindings);
|
nzsl::ShaderStageTypeFlags stageFlags = shaderModule.Attach(m_program, pipelineLayout.GetBindingMapping(), &explicitBindings);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace Nz
|
||||||
VulkanComputePipeline::VulkanComputePipeline(VulkanDevice& device, ComputePipelineInfo pipelineInfo) :
|
VulkanComputePipeline::VulkanComputePipeline(VulkanDevice& device, ComputePipelineInfo pipelineInfo) :
|
||||||
m_pipelineInfo(std::move(pipelineInfo))
|
m_pipelineInfo(std::move(pipelineInfo))
|
||||||
{
|
{
|
||||||
if (device.GetEnabledFeatures().computeShaders)
|
if (!device.GetEnabledFeatures().computeShaders)
|
||||||
throw std::runtime_error("compute shaders are not enabled on the device");
|
throw std::runtime_error("compute shaders are not enabled on the device");
|
||||||
|
|
||||||
VulkanShaderModule& vulkanModule = static_cast<VulkanShaderModule&>(*m_pipelineInfo.shaderModule);
|
VulkanShaderModule& vulkanModule = static_cast<VulkanShaderModule&>(*m_pipelineInfo.shaderModule);
|
||||||
|
|
|
||||||
|
|
@ -104,14 +104,9 @@ namespace Nz
|
||||||
nzsl::ShaderStageType stageType;
|
nzsl::ShaderStageType stageType;
|
||||||
switch (entryPoint.executionModel)
|
switch (entryPoint.executionModel)
|
||||||
{
|
{
|
||||||
case nzsl::SpirvExecutionModel::Fragment:
|
case nzsl::SpirvExecutionModel::GLCompute: stageType = nzsl::ShaderStageType::Compute; break;
|
||||||
stageType = nzsl::ShaderStageType::Fragment;
|
case nzsl::SpirvExecutionModel::Fragment: stageType = nzsl::ShaderStageType::Fragment; break;
|
||||||
break;
|
case nzsl::SpirvExecutionModel::Vertex: stageType = nzsl::ShaderStageType::Vertex; break;
|
||||||
|
|
||||||
case nzsl::SpirvExecutionModel::Vertex:
|
|
||||||
stageType = nzsl::ShaderStageType::Vertex;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
continue; //< Ignore
|
continue; //< Ignore
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue