Memory leak, but otherwise working
This commit is contained in:
+57
-57
@@ -13,72 +13,72 @@ struct SkyboxData
|
|||||||
layout(set=1)
|
layout(set=1)
|
||||||
ParameterBlock<SkyboxData> pSkyboxData;
|
ParameterBlock<SkyboxData> pSkyboxData;
|
||||||
|
|
||||||
float3 vertices[] = {
|
|
||||||
// Back
|
|
||||||
float3(-512, -512, 512),
|
|
||||||
float3(-512, 512, 512),
|
|
||||||
float3( 512, -512, 512),
|
|
||||||
|
|
||||||
float3( 512, -512, 512),
|
|
||||||
float3(-512, 512, 512),
|
|
||||||
float3( 512, 512, 512),
|
|
||||||
|
|
||||||
// Front
|
|
||||||
float3( 512, -512, -512),
|
|
||||||
float3( 512, 512, -512),
|
|
||||||
float3(-512, -512, -512),
|
|
||||||
|
|
||||||
float3(-512, -512, -512),
|
|
||||||
float3( 512, 512, -512),
|
|
||||||
float3(-512, 512, -512),
|
|
||||||
|
|
||||||
// Top
|
|
||||||
float3(-512, -512, -512),
|
|
||||||
float3(-512, -512, 512),
|
|
||||||
float3( 512, -512, -512),
|
|
||||||
|
|
||||||
float3( 512, -512, -512),
|
|
||||||
float3(-512, -512, 512),
|
|
||||||
float3( 512, -512, 512),
|
|
||||||
|
|
||||||
// Bottom
|
|
||||||
float3(-512, 512, 512),
|
|
||||||
float3(-512, 512, -512),
|
|
||||||
float3( 512, 512, 512),
|
|
||||||
|
|
||||||
float3( 512, 512, 512),
|
|
||||||
float3(-512, 512, -512),
|
|
||||||
float3( 512, 512, -512),
|
|
||||||
|
|
||||||
// Left
|
|
||||||
float3(-512, -512, -512),
|
|
||||||
float3(-512, 512, -512),
|
|
||||||
float3(-512, -512, 512),
|
|
||||||
|
|
||||||
float3(-512, -512, 512),
|
|
||||||
float3(-512, 512, -512),
|
|
||||||
float3(-512, 512, 512),
|
|
||||||
|
|
||||||
// Right
|
|
||||||
float3( 512, -512, 512),
|
|
||||||
float3( 512, 512, 512),
|
|
||||||
float3( 512, -512, -512),
|
|
||||||
|
|
||||||
float3( 512, -512, -512),
|
|
||||||
float3( 512, 512, 512),
|
|
||||||
float3( 512, 512, -512),
|
|
||||||
};
|
|
||||||
|
|
||||||
[shader("vertex")]
|
[shader("vertex")]
|
||||||
VertexShaderOutput vertexMain(
|
VertexShaderOutput vertexMain(
|
||||||
uint vertexIndex : SV_VertexId)
|
uint vertexIndex : SV_VertexId)
|
||||||
{
|
{
|
||||||
|
const float3 vertices[] = {
|
||||||
|
// Back
|
||||||
|
float3(-512, -512, 512),
|
||||||
|
float3(-512, 512, 512),
|
||||||
|
float3( 512, -512, 512),
|
||||||
|
|
||||||
|
float3( 512, -512, 512),
|
||||||
|
float3(-512, 512, 512),
|
||||||
|
float3( 512, 512, 512),
|
||||||
|
|
||||||
|
// Front
|
||||||
|
float3( 512, -512, -512),
|
||||||
|
float3( 512, 512, -512),
|
||||||
|
float3(-512, -512, -512),
|
||||||
|
|
||||||
|
float3(-512, -512, -512),
|
||||||
|
float3( 512, 512, -512),
|
||||||
|
float3(-512, 512, -512),
|
||||||
|
|
||||||
|
// Top
|
||||||
|
float3(-512, -512, -512),
|
||||||
|
float3(-512, -512, 512),
|
||||||
|
float3( 512, -512, -512),
|
||||||
|
|
||||||
|
float3( 512, -512, -512),
|
||||||
|
float3(-512, -512, 512),
|
||||||
|
float3( 512, -512, 512),
|
||||||
|
|
||||||
|
// Bottom
|
||||||
|
float3(-512, 512, 512),
|
||||||
|
float3(-512, 512, -512),
|
||||||
|
float3( 512, 512, 512),
|
||||||
|
|
||||||
|
float3( 512, 512, 512),
|
||||||
|
float3(-512, 512, -512),
|
||||||
|
float3( 512, 512, -512),
|
||||||
|
|
||||||
|
// Left
|
||||||
|
float3(-512, -512, -512),
|
||||||
|
float3(-512, 512, -512),
|
||||||
|
float3(-512, -512, 512),
|
||||||
|
|
||||||
|
float3(-512, -512, 512),
|
||||||
|
float3(-512, 512, -512),
|
||||||
|
float3(-512, 512, 512),
|
||||||
|
|
||||||
|
// Right
|
||||||
|
float3( 512, -512, 512),
|
||||||
|
float3( 512, 512, 512),
|
||||||
|
float3( 512, -512, -512),
|
||||||
|
|
||||||
|
float3( 512, -512, -512),
|
||||||
|
float3( 512, 512, 512),
|
||||||
|
float3( 512, 512, -512),
|
||||||
|
};
|
||||||
|
|
||||||
VertexShaderOutput output;
|
VertexShaderOutput output;
|
||||||
float3x3 cameraRotation = float3x3(pViewParams.viewMatrix);
|
float3x3 cameraRotation = float3x3(pViewParams.viewMatrix);
|
||||||
float4 worldPos = float4(mul(cameraRotation, vertices[vertexIndex]), 1.0f);
|
float4 worldPos = float4(mul(cameraRotation, vertices[vertexIndex]), 1.0f);
|
||||||
//clip(dot(worldPos, clipPlane));
|
//clip(dot(worldPos, clipPlane));
|
||||||
output.clipPos = mul(pViewParams.projectionMatrix, worldPos);
|
output.clipPos = mul(pViewParams.projectionMatrix, worldPos);
|
||||||
output.texCoords = normalize(input.position);
|
output.texCoords = normalize(vertices[vertexIndex]);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -216,9 +216,8 @@ int main()
|
|||||||
mainWindowInfo.title = "SeeleEngine";
|
mainWindowInfo.title = "SeeleEngine";
|
||||||
mainWindowInfo.width = 1280;
|
mainWindowInfo.width = 1280;
|
||||||
mainWindowInfo.height = 720;
|
mainWindowInfo.height = 720;
|
||||||
mainWindowInfo.bFullscreen = false;
|
|
||||||
mainWindowInfo.numSamples = 1;
|
mainWindowInfo.numSamples = 1;
|
||||||
mainWindowInfo.pixelFormat = Gfx::SE_FORMAT_B8G8R8A8_UNORM;
|
mainWindowInfo.preferredFormat = Gfx::SE_FORMAT_B8G8R8A8_SRGB;
|
||||||
auto window = windowManager->addWindow(graphics, mainWindowInfo);
|
auto window = windowManager->addWindow(graphics, mainWindowInfo);
|
||||||
ViewportCreateInfo sceneViewInfo;
|
ViewportCreateInfo sceneViewInfo;
|
||||||
sceneViewInfo.dimensions.size.x = 1280;
|
sceneViewInfo.dimensions.size.x = 1280;
|
||||||
|
|||||||
@@ -746,12 +746,14 @@ public:
|
|||||||
}
|
}
|
||||||
StaticArray(std::initializer_list<T> init)
|
StaticArray(std::initializer_list<T> init)
|
||||||
{
|
{
|
||||||
assert(init.size() == N);
|
|
||||||
auto beg = init.begin();
|
auto beg = init.begin();
|
||||||
for (size_t i = 0; i < N; ++i)
|
for (size_t i = 0; i < N; ++i)
|
||||||
{
|
{
|
||||||
_data[i] = *beg;
|
_data[i] = *beg;
|
||||||
beg++;
|
if (init.size() == N)
|
||||||
|
{
|
||||||
|
beg++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~StaticArray()
|
~StaticArray()
|
||||||
|
|||||||
@@ -179,7 +179,6 @@ public:
|
|||||||
, _size(std::move(other._size))
|
, _size(std::move(other._size))
|
||||||
, allocator(std::move(other.allocator))
|
, allocator(std::move(other.allocator))
|
||||||
{
|
{
|
||||||
other.clear();
|
|
||||||
}
|
}
|
||||||
List(List&& other, const Allocator& alloc)
|
List(List&& other, const Allocator& alloc)
|
||||||
: root(std::move(other.root))
|
: root(std::move(other.root))
|
||||||
|
|||||||
@@ -260,18 +260,6 @@ public:
|
|||||||
markIteratorsDirty();
|
markIteratorsDirty();
|
||||||
return getNode(root)->pair.value;
|
return getNode(root)->pair.value;
|
||||||
}
|
}
|
||||||
constexpr mapped_type& operator[](key_type&& key)
|
|
||||||
{
|
|
||||||
root = splay(root, std::move(key));
|
|
||||||
if (!isValid(root) || !equal(getNode(root)->pair.key, key))
|
|
||||||
{
|
|
||||||
root = insert(root, std::move(key));
|
|
||||||
_size++;
|
|
||||||
}
|
|
||||||
markIteratorsDirty();
|
|
||||||
return getNode(root)->pair.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const mapped_type& operator[](const key_type& key) const
|
constexpr const mapped_type& operator[](const key_type& key) const
|
||||||
{
|
{
|
||||||
size_t it = root;
|
size_t it = root;
|
||||||
@@ -288,23 +276,6 @@ public:
|
|||||||
}
|
}
|
||||||
return getNode(it)->pair.value;
|
return getNode(it)->pair.value;
|
||||||
}
|
}
|
||||||
constexpr const mapped_type& operator[](key_type&& key) const
|
|
||||||
{
|
|
||||||
size_t it = root;
|
|
||||||
while (!equal(getNode(it)->pair.key, key))
|
|
||||||
{
|
|
||||||
if (comp(key, getNode(it)->pair.key))
|
|
||||||
{
|
|
||||||
it = getNode(it)->leftChild;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
it = getNode(it)->rightChild;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return getNode(it)->pair.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr mapped_type& at(const key_type& key)
|
constexpr mapped_type& at(const key_type& key)
|
||||||
{
|
{
|
||||||
root = splay(root, key);
|
root = splay(root, key);
|
||||||
@@ -361,6 +332,7 @@ public:
|
|||||||
{
|
{
|
||||||
root = remove(root, key);
|
root = remove(root, key);
|
||||||
refreshIterators();
|
refreshIterators();
|
||||||
|
assert(root != SIZE_MAX || _size == 0);
|
||||||
return iterator(root, &nodeContainer);
|
return iterator(root, &nodeContainer);
|
||||||
}
|
}
|
||||||
constexpr iterator erase(key_type&& key)
|
constexpr iterator erase(key_type&& key)
|
||||||
@@ -528,7 +500,6 @@ private:
|
|||||||
endIndex = getNode(endIndex)->rightChild;
|
endIndex = getNode(endIndex)->rightChild;
|
||||||
}
|
}
|
||||||
return Iterator(endIndex, &nodeContainer, std::move(endTraversal));
|
return Iterator(endIndex, &nodeContainer, std::move(endTraversal));
|
||||||
|
|
||||||
}
|
}
|
||||||
Array<Node, NodeAlloc> nodeContainer = Array<Node, NodeAlloc>();
|
Array<Node, NodeAlloc> nodeContainer = Array<Node, NodeAlloc>();
|
||||||
size_t root;
|
size_t root;
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ target_sources(Engine
|
|||||||
Texture.h
|
Texture.h
|
||||||
Texture.cpp
|
Texture.cpp
|
||||||
VertexData.h
|
VertexData.h
|
||||||
VertexData.cpp)
|
VertexData.cpp
|
||||||
|
Window.h
|
||||||
|
Window.cpp)
|
||||||
|
|
||||||
target_sources(Engine
|
target_sources(Engine
|
||||||
PUBLIC FILE_SET HEADERS
|
PUBLIC FILE_SET HEADERS
|
||||||
@@ -47,7 +49,8 @@ target_sources(Engine
|
|||||||
Shader.h
|
Shader.h
|
||||||
StaticMeshVertexData.h
|
StaticMeshVertexData.h
|
||||||
Texture.h
|
Texture.h
|
||||||
VertexData.h)
|
VertexData.h
|
||||||
|
Window.h)
|
||||||
|
|
||||||
add_subdirectory(RenderPass/)
|
add_subdirectory(RenderPass/)
|
||||||
add_subdirectory(Vulkan/)
|
add_subdirectory(Vulkan/)
|
||||||
@@ -8,12 +8,12 @@ LegacyPipelineCreateInfo::LegacyPipelineCreateInfo()
|
|||||||
: topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
: topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
||||||
, multisampleState(MultisampleState{
|
, multisampleState(MultisampleState{
|
||||||
.samples = 1,
|
.samples = 1,
|
||||||
})
|
})
|
||||||
, rasterizationState(RasterizationState{
|
, rasterizationState(RasterizationState{
|
||||||
.polygonMode = Gfx::SE_POLYGON_MODE_FILL,
|
.polygonMode = Gfx::SE_POLYGON_MODE_FILL,
|
||||||
.cullMode = Gfx::SE_CULL_MODE_BACK_BIT,
|
.cullMode = Gfx::SE_CULL_MODE_BACK_BIT,
|
||||||
.frontFace = Gfx::SE_FRONT_FACE_COUNTER_CLOCKWISE,
|
.frontFace = Gfx::SE_FRONT_FACE_COUNTER_CLOCKWISE,
|
||||||
})
|
})
|
||||||
, depthStencilState(DepthStencilState{
|
, depthStencilState(DepthStencilState{
|
||||||
.depthTestEnable = true,
|
.depthTestEnable = true,
|
||||||
.depthWriteEnable = true,
|
.depthWriteEnable = true,
|
||||||
@@ -21,7 +21,7 @@ LegacyPipelineCreateInfo::LegacyPipelineCreateInfo()
|
|||||||
.stencilTestEnable = false,
|
.stencilTestEnable = false,
|
||||||
.minDepthBounds = 0.0f,
|
.minDepthBounds = 0.0f,
|
||||||
.maxDepthBounds = 1.0f,
|
.maxDepthBounds = 1.0f,
|
||||||
})
|
})
|
||||||
, colorBlend(ColorBlendState{
|
, colorBlend(ColorBlendState{
|
||||||
.logicOpEnable = false,
|
.logicOpEnable = false,
|
||||||
.attachmentCount = 0,
|
.attachmentCount = 0,
|
||||||
@@ -40,7 +40,7 @@ LegacyPipelineCreateInfo::LegacyPipelineCreateInfo()
|
|||||||
1.0f,
|
1.0f,
|
||||||
1.0f,
|
1.0f,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,9 +36,8 @@ struct WindowCreateInfo
|
|||||||
int32 width;
|
int32 width;
|
||||||
int32 height;
|
int32 height;
|
||||||
const char *title;
|
const char *title;
|
||||||
bool bFullscreen;
|
|
||||||
Gfx::SeSampleCountFlags numSamples;
|
Gfx::SeSampleCountFlags numSamples;
|
||||||
Gfx::SeFormat pixelFormat;
|
Gfx::SeFormat preferredFormat = Gfx::SE_FORMAT_MAX_ENUM;
|
||||||
void *windowHandle;
|
void *windowHandle;
|
||||||
};
|
};
|
||||||
struct ViewportCreateInfo
|
struct ViewportCreateInfo
|
||||||
|
|||||||
@@ -48,9 +48,6 @@ void BasePass::beginFrame(const Component::Camera& cam)
|
|||||||
RenderPass::beginFrame(cam);
|
RenderPass::beginFrame(cam);
|
||||||
|
|
||||||
lightCullingLayout->reset();
|
lightCullingLayout->reset();
|
||||||
descriptorSets[INDEX_VIEW_PARAMS] = viewParamsSet;
|
|
||||||
descriptorSets[INDEX_LIGHT_ENV] = scene->getLightEnvironment()->getDescriptorSet();
|
|
||||||
descriptorSets[INDEX_LIGHT_CULLING] = lightCullingLayout->allocateDescriptorSet();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasePass::render()
|
void BasePass::render()
|
||||||
@@ -68,6 +65,10 @@ void BasePass::render()
|
|||||||
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||||
|
|
||||||
|
descriptorSets[INDEX_VIEW_PARAMS] = viewParamsSet;
|
||||||
|
descriptorSets[INDEX_LIGHT_ENV] = scene->getLightEnvironment()->getDescriptorSet();
|
||||||
|
descriptorSets[INDEX_LIGHT_CULLING] = lightCullingLayout->allocateDescriptorSet();
|
||||||
|
|
||||||
descriptorSets[INDEX_LIGHT_CULLING]->updateBuffer(0, oLightIndexList);
|
descriptorSets[INDEX_LIGHT_CULLING]->updateBuffer(0, oLightIndexList);
|
||||||
descriptorSets[INDEX_LIGHT_CULLING]->updateBuffer(1, tLightIndexList);
|
descriptorSets[INDEX_LIGHT_CULLING]->updateBuffer(1, tLightIndexList);
|
||||||
descriptorSets[INDEX_LIGHT_CULLING]->updateTexture(2, oLightGrid);
|
descriptorSets[INDEX_LIGHT_CULLING]->updateTexture(2, oLightGrid);
|
||||||
|
|||||||
@@ -145,8 +145,8 @@ void DepthPrepass::publishOutputs()
|
|||||||
// still match the size of the whole image or their coordinate systems go out of sync
|
// still match the size of the whole image or their coordinate systems go out of sync
|
||||||
TextureCreateInfo depthBufferInfo = {
|
TextureCreateInfo depthBufferInfo = {
|
||||||
.format = Gfx::SE_FORMAT_D32_SFLOAT,
|
.format = Gfx::SE_FORMAT_D32_SFLOAT,
|
||||||
.width = viewport->getOwner()->getWidth(),
|
.width = viewport->getOwner()->getFramebufferWidth(),
|
||||||
.height = viewport->getOwner()->getHeight(),
|
.height = viewport->getOwner()->getFramebufferHeight(),
|
||||||
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
||||||
};
|
};
|
||||||
depthBuffer = graphics->createTexture2D(depthBufferInfo);
|
depthBuffer = graphics->createTexture2D(depthBufferInfo);
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ void SkyboxRenderPass::render()
|
|||||||
renderCommand->setViewport(viewport);
|
renderCommand->setViewport(viewport);
|
||||||
renderCommand->bindPipeline(pipeline);
|
renderCommand->bindPipeline(pipeline);
|
||||||
renderCommand->bindDescriptor({viewParamsSet, skyboxDataSet, textureSet});
|
renderCommand->bindDescriptor({viewParamsSet, skyboxDataSet, textureSet});
|
||||||
renderCommand->bindVertexBuffer({ cubeBuffer });
|
|
||||||
renderCommand->draw(36, 1, 0, 0);
|
renderCommand->draw(36, 1, 0, 0);
|
||||||
graphics->executeCommands(Array{ renderCommand });
|
graphics->executeCommands(Array{ renderCommand });
|
||||||
graphics->endRenderPass();
|
graphics->endRenderPass();
|
||||||
|
|||||||
@@ -3,40 +3,6 @@
|
|||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Gfx;
|
using namespace Seele::Gfx;
|
||||||
|
|
||||||
Window::Window(const WindowCreateInfo& createInfo)
|
|
||||||
: windowState(createInfo)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Window::~Window()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Viewport::Viewport(PWindow owner, const ViewportCreateInfo& viewportInfo)
|
|
||||||
: sizeX(std::min(owner->getWidth(), viewportInfo.dimensions.size.x))
|
|
||||||
, sizeY(std::min(owner->getHeight(), viewportInfo.dimensions.size.y))
|
|
||||||
, offsetX(viewportInfo.dimensions.offset.x)
|
|
||||||
, offsetY(viewportInfo.dimensions.offset.y)
|
|
||||||
, fieldOfView(viewportInfo.fieldOfView)
|
|
||||||
, owner(owner)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Viewport::~Viewport()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4 Viewport::getProjectionMatrix() const
|
|
||||||
{
|
|
||||||
if (fieldOfView > 0.0f)
|
|
||||||
{
|
|
||||||
return glm::perspective(fieldOfView, sizeX / static_cast<float>(sizeY), 0.1f, 1000.0f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return glm::ortho(0.0f, (float)sizeX, (float)sizeY, 0.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RenderTargetAttachment::RenderTargetAttachment(PTexture2D texture,
|
RenderTargetAttachment::RenderTargetAttachment(PTexture2D texture,
|
||||||
SeAttachmentLoadOp loadOp,
|
SeAttachmentLoadOp loadOp,
|
||||||
SeAttachmentStoreOp storeOp,
|
SeAttachmentStoreOp storeOp,
|
||||||
|
|||||||
@@ -1,71 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Resources.h"
|
#include "Resources.h"
|
||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
|
#include "Window.h"
|
||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
namespace Gfx
|
namespace Gfx
|
||||||
{
|
{
|
||||||
class Window
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Window(const WindowCreateInfo &createInfo);
|
|
||||||
virtual ~Window();
|
|
||||||
virtual void beginFrame() = 0;
|
|
||||||
virtual void endFrame() = 0;
|
|
||||||
virtual void onWindowCloseEvent() = 0;
|
|
||||||
virtual PTexture2D getBackBuffer() = 0;
|
|
||||||
virtual void setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifier)> callback) = 0;
|
|
||||||
virtual void setMouseMoveCallback(std::function<void(double, double)> callback) = 0;
|
|
||||||
virtual void setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback) = 0;
|
|
||||||
virtual void setScrollCallback(std::function<void(double, double)> callback) = 0;
|
|
||||||
virtual void setFileCallback(std::function<void(int, const char**)> callback) = 0;
|
|
||||||
virtual void setCloseCallback(std::function<void()> callback) = 0;
|
|
||||||
constexpr SeFormat getSwapchainFormat() const
|
|
||||||
{
|
|
||||||
return windowState.pixelFormat;
|
|
||||||
}
|
|
||||||
constexpr SeSampleCountFlags getNumSamples() const
|
|
||||||
{
|
|
||||||
return windowState.numSamples;
|
|
||||||
}
|
|
||||||
constexpr uint32 getWidth() const
|
|
||||||
{
|
|
||||||
return windowState.width;
|
|
||||||
}
|
|
||||||
constexpr uint32 getHeight() const
|
|
||||||
{
|
|
||||||
return windowState.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
WindowCreateInfo windowState;
|
|
||||||
};
|
|
||||||
DEFINE_REF(Window)
|
|
||||||
|
|
||||||
class Viewport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Viewport(PWindow owner, const ViewportCreateInfo &createInfo);
|
|
||||||
virtual ~Viewport();
|
|
||||||
virtual void resize(uint32 newX, uint32 newY) = 0;
|
|
||||||
virtual void move(uint32 newOffsetX, uint32 newOffsetY) = 0;
|
|
||||||
constexpr PWindow getOwner() const {return owner;}
|
|
||||||
constexpr uint32 getWidth() const {return sizeX;}
|
|
||||||
constexpr uint32 getHeight() const {return sizeY;}
|
|
||||||
constexpr uint32 getOffsetX() const {return offsetX;}
|
|
||||||
constexpr uint32 getOffsetY() const {return offsetY;}
|
|
||||||
Matrix4 getProjectionMatrix() const;
|
|
||||||
protected:
|
|
||||||
uint32 sizeX;
|
|
||||||
uint32 sizeY;
|
|
||||||
uint32 offsetX;
|
|
||||||
uint32 offsetY;
|
|
||||||
float fieldOfView;
|
|
||||||
PWindow owner;
|
|
||||||
};
|
|
||||||
DEFINE_REF(Viewport)
|
|
||||||
|
|
||||||
class RenderTargetAttachment
|
class RenderTargetAttachment
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -133,11 +74,11 @@ public:
|
|||||||
}
|
}
|
||||||
virtual uint32 getWidth() const
|
virtual uint32 getWidth() const
|
||||||
{
|
{
|
||||||
return owner->getWidth();
|
return owner->getFramebufferWidth();
|
||||||
}
|
}
|
||||||
virtual uint32 getHeight() const
|
virtual uint32 getHeight() const
|
||||||
{
|
{
|
||||||
return owner->getHeight();
|
return owner->getFramebufferHeight();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
PWindow owner;
|
PWindow owner;
|
||||||
|
|||||||
@@ -44,8 +44,9 @@ Allocation::Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, u
|
|||||||
VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
|
VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
|
||||||
: device(graphics->getDevice())
|
: device(graphics->getDevice())
|
||||||
, pool(pool)
|
, pool(pool)
|
||||||
, bytesAllocated(0)
|
, bytesAllocated(size)
|
||||||
, bytesUsed(0)
|
, bytesUsed(0)
|
||||||
|
, mappedPointer(nullptr)
|
||||||
, canMap((properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
, canMap((properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
||||||
, isMapped(false)
|
, isMapped(false)
|
||||||
, properties(properties)
|
, properties(properties)
|
||||||
@@ -59,9 +60,7 @@ Allocation::Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, u
|
|||||||
};
|
};
|
||||||
isDedicated = dedicatedInfo != nullptr;
|
isDedicated = dedicatedInfo != nullptr;
|
||||||
VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory));
|
VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory));
|
||||||
bytesAllocated = size;
|
|
||||||
freeRanges[0] = size;
|
freeRanges[0] = size;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Allocation::~Allocation()
|
Allocation::~Allocation()
|
||||||
@@ -95,6 +94,7 @@ OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
|
|||||||
VkDeviceSize allocatedSize = requestedSize + (alignedOffset - lower);
|
VkDeviceSize allocatedSize = requestedSize + (alignedOffset - lower);
|
||||||
if (size >= allocatedSize)
|
if (size >= allocatedSize)
|
||||||
{
|
{
|
||||||
|
//std::cout << "Allocating " << lower << "-" << lower + allocatedSize << std::endl;
|
||||||
VkDeviceSize newSize = size - allocatedSize;
|
VkDeviceSize newSize = size - allocatedSize;
|
||||||
VkDeviceSize newLower = lower + allocatedSize;
|
VkDeviceSize newLower = lower + allocatedSize;
|
||||||
OSubAllocation alloc = new SubAllocation(this, requestedSize, lower, allocatedSize, alignedOffset);
|
OSubAllocation alloc = new SubAllocation(this, requestedSize, lower, allocatedSize, alignedOffset);
|
||||||
@@ -113,6 +113,7 @@ OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
|
|||||||
|
|
||||||
void Allocation::markFree(PSubAllocation allocation)
|
void Allocation::markFree(PSubAllocation allocation)
|
||||||
{
|
{
|
||||||
|
//std::cout << "Freeing " << allocation->allocatedOffset << "-" << allocation->allocatedOffset + allocation->allocatedSize << std::endl;
|
||||||
assert(activeAllocations.find(allocation) != activeAllocations.end());
|
assert(activeAllocations.find(allocation) != activeAllocations.end());
|
||||||
VkDeviceSize lowerBound = allocation->allocatedOffset;
|
VkDeviceSize lowerBound = allocation->allocatedOffset;
|
||||||
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
|
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
|
||||||
@@ -121,7 +122,7 @@ void Allocation::markFree(PSubAllocation allocation)
|
|||||||
{
|
{
|
||||||
if (lower + size == lowerBound)
|
if (lower + size == lowerBound)
|
||||||
{
|
{
|
||||||
freeRanges[lower] = upperBound;
|
freeRanges[lower] = size + allocation->allocatedSize;
|
||||||
freeRanges.erase(lowerBound);
|
freeRanges.erase(lowerBound);
|
||||||
lowerBound = lower;
|
lowerBound = lower;
|
||||||
break;
|
break;
|
||||||
@@ -134,10 +135,6 @@ void Allocation::markFree(PSubAllocation allocation)
|
|||||||
}
|
}
|
||||||
activeAllocations.remove(allocation, false);
|
activeAllocations.remove(allocation, false);
|
||||||
bytesUsed -= allocation->allocatedSize;
|
bytesUsed -= allocation->allocatedSize;
|
||||||
if (bytesUsed == 0)
|
|
||||||
{
|
|
||||||
pool->free(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Allocation::flushMemory()
|
void Allocation::flushMemory()
|
||||||
@@ -205,7 +202,7 @@ OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2
|
|||||||
{
|
{
|
||||||
OAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo);
|
OAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo);
|
||||||
heaps[heapIndex].inUse += newAllocation->bytesAllocated;
|
heaps[heapIndex].inUse += newAllocation->bytesAllocated;
|
||||||
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl;
|
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
|
||||||
heaps[heapIndex].allocations.add(std::move(newAllocation));
|
heaps[heapIndex].allocations.add(std::move(newAllocation));
|
||||||
return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
|
return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
|
||||||
}
|
}
|
||||||
@@ -225,7 +222,7 @@ OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2
|
|||||||
// no suitable allocations found, allocate new block
|
// no suitable allocations found, allocate new block
|
||||||
OAllocation newAllocation = new Allocation(graphics, this, (requirements.size > DEFAULT_ALLOCATION) ? requirements.size : DEFAULT_ALLOCATION, memoryTypeIndex, properties, nullptr);
|
OAllocation newAllocation = new Allocation(graphics, this, (requirements.size > DEFAULT_ALLOCATION) ? requirements.size : DEFAULT_ALLOCATION, memoryTypeIndex, properties, nullptr);
|
||||||
heaps[heapIndex].inUse += newAllocation->bytesAllocated;
|
heaps[heapIndex].inUse += newAllocation->bytesAllocated;
|
||||||
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl;
|
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
|
||||||
heaps[heapIndex].allocations.add(std::move(newAllocation));
|
heaps[heapIndex].allocations.add(std::move(newAllocation));
|
||||||
return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
|
return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
|
||||||
}
|
}
|
||||||
@@ -240,7 +237,7 @@ void Allocator::free(PAllocation allocation)
|
|||||||
if (heaps[heapIndex].allocations[alloc] == allocation)
|
if (heaps[heapIndex].allocations[alloc] == allocation)
|
||||||
{
|
{
|
||||||
heaps[heapIndex].inUse -= allocation->bytesAllocated;
|
heaps[heapIndex].inUse -= allocation->bytesAllocated;
|
||||||
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl;
|
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
|
||||||
heaps[heapIndex].allocations.removeAt(alloc, false);
|
heaps[heapIndex].allocations.removeAt(alloc, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,14 +24,14 @@ target_sources(Engine
|
|||||||
Queue.cpp
|
Queue.cpp
|
||||||
RenderPass.h
|
RenderPass.h
|
||||||
RenderPass.cpp
|
RenderPass.cpp
|
||||||
RenderTarget.h
|
|
||||||
RenderTarget.cpp
|
|
||||||
Resources.h
|
Resources.h
|
||||||
Resources.cpp
|
Resources.cpp
|
||||||
Shader.h
|
Shader.h
|
||||||
Shader.cpp
|
Shader.cpp
|
||||||
Texture.h
|
Texture.h
|
||||||
Texture.cpp)
|
Texture.cpp
|
||||||
|
Window.h
|
||||||
|
Window.cpp)
|
||||||
|
|
||||||
target_sources(Engine
|
target_sources(Engine
|
||||||
PUBLIC FILE_SET HEADERS
|
PUBLIC FILE_SET HEADERS
|
||||||
@@ -48,8 +48,8 @@ target_sources(Engine
|
|||||||
PipelineCache.h
|
PipelineCache.h
|
||||||
Queue.h
|
Queue.h
|
||||||
RenderPass.h
|
RenderPass.h
|
||||||
RenderTarget.h
|
|
||||||
Resources.h
|
Resources.h
|
||||||
Shader.h
|
Shader.h
|
||||||
Texture.h)
|
Texture.h
|
||||||
|
Window.h)
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "RenderPass.h"
|
#include "RenderPass.h"
|
||||||
#include "Pipeline.h"
|
#include "Pipeline.h"
|
||||||
#include "Descriptor.h"
|
#include "Descriptor.h"
|
||||||
#include "RenderTarget.h"
|
#include "Window.h"
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
@@ -58,7 +58,8 @@ void Command::end()
|
|||||||
void Command::beginRenderPass(PRenderPass renderPass, PFramebuffer framebuffer)
|
void Command::beginRenderPass(PRenderPass renderPass, PFramebuffer framebuffer)
|
||||||
{
|
{
|
||||||
assert(state == State::Begin);
|
assert(state == State::Begin);
|
||||||
|
boundRenderPass = renderPass;
|
||||||
|
boundFramebuffer = framebuffer;
|
||||||
VkRenderPassBeginInfo beginInfo = {
|
VkRenderPassBeginInfo beginInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
@@ -74,6 +75,8 @@ void Command::beginRenderPass(PRenderPass renderPass, PFramebuffer framebuffer)
|
|||||||
|
|
||||||
void Command::endRenderPass()
|
void Command::endRenderPass()
|
||||||
{
|
{
|
||||||
|
boundRenderPass = nullptr;
|
||||||
|
boundFramebuffer = nullptr;
|
||||||
vkCmdEndRenderPass(handle);
|
vkCmdEndRenderPass(handle);
|
||||||
state = State::Begin;
|
state = State::Begin;
|
||||||
}
|
}
|
||||||
@@ -148,6 +151,7 @@ void Command::checkFence()
|
|||||||
for(auto& descriptor : boundDescriptors)
|
for(auto& descriptor : boundDescriptors)
|
||||||
{
|
{
|
||||||
descriptor->unbind();
|
descriptor->unbind();
|
||||||
|
//std::cout << "Unbinding descriptor " << descriptor.cast<DescriptorSet>()->getHandle() << " to cmd " << handle << std::endl;
|
||||||
}
|
}
|
||||||
boundDescriptors.clear();
|
boundDescriptors.clear();
|
||||||
graphics->getDestructionManager()->notifyCmdComplete(this);
|
graphics->getDestructionManager()->notifyCmdComplete(this);
|
||||||
@@ -282,6 +286,7 @@ void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorS
|
|||||||
assert(descriptorSet->writeDescriptors.size() == 0);
|
assert(descriptorSet->writeDescriptors.size() == 0);
|
||||||
descriptorSet->bind();
|
descriptorSet->bind();
|
||||||
|
|
||||||
|
//std::cout << "Binding descriptor " << descriptorSet->getHandle() << " to cmd " << handle << std::endl;
|
||||||
boundDescriptors.add(descriptorSet.getHandle());
|
boundDescriptors.add(descriptorSet.getHandle());
|
||||||
sets[descriptorSet->getSetIndex()] = descriptorSet->getHandle();
|
sets[descriptorSet->getSetIndex()] = descriptorSet->getHandle();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "PipelineCache.h"
|
#include "PipelineCache.h"
|
||||||
#include "Command.h"
|
#include "Command.h"
|
||||||
#include "Descriptor.h"
|
#include "Descriptor.h"
|
||||||
#include "RenderTarget.h"
|
#include "Window.h"
|
||||||
#include "RenderPass.h"
|
#include "RenderPass.h"
|
||||||
#include "Framebuffer.h"
|
#include "Framebuffer.h"
|
||||||
#include "Shader.h"
|
#include "Shader.h"
|
||||||
|
|||||||
@@ -23,8 +23,7 @@ void Queue::submitCommandBuffer(PCommand command, uint32 numSignalSemaphores, Vk
|
|||||||
std::unique_lock lock(queueLock);
|
std::unique_lock lock(queueLock);
|
||||||
assert(command->state == Command::State::End);
|
assert(command->state == Command::State::End);
|
||||||
|
|
||||||
PFence fence = command->fence;
|
assert(!(command->fence->isSignaled()));
|
||||||
assert(!fence->isSignaled());
|
|
||||||
|
|
||||||
VkCommandBuffer cmdHandle = command->handle;
|
VkCommandBuffer cmdHandle = command->handle;
|
||||||
|
|
||||||
@@ -49,15 +48,15 @@ void Queue::submitCommandBuffer(PCommand command, uint32 numSignalSemaphores, Vk
|
|||||||
.pSignalSemaphores = signalSemaphores,
|
.pSignalSemaphores = signalSemaphores,
|
||||||
};
|
};
|
||||||
|
|
||||||
VK_CHECK(vkQueueSubmit(queue, 1, &submitInfo, fence->getHandle()));
|
VK_CHECK(vkQueueSubmit(queue, 1, &submitInfo, command->fence->getHandle()));
|
||||||
command->state = Command::State::Submit;
|
command->state = Command::State::Submit;
|
||||||
command->waitFlags.clear();
|
command->waitFlags.clear();
|
||||||
command->waitSemaphores.clear();
|
command->waitSemaphores.clear();
|
||||||
|
|
||||||
if (Gfx::waitIdleOnSubmit)
|
if (Gfx::waitIdleOnSubmit)
|
||||||
{
|
{
|
||||||
fence->wait(200 * 1000ull);
|
command->fence->wait(200 * 1000ull);
|
||||||
}
|
}
|
||||||
|
|
||||||
command->checkFence();
|
command->checkFence();
|
||||||
}
|
}
|
||||||
@@ -121,7 +121,15 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::ORenderTargetLayout _layout, Gfx
|
|||||||
};
|
};
|
||||||
|
|
||||||
VK_CHECK(vkCreateRenderPass(graphics->getDevice(), &info, nullptr, &renderPass));
|
VK_CHECK(vkCreateRenderPass(graphics->getDevice(), &info, nullptr, &renderPass));
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderPass::~RenderPass()
|
||||||
|
{
|
||||||
|
vkDestroyRenderPass(graphics->getDevice(), renderPass, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 RenderPass::getFramebufferHash()
|
||||||
|
{
|
||||||
FramebufferDescription description;
|
FramebufferDescription description;
|
||||||
std::memset(&description, 0, sizeof(FramebufferDescription));
|
std::memset(&description, 0, sizeof(FramebufferDescription));
|
||||||
for (auto& inputAttachment : layout->inputAttachments)
|
for (auto& inputAttachment : layout->inputAttachments)
|
||||||
@@ -139,11 +147,5 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::ORenderTargetLayout _layout, Gfx
|
|||||||
PTexture2D tex = layout->depthAttachment->getTexture().cast<Texture2D>();
|
PTexture2D tex = layout->depthAttachment->getTexture().cast<Texture2D>();
|
||||||
description.depthAttachment = tex->getView();
|
description.depthAttachment = tex->getView();
|
||||||
}
|
}
|
||||||
framebufferHash = CRC::Calculate(&description, sizeof(FramebufferDescription), CRC::CRC_32());
|
return CRC::Calculate(&description, sizeof(FramebufferDescription), CRC::CRC_32());
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPass::~RenderPass()
|
|
||||||
{
|
|
||||||
vkDestroyRenderPass(graphics->getDevice(), renderPass, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,7 @@ class RenderPass : public Gfx::RenderPass
|
|||||||
public:
|
public:
|
||||||
RenderPass(PGraphics graphics, Gfx::ORenderTargetLayout layout, Gfx::PViewport viewport);
|
RenderPass(PGraphics graphics, Gfx::ORenderTargetLayout layout, Gfx::PViewport viewport);
|
||||||
virtual ~RenderPass();
|
virtual ~RenderPass();
|
||||||
constexpr uint32 getFramebufferHash() const
|
uint32 getFramebufferHash();
|
||||||
{
|
|
||||||
return framebufferHash;
|
|
||||||
}
|
|
||||||
constexpr VkRenderPass getHandle() const
|
constexpr VkRenderPass getHandle() const
|
||||||
{
|
{
|
||||||
return renderPass;
|
return renderPass;
|
||||||
|
|||||||
@@ -1,412 +0,0 @@
|
|||||||
#include "RenderTarget.h"
|
|
||||||
#include "Resources.h"
|
|
||||||
#include "Graphics.h"
|
|
||||||
#include "Enums.h"
|
|
||||||
#include "Command.h"
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
using namespace Seele;
|
|
||||||
using namespace Seele::Vulkan;
|
|
||||||
|
|
||||||
double currentFrameDelta = 0;
|
|
||||||
double Gfx::getCurrentFrameDelta()
|
|
||||||
{
|
|
||||||
return currentFrameDelta;
|
|
||||||
}
|
|
||||||
|
|
||||||
void glfwKeyCallback(GLFWwindow* handle, int key, int, int action, int modifier)
|
|
||||||
{
|
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
|
||||||
window->keyCallback((KeyCode)key, (InputAction)action, (KeyModifier)modifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glfwMouseMoveCallback(GLFWwindow* handle, double xpos, double ypos)
|
|
||||||
{
|
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
|
||||||
window->mouseMoveCallback(xpos, ypos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glfwMouseButtonCallback(GLFWwindow* handle, int button, int action, int modifier)
|
|
||||||
{
|
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
|
||||||
window->mouseButtonCallback((MouseButton)button, (InputAction)action, (KeyModifier)modifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glfwScrollCallback(GLFWwindow* handle, double xoffset, double yoffset)
|
|
||||||
{
|
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
|
||||||
window->scrollCallback(xoffset, yoffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glfwFileCallback(GLFWwindow* handle, int count, const char** paths)
|
|
||||||
{
|
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
|
||||||
window->fileCallback(count, paths);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glfwCloseCallback(GLFWwindow* handle)
|
|
||||||
{
|
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
|
||||||
window->closeCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
Window::Window(PGraphics graphics, const WindowCreateInfo &createInfo)
|
|
||||||
: Gfx::Window(createInfo)
|
|
||||||
, graphics(graphics)
|
|
||||||
, instance(graphics->getInstance())
|
|
||||||
, swapchain(VK_NULL_HANDLE)
|
|
||||||
, numSamples(createInfo.numSamples)
|
|
||||||
{
|
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
|
||||||
GLFWwindow *handle = glfwCreateWindow(createInfo.width, createInfo.height, createInfo.title, createInfo.bFullscreen ? glfwGetPrimaryMonitor() : nullptr, nullptr);
|
|
||||||
windowHandle = handle;
|
|
||||||
glfwSetWindowUserPointer(handle, this);
|
|
||||||
glfwGetWindowSize(handle, &windowState.width, &windowState.height);
|
|
||||||
|
|
||||||
glfwSetKeyCallback(handle, &glfwKeyCallback);
|
|
||||||
glfwSetCursorPosCallback(handle, &glfwMouseMoveCallback);
|
|
||||||
glfwSetMouseButtonCallback(handle, &glfwMouseButtonCallback);
|
|
||||||
glfwSetScrollCallback(handle, &glfwScrollCallback);
|
|
||||||
glfwSetDropCallback(handle, &glfwFileCallback);
|
|
||||||
glfwSetWindowCloseCallback(handle, &glfwCloseCallback);
|
|
||||||
|
|
||||||
glfwCreateWindowSurface(instance, handle, nullptr, &surface);
|
|
||||||
|
|
||||||
uint32_t numQueueFamilies = 0;
|
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(graphics->getPhysicalDevice(), &numQueueFamilies, nullptr);
|
|
||||||
Array<VkQueueFamilyProperties> queueProperties(numQueueFamilies);
|
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(graphics->getPhysicalDevice(), &numQueueFamilies, queueProperties.data());
|
|
||||||
|
|
||||||
bool viableDevice = false;
|
|
||||||
for (uint32 i = 0; i < numQueueFamilies; ++i)
|
|
||||||
{
|
|
||||||
VkBool32 supportsPresent;
|
|
||||||
vkGetPhysicalDeviceSurfaceSupportKHR(graphics->getPhysicalDevice(), i, surface, &supportsPresent);
|
|
||||||
if (supportsPresent)
|
|
||||||
{
|
|
||||||
viableDevice = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!viableDevice)
|
|
||||||
{
|
|
||||||
std::cerr << "Device not suitable for presenting to surface " << surface << ", use a different one" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
recreateSwapchain(windowState);
|
|
||||||
}
|
|
||||||
|
|
||||||
Window::~Window()
|
|
||||||
{
|
|
||||||
vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr);
|
|
||||||
vkDestroySurfaceKHR(instance, surface, nullptr);
|
|
||||||
glfwDestroyWindow(static_cast<GLFWwindow *>(windowHandle));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::beginFrame()
|
|
||||||
{
|
|
||||||
glfwPollEvents();
|
|
||||||
advanceBackBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::endFrame()
|
|
||||||
{
|
|
||||||
present();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::onWindowCloseEvent()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Gfx::PTexture2D Window::getBackBuffer()
|
|
||||||
{
|
|
||||||
return PTexture2D(backBufferImages[currentImageIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifier)> callback)
|
|
||||||
{
|
|
||||||
keyCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::setMouseMoveCallback(std::function<void(double, double)> callback)
|
|
||||||
{
|
|
||||||
mouseMoveCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback)
|
|
||||||
{
|
|
||||||
mouseButtonCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::setScrollCallback(std::function<void(double, double)> callback)
|
|
||||||
{
|
|
||||||
scrollCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::setFileCallback(std::function<void(int, const char**)> callback)
|
|
||||||
{
|
|
||||||
fileCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::setCloseCallback(std::function<void()> callback)
|
|
||||||
{
|
|
||||||
closeCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::advanceBackBuffer()
|
|
||||||
{
|
|
||||||
VkResult res = VK_ERROR_OUT_OF_DATE_KHR;
|
|
||||||
uint32 imageIndex = 0;
|
|
||||||
const int32 prevSemaphoreIndex = semaphoreIndex;
|
|
||||||
semaphoreIndex = (semaphoreIndex + 1) % Gfx::numFramesBuffered;
|
|
||||||
|
|
||||||
while (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
res = vkAcquireNextImageKHR(
|
|
||||||
graphics->getDevice(),
|
|
||||||
swapchain,
|
|
||||||
UINT64_MAX,
|
|
||||||
imageAcquired[semaphoreIndex]->getHandle(),
|
|
||||||
VK_NULL_HANDLE,
|
|
||||||
&imageIndex);
|
|
||||||
if (res == VK_ERROR_OUT_OF_DATE_KHR)
|
|
||||||
{
|
|
||||||
semaphoreIndex = prevSemaphoreIndex;
|
|
||||||
}
|
|
||||||
if (res == VK_ERROR_SURFACE_LOST_KHR)
|
|
||||||
{
|
|
||||||
semaphoreIndex = prevSemaphoreIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
imageAcquiredSemaphore = imageAcquired[semaphoreIndex];
|
|
||||||
currentImageIndex = imageIndex;
|
|
||||||
|
|
||||||
backBufferImages[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
|
||||||
VkClearColorValue clearColor = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
||||||
PCommand command = graphics->getGraphicsCommands()->getCommands();
|
|
||||||
VkImageSubresourceRange range = {
|
|
||||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
||||||
};
|
|
||||||
vkCmdClearColorImage(
|
|
||||||
command->getHandle(),
|
|
||||||
backBufferHandles[currentImageIndex],
|
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
||||||
&clearColor,
|
|
||||||
1,
|
|
||||||
&range);
|
|
||||||
|
|
||||||
backBufferImages[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
|
||||||
graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, imageAcquiredSemaphore);
|
|
||||||
graphics->getGraphicsCommands()->submitCommands();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::recreateSwapchain(const WindowCreateInfo &windowInfo)
|
|
||||||
{
|
|
||||||
destroySwapchain();
|
|
||||||
windowState = windowInfo;
|
|
||||||
uint32_t numFormats;
|
|
||||||
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(graphics->getPhysicalDevice(), surface, &numFormats, nullptr));
|
|
||||||
Array<VkSurfaceFormatKHR> formats(numFormats);
|
|
||||||
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(graphics->getPhysicalDevice(), surface, &numFormats, formats.data()));
|
|
||||||
|
|
||||||
uint32_t numPresentModes;
|
|
||||||
VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, nullptr));
|
|
||||||
Array<VkPresentModeKHR> modes(numPresentModes);
|
|
||||||
VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, modes.data()));
|
|
||||||
|
|
||||||
chooseSurfaceFormat(formats, windowInfo.pixelFormat);
|
|
||||||
choosePresentMode(modes);
|
|
||||||
createSwapchain();
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t currentFrameIndex = 0;
|
|
||||||
|
|
||||||
void Window::present()
|
|
||||||
{
|
|
||||||
backBufferImages[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
|
||||||
graphics->getGraphicsCommands()->submitCommands(renderFinished[currentImageIndex]);
|
|
||||||
VkSemaphore renderFinishedHandle = renderFinished[currentImageIndex]->getHandle();
|
|
||||||
VkPresentInfoKHR info = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.waitSemaphoreCount = 1,
|
|
||||||
.pWaitSemaphores = &renderFinishedHandle,
|
|
||||||
.swapchainCount = 1,
|
|
||||||
.pSwapchains = &swapchain,
|
|
||||||
.pImageIndices = (uint32*)¤tImageIndex,
|
|
||||||
.pResults = 0,
|
|
||||||
};
|
|
||||||
VkResult presentResult = VK_ERROR_OUT_OF_DATE_KHR;
|
|
||||||
// Trial and error
|
|
||||||
while (presentResult != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
presentResult = vkQueuePresentKHR(graphics->getGraphicsCommands()->getQueue()->getHandle(), &info);
|
|
||||||
}
|
|
||||||
currentFrameIndex = (currentFrameIndex + 1) % Gfx::numFramesBuffered;
|
|
||||||
static double lastFrameTime = 0.f;
|
|
||||||
double currentTime = glfwGetTime();
|
|
||||||
double currentDelta = currentTime - lastFrameTime;
|
|
||||||
currentFrameDelta = currentDelta;
|
|
||||||
lastFrameTime = currentTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::createSwapchain()
|
|
||||||
{
|
|
||||||
VkSurfaceCapabilitiesKHR surfProperties;
|
|
||||||
VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(graphics->getPhysicalDevice(), surface, &surfProperties));
|
|
||||||
|
|
||||||
uint32 desiredNumBuffers = Gfx::numFramesBuffered;
|
|
||||||
if (desiredNumBuffers < surfProperties.minImageCount)
|
|
||||||
{
|
|
||||||
throw new std::logic_error("Trying to buffer less than the minimal number of frames");
|
|
||||||
}
|
|
||||||
if (desiredNumBuffers > surfProperties.maxImageCount)
|
|
||||||
{
|
|
||||||
throw new std::logic_error("Trying to buffer more than the maximum number of frames");
|
|
||||||
}
|
|
||||||
|
|
||||||
VkSwapchainCreateInfoKHR swapchainInfo = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.surface = surface,
|
|
||||||
.minImageCount = desiredNumBuffers,
|
|
||||||
.imageFormat = surfaceFormat.format,
|
|
||||||
.imageColorSpace = surfaceFormat.colorSpace,
|
|
||||||
.imageExtent = {
|
|
||||||
.width = getWidth(),
|
|
||||||
.height = getHeight(),
|
|
||||||
},
|
|
||||||
.imageArrayLayers = 1,
|
|
||||||
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
|
||||||
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
||||||
.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
|
|
||||||
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
|
||||||
.presentMode = presentMode,
|
|
||||||
.clipped = VK_TRUE,
|
|
||||||
};
|
|
||||||
VK_CHECK(vkCreateSwapchainKHR(graphics->getDevice(), &swapchainInfo, nullptr, &swapchain));
|
|
||||||
|
|
||||||
uint32 numSwapchainImages;
|
|
||||||
VK_CHECK(vkGetSwapchainImagesKHR(graphics->getDevice(), swapchain, &numSwapchainImages, nullptr));
|
|
||||||
Array<VkImage> swapchainImages(numSwapchainImages);
|
|
||||||
VK_CHECK(vkGetSwapchainImagesKHR(graphics->getDevice(), swapchain, &numSwapchainImages, swapchainImages.data()));
|
|
||||||
|
|
||||||
|
|
||||||
TextureCreateInfo backBufferCreateInfo = {
|
|
||||||
.sourceData = {
|
|
||||||
.owner = Gfx::QueueType::GRAPHICS,
|
|
||||||
},
|
|
||||||
.format = cast(surfaceFormat.format),
|
|
||||||
.width = getWidth(),
|
|
||||||
.height = getHeight(),
|
|
||||||
.usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
|
||||||
};
|
|
||||||
for (uint32 i = 0; i < numSwapchainImages; ++i)
|
|
||||||
{
|
|
||||||
imageAcquired[i] = new Semaphore(graphics);
|
|
||||||
renderFinished[i] = new Semaphore(graphics);
|
|
||||||
backBufferImages[i] = new Texture2D(graphics, backBufferCreateInfo, swapchainImages[i]);
|
|
||||||
backBufferHandles[i] = swapchainImages[i];
|
|
||||||
|
|
||||||
VkClearColorValue clearColor;
|
|
||||||
std::memset(&clearColor, 0, sizeof(VkClearColorValue));
|
|
||||||
backBufferImages[i]->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
|
||||||
VkImageSubresourceRange range = {
|
|
||||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
||||||
.baseMipLevel = 0,
|
|
||||||
.levelCount = 1,
|
|
||||||
.baseArrayLayer = 0,
|
|
||||||
.layerCount = 1,
|
|
||||||
};
|
|
||||||
PCommand command = graphics->getGraphicsCommands()->getCommands();
|
|
||||||
vkCmdClearColorImage(command->getHandle(), backBufferHandles[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &range);
|
|
||||||
backBufferImages[i]->changeLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
|
||||||
}
|
|
||||||
graphics->getGraphicsCommands()->submitCommands();
|
|
||||||
currentImageIndex = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::destroySwapchain()
|
|
||||||
{
|
|
||||||
if (swapchain != VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr);
|
|
||||||
}
|
|
||||||
for (uint32 i = 0; i < Gfx::numFramesBuffered; ++i)
|
|
||||||
{
|
|
||||||
imageAcquired[i] = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::chooseSurfaceFormat(const Array<VkSurfaceFormatKHR> &available, Gfx::SeFormat preferred)
|
|
||||||
{
|
|
||||||
VkFormat preferredFormat = cast(preferred);
|
|
||||||
for (auto availabeFormat : available)
|
|
||||||
{
|
|
||||||
if (availabeFormat.format == preferredFormat)
|
|
||||||
{
|
|
||||||
surfaceFormat = availabeFormat;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (available.size() == 1 && available[0].format == VK_FORMAT_UNDEFINED)
|
|
||||||
{
|
|
||||||
surfaceFormat = {VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const auto &availableFormat : available)
|
|
||||||
{
|
|
||||||
if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
|
||||||
{
|
|
||||||
surfaceFormat = availableFormat;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
surfaceFormat = available[0];
|
|
||||||
}
|
|
||||||
void Window::choosePresentMode(const Array<VkPresentModeKHR> &modes)
|
|
||||||
{
|
|
||||||
for (auto mode : modes)
|
|
||||||
{
|
|
||||||
if (mode == VK_PRESENT_MODE_MAILBOX_KHR)
|
|
||||||
{
|
|
||||||
presentMode = mode;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
|
||||||
}
|
|
||||||
|
|
||||||
Viewport::Viewport(PGraphics graphics, PWindow owner, const ViewportCreateInfo &viewportInfo)
|
|
||||||
: Gfx::Viewport(owner, viewportInfo), graphics(graphics)
|
|
||||||
{
|
|
||||||
handle.width = static_cast<float>(sizeX);
|
|
||||||
handle.height = static_cast<float>(sizeY);
|
|
||||||
handle.x = static_cast<float>(offsetX);
|
|
||||||
handle.y = static_cast<float>(offsetY) + handle.height;
|
|
||||||
handle.height = -handle.height;
|
|
||||||
handle.minDepth = 0.f;
|
|
||||||
handle.maxDepth = 1.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
Viewport::~Viewport()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Viewport::resize(uint32 newX, uint32 newY)
|
|
||||||
{
|
|
||||||
sizeX = newX;
|
|
||||||
sizeY = newY;
|
|
||||||
handle.width = static_cast<float>(sizeX);
|
|
||||||
handle.y = static_cast<float>(sizeY + offsetX);
|
|
||||||
handle.height = -static_cast<float>(sizeY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Viewport::move(uint32 newOffsetX, uint32 newOffsetY)
|
|
||||||
{
|
|
||||||
offsetX = newOffsetX;
|
|
||||||
offsetY = newOffsetY;
|
|
||||||
handle.x = static_cast<float>(offsetX);
|
|
||||||
handle.y = static_cast<float>(offsetY + sizeY);
|
|
||||||
}
|
|
||||||
@@ -197,7 +197,9 @@ void TextureBase::changeLayout(Gfx::SeImageLayout newLayout)
|
|||||||
.image = image,
|
.image = image,
|
||||||
.subresourceRange = {
|
.subresourceRange = {
|
||||||
.aspectMask = aspect,
|
.aspectMask = aspect,
|
||||||
|
.baseMipLevel = 0,
|
||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
.layerCount = layerCount,
|
.layerCount = layerCount,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -328,6 +330,10 @@ void TextureBase::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStag
|
|||||||
.image = image,
|
.image = image,
|
||||||
.subresourceRange = {
|
.subresourceRange = {
|
||||||
.aspectMask = aspect,
|
.aspectMask = aspect,
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = 1,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
PCommand command = graphics->getQueueCommands(currentOwner)->getCommands();
|
PCommand command = graphics->getQueueCommands(currentOwner)->getCommands();
|
||||||
|
|||||||
@@ -0,0 +1,304 @@
|
|||||||
|
#include "Window.h"
|
||||||
|
#include "Resources.h"
|
||||||
|
#include "Graphics.h"
|
||||||
|
#include "Enums.h"
|
||||||
|
#include "Command.h"
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
using namespace Seele::Vulkan;
|
||||||
|
|
||||||
|
double currentFrameDelta = 0;
|
||||||
|
double Gfx::getCurrentFrameDelta()
|
||||||
|
{
|
||||||
|
return currentFrameDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
void glfwKeyCallback(GLFWwindow* handle, int key, int, int action, int modifier)
|
||||||
|
{
|
||||||
|
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
||||||
|
window->keyCallback((KeyCode)key, (InputAction)action, (KeyModifier)modifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void glfwMouseMoveCallback(GLFWwindow* handle, double xpos, double ypos)
|
||||||
|
{
|
||||||
|
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
||||||
|
window->mouseMoveCallback(xpos, ypos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void glfwMouseButtonCallback(GLFWwindow* handle, int button, int action, int modifier)
|
||||||
|
{
|
||||||
|
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
||||||
|
window->mouseButtonCallback((MouseButton)button, (InputAction)action, (KeyModifier)modifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void glfwScrollCallback(GLFWwindow* handle, double xoffset, double yoffset)
|
||||||
|
{
|
||||||
|
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
||||||
|
window->scrollCallback(xoffset, yoffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void glfwFileCallback(GLFWwindow* handle, int count, const char** paths)
|
||||||
|
{
|
||||||
|
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
||||||
|
window->fileCallback(count, paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
void glfwCloseCallback(GLFWwindow* handle)
|
||||||
|
{
|
||||||
|
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
||||||
|
window->closeCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
Window::Window(PGraphics graphics, const WindowCreateInfo &createInfo)
|
||||||
|
: graphics(graphics)
|
||||||
|
, preferences(createInfo)
|
||||||
|
, instance(graphics->getInstance())
|
||||||
|
, swapchain(VK_NULL_HANDLE)
|
||||||
|
, numSamples(createInfo.numSamples)
|
||||||
|
{
|
||||||
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
|
GLFWwindow *handle = glfwCreateWindow(createInfo.width, createInfo.height, createInfo.title, nullptr, nullptr);
|
||||||
|
windowHandle = handle;
|
||||||
|
glfwSetWindowUserPointer(handle, this);
|
||||||
|
|
||||||
|
glfwSetKeyCallback(handle, &glfwKeyCallback);
|
||||||
|
glfwSetCursorPosCallback(handle, &glfwMouseMoveCallback);
|
||||||
|
glfwSetMouseButtonCallback(handle, &glfwMouseButtonCallback);
|
||||||
|
glfwSetScrollCallback(handle, &glfwScrollCallback);
|
||||||
|
glfwSetDropCallback(handle, &glfwFileCallback);
|
||||||
|
glfwSetWindowCloseCallback(handle, &glfwCloseCallback);
|
||||||
|
|
||||||
|
glfwCreateWindowSurface(instance, handle, nullptr, &surface);
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(graphics->getPhysicalDevice(), surface, &capabilities);
|
||||||
|
|
||||||
|
uint32 numFormats;
|
||||||
|
vkGetPhysicalDeviceSurfaceFormatsKHR(graphics->getPhysicalDevice(), surface, &numFormats, nullptr);
|
||||||
|
supportedFormats.resize(numFormats);
|
||||||
|
vkGetPhysicalDeviceSurfaceFormatsKHR(graphics->getPhysicalDevice(), surface, &numFormats, supportedFormats.data());
|
||||||
|
|
||||||
|
uint32 numPresentModes;
|
||||||
|
vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, nullptr);
|
||||||
|
supportedPresentModes.resize(numFormats);
|
||||||
|
vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, supportedPresentModes.data());
|
||||||
|
chooseSwapSurfaceFormat();
|
||||||
|
framebufferFormat = cast(format.format);
|
||||||
|
chooseSwapPresentMode();
|
||||||
|
chooseSwapExtent();
|
||||||
|
framebufferWidth = extent.width;
|
||||||
|
framebufferHeight = extent.height;
|
||||||
|
sampleFlags = createInfo.numSamples;
|
||||||
|
createSwapChain();
|
||||||
|
}
|
||||||
|
|
||||||
|
Window::~Window()
|
||||||
|
{
|
||||||
|
vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr);
|
||||||
|
vkDestroySurfaceKHR(instance, surface, nullptr);
|
||||||
|
glfwDestroyWindow(static_cast<GLFWwindow *>(windowHandle));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::beginFrame()
|
||||||
|
{
|
||||||
|
glfwPollEvents();
|
||||||
|
vkAcquireNextImageKHR(graphics->getDevice(), swapchain, std::numeric_limits<uint64>::max(), imageAvailableSemaphores[currentSemaphoreIndex]->getHandle(), VK_NULL_HANDLE, ¤tImageIndex);
|
||||||
|
swapChainTextures[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
|
graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, imageAvailableSemaphores[currentSemaphoreIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::endFrame()
|
||||||
|
{
|
||||||
|
swapChainTextures[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
|
graphics->getGraphicsCommands()->submitCommands(renderingDoneSemaphores[currentSemaphoreIndex]);
|
||||||
|
VkSemaphore renderDoneHandle = renderingDoneSemaphores[currentSemaphoreIndex]->getHandle();
|
||||||
|
VkPresentInfoKHR presentInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.waitSemaphoreCount = 1,
|
||||||
|
.pWaitSemaphores = &renderDoneHandle,
|
||||||
|
.swapchainCount = 1,
|
||||||
|
.pSwapchains = &swapchain,
|
||||||
|
.pImageIndices = ¤tImageIndex,
|
||||||
|
.pResults = nullptr,
|
||||||
|
};
|
||||||
|
VkResult r = vkQueuePresentKHR(graphics->getGraphicsCommands()->getQueue()->getHandle(), &presentInfo);
|
||||||
|
if(r == VK_SUCCESS)
|
||||||
|
{ }
|
||||||
|
else if (r == VK_ERROR_OUT_OF_DATE_KHR || r == VK_SUBOPTIMAL_KHR)
|
||||||
|
{
|
||||||
|
createSwapChain();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VK_CHECK(r);
|
||||||
|
}
|
||||||
|
currentSemaphoreIndex = (currentSemaphoreIndex + 1) % Gfx::numFramesBuffered;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::onWindowCloseEvent()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Gfx::PTexture2D Window::getBackBuffer()
|
||||||
|
{
|
||||||
|
return PTexture2D(swapChainTextures[currentImageIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifier)> callback)
|
||||||
|
{
|
||||||
|
keyCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setMouseMoveCallback(std::function<void(double, double)> callback)
|
||||||
|
{
|
||||||
|
mouseMoveCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback)
|
||||||
|
{
|
||||||
|
mouseButtonCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setScrollCallback(std::function<void(double, double)> callback)
|
||||||
|
{
|
||||||
|
scrollCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setFileCallback(std::function<void(int, const char**)> callback)
|
||||||
|
{
|
||||||
|
fileCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setCloseCallback(std::function<void()> callback)
|
||||||
|
{
|
||||||
|
closeCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::chooseSwapSurfaceFormat()
|
||||||
|
{
|
||||||
|
for (const auto& supportedFormat : supportedFormats)
|
||||||
|
{
|
||||||
|
if (supportedFormat.format == cast(preferences.preferredFormat))
|
||||||
|
{
|
||||||
|
format = supportedFormat;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto& supportedFormat : supportedFormats)
|
||||||
|
{
|
||||||
|
if (supportedFormat.format == VK_FORMAT_R8G8B8A8_SRGB && supportedFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||||
|
{
|
||||||
|
format = supportedFormat;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
format = supportedFormats[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::chooseSwapPresentMode()
|
||||||
|
{
|
||||||
|
for (const auto& supportedPresentMode : supportedPresentModes)
|
||||||
|
{
|
||||||
|
if (supportedPresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
|
||||||
|
{
|
||||||
|
presentMode = supportedPresentMode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::chooseSwapExtent()
|
||||||
|
{
|
||||||
|
if (capabilities.currentExtent.width != std::numeric_limits<uint32>::max()) {
|
||||||
|
extent = capabilities.currentExtent;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int width, height;
|
||||||
|
glfwGetFramebufferSize(static_cast<GLFWwindow*>(windowHandle), &width, &height);
|
||||||
|
|
||||||
|
extent = {
|
||||||
|
static_cast<uint32>(width),
|
||||||
|
static_cast<uint32>(height),
|
||||||
|
};
|
||||||
|
extent.width = std::clamp(extent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
|
||||||
|
extent.height = std::clamp(extent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::createSwapChain()
|
||||||
|
{
|
||||||
|
uint32 imageCount = Gfx::numFramesBuffered;
|
||||||
|
VkSwapchainCreateInfoKHR createInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.surface = surface,
|
||||||
|
.minImageCount = Gfx::numFramesBuffered,
|
||||||
|
.imageFormat = format.format,
|
||||||
|
.imageColorSpace = format.colorSpace,
|
||||||
|
.imageExtent = extent,
|
||||||
|
.imageArrayLayers = 1,
|
||||||
|
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||||
|
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||||
|
.preTransform = capabilities.currentTransform,
|
||||||
|
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
||||||
|
.presentMode = presentMode,
|
||||||
|
.clipped = VK_TRUE,
|
||||||
|
.oldSwapchain = swapchain,
|
||||||
|
};
|
||||||
|
VK_CHECK(vkCreateSwapchainKHR(graphics->getDevice(), &createInfo, nullptr, &swapchain));
|
||||||
|
|
||||||
|
uint32 numImages;
|
||||||
|
vkGetSwapchainImagesKHR(graphics->getDevice(), swapchain, &numImages, swapChainImages.data());
|
||||||
|
|
||||||
|
assert(numImages == Gfx::numFramesBuffered);
|
||||||
|
for (uint32 i = 0; i < numImages; ++i)
|
||||||
|
{
|
||||||
|
swapChainTextures[i] = new Texture2D(graphics, TextureCreateInfo{
|
||||||
|
.format = cast(format.format),
|
||||||
|
.width = extent.width,
|
||||||
|
.height = extent.height,
|
||||||
|
.depth = 1,
|
||||||
|
.mipLevels = 1,
|
||||||
|
.layers = 1,
|
||||||
|
.elements = 1,
|
||||||
|
.samples = 1,
|
||||||
|
.usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||||
|
}, swapChainImages[i]);
|
||||||
|
imageAvailableSemaphores[i] = new Semaphore(graphics);
|
||||||
|
renderingDoneSemaphores[i] = new Semaphore(graphics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Viewport::Viewport(PGraphics graphics, PWindow owner, const ViewportCreateInfo &viewportInfo)
|
||||||
|
: Gfx::Viewport(owner, viewportInfo), graphics(graphics)
|
||||||
|
{
|
||||||
|
handle.width = static_cast<float>(sizeX);
|
||||||
|
handle.height = static_cast<float>(sizeY);
|
||||||
|
handle.x = static_cast<float>(offsetX);
|
||||||
|
handle.y = static_cast<float>(offsetY) + handle.height;
|
||||||
|
handle.height = -handle.height;
|
||||||
|
handle.minDepth = 0.f;
|
||||||
|
handle.maxDepth = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Viewport::~Viewport()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewport::resize(uint32 newX, uint32 newY)
|
||||||
|
{
|
||||||
|
sizeX = newX;
|
||||||
|
sizeY = newY;
|
||||||
|
handle.width = static_cast<float>(sizeX);
|
||||||
|
handle.y = static_cast<float>(sizeY + offsetX);
|
||||||
|
handle.height = -static_cast<float>(sizeY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewport::move(uint32 newOffsetX, uint32 newOffsetY)
|
||||||
|
{
|
||||||
|
offsetX = newOffsetX;
|
||||||
|
offsetY = newOffsetY;
|
||||||
|
handle.x = static_cast<float>(offsetX);
|
||||||
|
handle.y = static_cast<float>(offsetY + sizeY);
|
||||||
|
}
|
||||||
@@ -24,11 +24,6 @@ public:
|
|||||||
virtual void setFileCallback(std::function<void(int, const char**)> callback) override;
|
virtual void setFileCallback(std::function<void(int, const char**)> callback) override;
|
||||||
virtual void setCloseCallback(std::function<void()> callback);
|
virtual void setCloseCallback(std::function<void()> callback);
|
||||||
|
|
||||||
VkFormat getPixelFormat() const
|
|
||||||
{
|
|
||||||
return cast(windowState.pixelFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::function<void(KeyCode, InputAction, KeyModifier)> keyCallback;
|
std::function<void(KeyCode, InputAction, KeyModifier)> keyCallback;
|
||||||
std::function<void(double, double)> mouseMoveCallback;
|
std::function<void(double, double)> mouseMoveCallback;
|
||||||
std::function<void(MouseButton, InputAction, KeyModifier)> mouseButtonCallback;
|
std::function<void(MouseButton, InputAction, KeyModifier)> mouseButtonCallback;
|
||||||
@@ -36,32 +31,30 @@ public:
|
|||||||
std::function<void(int, const char**)> fileCallback;
|
std::function<void(int, const char**)> fileCallback;
|
||||||
std::function<void()> closeCallback;
|
std::function<void()> closeCallback;
|
||||||
protected:
|
protected:
|
||||||
void advanceBackBuffer();
|
void chooseSwapSurfaceFormat();
|
||||||
void recreateSwapchain(const WindowCreateInfo &createInfo);
|
void chooseSwapPresentMode();
|
||||||
void present();
|
void chooseSwapExtent();
|
||||||
void destroySwapchain();
|
void createSwapChain();
|
||||||
void createSwapchain();
|
|
||||||
void chooseSurfaceFormat(const Array<VkSurfaceFormatKHR> &available, Gfx::SeFormat preferred);
|
|
||||||
void choosePresentMode(const Array<VkPresentModeKHR> &modes);
|
|
||||||
|
|
||||||
OTexture2D backBufferImages[Gfx::numFramesBuffered];
|
|
||||||
VkImage backBufferHandles[Gfx::numFramesBuffered];
|
|
||||||
OSemaphore renderFinished[Gfx::numFramesBuffered];
|
|
||||||
OSemaphore imageAcquired[Gfx::numFramesBuffered];
|
|
||||||
PSemaphore imageAcquiredSemaphore;
|
|
||||||
|
|
||||||
PGraphics graphics;
|
PGraphics graphics;
|
||||||
|
WindowCreateInfo preferences;
|
||||||
VkInstance instance;
|
VkInstance instance;
|
||||||
VkSwapchainKHR swapchain;
|
VkSwapchainKHR swapchain;
|
||||||
VkSampleCountFlags numSamples;
|
VkSampleCountFlags numSamples;
|
||||||
VkPresentModeKHR presentMode;
|
|
||||||
VkSurfaceKHR surface;
|
VkSurfaceKHR surface;
|
||||||
VkSurfaceFormatKHR surfaceFormat;
|
VkSurfaceCapabilitiesKHR capabilities;
|
||||||
|
Array<VkSurfaceFormatKHR> supportedFormats;
|
||||||
|
Array<VkPresentModeKHR> supportedPresentModes;
|
||||||
|
// the values used for the current swapchain
|
||||||
|
VkSurfaceFormatKHR format;
|
||||||
|
VkPresentModeKHR presentMode;
|
||||||
|
VkExtent2D extent;
|
||||||
void *windowHandle;
|
void *windowHandle;
|
||||||
int32 currentImageIndex;
|
StaticArray<VkImage, Gfx::numFramesBuffered> swapChainImages;
|
||||||
int32 acquiredImageIndex;
|
StaticArray<OTexture2D, Gfx::numFramesBuffered> swapChainTextures;
|
||||||
int32 preAcquiredImageIndex;
|
StaticArray<OSemaphore, Gfx::numFramesBuffered> imageAvailableSemaphores;
|
||||||
int32 semaphoreIndex;
|
StaticArray<OSemaphore, Gfx::numFramesBuffered> renderingDoneSemaphores;
|
||||||
|
uint32 currentImageIndex = 0;
|
||||||
|
uint32 currentSemaphoreIndex = 0;
|
||||||
};
|
};
|
||||||
DEFINE_REF(Window)
|
DEFINE_REF(Window)
|
||||||
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#include "Window.h"
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
using namespace Seele::Gfx;
|
||||||
|
|
||||||
|
|
||||||
|
Window::Window()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Window::~Window()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Viewport::Viewport(PWindow owner, const ViewportCreateInfo& viewportInfo)
|
||||||
|
: sizeX(std::min(owner->getFramebufferWidth(), viewportInfo.dimensions.size.x))
|
||||||
|
, sizeY(std::min(owner->getFramebufferHeight(), viewportInfo.dimensions.size.y))
|
||||||
|
, offsetX(viewportInfo.dimensions.offset.x)
|
||||||
|
, offsetY(viewportInfo.dimensions.offset.y)
|
||||||
|
, fieldOfView(viewportInfo.fieldOfView)
|
||||||
|
, owner(owner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Viewport::~Viewport()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix4 Viewport::getProjectionMatrix() const
|
||||||
|
{
|
||||||
|
if (fieldOfView > 0.0f)
|
||||||
|
{
|
||||||
|
return glm::perspective(fieldOfView, sizeX / static_cast<float>(sizeY), 0.1f, 1000.0f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return glm::ortho(0.0f, (float)sizeX, (float)sizeY, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Initializer.h"
|
||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
namespace Seele
|
||||||
|
{
|
||||||
|
namespace Gfx
|
||||||
|
{
|
||||||
|
class Window
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Window();
|
||||||
|
virtual ~Window();
|
||||||
|
virtual void beginFrame() = 0;
|
||||||
|
virtual void endFrame() = 0;
|
||||||
|
virtual void onWindowCloseEvent() = 0;
|
||||||
|
virtual PTexture2D getBackBuffer() = 0;
|
||||||
|
virtual void setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifier)> callback) = 0;
|
||||||
|
virtual void setMouseMoveCallback(std::function<void(double, double)> callback) = 0;
|
||||||
|
virtual void setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback) = 0;
|
||||||
|
virtual void setScrollCallback(std::function<void(double, double)> callback) = 0;
|
||||||
|
virtual void setFileCallback(std::function<void(int, const char**)> callback) = 0;
|
||||||
|
virtual void setCloseCallback(std::function<void()> callback) = 0;
|
||||||
|
constexpr SeFormat getSwapchainFormat() const
|
||||||
|
{
|
||||||
|
return framebufferFormat;
|
||||||
|
}
|
||||||
|
constexpr SeSampleCountFlags getNumSamples() const
|
||||||
|
{
|
||||||
|
return sampleFlags;
|
||||||
|
}
|
||||||
|
constexpr uint32 getFramebufferWidth() const
|
||||||
|
{
|
||||||
|
return framebufferWidth;
|
||||||
|
}
|
||||||
|
constexpr uint32 getFramebufferHeight() const
|
||||||
|
{
|
||||||
|
return framebufferHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SeFormat framebufferFormat;
|
||||||
|
SeSampleCountFlags sampleFlags;
|
||||||
|
uint32 framebufferWidth;
|
||||||
|
uint32 framebufferHeight;
|
||||||
|
};
|
||||||
|
DEFINE_REF(Window)
|
||||||
|
|
||||||
|
class Viewport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Viewport(PWindow owner, const ViewportCreateInfo& createInfo);
|
||||||
|
virtual ~Viewport();
|
||||||
|
virtual void resize(uint32 newX, uint32 newY) = 0;
|
||||||
|
virtual void move(uint32 newOffsetX, uint32 newOffsetY) = 0;
|
||||||
|
constexpr PWindow getOwner() const { return owner; }
|
||||||
|
constexpr uint32 getWidth() const { return sizeX; }
|
||||||
|
constexpr uint32 getHeight() const { return sizeY; }
|
||||||
|
constexpr uint32 getOffsetX() const { return offsetX; }
|
||||||
|
constexpr uint32 getOffsetY() const { return offsetY; }
|
||||||
|
Matrix4 getProjectionMatrix() const;
|
||||||
|
protected:
|
||||||
|
uint32 sizeX;
|
||||||
|
uint32 sizeY;
|
||||||
|
uint32 offsetX;
|
||||||
|
uint32 offsetY;
|
||||||
|
float fieldOfView;
|
||||||
|
PWindow owner;
|
||||||
|
};
|
||||||
|
DEFINE_REF(Viewport)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ void Window::render()
|
|||||||
view->render();
|
view->render();
|
||||||
}
|
}
|
||||||
gfxHandle->endFrame();
|
gfxHandle->endFrame();
|
||||||
|
std::cout << "Render" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user