Move ComputeTest,GraphicsTest,RenderTest and Std140Debug to the tests folder

Also renamed NazaraUnitTests to UnitTests
This commit is contained in:
SirLynix
2022-12-26 08:44:11 +01:00
parent fe8715f1fb
commit 4b804dc613
71 changed files with 33 additions and 36 deletions

View File

@@ -1,457 +0,0 @@
#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()
struct ComputePipeline
{
std::shared_ptr<Nz::RenderPipelineLayout> layout;
std::shared_ptr<Nz::ComputePipeline> pipeline;
};
struct SpriteRenderData
{
std::shared_ptr<Nz::RenderBuffer> vertexBuffer;
std::shared_ptr<Nz::ShaderBinding> shaderBinding;
};
struct SpriteRenderPipeline
{
std::shared_ptr<Nz::RenderPipeline> pipeline;
std::shared_ptr<Nz::RenderPipelineLayout> pipelineLayout;
};
ComputePipeline BuildComputePipeline(Nz::RenderDevice& device);
SpriteRenderPipeline BuildSpritePipeline(Nz::RenderDevice& device);
SpriteRenderData BuildSpriteData(Nz::RenderDevice& device, const SpriteRenderPipeline& pipelineData, const Nz::Rectf& textureRect, const Nz::Vector2f& screenSize, const Nz::Texture& texture, const Nz::TextureSampler& sampler);
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.textureReadWrite = true;
std::shared_ptr<Nz::RenderDevice> device = Nz::Renderer::Instance()->InstanciateRenderDevice(0, enabledFeatures);
// Source texture
Nz::TextureParams texParams;
texParams.renderDevice = device;
texParams.loadFormat = Nz::PixelFormat::RGBA8;
texParams.usageFlags = Nz::TextureUsage::ShaderReadWrite | Nz::TextureUsage::ShaderSampling | Nz::TextureUsage::TransferDestination;
std::shared_ptr<Nz::Texture> texture = Nz::Texture::LoadFromFile(resourceDir / "lynix.jpg", texParams);
// Destination texture
Nz::TextureInfo destTexParams = texture->GetTextureInfo();
destTexParams.usageFlags = Nz::TextureUsage::ShaderReadWrite | Nz::TextureUsage::ShaderSampling;
std::shared_ptr<Nz::Texture> targetTexture = device->InstantiateTexture(destTexParams);
std::shared_ptr<Nz::TextureSampler> textureSampler = device->InstantiateTextureSampler({});
// Compute part
ComputePipeline computePipeline = BuildComputePipeline(*device);
std::shared_ptr<Nz::ShaderBinding> computeBinding = computePipeline.layout->AllocateShaderBinding(0);
computeBinding->Update({
{
0,
Nz::ShaderBinding::TextureBinding {
texture.get(),
Nz::TextureAccess::ReadOnly
}
},
{
1,
Nz::ShaderBinding::TextureBinding {
targetTexture.get(),
Nz::TextureAccess::WriteOnly
}
}
});
std::string windowTitle = "Compute test";
Nz::RenderWindow window;
if (!window.Create(device, Nz::VideoMode(1280, 720, 32), windowTitle))
{
std::cout << "Failed to create Window" << std::endl;
std::abort();
}
Nz::Vector2ui windowSize = window.GetSize();
constexpr float textureSize = 512.f;
float margin = (windowSize.y - textureSize) * 0.5f;
SpriteRenderPipeline spriteRenderPipeline = BuildSpritePipeline(*device);
SpriteRenderData spriteRenderData1 = BuildSpriteData(*device, spriteRenderPipeline, Nz::Rectf(margin, windowSize.y - margin - textureSize, textureSize, textureSize), Nz::Vector2f(windowSize), *texture, *textureSampler);
SpriteRenderData spriteRenderData2 = BuildSpriteData(*device, spriteRenderPipeline, Nz::Rectf(windowSize.x - textureSize - margin, windowSize.y - margin - textureSize, textureSize, textureSize), Nz::Vector2f(windowSize), *targetTexture, *textureSampler);
Nz::Clock secondClock;
unsigned int fps = 0;
while (window.IsOpen())
{
window.ProcessEvents();
Nz::RenderFrame frame = window.AcquireFrame();
if (!frame)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}
const Nz::RenderTarget* windowRT = window.GetRenderTarget();
frame.Execute([&](Nz::CommandBufferBuilder& builder)
{
builder.BeginDebugRegion("Compute part", Nz::Color::Blue);
{
builder.TextureBarrier(Nz::PipelineStage::FragmentShader, Nz::PipelineStage::ComputeShader, Nz::MemoryAccess::ShaderRead, Nz::MemoryAccess::ShaderRead, Nz::TextureLayout::ColorInput, Nz::TextureLayout::General, *texture);
builder.TextureBarrier(Nz::PipelineStage::FragmentShader, Nz::PipelineStage::ComputeShader, Nz::MemoryAccess::ShaderRead, Nz::MemoryAccess::ShaderWrite, Nz::TextureLayout::Undefined, Nz::TextureLayout::General, *targetTexture);
builder.BindComputePipeline(*computePipeline.pipeline);
builder.BindComputeShaderBinding(0, *computeBinding);
builder.Dispatch(destTexParams.width / 32, destTexParams.height / 32, 1);
builder.TextureBarrier(Nz::PipelineStage::ComputeShader, Nz::PipelineStage::FragmentShader, Nz::MemoryAccess::ShaderRead, Nz::MemoryAccess::ShaderRead, Nz::TextureLayout::General, Nz::TextureLayout::ColorInput, *texture);
builder.TextureBarrier(Nz::PipelineStage::ComputeShader, Nz::PipelineStage::FragmentShader, Nz::MemoryAccess::ShaderWrite, Nz::MemoryAccess::ShaderRead, Nz::TextureLayout::General, Nz::TextureLayout::ColorInput, *targetTexture);
}
builder.EndDebugRegion();
builder.BeginDebugRegion("Main window rendering", Nz::Color::Green);
{
Nz::Recti renderRect(0, 0, window.GetSize().x, window.GetSize().y);
Nz::CommandBufferBuilder::ClearValues clearValues[2];
clearValues[0].color = Nz::Color::Gray;
clearValues[1].depth = 1.f;
clearValues[1].stencil = 0;
builder.BeginRenderPass(windowRT->GetFramebuffer(frame.GetFramebufferIndex()), windowRT->GetRenderPass(), renderRect, { clearValues[0], clearValues[1] });
{
builder.SetScissor(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) });
builder.SetViewport(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) });
builder.BindRenderPipeline(*spriteRenderPipeline.pipeline);
builder.BindVertexBuffer(0, *spriteRenderData1.vertexBuffer);
builder.BindRenderShaderBinding(0, *spriteRenderData1.shaderBinding);
builder.Draw(4);
builder.BindVertexBuffer(0, *spriteRenderData2.vertexBuffer);
builder.BindRenderShaderBinding(0, *spriteRenderData2.shaderBinding);
builder.Draw(4);
}
builder.EndRenderPass();
}
builder.EndDebugRegion();
}, Nz::QueueType::Graphics);
frame.Present();
fps++;
if (secondClock.GetMilliseconds() >= 1000)
{
window.SetTitle(windowTitle + " - " + Nz::NumberToString(fps) + " FPS");
fps = 0;
secondClock.Restart();
}
}
return EXIT_SUCCESS;
}
// Edge detection, translated to NZSL from Sascha Willems compute shader example
const char computeSource[] = 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(32, 32, 1)]
fn main(input: Input)
{
let indices = vec2[i32](input.global_invocation_id.xy);
// Fetch neighbouring texels
let avg: array[f32, 9];
let n = 0;
[unroll]
for i in -1 -> 2
{
[unroll]
for j in -1 -> 2
{
let rgb = input_tex.Read(indices + vec2[i32](i, j)).rgb;
avg[n] = (rgb.r + rgb.b + rgb.b) / 3.0;
n += 1;
}
}
let kernel: array[f32, 9];
[unroll]
for i in 0 -> 9
{
if (i == 4)
kernel[i] = 1.0;
else
kernel[i] = -1.0/8.0;
}
let res = vec4[f32](conv(kernel, avg, 0.1, 0.0).rrr, 1.0);
output_tex.Write(indices, res);
}
fn conv(kernel: array[f32, 9], data: array[f32, 9], denom: f32, offset: f32) -> f32
{
let res = 0.0;
[unroll]
for i in 0 -> 9
res += kernel[i] * data[i];
return clamp(res/denom + offset, 0.0, 1.0);
}
)";
ComputePipeline BuildComputePipeline(Nz::RenderDevice& device)
{
try
{
nzsl::Ast::ModulePtr shaderModule = nzsl::Parse(std::string_view(computeSource, sizeof(computeSource)));
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();
}
}
const char fragVertSource[] = R"(
[nzsl_version("1.0")]
module;
external
{
[binding(0)] texture: sampler2D[f32]
}
struct FragOut
{
[location(0)] color: vec4[f32]
}
struct VertIn
{
[location(0)] pos: vec2[f32],
[location(1)] uv: vec2[f32]
}
struct VertOut
{
[location(0)] uv: vec2[f32],
[builtin(position)] pos: vec4[f32]
}
[entry(frag)]
fn main(input: VertOut) -> FragOut
{
let output: FragOut;
output.color = texture.Sample(input.uv);
return output;
}
[entry(vert)]
fn main(input: VertIn) -> VertOut
{
let output: VertOut;
output.pos = vec4[f32](input.pos, 0.0, 1.0);
output.uv = input.uv;
return output;
}
)";
SpriteRenderPipeline BuildSpritePipeline(Nz::RenderDevice& device)
{
try
{
nzsl::Ast::ModulePtr shaderModule = nzsl::Parse(std::string_view(fragVertSource, sizeof(fragVertSource)));
if (!shaderModule)
{
std::cout << "Failed to parse shader module" << std::endl;
std::abort();
}
nzsl::ShaderWriter::States states;
states.optimize = true;
auto fragVertShader = device.InstantiateShaderModule(nzsl::ShaderStageType::Fragment | nzsl::ShaderStageType::Vertex, *shaderModule, states);
if (!fragVertShader)
{
std::cout << "Failed to instantiate shader" << std::endl;
std::abort();
}
std::shared_ptr<Nz::VertexDeclaration> vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XY_UV);
SpriteRenderPipeline pipelineData;
Nz::RenderPipelineLayoutInfo pipelineLayoutInfo;
pipelineLayoutInfo.bindings.push_back({
0, 0, 1,
Nz::ShaderBindingType::Sampler,
nzsl::ShaderStageType::Fragment
});
pipelineData.pipelineLayout = device.InstantiateRenderPipelineLayout(std::move(pipelineLayoutInfo));
Nz::RenderPipelineInfo pipelineInfo;
pipelineInfo.primitiveMode = Nz::PrimitiveMode::TriangleStrip;
pipelineInfo.pipelineLayout = pipelineData.pipelineLayout;
pipelineInfo.shaderModules.push_back(fragVertShader);
pipelineInfo.vertexBuffers.push_back({
0, vertexDeclaration
});
pipelineData.pipeline = device.InstantiateRenderPipeline(std::move(pipelineInfo));
return pipelineData;
}
catch (const std::exception& e)
{
std::cerr << e.what() << std::endl;
std::abort();
}
}
SpriteRenderData BuildSpriteData(Nz::RenderDevice& device, const SpriteRenderPipeline& pipelineData, const Nz::Rectf& textureRect, const Nz::Vector2f& screenSize, const Nz::Texture& texture, const Nz::TextureSampler& sampler)
{
try
{
auto ToClipSpace = [&](Nz::Vector2f pos) -> Nz::Vector2f
{
// From 0..size to 0..1
pos /= screenSize;
// From 0..1 to -1..1
pos *= 2.f;
pos -= Nz::Vector2f(1.f, 1.f);
// Reverse Y
pos.y = -pos.y;
return pos;
};
std::array<Nz::VertexStruct_XY_UV, 4> pos;
pos[0].position = ToClipSpace(textureRect.GetCorner(Nz::RectCorner::LeftBottom));
pos[0].uv = Nz::Vector2f(0.f, 0.f);
pos[1].position = ToClipSpace(textureRect.GetCorner(Nz::RectCorner::LeftTop));
pos[1].uv = Nz::Vector2f(0.f, 1.f);
pos[2].position = ToClipSpace(textureRect.GetCorner(Nz::RectCorner::RightBottom));
pos[2].uv = Nz::Vector2f(1.f, 0.f);
pos[3].position = ToClipSpace(textureRect.GetCorner(Nz::RectCorner::RightTop));
pos[3].uv = Nz::Vector2f(1.f, 1.f);
SpriteRenderData renderData;
renderData.vertexBuffer = device.InstantiateBuffer(Nz::BufferType::Vertex, 4 * 4 * sizeof(float), Nz::BufferUsage::DeviceLocal, pos.data());
renderData.shaderBinding = pipelineData.pipelineLayout->AllocateShaderBinding(0);
renderData.shaderBinding->Update({
{
0,
Nz::ShaderBinding::SampledTextureBinding {
&texture, &sampler
}
}
});
return renderData;
}
catch (const std::exception& e)
{
std::cerr << e.what() << std::endl;
std::abort();
}
}

View File

@@ -1,3 +0,0 @@
target("ComputeTest")
add_deps("NazaraRenderer")
add_files("main.cpp")

View File

@@ -1,255 +0,0 @@
#include <Nazara/Core.hpp>
#include <Nazara/Platform.hpp>
#include <Nazara/Graphics.hpp>
#include <Nazara/Graphics/PropertyHandler/TexturePropertyHandler.hpp>
#include <Nazara/Graphics/PropertyHandler/UniformValuePropertyHandler.hpp>
#include <Nazara/Renderer.hpp>
#include <Nazara/Utility.hpp>
#include <array>
#include <chrono>
#include <iostream>
#include <thread>
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::Graphics> nazara(rendererConfig);
Nz::RenderWindow window;
Nz::MeshParams meshParams;
meshParams.center = true;
meshParams.vertexRotation = Nz::EulerAnglesf(0.f, -90.f, 0.f);
meshParams.vertexScale = Nz::Vector3f(0.002f);
meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ_Normal_UV_Tangent);
std::shared_ptr<Nz::RenderDevice> device = Nz::Graphics::Instance()->GetRenderDevice();
std::string windowTitle = "Graphics Test";
if (!window.Create(device, Nz::VideoMode(1920, 1080, 32), windowTitle))
{
std::cout << "Failed to create Window" << std::endl;
return __LINE__;
}
std::shared_ptr<Nz::Mesh> spaceshipMesh = Nz::Mesh::LoadFromFile(resourceDir / "Spaceship/spaceship.obj", meshParams);
if (!spaceshipMesh)
{
NazaraError("Failed to load model");
return __LINE__;
}
std::shared_ptr<Nz::GraphicalMesh> gfxMesh = Nz::GraphicalMesh::BuildFromMesh(*spaceshipMesh);
// Texture
std::shared_ptr<Nz::Image> diffuseImage = Nz::Image::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png");
if (!diffuseImage || !diffuseImage->Convert(Nz::PixelFormat::RGBA8_SRGB))
{
NazaraError("Failed to load image");
return __LINE__;
}
Nz::TextureParams texParams;
texParams.renderDevice = device;
texParams.loadFormat = Nz::PixelFormat::RGBA8_SRGB;
std::shared_ptr<Nz::Texture> diffuseTexture = Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams);
std::shared_ptr<Nz::Material> material = Nz::Graphics::Instance()->GetDefaultMaterials().basicMaterial;
std::shared_ptr<Nz::MaterialInstance> materialInstance = std::make_shared<Nz::MaterialInstance>(material);
materialInstance->SetTextureProperty(0, diffuseTexture);
materialInstance->SetValueProperty(0, Nz::Color::White);
std::shared_ptr<Nz::MaterialInstance> materialInstance2 = std::make_shared<Nz::MaterialInstance>(material);
materialInstance2->SetValueProperty(0, Nz::Color::Green);
Nz::Model model(std::move(gfxMesh), spaceshipMesh->GetAABB());
for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i)
model.SetMaterial(i, materialInstance);
Nz::Vector2ui windowSize = window.GetSize();
Nz::Camera camera(window.GetRenderTarget());
camera.UpdateClearColor(Nz::Color::Gray);
Nz::ViewerInstance& viewerInstance = camera.GetViewerInstance();
viewerInstance.UpdateTargetSize(Nz::Vector2f(window.GetSize()));
viewerInstance.UpdateProjViewMatrices(Nz::Matrix4f::Perspective(Nz::DegreeAnglef(70.f), float(windowSize.x) / windowSize.y, 0.1f, 1000.f), Nz::Matrix4f::Translate(Nz::Vector3f::Backward() * 1));
Nz::WorldInstancePtr modelInstance = std::make_shared<Nz::WorldInstance>();
modelInstance->UpdateWorldMatrix(Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Left()));
Nz::WorldInstancePtr modelInstance2 = std::make_shared<Nz::WorldInstance>();
modelInstance2->UpdateWorldMatrix(Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right()));
Nz::Recti scissorBox(Nz::Vector2i::Zero(), Nz::Vector2i(window.GetSize()));
Nz::ElementRendererRegistry elementRegistry;
Nz::ForwardFramePipeline framePipeline(elementRegistry);
std::size_t cameraIndex = framePipeline.RegisterViewer(&camera, 0);
std::size_t worldInstanceIndex1 = framePipeline.RegisterWorldInstance(modelInstance);
std::size_t worldInstanceIndex2 = framePipeline.RegisterWorldInstance(modelInstance2);
framePipeline.RegisterRenderable(worldInstanceIndex1, Nz::FramePipeline::NoSkeletonInstance, &model, 0xFFFFFFFF, scissorBox);
framePipeline.RegisterRenderable(worldInstanceIndex2, Nz::FramePipeline::NoSkeletonInstance, &model, 0xFFFFFFFF, scissorBox);
std::unique_ptr<Nz::SpotLight> light = std::make_unique<Nz::SpotLight>();
light->UpdateInnerAngle(Nz::DegreeAnglef(15.f));
light->UpdateOuterAngle(Nz::DegreeAnglef(20.f));
framePipeline.RegisterLight(light.get(), 0xFFFFFFFF);
Nz::Vector3f viewerPos = Nz::Vector3f::Zero();
Nz::EulerAnglesf camAngles(0.f, 0.f, 0.f);
Nz::Quaternionf camQuat(camAngles);
window.EnableEventPolling(true);
Nz::Clock updateClock;
Nz::Clock secondClock;
unsigned int fps = 0;
Nz::Mouse::SetRelativeMouseMode(true);
while (window.IsOpen())
{
Nz::WindowEvent event;
while (window.PollEvent(&event))
{
switch (event.type)
{
case Nz::WindowEventType::Quit:
window.Close();
break;
case Nz::WindowEventType::KeyPressed:
if (event.key.virtualKey == Nz::Keyboard::VKey::A)
{
for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i)
model.SetMaterial(i, materialInstance);
}
else if (event.key.virtualKey == Nz::Keyboard::VKey::B)
{
for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i)
model.SetMaterial(i, materialInstance2);
}
else if (event.key.virtualKey == Nz::Keyboard::VKey::Space)
{
modelInstance->UpdateWorldMatrix(Nz::Matrix4f::Translate(viewerPos));
}
break;
case Nz::WindowEventType::MouseMoved: // La souris a bougé
{
// Gestion de la caméra free-fly (Rotation)
float sensitivity = 0.3f; // Sensibilité de la souris
// On modifie l'angle de la caméra grâce au déplacement relatif sur X de la souris
camAngles.yaw = camAngles.yaw - event.mouseMove.deltaX * sensitivity;
camAngles.yaw.Normalize();
// Idem, mais pour éviter les problèmes de calcul de la matrice de vue, on restreint les angles
camAngles.pitch = Nz::Clamp(camAngles.pitch - event.mouseMove.deltaY*sensitivity, -89.f, 89.f);
camQuat = camAngles;
light->UpdateRotation(camQuat);
break;
}
case Nz::WindowEventType::Resized:
{
Nz::Vector2ui newWindowSize = window.GetSize();
viewerInstance.UpdateProjectionMatrix(Nz::Matrix4f::Perspective(Nz::DegreeAnglef(70.f), float(newWindowSize.x) / newWindowSize.y, 0.1f, 1000.f));
viewerInstance.UpdateTargetSize(Nz::Vector2f(newWindowSize));
break;
}
default:
break;
}
}
if (updateClock.GetMilliseconds() > 1000 / 60)
{
float cameraSpeed = 2.f * updateClock.GetSeconds();
updateClock.Restart();
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Up) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Z))
viewerPos += camQuat * Nz::Vector3f::Forward() * cameraSpeed;
// Si la flèche du bas ou la touche S est pressée, on recule
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Down) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::S))
viewerPos += camQuat * Nz::Vector3f::Backward() * cameraSpeed;
// Etc...
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Left) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Q))
viewerPos += camQuat * Nz::Vector3f::Left() * cameraSpeed;
// Etc...
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Right) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::D))
viewerPos += camQuat * Nz::Vector3f::Right() * cameraSpeed;
// Majuscule pour monter, notez l'utilisation d'une direction globale (Non-affectée par la rotation)
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::LShift) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::RShift))
viewerPos += Nz::Vector3f::Up() * cameraSpeed;
// Contrôle (Gauche ou droite) pour descendre dans l'espace global, etc...
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::LControl) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::RControl))
viewerPos += Nz::Vector3f::Down() * cameraSpeed;
light->UpdatePosition(viewerPos);
}
Nz::RenderFrame frame = window.AcquireFrame();
if (!frame)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}
framePipeline.GetDebugDrawer().DrawLine(Nz::Vector3f::Zero(), Nz::Vector3f::Forward(), Nz::Color::Blue);
viewerInstance.UpdateViewMatrix(Nz::Matrix4f::TransformInverse(viewerPos, camAngles));
viewerInstance.UpdateEyePosition(viewerPos);
framePipeline.Render(frame);
frame.Present();
// On incrémente le compteur de FPS improvisé
fps++;
if (secondClock.GetMilliseconds() >= 1000) // Toutes les secondes
{
// Et on insère ces données dans le titre de la fenêtre
window.SetTitle(windowTitle + " - " + Nz::NumberToString(fps) + " FPS");
/*
Note: En C++11 il est possible d'insérer de l'Unicode de façon standard, quel que soit l'encodage du fichier,
via quelque chose de similaire à u8"Cha\u00CEne de caract\u00E8res".
Cependant, si le code source est encodé en UTF-8 (Comme c'est le cas dans ce fichier),
cela fonctionnera aussi comme ceci : "Chaîne de caractères".
*/
// Et on réinitialise le compteur de FPS
fps = 0;
// Et on relance l'horloge pour refaire ça dans une seconde
secondClock.Restart();
}
}
return EXIT_SUCCESS;
}

View File

@@ -1,3 +0,0 @@
target("GraphicsTest")
add_deps("NazaraGraphics")
add_files("main.cpp")

View File

@@ -1,436 +0,0 @@
#include <Nazara/Core.hpp>
#include <Nazara/Math.hpp>
#include <Nazara/Platform.hpp>
#include <Nazara/Renderer.hpp>
#include <Nazara/Renderer/DebugDrawer.hpp>
#include <NZSL/FilesystemModuleResolver.hpp>
#include <NZSL/LangWriter.hpp>
#include <NZSL/Parser.hpp>
#include <NZSL/Ast/SanitizeVisitor.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;
option red: bool = false;
[layout(std140)]
struct Data
{
projectionMatrix: mat4[f32],
worldMatrix: mat4[f32],
viewMatrix: mat4[f32]
}
[set(0)]
external
{
[binding(0)] data: uniform[Data]
}
[set(1)]
external
{
[binding(0)] tex: sampler2D[f32]
}
struct VertIn
{
[location(0)] position: vec3[f32],
[location(1)] normal: vec3[f32],
[location(2)] uv: vec2[f32]
}
struct VertOut
{
[builtin(position)] position: vec4[f32],
[location(0)] normal: vec3[f32],
[location(1)] uv: vec2[f32]
}
struct FragOut
{
[location(0)] color: vec4[f32]
}
[entry(frag)]
fn main(fragIn: VertOut) -> FragOut
{
let lightDir = vec3[f32](0.0, 0.707, 0.707);
let lightFactor = dot(fragIn.normal, lightDir);
let fragOut: FragOut;
fragOut.color = lightFactor * tex.Sample(fragIn.uv) * const_select(red, vec4[f32](1.0, 0.0, 0.0, 1.0), vec4[f32](1.0, 1.0, 1.0, 1.0));
return fragOut;
}
[entry(vert)]
fn main(vertIn: VertIn) -> VertOut
{
let vertOut: VertOut;
vertOut.position = data.projectionMatrix * data.viewMatrix * data.worldMatrix * vec4[f32](vertIn.position, 1.0);
vertOut.normal = vertIn.normal;
vertOut.uv = vertIn.uv;
return vertOut;
}
)";
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);
std::shared_ptr<Nz::RenderDevice> device = Nz::Renderer::Instance()->InstanciateRenderDevice(0);
Nz::RenderWindow window;
std::string windowTitle = "Render Test";
if (!window.Create(device, Nz::VideoMode(800, 600, 32), windowTitle))
{
std::cout << "Failed to create Window" << std::endl;
return __LINE__;
}
nzsl::Ast::ModulePtr shaderModule = nzsl::Parse(std::string_view(shaderSource, sizeof(shaderSource)));
if (!shaderModule)
{
std::cout << "Failed to parse shader module" << std::endl;
return __LINE__;
}
nzsl::ShaderWriter::States states;
states.optionValues[Nz::CRC32("red")] = false; //< Try enabling this!
states.optimize = true;
auto fragVertShader = device->InstantiateShaderModule(nzsl::ShaderStageType::Fragment | nzsl::ShaderStageType::Vertex, *shaderModule, states);
if (!fragVertShader)
{
std::cout << "Failed to instantiate shader" << std::endl;
return __LINE__;
}
Nz::MeshParams meshParams;
meshParams.center = true;
meshParams.vertexRotation = Nz::EulerAnglesf(0.f, -90.f, 0.f);
meshParams.vertexScale = Nz::Vector3f(0.002f);
meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ_Normal_UV);
std::shared_ptr<Nz::Mesh> spaceship = Nz::Mesh::LoadFromFile(resourceDir / "Spaceship/spaceship.obj", meshParams);
if (!spaceship)
{
NazaraError("Failed to load model");
return __LINE__;
}
std::shared_ptr<Nz::StaticMesh> spaceshipMesh = std::static_pointer_cast<Nz::StaticMesh>(spaceship->GetSubMesh(0));
const std::shared_ptr<Nz::VertexBuffer>& meshVB = spaceshipMesh->GetVertexBuffer();
const std::shared_ptr<const Nz::IndexBuffer>& meshIB = spaceshipMesh->GetIndexBuffer();
// Index buffer
std::cout << "Index count: " << meshIB->GetIndexCount() << std::endl;
// Vertex buffer
std::cout << "Vertex count: " << meshVB->GetVertexCount() << std::endl;
// Create renderbuffers (GPU buffers)
const std::shared_ptr<Nz::RenderDevice>& renderDevice = window.GetRenderDevice();
assert(meshIB->GetBuffer()->GetStorage() == Nz::DataStorage::Software);
assert(meshVB->GetBuffer()->GetStorage() == Nz::DataStorage::Software);
const Nz::SoftwareBuffer* indexBufferContent = static_cast<const Nz::SoftwareBuffer*>(meshIB->GetBuffer().get());
const Nz::SoftwareBuffer* vertexBufferContent = static_cast<const Nz::SoftwareBuffer*>(meshVB->GetBuffer().get());
std::shared_ptr<Nz::RenderBuffer> renderBufferIB = renderDevice->InstantiateBuffer(Nz::BufferType::Index, indexBufferContent->GetSize(), Nz::BufferUsage::DeviceLocal, indexBufferContent->GetData());
std::shared_ptr<Nz::RenderBuffer> renderBufferVB = renderDevice->InstantiateBuffer(Nz::BufferType::Vertex, vertexBufferContent->GetSize(), Nz::BufferUsage::DeviceLocal, vertexBufferContent->GetData());
// Texture
Nz::TextureParams texParams;
texParams.renderDevice = device;
texParams.loadFormat = Nz::PixelFormat::RGBA8_SRGB;
std::shared_ptr<Nz::Texture> texture = Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams);
std::shared_ptr<Nz::TextureSampler> textureSampler = device->InstantiateTextureSampler({});
struct
{
Nz::Matrix4f projectionMatrix;
Nz::Matrix4f modelMatrix;
Nz::Matrix4f viewMatrix;
}
ubo;
Nz::Vector2ui windowSize = window.GetSize();
ubo.projectionMatrix = Nz::Matrix4f::Perspective(Nz::DegreeAnglef(70.f), float(windowSize.x) / windowSize.y, 0.1f, 1000.f);
ubo.viewMatrix = Nz::Matrix4f::Translate(Nz::Vector3f::Backward() * 1);
ubo.modelMatrix = Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2);
Nz::UInt32 uniformSize = sizeof(ubo);
Nz::RenderPipelineLayoutInfo pipelineLayoutInfo;
auto& uboBinding = pipelineLayoutInfo.bindings.emplace_back();
uboBinding.setIndex = 0;
uboBinding.bindingIndex = 0;
uboBinding.shaderStageFlags = nzsl::ShaderStageType::Vertex;
uboBinding.type = Nz::ShaderBindingType::UniformBuffer;
std::shared_ptr<Nz::RenderPipelineLayout> basePipelineLayout = device->InstantiateRenderPipelineLayout(pipelineLayoutInfo);
auto& pipelineTextureBinding = pipelineLayoutInfo.bindings.emplace_back();
pipelineTextureBinding.setIndex = 1;
pipelineTextureBinding.bindingIndex = 0;
pipelineTextureBinding.shaderStageFlags = nzsl::ShaderStageType::Fragment;
pipelineTextureBinding.type = Nz::ShaderBindingType::Sampler;
std::shared_ptr<Nz::RenderPipelineLayout> renderPipelineLayout = device->InstantiateRenderPipelineLayout(std::move(pipelineLayoutInfo));
Nz::ShaderBindingPtr viewerShaderBinding = basePipelineLayout->AllocateShaderBinding(0);
Nz::ShaderBindingPtr textureShaderBinding = renderPipelineLayout->AllocateShaderBinding(1);
std::shared_ptr<Nz::RenderBuffer> uniformBuffer = device->InstantiateBuffer(Nz::BufferType::Uniform, uniformSize, Nz::BufferUsage::DeviceLocal | Nz::BufferUsage::Dynamic);
viewerShaderBinding->Update({
{
0,
Nz::ShaderBinding::UniformBufferBinding {
uniformBuffer.get(), 0, uniformSize
}
}
});
Nz::ShaderBinding::SampledTextureBinding textureBinding {
texture.get(), textureSampler.get()
};
textureShaderBinding->Update({
{
0,
Nz::ShaderBinding::SampledTextureBindings {
1, &textureBinding
}
}
});
Nz::RenderPipelineInfo pipelineInfo;
pipelineInfo.pipelineLayout = renderPipelineLayout;
pipelineInfo.faceCulling = Nz::FaceCulling::Back;
pipelineInfo.depthBuffer = true;
pipelineInfo.shaderModules.emplace_back(fragVertShader);
auto& pipelineVertexBuffer = pipelineInfo.vertexBuffers.emplace_back();
pipelineVertexBuffer.binding = 0;
pipelineVertexBuffer.declaration = meshVB->GetVertexDeclaration();
std::shared_ptr<Nz::RenderPipeline> pipeline = device->InstantiateRenderPipeline(pipelineInfo);
std::shared_ptr<Nz::CommandPool> commandPool = renderDevice->InstantiateCommandPool(Nz::QueueType::Graphics);
Nz::Vector3f viewerPos = Nz::Vector3f::Zero();
Nz::EulerAnglesf camAngles(0.f, 0.f, 0.f);
Nz::Quaternionf camQuat(camAngles);
window.EnableEventPolling(true);
Nz::Clock updateClock;
Nz::Clock secondClock;
unsigned int fps = 0;
bool uboUpdate = true;
Nz::Mouse::SetRelativeMouseMode(true);
Nz::DebugDrawer debugDrawer(*renderDevice);
while (window.IsOpen())
{
Nz::WindowEvent event;
while (window.PollEvent(&event))
{
switch (event.type)
{
case Nz::WindowEventType::Quit:
window.Close();
break;
case Nz::WindowEventType::MouseMoved: // La souris a bougé
{
// Gestion de la caméra free-fly (Rotation)
float sensitivity = 0.3f; // Sensibilité de la souris
// On modifie l'angle de la caméra grâce au déplacement relatif sur X de la souris
camAngles.yaw = camAngles.yaw - event.mouseMove.deltaX * sensitivity;
camAngles.yaw.Normalize();
// Idem, mais pour éviter les problèmes de calcul de la matrice de vue, on restreint les angles
camAngles.pitch = Nz::Clamp(camAngles.pitch - event.mouseMove.deltaY*sensitivity, -89.f, 89.f);
camQuat = camAngles;
uboUpdate = true;
break;
}
case Nz::WindowEventType::Resized:
{
windowSize = window.GetSize();
ubo.projectionMatrix = Nz::Matrix4f::Perspective(Nz::DegreeAnglef(70.f), float(windowSize.x) / windowSize.y, 0.1f, 1000.f);
uboUpdate = true;
break;
}
default:
break;
}
}
if (updateClock.GetMilliseconds() > 1000 / 60)
{
float cameraSpeed = 2.f * updateClock.GetSeconds();
updateClock.Restart();
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Up) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Z))
viewerPos += camQuat * Nz::Vector3f::Forward() * cameraSpeed;
// Si la flèche du bas ou la touche S est pressée, on recule
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Down) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::S))
viewerPos += camQuat * Nz::Vector3f::Backward() * cameraSpeed;
// Etc...
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Left) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Q))
viewerPos += camQuat * Nz::Vector3f::Left() * cameraSpeed;
// Etc...
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Right) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::D))
viewerPos += camQuat * Nz::Vector3f::Right() * cameraSpeed;
// Majuscule pour monter, notez l'utilisation d'une direction globale (Non-affectée par la rotation)
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::LShift) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::RShift))
viewerPos += Nz::Vector3f::Up() * cameraSpeed;
// Contrôle (Gauche ou droite) pour descendre dans l'espace global, etc...
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::LControl) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::RControl))
viewerPos += Nz::Vector3f::Down() * cameraSpeed;
uboUpdate = true;
}
Nz::RenderFrame frame = window.AcquireFrame();
if (!frame)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}
debugDrawer.Reset(frame);
debugDrawer.SetViewerData(ubo.viewMatrix * ubo.projectionMatrix);
Nz::Boxf aabb = spaceship->GetAABB();
aabb.Transform(ubo.modelMatrix);
debugDrawer.DrawBox(aabb, Nz::Color::Green);
ubo.viewMatrix = Nz::Matrix4f::TransformInverse(viewerPos, camAngles);
if (uboUpdate)
{
auto& allocation = frame.GetUploadPool().Allocate(uniformSize);
std::memcpy(allocation.mappedPtr, &ubo, sizeof(ubo));
frame.Execute([&](Nz::CommandBufferBuilder& builder)
{
builder.BeginDebugRegion("UBO Update", Nz::Color::Yellow);
{
builder.PreTransferBarrier();
builder.CopyBuffer(allocation, uniformBuffer.get());
builder.PostTransferBarrier();
}
builder.EndDebugRegion();
}, Nz::QueueType::Transfer);
uboUpdate = false;
}
debugDrawer.Prepare(frame);
const Nz::RenderTarget* windowRT = window.GetRenderTarget();
frame.Execute([&](Nz::CommandBufferBuilder& builder)
{
Nz::Recti renderRect(0, 0, window.GetSize().x, window.GetSize().y);
Nz::CommandBufferBuilder::ClearValues clearValues[2];
clearValues[0].color = Nz::Color::Black;
clearValues[1].depth = 1.f;
clearValues[1].stencil = 0;
builder.BeginDebugRegion("Main window rendering", Nz::Color::Green);
{
builder.BeginRenderPass(windowRT->GetFramebuffer(frame.GetFramebufferIndex()), windowRT->GetRenderPass(), renderRect, { clearValues[0], clearValues[1] });
{
builder.BindIndexBuffer(*renderBufferIB, Nz::IndexType::U16);
builder.BindRenderPipeline(*pipeline);
builder.BindVertexBuffer(0, *renderBufferVB);
builder.BindRenderShaderBinding(0, *viewerShaderBinding);
builder.BindRenderShaderBinding(1, *textureShaderBinding);
builder.SetScissor(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) });
builder.SetViewport(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) });
builder.DrawIndexed(meshIB->GetIndexCount());
debugDrawer.Draw(builder);
}
builder.EndRenderPass();
}
builder.EndDebugRegion();
}, Nz::QueueType::Graphics);
frame.Present();
// On incrémente le compteur de FPS improvisé
fps++;
if (secondClock.GetMilliseconds() >= 1000) // Toutes les secondes
{
// Et on insère ces données dans le titre de la fenêtre
window.SetTitle(windowTitle + " - " + Nz::NumberToString(fps) + " FPS");
/*
Note: En C++11 il est possible d'insérer de l'Unicode de façon standard, quel que soit l'encodage du fichier,
via quelque chose de similaire à u8"Cha\u00CEne de caract\u00E8res".
Cependant, si le code source est encodé en UTF-8 (Comme c'est le cas dans ce fichier),
cela fonctionnera aussi comme ceci : "Chaîne de caractères".
*/
// Et on réinitialise le compteur de FPS
fps = 0;
// Et on relance l'horloge pour refaire ça dans une seconde
secondClock.Restart();
}
}
return EXIT_SUCCESS;
}

View File

@@ -1,3 +0,0 @@
target("RenderTest")
add_deps("NazaraRenderer")
add_files("main.cpp")

View File

@@ -1,174 +0,0 @@
#include <Nazara/Core.hpp>
#include <Nazara/OpenGLRenderer.hpp>
#include <Nazara/OpenGLRenderer/Wrapper.hpp>
#include <Nazara/Renderer.hpp>
#include <NZSL/Math/FieldOffsets.hpp>
#include <iostream>
#include <numeric>
const char fragmentSource[] = R"(
#version 300 es
#if GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
layout(std140) uniform LightParameters
{
mat4 projectionMatrix;
mat4 invProjectionMatrix;
mat4 viewMatrix;
mat4 invViewMatrix;
mat4 viewProjMatrix;
mat4 invViewProjMatrix;
vec2 renderTargetSize;
vec2 invRenderTargetSize;
vec3 eyePosition;
};
void main()
{
}
)";
const char vertexSource[] = R"(
#version 300 es
void main()
{
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
}
)";
template <typename T, typename Compare>
std::vector<std::size_t> SortIndexes(const std::vector<T>& vec, Compare&& compare)
{
std::vector<std::size_t> p(vec.size());
std::iota(p.begin(), p.end(), 0);
std::sort(p.begin(), p.end(), [&](std::size_t i, std::size_t j) { return compare(vec[i], vec[j]); });
return p;
}
int main()
{
Nz::Renderer::Config rendererConfig;
rendererConfig.preferredAPI = Nz::RenderAPI::OpenGL;
Nz::Modules<Nz::Renderer> nazara(rendererConfig);
if (Nz::Renderer::Instance()->QueryAPI() != Nz::RenderAPI::OpenGL)
{
std::cout << "This program only works with OpenGL" << std::endl;
return EXIT_FAILURE;
}
std::shared_ptr<Nz::OpenGLDevice> device = std::static_pointer_cast<Nz::OpenGLDevice>(Nz::Renderer::Instance()->InstanciateRenderDevice(0));
std::string err;
// Fragment shader
Nz::GL::Shader fragmentShader;
if (!fragmentShader.Create(*device, GL_FRAGMENT_SHADER))
{
std::cerr << "Failed to create fragment shader" << std::endl;
return EXIT_FAILURE;
}
fragmentShader.SetSource(fragmentSource, sizeof(fragmentSource));
fragmentShader.Compile();
if (!fragmentShader.GetCompilationStatus(&err))
{
std::cerr << "Failed to compile fragment shader: " << err << std::endl;
return EXIT_FAILURE;
}
// Vertex shader
Nz::GL::Shader vertexShader;
if (!vertexShader.Create(*device, GL_VERTEX_SHADER))
{
std::cerr << "Failed to create vertex shader" << std::endl;
return EXIT_FAILURE;
}
vertexShader.SetSource(vertexSource, sizeof(vertexSource));
vertexShader.Compile();
if (!vertexShader.GetCompilationStatus(&err))
{
std::cerr << "Failed to compile vertex shader: " << err << std::endl;
return EXIT_FAILURE;
}
// Program
Nz::GL::Program program;
if (!program.Create(*device))
{
std::cerr << "Failed to create program" << std::endl;
return EXIT_FAILURE;
}
program.AttachShader(fragmentShader.GetObjectId());
program.AttachShader(vertexShader.GetObjectId());
program.Link();
if (!program.GetLinkStatus(&err))
{
std::cerr << "Failed to link program: " << err << std::endl;
return EXIT_FAILURE;
}
// Get infos
GLuint blockIndex = program.GetUniformBlockIndex("LightParameters");
if (blockIndex == GL_INVALID_INDEX)
{
std::cerr << "Failed to find uniform block in program" << std::endl;
return EXIT_FAILURE;
}
std::vector<GLint> uniformIndices = program.GetActiveUniformBlockUniformIndices(blockIndex);
std::vector<GLint> offsets = program.GetActiveUniforms(GLsizei(uniformIndices.size()), reinterpret_cast<GLuint*>(uniformIndices.data()), GL_UNIFORM_OFFSET);
auto p = SortIndexes(offsets, std::less<std::size_t>());
std::vector<std::size_t> computedOffsets;
nzsl::FieldOffsets fieldOffsets(nzsl::StructLayout::Std140);
computedOffsets.push_back(fieldOffsets.AddMatrix(nzsl::StructFieldType::Float1, 4, 4, true));
computedOffsets.push_back(fieldOffsets.AddMatrix(nzsl::StructFieldType::Float1, 4, 4, true));
computedOffsets.push_back(fieldOffsets.AddMatrix(nzsl::StructFieldType::Float1, 4, 4, true));
computedOffsets.push_back(fieldOffsets.AddMatrix(nzsl::StructFieldType::Float1, 4, 4, true));
computedOffsets.push_back(fieldOffsets.AddMatrix(nzsl::StructFieldType::Float1, 4, 4, true));
computedOffsets.push_back(fieldOffsets.AddMatrix(nzsl::StructFieldType::Float1, 4, 4, true));
computedOffsets.push_back(fieldOffsets.AddField(nzsl::StructFieldType::Float2));
computedOffsets.push_back(fieldOffsets.AddField(nzsl::StructFieldType::Float2));
computedOffsets.push_back(fieldOffsets.AddField(nzsl::StructFieldType::Float3));
GLint dataSize;
program.GetActiveUniformBlock(blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &dataSize);
if (fieldOffsets.GetAlignedSize() != dataSize)
std::cout << "size mismatch (computed " << fieldOffsets.GetAlignedSize() << ", reference has " << dataSize << ")" << std::endl;;
if (computedOffsets.size() != uniformIndices.size())
{
std::cout << "member count mismatch" << std::endl;
return EXIT_FAILURE;
}
for (std::size_t i = 0; i < uniformIndices.size(); ++i)
{
GLint realOffset = offsets[p[i]];
std::cout << program.GetActiveUniformName(uniformIndices[p[i]]) << ": " << realOffset;
if (realOffset != computedOffsets[i])
std::cout << " ERR";
std::cout << std::endl;
}
return EXIT_SUCCESS;
}

View File

@@ -1,8 +0,0 @@
target("Std140Debug")
add_files("main.cpp")
if has_config("embed_rendererbackends") then
add_deps("NazaraRenderer")
else
add_deps("NazaraOpenGLRenderer")
end

View File

@@ -1,9 +1,7 @@
option("examples", { description = "Build examples", default = true })
if has_config("examples") then
-- Common config
set_group("Examples")
set_kind("binary")
includes("*/xmake.lua")
end