Somewhat working camera

This commit is contained in:
Dynamitos
2022-03-19 22:45:30 +01:00
parent 84049a762c
commit cd28e433cc
41 changed files with 602 additions and 496 deletions
+2
View File
@@ -55,6 +55,7 @@
"environment": [],
"symbolSearchPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.25.28610\\lib\\x64",
"requireExactSource": false,
"visualizerFile": "${workspaceRoot}/Seele.natvis",
"logging": {
"moduleLoad": false,
"exceptions": true,
@@ -82,6 +83,7 @@
"stopAtEntry": false,
"console": "internalConsole",
"cwd": "${workspaceRoot}/bin/Debug",
"visualizerFile": "${workspaceRoot}/Seele.natvis",
"environment": [],
},
]
+1 -1
View File
@@ -31,7 +31,7 @@
</Expand>
</Type>
<Type Name="Seele::Map&lt;*&gt;">
<DisplayString>{{size={_size}}</DisplayString>
<DisplayString>{{ size={_size} }</DisplayString>
<Expand>
<Item Name="[size]">_size</Item>
<Item Name="[comp]">comp</Item>
+1 -1
+8 -8
View File
@@ -28,10 +28,10 @@ void computeFrustums(ComputeShaderInput in)
float4 screenSpace[4];
screenSpace[0] = float4(in.dispatchThreadID.xy * BLOCK_SIZE, 1.0f, 1.0f);
screenSpace[1] = float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y) * BLOCK_SIZE, 1.0f, 1.0f);
screenSpace[2] = float4(float2(in.dispatchThreadID.x, in.dispatchThreadID.y + 1) * BLOCK_SIZE, 1.0f, 1.0f);
screenSpace[3] = float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y + 1) * BLOCK_SIZE, 1.0f, 1.0f);
screenSpace[0] = float4(in.dispatchThreadID.xy * BLOCK_SIZE, -1.0f, 1.0f);
screenSpace[1] = float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y) * BLOCK_SIZE, -1.0f, 1.0f);
screenSpace[2] = float4(float2(in.dispatchThreadID.x, in.dispatchThreadID.y + 1) * BLOCK_SIZE, -1.0f, 1.0f);
screenSpace[3] = float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y + 1) * BLOCK_SIZE, -1.0f, 1.0f);
//Convert to viewSpace
float3 viewSpace[4];
@@ -44,10 +44,10 @@ void computeFrustums(ComputeShaderInput in)
//Compute frustum
Frustum frustum;
frustum.planes[0] = computePlane(eyePos, viewSpace[0], viewSpace[2]);
frustum.planes[1] = computePlane(eyePos, viewSpace[3], viewSpace[1]);
frustum.planes[2] = computePlane(eyePos, viewSpace[1], viewSpace[0]);
frustum.planes[3] = computePlane(eyePos, viewSpace[2], viewSpace[3]);
frustum.planes[0] = computePlane(eyePos, viewSpace[2], viewSpace[0]);
frustum.planes[1] = computePlane(eyePos, viewSpace[1], viewSpace[3]);
frustum.planes[2] = computePlane(eyePos, viewSpace[0], viewSpace[1]);
frustum.planes[3] = computePlane(eyePos, viewSpace[3], viewSpace[2]);
if(in.dispatchThreadID.x < numThreads.x && in.dispatchThreadID.y < numThreads.y)
{
+7 -6
View File
@@ -32,9 +32,9 @@ VertexStageOutput vertexMain(
float4 clipSpacePosition;
float3x3 tangentToLocal = cache.getTangentToLocal();
MaterialVertexParameter vertexParams = input.getMaterialVertexParameters(cache, worldPosition, tangentToLocal);
float4 viewSpacePosition = mul(gViewParams.viewMatrix, float4(worldPosition, 1));
MaterialVertexParameter vertexParams = input.getMaterialVertexParameters(cache, worldPosition, viewSpacePosition.xyz, tangentToLocal);
clipSpacePosition = mul(gViewParams.projectionMatrix, viewSpacePosition);
output.position = clipSpacePosition;
output.shaderAttributeInterpolation = input.getInterpolants(cache, vertexParams);
@@ -66,12 +66,13 @@ float4 fragmentMain(
uint startOffset = gridValue.x;
uint lightCount = gridValue.y;
for (int j = 0; j < lightCount; ++j)
for (int j = 0; j < numPointLights; ++j)
{
uint lightIndex = lightIndexList[startOffset + j];
PointLight pointLight = pointLights[lightIndex];
//uint lightIndex = lightIndexList[startOffset + j];
PointLight pointLight = pointLights[j];
if(pointLight.colorRange.w < length(pointLight.getViewPos() - input.viewPosition)) continue;
result += pointLight.illuminate(materialParams, brdf, viewDir);
}
return float4(result, 0.1f);
return float4(result, 1.0f);
}
+30 -30
View File
@@ -4,18 +4,18 @@ import Common;
interface ILightEnv
{
float3 illuminate<B:IBRDF>(MaterialFragmentParameter input, B brdf, float3 wo);
float3 illuminate<B:IBRDF>(MaterialFragmentParameter input, B brdf, float3 wo);
};
struct DirectionalLight : ILightEnv
{
float4 color;
float4 direction;
float4 intensity;
float4 color;
float4 direction;
float4 intensity;
float3 illuminate<B:IBRDF>(MaterialFragmentParameter input, B brdf, float3 wo)
{
return intensity.xyz * brdf.evaluate(wo, normalize(direction.xyz), input.worldNormal, input.worldTangent, input.worldBiTangent, color.xyz);
{
return intensity.xyz * brdf.evaluate(wo, normalize(direction.xyz), input.worldNormal, input.worldTangent, input.worldBiTangent, color.xyz);
}
};
@@ -25,40 +25,40 @@ struct PointLight : ILightEnv
float4 colorRange;
float3 illuminate<B:IBRDF>(MaterialFragmentParameter input, B brdf, float3 viewDir)
{
{
float3 lightVec = positionWS.xyz - input.worldPosition;
float d = length(lightVec);
float3 direction = normalize(lightVec);
float illuminance = max(1 - d / colorRange.w, 0);
return illuminance * brdf.evaluate(viewDir, direction, input.worldNormal, input.worldTangent, input.worldBiTangent, colorRange.xyz);
return illuminance * brdf.evaluate(viewDir, direction, input.worldNormal, input.worldTangent, input.worldBiTangent, colorRange.xyz);
}
bool insidePlane(Plane plane)
{
bool insidePlane(Plane plane)
{
return dot(plane.n, getViewPos().xyz) - plane.d < -colorRange.w;
}
}
bool insideFrustum(Frustum frustum, float zNear, float zFar)
{
bool insideFrustum(Frustum frustum, float zNear, float zFar)
{
bool result = true;
if(getViewPos().z - colorRange.w > zNear || getViewPos().z + colorRange.w < zFar)
{
result = false;
}
for(int i = 0; i < 4 && result; ++i)
{
if(insidePlane(frustum.planes[i]))
{
result = false;
}
}
return result;
}
float3 getViewPos()
{
return mul(gViewParams.viewMatrix, positionWS).xyz;
}
if(getViewPos().z - colorRange.w > zNear || getViewPos().z + colorRange.w < zFar)
{
//result = false;
}
for(int i = 0; i < 4 && result; ++i)
{
if(insidePlane(frustum.planes[i]))
{
//result = false;
}
}
return result;
}
float3 getViewPos()
{
return mul(gViewParams.viewMatrix, positionWS).xyz;
}
};
layout(set = INDEX_LIGHT_ENV, binding = 0, std430)
+1
View File
@@ -1,6 +1,7 @@
struct MaterialVertexParameter
{
float3 worldPosition;
float3 viewPosition;
float3x3 tangentToWorld;
#if NUM_MATERIAL_TEXCOORDS
float2 texCoords[NUM_MATERIAL_TEXCOORDS];
+4 -1
View File
@@ -45,6 +45,7 @@ struct VertexValueCache
struct ShaderAttributeInterpolation
{
float3 worldPosition;
float3 viewPosition;
float3 normal;
float3 tangent;
float3 biTangent;
@@ -158,10 +159,11 @@ struct VertexShaderInput
return cache;
}
MaterialVertexParameter getMaterialVertexParameters(VertexValueCache cache, float3 worldPosition, float3x3 tangentToLocal)
MaterialVertexParameter getMaterialVertexParameters(VertexValueCache cache, float3 worldPosition, float3 viewPosition, float3x3 tangentToLocal)
{
MaterialVertexParameter result;
result.worldPosition = worldPosition;
result.viewPosition = viewPosition;
result.vertexColor = cache.color;
result.tangentToWorld = cache.getTangentToWorld();
// TODO instancing
@@ -186,6 +188,7 @@ struct VertexShaderInput
result.biTangent = mul(gSceneData.localToWorld, float4(biTangent, 0.0f)).xyz;
result.color = color;
result.worldPosition = vertexParams.worldPosition;
result.viewPosition = vertexParams.viewPosition;
for(int i = 0; i < NUM_MATERIAL_TEXCOORDS; ++i)
{
if(i % 2)
+2 -1
View File
@@ -27,7 +27,8 @@ void AssetRegistry::importFile(const std::string &filePath)
std::filesystem::path fsPath = std::filesystem::path(filePath);
std::string extension = fsPath.extension().string();
if (extension.compare(".fbx") == 0
|| extension.compare(".obj") == 0)
|| extension.compare(".obj") == 0
|| extension.compare(".blend") == 0)
{
get().importMesh(fsPath);
}
-5
View File
@@ -3,11 +3,6 @@
namespace Seele
{
template<typename A>
concept iterable = requires(A&& a)
{
a.begin(); a.end();
};
template<class F, class... Args>
concept invocable = std::invocable<F, Args...>;
}
+1 -1
View File
@@ -148,7 +148,7 @@ enum class InputAction
REPEAT = 2
};
enum class KeyModifier
enum class KeyModifier : uint32
{
MOD_SHIFT = 0x0001,
MOD_CONTROL = 0x0002,
+1 -1
View File
@@ -20,7 +20,7 @@ BasePassMeshProcessor::~BasePassMeshProcessor()
{
}
Job BasePassMeshProcessor::processMeshBatch(
MainJob BasePassMeshProcessor::processMeshBatch(
const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass,
+1 -1
View File
@@ -11,7 +11,7 @@ public:
BasePassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics, uint8 translucentBasePass);
virtual ~BasePassMeshProcessor();
virtual Job processMeshBatch(
virtual MainJob processMeshBatch(
const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass,
@@ -18,7 +18,7 @@ DepthPrepassMeshProcessor::~DepthPrepassMeshProcessor()
{
}
Job DepthPrepassMeshProcessor::processMeshBatch(
MainJob DepthPrepassMeshProcessor::processMeshBatch(
const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass,
@@ -11,7 +11,7 @@ public:
DepthPrepassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics);
virtual ~DepthPrepassMeshProcessor();
virtual Job processMeshBatch(
virtual MainJob processMeshBatch(
const MeshBatch& batch,
const Gfx::PRenderPass& renderPass,
Gfx::PPipelineLayout pipelineLayout,
@@ -98,7 +98,7 @@ MainJob LightCullingPass::render()
computeCommand->bindPipeline(cullingPipeline);
Array<Gfx::PDescriptorSet> descriptorSets = {cullingDescriptorSet, lightEnvDescriptorSet};
computeCommand->bindDescriptor(descriptorSets);
computeCommand->dispatch(dispatchParams.numThreadGroups.x, dispatchParams.numThreadGroups.y, dispatchParams.numThreadGroups.z);
//computeCommand->dispatch(dispatchParams.numThreadGroups.x, dispatchParams.numThreadGroups.y, dispatchParams.numThreadGroups.z);
Array<Gfx::PComputeCommand> commands = {computeCommand};
graphics->executeCommands(commands);
depthAttachment->changeLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
@@ -17,7 +17,7 @@ public:
protected:
PScene scene;
Gfx::PGraphics graphics;
virtual Job processMeshBatch(
virtual MainJob processMeshBatch(
const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass,
@@ -81,7 +81,7 @@ void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
assert(state == State::RenderPassActive);
if(commands.size() == 0)
{
std::cout << "No commands provided" << std::endl;
//std::cout << "No commands provided" << std::endl;
return;
}
std::scoped_lock lock(handleLock);
+1 -2
View File
@@ -106,11 +106,10 @@ void MaterialAsset::load()
std::string defaultString = defaultValue.value().get<std::string>();
p->data = AssetRegistry::findTexture(defaultString);
}
else
if(p->data == nullptr)
{
p->data = AssetRegistry::findTexture(""); // this will return placeholder texture
}
assert(p->data != nullptr);
parameters.add(p);
}
else if(type.compare("SamplerState") == 0)
+31 -4
View File
@@ -4,7 +4,7 @@
using namespace Seele;
Transform::Transform()
: position(Vector4(0, 0, 0, 0)), rotation(Quaternion(0, 0, 0, 0)), scale(Vector4(1, 1, 1, 0))
: position(Vector4(0, 0, 0, 0)), rotation(Quaternion(1, 0, 0, 0)), scale(Vector4(1, 1, 1, 0))
{
}
@@ -12,7 +12,7 @@ Transform::Transform(Transform &&other)
: position(other.position), rotation(other.rotation), scale(other.scale)
{
other.position = Vector4(0, 0, 0, 0);
other.rotation = Quaternion(0, 0, 0, 0);
other.rotation = Quaternion(1, 0, 0, 0);
other.scale = Vector4(0, 0, 0, 0);
}
@@ -22,7 +22,7 @@ Transform::Transform(const Transform &other)
}
Transform::Transform(Vector position)
: position(Vector4(position, 0)), rotation(Quaternion(0, 0, 0, 0)), scale(Vector4(1, 1, 1, 0))
: position(Vector4(position, 0)), rotation(Quaternion(1, 0, 0, 0)), scale(Vector4(1, 1, 1, 0))
{
}
Transform::Transform(Vector position, Quaternion rotation)
@@ -144,6 +144,19 @@ Vector Transform::getScale() const
return Vector(scale);
}
Vector Transform::getForward() const
{
return Vector(0, 0, 1) * rotation;
}
Vector Transform::getRight() const
{
return Vector(1, 0, 0) * rotation;
}
Vector Transform::getUp() const
{
return Vector(0, 1, 0) * rotation;
}
bool Transform::equals(const Transform &other, float tolerance)
{
if (abs(position - other.position).length() > tolerance)
@@ -174,6 +187,13 @@ void Transform::multiply(Transform *outTransform, const Transform *a, const Tran
outTransform->position = b->rotation * (b->scale * a->position) + b->position;
outTransform->scale = b->scale * a->scale;
}
void Transform::add(Transform *outTransform, const Transform *a, const Transform *b)
{
outTransform->position = a->position + b->position;
outTransform->rotation = a->rotation + b->rotation;
outTransform->scale = a->scale + b->scale;
}
Transform &Transform::operator=(const Transform &other)
{
@@ -189,11 +209,18 @@ Transform &Transform::operator=(Transform &&other)
rotation = other.rotation;
scale = other.scale;
other.position = Vector4(0, 0, 0, 0);
other.rotation = Quaternion(0, 0, 0, 0);
other.rotation = Quaternion(1, 0, 0, 0);
other.scale = Vector4(0, 0, 0, 0);
return *this;
}
Transform Transform::operator+(const Transform & other) const
{
Transform outTransform;
add(&outTransform, this, &other);
return outTransform;
}
Transform Transform::operator*(const Transform &other) const
{
Transform outTransform;
+5
View File
@@ -23,12 +23,17 @@ public:
Vector getPosition() const;
Quaternion getRotation() const;
Vector getScale() const;
Vector getForward() const;
Vector getRight() const;
Vector getUp() const;
bool equals(const Transform &other, float tolerance = 0.000000001f);
static void multiply(Transform *outTransform, const Transform *a, const Transform *b);
static void add(Transform *outTransform, const Transform *a, const Transform *b);
Transform &operator=(const Transform &other);
Transform &operator=(Transform &&other);
Transform operator+(const Transform& other) const;
Transform operator*(const Transform &other) const;
private:
-24
View File
@@ -64,30 +64,6 @@ static inline float normalizeRotatorAxis(float angle)
return angle;
}
static inline Quaternion toQuaternion(const Vector &other)
{
Quaternion result;
const float DEG_TO_RAD = glm::pi<float>() / (180.f);
const float RADS_DIVIDED_BY_2 = DEG_TO_RAD / 2.f;
const float PitchNoWinding = fmod(other.x, 360.0f);
const float YawNoWinding = fmod(other.y, 360.0f);
const float RollNoWinding = fmod(other.z, 360.0f);
const float SP = sin(PitchNoWinding * RADS_DIVIDED_BY_2);
const float SY = sin(YawNoWinding * RADS_DIVIDED_BY_2);
const float SR = sin(RollNoWinding * RADS_DIVIDED_BY_2);
const float CP = cos(PitchNoWinding * RADS_DIVIDED_BY_2);
const float CY = cos(YawNoWinding * RADS_DIVIDED_BY_2);
const float CR = cos(RollNoWinding * RADS_DIVIDED_BY_2);
result.x = CR * SP * SY - SR * CP * CY;
result.y = -CR * SP * CY - SR * CP * SY;
result.z = CR * CP * SY - SR * SP * CY;
result.w = CR * CP * CY + SR * SP * SY;
return result;
}
static inline Vector toRotator(const Quaternion &other)
{
+35 -23
View File
@@ -74,23 +74,23 @@ void Actor::detachChild(PActor child)
child->setParent(nullptr);
child->notifySceneAttach(nullptr);
}
void Actor::setWorldLocation(Vector location)
{
rootComponent->setWorldLocation(location);
}
void Actor::setWorldRotation(Quaternion rotation)
{
rootComponent->setWorldRotation(rotation);
}
void Actor::setWorldRotation(Vector rotation)
{
rootComponent->setWorldRotation(rotation);
}
void Actor::setWorldScale(Vector scale)
{
rootComponent->setWorldScale(scale);
}
//void Actor::setAbsoluteLocation(Vector location)
//{
// rootComponent->setWorldLocation(location);
//}
//
//void Actor::setAbsoluteRotation(Quaternion rotation)
//{
// rootComponent->setAbsoluteRotation(rotation);
//}
//void Actor::setAbsoluteRotation(Vector rotation)
//{
// rootComponent->setAbsoluteRotation(rotation);
//}
//void Actor::setWorldScale(Vector scale)
//{
// rootComponent->setWorldScale(scale);
//}
void Actor::setRelativeLocation(Vector location)
{
rootComponent->setRelativeLocation(location);
@@ -107,17 +107,29 @@ void Actor::setRelativeScale(Vector scale)
{
rootComponent->setRelativeScale(scale);
}
void Actor::addWorldTranslation(Vector translation)
//void Actor::addAbsoluteTranslation(Vector translation)
//{
// rootComponent->addAbsoluteTranslation(translation);
//}
//void Actor::addAbsoluteRotation(Quaternion rotation)
//{
// rootComponent->addAbsoluteRotation(rotation);
//}
//void Actor::addAbsoluteRotation(Vector rotation)
//{
// rootComponent->addAbsoluteRotation(rotation);
//}
void Actor::addRelativeLocation(Vector translation)
{
rootComponent->addWorldTranslation(translation);
rootComponent->addRelativeLocation(translation);
}
void Actor::addWorldRotation(Quaternion rotation)
void Actor::addRelativeRotation(Quaternion rotation)
{
rootComponent->addWorldRotation(rotation);
rootComponent->addRelativeRotation(rotation);
}
void Actor::addWorldRotation(Vector rotation)
void Actor::addRelativeRotation(Vector rotation)
{
rootComponent->addWorldRotation(rotation);
rootComponent->addRelativeRotation(rotation);
}
PComponent Actor::getRootComponent()
{
+11 -7
View File
@@ -26,19 +26,23 @@ public:
void addChild(PActor child);
void detachChild(PActor child);
Array<PActor> getChildren();
void setWorldLocation(Vector location);
void setWorldRotation(Quaternion rotation);
void setWorldRotation(Vector rotation);
void setWorldScale(Vector scale);
//void setAbsoluteLocation(Vector location);
//void setAbsoluteRotation(Quaternion rotation);
//void setAbsoluteRotation(Vector rotation);
//void setWorldScale(Vector scale);
void setRelativeLocation(Vector location);
void setRelativeRotation(Quaternion rotation);
void setRelativeRotation(Vector rotation);
void setRelativeScale(Vector scale);
void addWorldTranslation(Vector translation);
void addWorldRotation(Quaternion rotation);
void addWorldRotation(Vector rotation);
//void addAbsoluteTranslation(Vector translation);
//void addAbsoluteRotation(Quaternion rotation);
//void addAbsoluteRotation(Vector rotation);
void addRelativeLocation(Vector translation);
void addRelativeRotation(Quaternion rotation);
void addRelativeRotation(Vector rotation);
PComponent getRootComponent();
void setRootComponent(PComponent newRoot);
-2
View File
@@ -14,8 +14,6 @@ CameraActor::CameraActor()
cameraComponent->aspectRatio = 1.777778f;
cameraComponent->setParent(sceneComponent);
cameraComponent->setOwner(this);
addWorldTranslation(Vector(0, 0, 50));
addWorldRotation(Vector(0, -100, 0));
}
CameraActor::~CameraActor()
+36 -41
View File
@@ -6,19 +6,16 @@
using namespace Seele;
CameraComponent::CameraComponent()
: aspectRatio(0)
, fieldOfView(0)
: aspectRatio(0)
, fieldOfView(0)
, bNeedsViewBuild(true)
, bNeedsProjectionBuild(true)
, originPoint(0, 0, 0)
, cameraPosition(0, 0, 50)
, eye(Vector())
, projectionMatrix(Matrix4())
, viewMatrix(Matrix4())
, projectionMatrix(Matrix4())
, viewMatrix(Matrix4())
{
distance = 50;
rotationX = 0;
rotationY = -1.f;
rotationY = 0;
setRelativeLocation(Vector(0, 10, -50));
}
CameraComponent::~CameraComponent()
@@ -27,54 +24,52 @@ CameraComponent::~CameraComponent()
void CameraComponent::mouseMove(float deltaX, float deltaY)
{
//0.01 mouse sensitivity
rotationX += deltaX/500.f;
rotationY += deltaY/500.f;
rotationY = std::clamp(rotationY, -1.5f, 1.5f);
getParent()->setWorldRotation(glm::rotate(glm::quat(), rotationX, Vector(0, 1, 0)));
getParent()->setWorldRotation(glm::rotate(glm::quat(), rotationY, Vector(1, 0, 0)));
bNeedsViewBuild = true;
rotationX -= deltaX / 1000.f;
rotationY += deltaY / 1000.f;
//std::cout << "X:" << rotationX << " Y: " << rotationY << std::endl;
setRelativeRotation(Vector(rotationY, rotationX, 0));
bNeedsViewBuild = true;
}
void CameraComponent::mouseScroll(double x)
void CameraComponent::mouseScroll(float x)
{
distance -= static_cast<float>(x);
distance = std::max(distance, 1.f);
getParent()->addWorldTranslation(Vector(0, 0, x));
bNeedsViewBuild = true;
addRelativeLocation(getTransform().getForward()*x);
bNeedsViewBuild = true;
}
void CameraComponent::moveOrigin(float up)
void CameraComponent::moveX(float amount)
{
originPoint.y += up;
getParent()->addWorldTranslation(Vector(0, up, 0));
bNeedsViewBuild = true;
addRelativeLocation(getTransform().getForward()*amount);
bNeedsViewBuild = true;
}
void CameraComponent::moveY(float amount)
{
addRelativeLocation(getTransform().getRight()*amount);
bNeedsViewBuild = true;
}
void CameraComponent::buildViewMatrix()
{
Matrix4 rotation = glm::rotate(Matrix4(1.0f), rotationX, Vector(0, 1, 0));
rotation = glm::rotate(rotation, rotationY, Vector(1, 0, 0));
Vector4 translation(0, 0, distance, 1);
translation = rotation * translation;
Vector eyePos = getTransform().getPosition();
Vector lookAt = eyePos + getTransform().getForward();
std::cout << "Eye: " << eyePos << " lookAt: " << lookAt << std::endl;
viewMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
cameraPosition = originPoint + Vector(translation);
viewMatrix = glm::lookAt(cameraPosition, originPoint, Vector(0, 1, 0));
bNeedsViewBuild = false;
bNeedsViewBuild = false;
}
void CameraComponent::buildProjectionMatrix()
{
projectionMatrix = glm::perspective(fieldOfView, aspectRatio, 1.0f, 1000.f);
static Matrix4 correctionMatrix =
Matrix4(
Vector4(1, 0, 0, 0),
Vector4(0, 1, 0, 0),
Vector4(0, 0, 0.5f, 0),
Vector4(0, 0, 0.5f, 1));
projectionMatrix = correctionMatrix * projectionMatrix;
bNeedsProjectionBuild = false;
static Matrix4 correctionMatrix =
Matrix4(
Vector4(1, 0, 0, 0),
Vector4(0, 1, 0, 0),
Vector4(0, 0, 0.5f, 0),
Vector4(0, 0, 0.5f, 1));
projectionMatrix = correctionMatrix * projectionMatrix;
bNeedsProjectionBuild = false;
}
+34 -42
View File
@@ -10,51 +10,43 @@ public:
CameraComponent();
virtual ~CameraComponent();
Matrix4 getViewMatrix()
{
if (bNeedsViewBuild)
{
buildViewMatrix();
}
return viewMatrix;
}
Matrix4 getProjectionMatrix()
{
if (bNeedsProjectionBuild)
{
buildProjectionMatrix();
}
return projectionMatrix;
}
Vector getCameraPosition()
{
if(bNeedsViewBuild)
{
buildViewMatrix();
}
return cameraPosition;
}
void mouseMove(float deltaX, float deltaY);
void mouseScroll(double x);
void moveOrigin(float up);
float aspectRatio;
float fieldOfView;
Matrix4 getViewMatrix()
{
if (bNeedsViewBuild)
{
buildViewMatrix();
}
return viewMatrix;
}
Matrix4 getProjectionMatrix()
{
if (bNeedsProjectionBuild)
{
buildProjectionMatrix();
}
return projectionMatrix;
}
Vector getCameraPosition()
{
return getTransform().getPosition();
}
void mouseMove(float deltaX, float deltaY);
void mouseScroll(float x);
void moveX(float amount);
void moveY(float amount);
float aspectRatio;
float fieldOfView;
private:
bool bNeedsViewBuild;
bool bNeedsProjectionBuild;
void buildViewMatrix();
void buildProjectionMatrix();
bool bNeedsProjectionBuild;
void buildViewMatrix();
void buildProjectionMatrix();
float rotationX;
float rotationY;
float distance;
Vector eye;
Vector originPoint;
Vector cameraPosition;
//Transforms relative to actor
Matrix4 viewMatrix;
Matrix4 projectionMatrix;
//Transforms relative to actor
Matrix4 viewMatrix;
Matrix4 projectionMatrix;
float rotationX;
float rotationY;
};
DEFINE_REF(CameraComponent)
} // namespace Seele
+71 -135
View File
@@ -6,9 +6,6 @@ using namespace Seele;
Component::Component()
{
relativeLocation = Vector(0);
relativeRotation = Vector(0);
relativeScale = Vector(1, 1, 1);
}
Component::~Component()
{
@@ -89,162 +86,101 @@ void Component::notifySceneAttach(PScene scene)
child->notifySceneAttach(scene);
}
}
void Component::setWorldLocation(Vector location)
{
Vector newRelLocation = location;
if (parent != nullptr)
{
Transform parentToWorld = getParent()->getTransform();
newRelLocation = parentToWorld.inverseTransformPosition(location);
}
setRelativeLocation(newRelLocation);
}
void Component::setWorldRotation(Vector rotation)
{
Vector newRelRotator = rotation;
if (parent == nullptr)
{
setRelativeRotation(rotation);
}
else
{
setWorldRotation(toQuaternion(newRelRotator));
}
}
void Component::setWorldRotation(Quaternion rotation)
{
Quaternion newRelRotation = getRelativeWorldRotation(rotation);
setRelativeRotation(newRelRotation);
}
void Component::setWorldScale(Vector scale)
{
Vector newRelScale = scale;
if (parent != nullptr)
{
Transform parentToWorld = parent->getTransform();
newRelScale = scale * parentToWorld.getSafeScaleReciprocal(Vector4(parentToWorld.getScale(), 0));
}
setRelativeScale(newRelScale);
}
//void Component::setAbsoluteLocation(Vector location)
//{
// Vector newRelLocation = location;
// if (parent != nullptr)
// {
// Transform parentToWorld = getParent()->getTransform();
// newRelLocation = parentToWorld.inverseTransformPosition(location);
// }
// setRelativeLocation(newRelLocation);
//}
//void Component::setAbsoluteRotation(Vector rotation)
//{
// Vector newRelRotator = rotation;
// if (parent == nullptr)
// {
// setRelativeRotation(rotation);
// }
// else
// {
// setAbsoluteRotation(toQuaternion(newRelRotator));
// }
//}
//void Component::setAbsoluteRotation(Quaternion rotation)
//{
// Quaternion newRelRotation = getRelativeWorldRotation(rotation);
// setRelativeRotation(newRelRotation);
//}
//void Component::setWorldScale(Vector scale)
//{
// Vector newRelScale = scale;
// if (parent != nullptr)
// {
// Transform parentToWorld = parent->getTransform();
// newRelScale = scale * parentToWorld.getSafeScaleReciprocal(Vector4(parentToWorld.getScale(), 0));
// }
// setRelativeScale(newRelScale);
//}
void Component::setRelativeLocation(Vector location)
{
setRelativeLocationAndRotation(location, relativeRotation);
transform = Transform(location, transform.getRotation(), transform.getScale());
}
void Component::setRelativeRotation(Vector rotation)
{
setRelativeLocationAndRotation(relativeLocation, toQuaternion(rotation));
transform = Transform(transform.getPosition(), Quaternion(rotation), transform.getScale());
}
void Component::setRelativeRotation(Quaternion rotation)
{
setRelativeLocationAndRotation(relativeLocation, rotation);
transform = Transform(transform.getPosition(), rotation, transform.getScale());
}
void Component::setRelativeScale(Vector scale)
{
if (scale != relativeScale)
{
relativeScale = scale;
updateComponentTransform(relativeRotation);
}
transform = Transform(transform.getPosition(), transform.getRotation(), scale);
}
void Component::addWorldTranslation(Vector translation)
//void Component::addAbsoluteTranslation(Vector translation)
//{
// const Vector newWorldLocation = translation + getTransform().getPosition();
// setAbsoluteLocation(newWorldLocation);
//}
//void Component::addAbsoluteRotation(Vector rotation)
//{
// const Quaternion newWorldRotation = toQuaternion(rotation) * getTransform().getRotation();
// setAbsoluteRotation(newWorldRotation);
//}
//void Component::addAbsoluteRotation(Quaternion rotation)
//{
// const Quaternion newWorldRotation = rotation * getTransform().getRotation();
// setAbsoluteRotation(newWorldRotation);
//}
void Component::addRelativeLocation(Vector translation)
{
const Vector newWorldLocation = translation + getTransform().getPosition();
setWorldLocation(newWorldLocation);
transform = Transform(transform.getPosition() + translation, transform.getRotation(), transform.getScale());
}
void Component::addWorldRotation(Vector rotation)
void Component::addRelativeRotation(Vector rotation)
{
const Quaternion newWorldRotation = toQuaternion(rotation) * getTransform().getRotation();
setWorldRotation(newWorldRotation);
transform = Transform(transform.getPosition(), transform.getRotation() + Quaternion(rotation), transform.getScale());
}
void Component::addWorldRotation(Quaternion rotation)
void Component::addRelativeRotation(Quaternion rotation)
{
const Quaternion newWorldRotation = rotation * getTransform().getRotation();
setWorldRotation(newWorldRotation);
transform = Transform(transform.getPosition(), transform.getRotation(), transform.getScale());
}
Transform Component::getTransform() const
{
return transform;
}
void Component::internalSetTransform(Vector newLocation, Quaternion newRotation)
Transform Component::getAbsoluteTransform() const
{
if (parent != nullptr)
{
Transform parentTransform = parent->getTransform();
newLocation = parentTransform.inverseTransformPosition(newLocation);
newRotation = glm::inverse(parentTransform.getRotation()) * newRotation;
}
const Vector newRelRotation = toRotator(newRotation);
if (newLocation != relativeLocation || newRelRotation != relativeLocation)
{
relativeLocation = newLocation;
relativeRotation = newRelRotation;
updateComponentTransform(newRelRotation);
}
}
void Component::propagateTransformUpdate()
{
for (auto child : children)
{
child->updateComponentTransform(child->relativeRotation);
}
}
void Component::updateComponentTransform(Quaternion relativeRotationQuat)
{
if (parent != nullptr && !parent->bComponentTransformClean)
{
parent->updateComponentTransform(parent->relativeRotation);
if (bComponentTransformClean)
{
return;
}
}
bComponentTransformClean = true;
Transform newTransform;
const Transform relTransform(relativeLocation, relativeRotationQuat, relativeScale);
if(parent != nullptr)
{
newTransform = relTransform * parent->getTransform();
return transform + parent->getAbsoluteTransform();
}
else
{
newTransform = relTransform;
}
bool bHasChanged = !getTransform().equals(newTransform);
if (bHasChanged)
{
transform = newTransform;
propagateTransformUpdate();
}
}
Quaternion Component::getRelativeWorldRotation(Quaternion worldRotation)
{
Quaternion newRelRotation = worldRotation;
if (parent != nullptr)
{
const Transform parentToWorld = parent->getTransform();
const Quaternion parentToWorldQuat = parentToWorld.getRotation();
const Quaternion newRelQuat = glm::inverse(parentToWorldQuat) * worldRotation;
newRelRotation = newRelQuat;
}
return newRelRotation;
}
void Component::setRelativeLocationAndRotation(Vector newLocation, Quaternion newRotation)
{
if (!bComponentTransformClean)
{
updateComponentTransform(toQuaternion(relativeRotation));
}
const Transform desiredRelTransform(newLocation, newRotation);
const Transform desiredWorldTransform = desiredRelTransform; // Check for absolutes etc
internalSetTransform(desiredWorldTransform.getPosition(), desiredWorldTransform.getRotation());
}
return transform;
}
+13 -16
View File
@@ -28,27 +28,33 @@ public:
void addChildComponent(PComponent component);
virtual void notifySceneAttach(PScene scene);
void setWorldLocation(Vector location);
void setWorldRotation(Vector rotation);
void setWorldRotation(Quaternion rotation);
void setWorldScale(Vector scale);
//void setAbsoluteLocation(Vector location);
//void setAbsoluteRotation(Vector rotation);
//void setAbsoluteRotation(Quaternion rotation);
//void setWorldScale(Vector scale);
void setRelativeLocation(Vector location);
void setRelativeRotation(Vector rotation);
void setRelativeRotation(Quaternion rotation);
void setRelativeScale(Vector scale);
void addWorldTranslation(Vector translation);
void addWorldRotation(Vector rotation);
void addWorldRotation(Quaternion rotation);
//void addAbsoluteTranslation(Vector translation);
//void addAbsoluteRotation(Vector rotation);
//void addAbsoluteRotation(Quaternion rotation);
void addRelativeLocation(Vector translation);
void addRelativeRotation(Vector rotation);
void addRelativeRotation(Quaternion rotation);
Transform getTransform() const;
Transform getAbsoluteTransform() const;
template<typename ComponentType>
RefPtr<ComponentType> getComponent()
{
return tryFindComponent<ComponentType>();
}
private:
template<typename ComponentType>
RefPtr<ComponentType> tryFindComponent()
@@ -68,15 +74,6 @@ private:
}
return nullptr;
}
void internalSetTransform(Vector newLocation, Quaternion newRotation);
void propagateTransformUpdate();
void updateComponentTransform(Quaternion relativeRotationQuat);
Quaternion getRelativeWorldRotation(Quaternion worldRotation);
void setRelativeLocationAndRotation(Vector newLocation, Quaternion newRotation);
uint8 bComponentTransformClean : 1;
Vector relativeLocation;
Vector relativeRotation;
Vector relativeScale;
Transform transform;
PScene owningScene;
PActor owner;
@@ -50,5 +50,5 @@ void PrimitiveComponent::notifySceneAttach(PScene scene)
Matrix4 PrimitiveComponent::getRenderMatrix()
{
return getTransform().toMatrix();
return getAbsoluteTransform().toMatrix();
}
+14 -5
View File
@@ -19,12 +19,12 @@ Scene::Scene(Gfx::PGraphics graphics)
lightEnv.directionalLights[0].intensity = Vector4(1, 1, 1, 1);
lightEnv.numDirectionalLights = 1;
srand((unsigned int)time(NULL));
for(uint32 i = 0; i < 256; ++i)
for(uint32 i = 0; i < 16; ++i)
{
lightEnv.pointLights[i].colorRange = Vector4(frand(), frand(), frand(), frand() * 300);
lightEnv.pointLights[i].positionWS = Vector4(frand() * 100-50, frand(), frand() * 100-50, 1);
}
lightEnv.numPointLights = 256;
lightEnv.numPointLights = 16;
lightEnv.pointLights[0].colorRange = Vector4(1, 0, 1, 1000);
lightEnv.pointLights[0].positionWS = Vector4(0, 10, 0, 1);
}
@@ -41,19 +41,28 @@ void Scene::start()
}
}
static float lastUpdate;
static uint64 numUpdates;
Job Scene::beginUpdate(double deltaTime)
{
//std::cout << "Scene::beginUpdate" << std::endl;
auto startTime = std::chrono::high_resolution_clock::now();
Array<Job> jobs;
for(auto actor : rootActors)
{
jobs.addAll(actor->launchTick(static_cast<float>(deltaTime)));
}
co_await Job::all(jobs);
//std::cout << "Scene::beginUpdate finished waiting" << std::endl;
for(auto job : jobs)
auto endTime = std::chrono::high_resolution_clock::now();
float delta = std::chrono::duration_cast<std::chrono::seconds>(endTime - startTime).count();
lastUpdate += delta;
numUpdates++;
if(lastUpdate > 1.0f)
{
assert(job.done());
lastUpdate -= 1.0f;
std::cout << numUpdates << " updates per second" << std::endl;
numUpdates = 0;
}
}
+1
View File
@@ -19,6 +19,7 @@ struct DirectionalLight
struct PointLight
{
Vector4 positionWS;
//Vector4 positionVS;
Vector4 colorRange;
};
+1 -1
View File
@@ -123,7 +123,7 @@ public:
void update()
{
// lock should not be necessary, but lets keep it for now
std::scoped_lock lock(dataLock);
//std::scoped_lock lock(dataLock);
data = toBeWritten;
dirty = false;
}
+71 -65
View File
@@ -3,7 +3,6 @@
using namespace Seele;
std::atomic_uint64_t Seele::globalCounter;
Event::Event()
: flag(std::make_shared<StateStore>())
@@ -16,11 +15,20 @@ Event::Event(nullptr_t)
}
Event::Event(const std::string &name)
: name(name)
, flag(std::make_shared<StateStore>())
: flag(std::make_shared<StateStore>())
{
flag->name = name;
}
Event::Event(const std::source_location &location)
: flag(std::make_shared<StateStore>())
{
flag->name = location.function_name();
flag->location = location;
}
void Event::raise()
{
std::scoped_lock lock(flag->lock);
@@ -50,43 +58,34 @@ ThreadPool::ThreadPool(uint32 threadCount)
running.store(true);
for (uint32 i = 0; i < threadCount; ++i)
{
workers[i] = std::thread(&ThreadPool::threadLoop, this, false);
workers[i] = std::thread(&ThreadPool::threadLoop, this);
workers[i].detach();
}
}
ThreadPool::~ThreadPool()
{
cleanup();
workers.clear();
}
void ThreadPool::cleanup()
void ThreadPool::waitIdle()
{
bool temp = true;
running.compare_exchange_strong(temp, false);
if(!temp)
return;
while(true)
{
std::scoped_lock lock(jobQueueLock);
jobQueueCV.notify_all();
std::unique_lock lock(numIdlingLock);
numIdlingIncr.wait(lock);
if(numIdling == workers.size())
{
return;
}
}
{
std::scoped_lock lock(mainJobLock);
mainJobCV.notify_all();
}
for (auto &thread : workers)
{
thread.join();
}
workers.clear();
waitingJobs.clear();
waitingMainJobs.clear();
}
void ThreadPool::enqueueWaiting(Event &event, Promise* job)
{
assert(!job->done());
std::scoped_lock lock(waitingLock);
//std::cout << "Job " << job->finishedEvent.name << " waiting on event " << event.name << std::endl;
waitingJobs[event].push_back(job);
waitingJobs[event].add(job);
job->addRef();
}
void ThreadPool::enqueueWaiting(Event &event, MainPromise* job)
@@ -94,15 +93,15 @@ void ThreadPool::enqueueWaiting(Event &event, MainPromise* job)
assert(!job->done());
std::scoped_lock lock(waitingMainLock);
//std::cout << job->finishedEvent.name << " waiting on event " << event.name << std::endl;
waitingMainJobs[event].push_back(job);
waitingMainJobs[event].add(job);
job->addRef();
}
void ThreadPool::scheduleJob(Promise* job)
{
assert(!job->done());
std::scoped_lock lock(jobQueueLock);
//std::cout << "Queueing job " << job->finishedEvent.name << std::endl;
jobQueue.push_back(job);
//std::cout << "Queueing job " << job->finishedEvent << std::endl;
jobQueue.add(job);
jobQueueCV.notify_one();
job->addRef();
}
@@ -110,8 +109,8 @@ void ThreadPool::scheduleJob(MainPromise* job)
{
assert(!job->done());
std::scoped_lock lock(mainJobLock);
//std::cout << "Queueing job " << job->finishedEvent.name << std::endl;
mainJobs.push_back(job);
//std::cout << "Queueing job " << job->finishedEvent << std::endl;
mainJobs.add(job);
mainJobCV.notify_one();
job->addRef();
}
@@ -120,79 +119,86 @@ void ThreadPool::notify(Event &event)
//std::cout << "Event " << event.name << " raised" << std::endl;
{
std::scoped_lock lock(jobQueueLock, waitingLock);
std::list<Promise*> jobs = std::move(waitingJobs[event]);
List<Promise*> jobs = std::move(waitingJobs[event]);
waitingJobs.erase(event);
for (auto &job : jobs)
{
//assert(job.id != -1ull);
//std::cout << "Waking up " << job->finishedEvent.name << std::endl;
job->state = Promise::State::SCHEDULED;
jobQueue.push_back(job);
jobQueue.add(job);
jobQueueCV.notify_one();
}
}
{
std::scoped_lock lock(mainJobLock, waitingMainLock);
std::list<MainPromise*> jobs = std::move(waitingMainJobs[event]);
List<MainPromise*> jobs = std::move(waitingMainJobs[event]);
waitingMainJobs.erase(event);
for (auto &job : jobs)
{
//assert(job.id != -1ull);
//std::cout << "Waking up main " << job->finishedEvent.name << std::endl;
job->state = MainPromise::State::SCHEDULED;
mainJobs.push_back(job);
mainJobs.add(job);
mainJobCV.notify_one();
}
}
}
void ThreadPool::threadLoop(const bool mainThread)
void ThreadPool::mainLoop()
{
while (running.load())
while(true)
{
if (mainThread)
MainPromise* job;
{
MainPromise* job;
std::unique_lock lock(mainJobLock);
if(mainJobs.empty())
{
std::unique_lock lock(mainJobLock);
if(mainJobs.empty())
{
mainJobCV.wait(lock);
}
if (!mainJobs.empty())
{
job = mainJobs.front();
mainJobs.pop_front();
}
else
{
continue;
}
mainJobCV.wait(lock);
}
job = mainJobs.front();
mainJobs.popFront();
}
job->resume();
job->removeRef();
}
}
void ThreadPool::threadLoop()
{
List<Promise*> localQueue;
while (true)
{
[[likely]]
if(!localQueue.empty())
{
Promise* job = localQueue.retrieve();
job->resume();
job->removeRef();
}
else
{
Promise* job;
std::unique_lock lock(jobQueueLock);
if (jobQueue.empty())
{
std::unique_lock lock(jobQueueLock);
if (jobQueue.empty())
{
jobQueueCV.wait(lock);
std::unique_lock lock2(numIdlingLock);
numIdling++;
numIdlingIncr.notify_one();
}
if (!jobQueue.empty())
jobQueueCV.wait(lock);
{
job = jobQueue.front();
jobQueue.pop_front();
}
else
{
continue;
std::unique_lock lock2(numIdlingLock);
numIdling--;
}
}
//std::cout << "Starting job " << job.id << std::endl;
job->resume();
job->removeRef();
// take 1/numThreads jobs, maybe make this a parameter that
// adjusts based on past workload
uint32 numTaken = std::max(jobQueue.size() / workers.size(), 1ull);
while (!jobQueue.empty() && localQueue.size() < numTaken)
{
localQueue.add(jobQueue.retrieve());
}
}
}
}
+91 -41
View File
@@ -17,6 +17,7 @@ public:
Event();
Event(nullptr_t);
Event(const std::string& name);
Event(const std::source_location& location);
~Event() = default;
auto operator<=>(const Event& other) const
{
@@ -36,6 +37,19 @@ public:
return flag->data;
}
friend std::ostream& operator<<(std::ostream& stream, const Event& event)
{
stream
<< event.flag->location.file_name()
<< "("
<< event.flag->location.line()
<< ":"
<< event.flag->location.column()
<< "): "
<< event.flag->location.function_name();
return stream;
}
void raise();
void reset();
bool await_ready();
@@ -43,17 +57,17 @@ public:
constexpr void await_suspend(std::coroutine_handle<JobPromiseBase<MainJob>> h);
constexpr void await_resume() {}
private:
std::string name;
struct StateStore
{
std::mutex lock;
std::string name;
std::source_location location;
bool data;
};
std::shared_ptr<StateStore> flag;
friend class ThreadPool;
};
extern std::atomic_uint64_t globalCounter;
template<bool MainJob>
struct JobBase;
template<bool MainJob>
@@ -70,8 +84,7 @@ struct JobPromiseBase
JobPromiseBase(const std::source_location& location = std::source_location::current())
{
handle = std::coroutine_handle<JobPromiseBase<MainJob>>::from_promise(*this);
id = globalCounter++;
finishedEvent = Event(std::string(location.file_name()).append(": ").append(location.function_name()));
finishedEvent = Event(location);
}
~JobPromiseBase()
{}
@@ -81,9 +94,10 @@ struct JobPromiseBase
inline auto final_suspend() noexcept;
void return_void() noexcept {}
void unhandled_exception() noexcept {
std::cerr << "Unhandled exception! Exiting" << std::endl;
exit(1);
void unhandled_exception() {
std::exception_ptr exception = std::current_exception();
std::cerr << "Unhandled exception!" << std::endl;
throw exception;
};
void resume()
@@ -165,16 +179,22 @@ struct JobPromiseBase
}
void removeRef()
{
if(--numRefs < 1 && done())
if(--numRefs < 1)
{
handle.destroy();
}
if(done())
{
handle.destroy();
}
else
{
schedule();
}
}
}
std::mutex promiseLock;
std::coroutine_handle<JobPromiseBase> handle;
JobPromiseBase* continuation = nullptr;
uint64 id;
std::atomic_uint64_t numRefs = 0;
Event finishedEvent;
State state = State::READY;
@@ -210,7 +230,7 @@ public:
{
if(promise)
{
promise->schedule();
//promise->schedule();
promise->removeRef();
}
}
@@ -253,19 +273,25 @@ public:
{
return promise->done();
}
void finalize()
{
promise->finalize();
}
Event operator co_await() const
{
// the co_await operator keeps a reference to this, we it won't
// the co_await operator keeps a reference to this, it won't
// be scheduled from the destructor
promise->schedule();
return promise->finishedEvent;
}
static JobBase all() = delete;
template<iterable Iterable>
template<std::ranges::range Iterable>
requires std::same_as<std::ranges::range_value_t<Iterable>, JobBase>
static JobBase all(Iterable collection)
{
getGlobalThreadPool().scheduleBatch(collection);
for(auto it : collection)
{
co_await it;
}
}
template<std::ranges::range Iterable>
static JobBase all(Iterable collection)
{
for(auto it : collection)
@@ -278,14 +304,17 @@ public:
{
return JobBase::all(Array{jobs...});
}
template<std::invocable JobFunc, iterable IterableParams>
static JobBase launchJobs(JobFunc&& func, IterableParams params)
template<typename JobFunc, std::ranges::input_range Iterable>
requires std::invocable<JobFunc, std::ranges::range_reference_t<Iterable>>
static JobBase launchJobs(JobFunc&& func, Iterable params)
{
List<JobBase> jobs;
Array<JobBase> jobs;
for(auto&& param : params)
{
jobs.add(func(param));
JobBase base = func(param);
jobs.add(base);
}
getGlobalThreadPool().scheduleBatch(jobs);
for(auto job : jobs)
{
co_await job;
@@ -293,6 +322,7 @@ public:
}
private:
JobPromiseBase<MainJob>* promise;
friend class ThreadPool;
};
using MainJob = JobBase<true>;
@@ -305,32 +335,64 @@ class ThreadPool
public:
ThreadPool(uint32 threadCount = std::thread::hardware_concurrency());
virtual ~ThreadPool();
void cleanup();
void waitIdle();
// Adds a job to the waiting queue for event
void enqueueWaiting(Event& event, Promise* job);
// Adds a job to the waiting queue for event
void enqueueWaiting(Event& event, MainPromise* job);
void scheduleJob(Promise* job);
void scheduleJob(MainPromise* job);
template<std::ranges::range Iterable>
requires std::same_as<std::ranges::range_value_t<Iterable>, MainJob>
void scheduleBatch(Iterable jobs)
{
std::scoped_lock lock(mainJobLock);
for(auto job : jobs)
{
job.promise->addRef();
job.promise->state = JobPromiseBase<true>::State::SCHEDULED;
mainJobs.add(job.promise);
}
mainJobCV.notify_one();
}
template<std::ranges::range Iterable>
requires std::same_as<std::ranges::range_value_t<Iterable>, Job>
void scheduleBatch(Iterable jobs)
{
std::scoped_lock lock(jobQueueLock);
for(auto job : jobs)
{
job.promise->addRef();
job.promise->state = JobPromiseBase<false>::State::SCHEDULED;
jobQueue.add(job.promise);
}
jobQueueCV.notify_all();
}
void notify(Event& event);
void threadLoop(const bool isMainThread);
void mainLoop();
void threadLoop();
private:
std::atomic_bool running;
std::vector<std::thread> workers;
std::mutex numIdlingLock;
std::condition_variable numIdlingIncr;
uint32 numIdling;
Array<std::thread> workers;
std::list<MainPromise*> mainJobs;
List<MainPromise*> mainJobs;
std::mutex mainJobLock;
std::condition_variable mainJobCV;
std::list<Promise*> jobQueue;
List<Promise*> jobQueue;
std::mutex jobQueueLock;
std::condition_variable jobQueueCV;
std::map<Event, std::list<MainPromise*>> waitingMainJobs;
Map<Event, List<MainPromise*>> waitingMainJobs;
std::mutex waitingMainLock;
std::map<Event, std::list<Promise*>> waitingJobs;
Map<Event, List<Promise*>> waitingJobs;
std::mutex waitingLock;
uint32 maxLocalQueueSize = 50;
};
template<bool MainJob>
@@ -349,18 +411,6 @@ inline auto JobPromiseBase<MainJob>::initial_suspend() noexcept
template<bool MainJob>
inline auto JobPromiseBase<MainJob>::final_suspend() noexcept
{
/*struct JobAwaitable
{
constexpr bool await_ready() const noexcept { return false; }
constexpr auto await_suspend(std::coroutine_handle<JobPromiseBase<MainJob>> h) const noexcept
{
auto continuation = h.promise().continuation;
h.destroy();
}
constexpr void await_resume() const noexcept {}
};
return JobAwaitable{};*/
markDone();
return std::suspend_always{};
}
+32 -18
View File
@@ -32,15 +32,15 @@ Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const Viewpo
AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Plane\\plane.fbx");
PPrimitiveComponent ayaka = new PrimitiveComponent(AssetRegistry::findMesh("Ayaka"));
ayaka->addWorldTranslation(Vector(0, 0, 0));
ayaka->setWorldScale(Vector(10, 10, 10));
ayaka->setRelativeLocation(Vector(0, 0, 0));
ayaka->setRelativeScale(Vector(10, 10, 10));
//scene->addPrimitiveComponent(ayaka);
PPrimitiveComponent plane = new PrimitiveComponent(AssetRegistry::findMesh("plane"));
plane->setWorldScale(Vector(100, 100, 100));
plane->setRelativeScale(Vector(100, 100, 100));
scene->addPrimitiveComponent(plane);
for(uint32 i = 0; i < 1; ++i)
for(uint32 i = 0; i < 100000; ++i)
{
PMyComponent myComp = new MyComponent();
PMyOtherComponent myOtherComp = new MyOtherComponent();
@@ -97,32 +97,46 @@ void SceneView::prepareRender()
MainJob SceneView::render()
{
return MainJob::all(
depthPrepass.beginFrame(),
lightCullingPass.beginFrame(),
basePass.beginFrame())
return depthPrepass.beginFrame()
.then(lightCullingPass.beginFrame())
.then(basePass.beginFrame())
.then(depthPrepass.render())
.then(lightCullingPass.render())
.then(basePass.render())
.then(
MainJob::all(
depthPrepass.endFrame(),
lightCullingPass.endFrame(),
basePass.endFrame())
);
.then(depthPrepass.endFrame())
.then(lightCullingPass.endFrame())
.then(basePass.endFrame());
}
void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifier)
static float cameraSpeed = 1;
void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifier mod)
{
if((KeyModifierFlags)mod & (KeyModifierFlags)KeyModifier::MOD_SHIFT)
{
cameraSpeed = 5;
}
else
{
cameraSpeed = 1;
}
if(action != InputAction::RELEASE)
{
if(code == KeyCode::KEY_W)
{
activeCamera->getCameraComponent()->moveOrigin(1);
activeCamera->getCameraComponent()->moveX(1);
}
if(code == KeyCode::KEY_S)
{
activeCamera->getCameraComponent()->moveOrigin(-1);
activeCamera->getCameraComponent()->moveX(-1);
}
if(code == KeyCode::KEY_A)
{
activeCamera->getCameraComponent()->moveY(1);
}
if(code == KeyCode::KEY_D)
{
activeCamera->getCameraComponent()->moveY(-1);
}
}
}
@@ -144,7 +158,7 @@ void SceneView::mouseMoveCallback(double xPos, double yPos)
void SceneView::mouseButtonCallback(MouseButton button, InputAction action, KeyModifier)
{
if(button == MouseButton::MOUSE_BUTTON_1 && action != InputAction::RELEASE)
if(button == MouseButton::MOUSE_BUTTON_2 && action != InputAction::RELEASE)
{
mouseDown = true;
}
+1 -3
View File
@@ -27,16 +27,14 @@ void Window::addView(PView view)
MainJob Window::render()
{
gfxHandle->beginFrame();
Array<MainJob> jobs;
for(auto& windowView : views)
{
{
std::scoped_lock lock(windowView->workerMutex);
windowView->view->prepareRender();
}
jobs.add(windowView->view->render());
co_await windowView->view->render();
}
co_await MainJob::all(jobs);
gfxHandle->endFrame();
if(owner->isActive())
{
+1 -1
View File
@@ -41,6 +41,6 @@ void WindowManager::notifyWindowClosed(PWindow window)
windows.remove(windows.find(window));
if(windows.empty())
{
getGlobalThreadPool().cleanup();
exit(0);
}
}
+2 -2
View File
@@ -34,9 +34,9 @@ int main()
//PInspectorView inspectorView = new InspectorView(windowManager->getGraphics(), window, inspectorViewInfo);
//window->addView(inspectorView);
sceneView->setFocused();
window->render();
getGlobalThreadPool().threadLoop(true);
getGlobalThreadPool().mainLoop();
return 0;
}
+2 -2
View File
@@ -1,5 +1,5 @@
#pragma once
//#include <vld.h>
#include <vld.h>
#include "ThreadPool.h"
namespace Seele
@@ -12,7 +12,7 @@ namespace Seele
}
~GlobalFixture()
{
getGlobalThreadPool().cleanup();
getGlobalThreadPool().waitIdle();
}
void setup()
{
+84
View File
@@ -1,6 +1,9 @@
#include "EngineTest.h"
#include "ThreadPool.h"
#include <boost/test/unit_test.hpp>
#include <numeric>
using namespace std::chrono_literals;
BOOST_AUTO_TEST_SUITE(ThreadPool)
@@ -9,18 +12,21 @@ uint64 basicAwaitState = 0;
Job basicAwaitFirst()
{
BOOST_REQUIRE_EQUAL(basicAwaitState, 5);
std::this_thread::sleep_for(500ms);
basicAwaitState = 10;
co_return;
}
Job basicAwaitSecond()
{
BOOST_REQUIRE_EQUAL(basicAwaitState, 15);
std::this_thread::sleep_for(500ms);
basicAwaitState = 20;
co_return;
}
Job basicAwaitThird()
{
BOOST_REQUIRE_EQUAL(basicAwaitState, 25);
std::this_thread::sleep_for(500ms);
basicAwaitState = 30;
co_return;
}
@@ -48,18 +54,21 @@ uint64 basicThenState = 5;
Job basicThenFirst()
{
BOOST_REQUIRE_EQUAL(basicThenState, 5);
std::this_thread::sleep_for(500ms);
basicThenState = 10;
co_return;
}
Job basicThenSecond()
{
BOOST_REQUIRE_EQUAL(basicThenState, 15);
std::this_thread::sleep_for(500ms);
basicThenState = 20;
co_return;
}
Job basicThenThird()
{
BOOST_REQUIRE_EQUAL(basicThenState, 25);
std::this_thread::sleep_for(500ms);
basicThenState = 30;
co_return;
}
@@ -70,6 +79,7 @@ BOOST_AUTO_TEST_CASE(basic_thenchain)
.then([]() -> Job
{
BOOST_REQUIRE_EQUAL(basicThenState, 10);
std::this_thread::sleep_for(500ms);
basicThenState = 15;
co_return;
})
@@ -77,6 +87,7 @@ BOOST_AUTO_TEST_CASE(basic_thenchain)
.then([]() -> Job
{
BOOST_REQUIRE_EQUAL(basicThenState, 20);
std::this_thread::sleep_for(500ms);
basicThenState = 25;
co_return;
})
@@ -92,11 +103,13 @@ uint64 basicAllState1 = 0;
uint64 basicAllState2 = 0;
Job basicAllFirst()
{
std::this_thread::sleep_for(500ms);
basicAllState1 = 10;
co_return;
}
Job basicAllSecond()
{
std::this_thread::sleep_for(500ms);
basicAllState2 = 10;
co_return;
}
@@ -112,10 +125,41 @@ BOOST_AUTO_TEST_CASE(basic_all)
Job::all(basicAllFirst(), basicAllSecond()).then(basicAllThen());
}
uint64 allThenState = 0;
Job allThenInitial()
{
std::this_thread::sleep_for(500ms);
allThenState = 10;
co_return;
}
Job allThenIntermediate()
{
std::this_thread::sleep_for(500ms);
BOOST_REQUIRE_EQUAL(allThenState, 10);
allThenState = 20;
co_return;
}
Job allThenFinal()
{
BOOST_REQUIRE_EQUAL(allThenState, 20);
co_return;
}
BOOST_AUTO_TEST_CASE(all_then_interaction)
{
Job::all(allThenInitial())
.then(allThenIntermediate())
.then(Job::all(allThenFinal()));
}
uint64 basicCallable = 0;
Job basicCallableFunc()
{
std::this_thread::sleep_for(500ms);
basicCallable = 10;
co_return;
}
@@ -130,4 +174,44 @@ BOOST_AUTO_TEST_CASE(basic_callable)
});
}
struct Payload
{
StaticArray<uint64, 1000> data;
uint64 result = 0;
};
Job worker(Payload& payload)
{
for(uint32 i = 0; i < 100000; ++i)
{
payload.result = std::accumulate(payload.data.begin(), payload.data.end(), (uint64)1, std::multiplies<uint64>());
}
co_return;
}
Job launchStressTest()
{
Array<Payload> payloads(100);
Array<Job> jobs;
for(auto& payload : payloads)
{
for(uint64 i = 0; i < payload.data.size(); ++i)
{
payload.data[i] = i;
}
}
auto startTime = std::chrono::high_resolution_clock::now();
std::cout << "Starting up" << std::endl;
co_await Job::launchJobs(&worker, payloads);
std::cout << "Finished waiting" << std::endl;
auto endTime = std::chrono::high_resolution_clock::now();
float delta = std::chrono::duration_cast<std::chrono::seconds>(endTime - startTime).count();
std::cout << "Update took " << delta << " seconds";
}
BOOST_AUTO_TEST_CASE(stress_test)
{
//launchStressTest();
}
BOOST_AUTO_TEST_SUITE_END()