diff --git a/projects/triangle/triangle.lpi b/projects/triangle/triangle.lpi
index e65fc77..8a68b03 100644
--- a/projects/triangle/triangle.lpi
+++ b/projects/triangle/triangle.lpi
@@ -33,7 +33,7 @@
-
+
@@ -209,6 +209,10 @@
+
+
+
+
diff --git a/projects/triangle/triangle.lpr b/projects/triangle/triangle.lpr
index 291da12..49b8a7b 100644
--- a/projects/triangle/triangle.lpr
+++ b/projects/triangle/triangle.lpr
@@ -8,7 +8,7 @@ uses
cthreads,
{$ENDIF}{$ENDIF}
SysUtils, Interfaces, Dialogs, Forms,
- uMainForm, Vulkan;
+ uMainForm, Vulkan, uvkuDebugReporter;
{$R *.res}
diff --git a/projects/triangle/triangle.lps b/projects/triangle/triangle.lps
index f810685..6596f79 100644
--- a/projects/triangle/triangle.lps
+++ b/projects/triangle/triangle.lps
@@ -4,14 +4,13 @@
-
+
-
+
-
-
+
@@ -20,25 +19,25 @@
-
-
-
+
+
+
+
-
-
-
-
+
+
+
-
-
+
+
-
+
@@ -46,49 +45,47 @@
-
+
-
+
-
-
+
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -96,7 +93,7 @@
-
+
@@ -104,15 +101,15 @@
-
+
-
-
-
-
+
+
+
+
@@ -120,7 +117,7 @@
-
+
@@ -128,7 +125,7 @@
-
+
@@ -136,7 +133,7 @@
-
+
@@ -144,15 +141,16 @@
-
+
-
-
-
-
+
+
+
+
+
@@ -160,7 +158,7 @@
-
+
@@ -168,7 +166,7 @@
-
+
@@ -176,7 +174,7 @@
-
+
@@ -184,7 +182,7 @@
-
+
@@ -192,7 +190,7 @@
-
+
@@ -200,52 +198,57 @@
-
+
-
+
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
@@ -253,30 +256,29 @@
-
+
-
+
-
+
-
+
-
-
+
@@ -284,7 +286,7 @@
-
+
@@ -292,14 +294,14 @@
-
+
-
+
@@ -307,7 +309,7 @@
-
+
@@ -315,7 +317,7 @@
-
+
@@ -323,7 +325,7 @@
-
+
@@ -331,7 +333,7 @@
-
+
@@ -339,15 +341,15 @@
-
+
-
-
-
+
+
+
@@ -355,7 +357,7 @@
-
+
@@ -412,8 +414,7 @@
-
-
+
@@ -500,126 +501,136 @@
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
+
-
-
+
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/projects/triangle/uMainForm.pas b/projects/triangle/uMainForm.pas
index 573e0d3..dc5ded3 100644
--- a/projects/triangle/uMainForm.pas
+++ b/projects/triangle/uMainForm.pas
@@ -23,7 +23,14 @@ type
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
+ fGraphicsQueueFamilyIndex: VkUint32;
+ fGraphicsQueueNodeIndex: VkUint32;
+ fPresentQueueNodeIndex: VkUint32;
+ fSurfaceFormat: TVkFormat;
+ fSurfaceColorSpace: TVkColorSpaceKHR;
+
fAllocHandler: TCustomAllocHandler;
+ fDebugReporter: TvkuConsoleDebugReporter;
fInstance: TvkuInstance;
fPhyDevice: TvkuPhysicalDevice;
fDevice: TvkuDevice;
@@ -38,6 +45,8 @@ type
fVertexShader: TvkuShaderModule;
fFragmentShader: TvkuShaderModule;
fPipeline: TvkuGraphicsPipeline;
+ fCommandPool: TvkuCommandPool;
+ fCommandBuffer: TvkuCommandBuffer;
end;
var
@@ -54,7 +63,7 @@ implementation
function TCustomAllocHandler.AllocateMemory(const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid;
begin
result := inherited AllocateMemory(aSize, aAlignment, aScope);
- WriteLn(Format(' %d bytes of memory allocated at %p', [ aSize, result ]));
+ WriteLn(Format(' MEM - %d bytes of memory allocated at %p', [ aSize, result ]));
end;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -63,13 +72,13 @@ var p: PVkVoid;
begin
p := aOriginal;
result := inherited ReallocateMemory(aOriginal, aSize, aAlignment, aScope);
- WriteLn(Format(' %d bytes of memory (from %p) reallocated at %p', [ aSize, p, result ]));
+ WriteLn(Format(' MEM - %d bytes of memory (from %p) reallocated at %p', [ aSize, p, result ]));
end;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TCustomAllocHandler.FreeMemory(const aMemory: PVkVoid);
begin
- WriteLn(Format(' free memory at %p', [ aMemory ]));
+ WriteLn(Format(' MEM - free memory at %p', [ aMemory ]));
inherited FreeMemory(aMemory);
end;
@@ -82,6 +91,7 @@ var
InstanceFactory: TvkuInstanceFactory;
DeviceFactory: TvkuDeviceFactory;
SurfaceFactory: TvkuSurfaceFactory;
+ CommandPoolFactory: TvkuCommandPoolFactory;
SwapChainFactory: TvkuSwapChainFactory;
ImageViewFactory: TvkuImageViewFactory;
RenderPassFactory: TvkuRenderPassFactory;
@@ -91,9 +101,9 @@ var
ShaderModuleFactory: TvkuShaderModuleFactory;
PipelineFactory: TvkuGraphicsPipelineFactory;
+ QueueFamProps: TVkQueueFamilyPropertiesArr;
DepthFormat: TVkFormat;
f: TVkFormat;
- SurcafeFormat: TVkSurfaceFormatKHR;
i: Integer;
SrfFormats: TVkSurfaceFormatArr;
SurfaceCapabilities: TVkSurfaceCapabilitiesKHR;
@@ -105,23 +115,44 @@ begin
fAllocHandler := TCustomAllocHandler.Create;
//////////////////////////////////////////////////////////////////////////////
- WriteLn('create instance');
+ WriteLn('create instance: ');
InstanceFactory := TvkuInstanceFactory.Create;
try
InstanceFactory.AllocHandler := fAllocHandler;
InstanceFactory.EnabledExtensionNames.Add(VK_KHR_SURFACE_EXTENSION_NAME);
+ InstanceFactory.EnabledExtensionNames.Add(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
InstanceFactory.EnabledExtensionNames.Add(TvkuSurface.GetPlatformSurfaceExtensionName);
fInstance := InstanceFactory.CreateInstance;
+ WriteLn(' handle: ', PtrUInt(fInstance.Handle));
+ WriteLn(' done');
finally
FreeAndNil(InstanceFactory);
end;
+ fDebugReporter := TvkuConsoleDebugReporter.Create(fInstance.InstanceCommands, fAllocHandler);
+
//////////////////////////////////////////////////////////////////////////////
WriteLn('find suitable physical device');
PhyDevices := fInstance.GetPhysicalDevices;
if (Length(PhyDevices) <= 0) then
- raise Exception.Create('unable to get physical device');
+ raise TvkuException.Create('unable to get physical device');
fPhyDevice := TvkuPhysicalDevice.Create(PhyDevices[0], fInstance.InstanceCommands);
+ WriteLn(' handle: ', PtrUInt(fPhyDevice.Handle));
+
+ Write(' find suitable graphics queue index... ');
+ QueueFamProps := fPhyDevice.GetQueueFamilyProperties;
+ fGraphicsQueueFamilyIndex := high(fGraphicsQueueFamilyIndex);
+ for i := low(QueueFamProps) to high(QueueFamProps) do begin
+ if (VK_QUEUE_GRAPHICS_BIT in QueueFamProps[i].queueFlags) then begin
+ fGraphicsQueueFamilyIndex := i;
+ WriteLn(fGraphicsQueueFamilyIndex);
+ break;
+ end;
+ end;
+ if (fGraphicsQueueFamilyIndex = high(fGraphicsQueueFamilyIndex)) then
+ raise TvkuException.Create('unable to find graphics queue index');
+
+ Write(' find suitable depth format... ');
f := VK_FORMAT_UNDEFINED;
for f in [ VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D16_UNORM ] do begin
if (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT in fPhyDevice.GetFormatProperties(f).optimalTilingFeatures) then begin
@@ -129,39 +160,111 @@ begin
break;
end;
end;
+ WriteLn(DepthFormat);
+ WriteLn(' done');
//////////////////////////////////////////////////////////////////////////////
WriteLn('create device');
DeviceFactory := TvkuDeviceFactory.Create(fInstance);
try
DeviceFactory.AllocHandler := fAllocHandler;
+ DeviceFactory.EnabledExtensions.Add('VK_KHR_swapchain');
DeviceFactory.QueueCreateInfos.Length := 1;
with DeviceFactory.QueueCreateInfos[0] do begin
Flags := 0;
- QueueFamilyIndex := 0;
+ QueueFamilyIndex := fGraphicsQueueFamilyIndex;
QueuePriorities.Length := 1;
QueuePriorities[0] := 1.0;
end;
fDevice := DeviceFactory.CreateDevice(fPhyDevice.Handle);
+ WriteLn(' handle: ', PtrUInt(fDevice.Handle));
+ WriteLn(' done');
finally
FreeAndNil(DeviceFactory);
end;
//////////////////////////////////////////////////////////////////////////////
WriteLn('find suitable queue');
- fQueue := TvkuQueue.Create(fDevice.GetQueue(0, 0), fDevice.DeviceCommands);
+ fQueue := TvkuQueue.Create(fDevice.GetQueue(fGraphicsQueueFamilyIndex, 0), fDevice.DeviceCommands);
+ WriteLn(' handle: ', PtrUInt(fQueue.Handle));
+ WriteLn(' done');
//////////////////////////////////////////////////////////////////////////////
- WriteLn('create surface');
+ WriteLn('create surface: ');
SurfaceFactory := TvkuSurfaceFactory.Create(fInstance);
try
SurfaceFactory.AllocHandler := fAllocHandler;
SurfaceFactory.WinControl := RenderPanel;
fSurface := SurfaceFactory.CreateSurface;
+ WriteLn(' handle: ', PtrUInt(fSurface.Handle));
+
+ WriteLn(' find suitable graphics and present queue node index');
+ fGraphicsQueueNodeIndex := high(fGraphicsQueueNodeIndex);
+ fPresentQueueNodeIndex := high(fPresentQueueNodeIndex);
+ QueueFamProps := fPhyDevice.GetQueueFamilyProperties;
+ for i := low(QueueFamProps) to high(QueueFamProps) do begin
+ if (VK_QUEUE_GRAPHICS_BIT in QueueFamProps[i].queueFlags) then
+ fGraphicsQueueNodeIndex := i;
+
+ if fPhyDevice.GetSurfaceSupport(i, fSurface.Handle) then begin
+ fGraphicsQueueNodeIndex := i;
+ fPresentQueueNodeIndex := i;
+ break;
+ end;
+ end;
+ if (fPresentQueueNodeIndex = high(fPresentQueueNodeIndex)) then begin
+ for i := low(QueueFamProps) to high(QueueFamProps) do begin
+ if fPhyDevice.GetSurfaceSupport(i, fSurface.Handle) then begin
+ fPresentQueueNodeIndex := i;
+ break;
+ end;
+ end;
+ end;
+ WriteLn(' graphics queue node index: ', fGraphicsQueueNodeIndex);
+ WriteLn(' present queue node index: ', fPresentQueueNodeIndex);
+ if (fGraphicsQueueNodeIndex = high(fGraphicsQueueNodeIndex)) or
+ (fPresentQueueNodeIndex = high(fPresentQueueNodeIndex)) or
+ (fPresentQueueNodeIndex <> fGraphicsQueueNodeIndex) then
+ raise TvkuException.Create('different graphic and present queue node index is not supported yet');
+
+ WriteLn(' find suitable image format');
+ SrfFormats := fPhyDevice.GetSurfaceFormats(fSurface.Handle);
+ if (Length(SrfFormats) = 0) then
+ raise TvkuException.Create('no suitable formats found');
+ if (Length(SrfFormats) = 1) and (SrfFormats[0].format = VK_FORMAT_UNDEFINED) then begin
+ fSurfaceFormat := VK_FORMAT_R8G8B8A8_UNORM;
+ fSurfaceColorSpace := VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+ end else begin
+ fSurfaceFormat := SrfFormats[0].format;
+ fSurfaceColorSpace := SrfFormats[0].colorSpace;
+ end;
+ WriteLn(' format: ', fSurfaceFormat);
+ WriteLn(' color space: ', fSurfaceColorSpace);
+
+ WriteLn(' done');
finally
FreeAndNil(SurfaceFactory);
end;
+ //////////////////////////////////////////////////////////////////////////////
+ WriteLn('create command pool');
+ CommandPoolFactory := TvkuCommandPoolFactory.Create(fDevice);
+ try
+ CommandPoolFactory.Flags := [ VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT ];
+ CommandPoolFactory.QueueFamilyIndex := fGraphicsQueueNodeIndex;
+ fCommandPool := CommandPoolFactory.CreateCommandPool;
+ WriteLn(' handle: ', PtrUInt(fCommandPool.Handle));
+
+ WriteLn(' alloc command buffer');
+ fCommandBuffer := TvkuCommandBuffer.Create(
+ fCommandPool.CreateCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY),
+ true, fCommandPool.Handle, fDevice.DeviceCommands);
+ WriteLn(' handle: ', PtrUInt(fCommandBuffer.Handle));
+ WriteLn(' done');
+ finally
+ FreeAndNil(CommandPoolFactory);
+ end;
+
//////////////////////////////////////////////////////////////////////////////
WriteLn('create swap chain');
SwapChainFactory := TvkuSwapChainFactory.Create(fDevice);
@@ -173,6 +276,8 @@ begin
SwapChainFactory.ImageSharingMode := VK_SHARING_MODE_EXCLUSIVE;
SwapChainFactory.Clipped := true;
SwapChainFactory.ComposideAlpha := [ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR ];
+ SwapChainFactory.ImageFormat := fSurfaceFormat;
+ SwapChainFactory.ImageColorSpace := fSurfaceColorSpace;
WriteLn(' get surface capabilities');
SurfaceCapabilities := fPhyDevice.GetSurfaceCapabilities(fSurface.Handle);
@@ -183,50 +288,37 @@ begin
ClientWidth := SurfaceCapabilities.currentExtent.width;
ClientHeight := SurfaceCapabilities.currentExtent.height;
end;
+ WriteLn(' width: ', SurfaceCapabilities.currentExtent.width);
+ WriteLn(' height: ', SurfaceCapabilities.currentExtent.height);
SwapChainFactory.ImageExtent := SurfaceCapabilities.currentExtent;
- WriteLn(' set min image count');
+ Write(' set min image count... ');
SwapChainFactory.MinImageCount := SurfaceCapabilities.minImageCount + 1;
if (SurfaceCapabilities.maxImageCount > 0) and
(SwapChainFactory.MinImageCount > SurfaceCapabilities.maxImageCount) then
SwapChainFactory.MinImageCount := SurfaceCapabilities.maxImageCount;
+ WriteLn(SwapChainFactory.MinImageCount);
- WriteLn(' find suitable image format');
- SrfFormats := fPhyDevice.GetSurfaceFormats(fSurface.Handle);
- if (Length(SrfFormats) = 0) then begin
- WriteLn('no suitable formats found');
- halt;
- end;
- if (Length(SrfFormats) = 1) and (SrfFormats[0].format = VK_FORMAT_UNDEFINED) then begin
- SurcafeFormat.format := VK_FORMAT_R8G8B8A8_UNORM;
- SurcafeFormat.colorSpace := VK_COLORSPACE_SRGB_NONLINEAR_KHR;
- end else begin
- SurcafeFormat.format := SrfFormats[0].format;
- SurcafeFormat.colorSpace := SrfFormats[0].colorSpace;
- end;
- SwapChainFactory.ImageFormat := SurcafeFormat.format;
- SwapChainFactory.ImageColorSpace := SurcafeFormat.colorSpace;
-
-
- WriteLn(' set pre transform');
+ WriteLn(' set pre transform...');
SwapChainFactory.PreTransform := SurfaceCapabilities.currentTransform;
if (VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR in SurfaceCapabilities.supportedTransforms) then
- SwapChainFactory.PreTransform := SwapChainFactory.PreTransform + [ VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ];
+ SwapChainFactory.PreTransform := [ VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ];
- WriteLn(' find suitable present mode');
+ Write(' find suitable present mode... ');
PresentModes := fPhyDevice.GetSurfacePresentModes(fSurface.Handle);
- if (Length(PresentModes) = 0) then begin
- WriteLn('unable to get present modes');
- halt;
- end;
+ if (Length(PresentModes) = 0) then
+ raise TvkuException.Create('unable to get present modes');
for pm in PresentModes do begin
if (pm = VK_PRESENT_MODE_MAILBOX_KHR) then begin
SwapChainFactory.PresentMode := pm;
break;
end;
end;
+ WriteLn(SwapChainFactory.PresentMode);
fSwapChain := SwapChainFactory.CreateSwapchain;
+ WriteLn(' handle: ', PtrUInt(fSwapChain.Handle));
+ WriteLn(' done');
finally
FreeAndNil(SwapChainFactory);
end;
@@ -237,14 +329,8 @@ begin
SetLength(fImageViews, Length(Images));
ImageViewFactory := TvkuImageViewFactory.Create(fDevice);
try
- ComponentMapping.r := VK_COMPONENT_SWIZZLE_R;
- ComponentMapping.g := VK_COMPONENT_SWIZZLE_G;
- ComponentMapping.b := VK_COMPONENT_SWIZZLE_B;
- ComponentMapping.a := VK_COMPONENT_SWIZZLE_A;
-
ImageViewFactory.AllocHandler := fAllocHandler;
- ImageViewFactory.Format := SurcafeFormat.format;
- ImageViewFactory.Components := ComponentMapping;
+ ImageViewFactory.Format := fSurfaceFormat;
ImageViewFactory.ViewType := VK_IMAGE_VIEW_TYPE_2D;
with ImageViewFactory.SubresourceRange do begin
AspectMask := [ VK_IMAGE_ASPECT_COLOR_BIT ];
@@ -253,10 +339,19 @@ begin
BaseArrayLayer := 0;
LayerCount := 1;
end;
+ with ImageViewFactory.Components do begin
+ r := VK_COMPONENT_SWIZZLE_R;
+ g := VK_COMPONENT_SWIZZLE_G;
+ b := VK_COMPONENT_SWIZZLE_B;
+ a := VK_COMPONENT_SWIZZLE_A;
+ end;
for i := Low(fImageViews) to High(fImageViews) do begin
+ // TODO create image barrier
ImageViewFactory.Image := Images[i];
fImageViews[i] := ImageViewFactory.CreateImageView;
+ WriteLn(' handle: ', PtrUInt(fImageViews[i].Handle));
end;
+ WriteLn(' done');
finally
FreeAndNil(ImageViewFactory);
end;
@@ -267,7 +362,7 @@ begin
try
RenderPassFactory.Attachments.Length := 2;
with RenderPassFactory.Attachments[0] do begin
- Format := SurcafeFormat.format;
+ Format := fSurfaceFormat;
Samples := [ VK_SAMPLE_COUNT_1_BIT ];
LoadOp := VK_ATTACHMENT_LOAD_OP_CLEAR;
StoreOp := VK_ATTACHMENT_STORE_OP_STORE;
@@ -303,6 +398,9 @@ begin
RenderPassFactory.AllocHandler := fAllocHandler;
fRenderPass := RenderPassFactory.CreateRenderPass;
+
+ WriteLn(' handle: ', PtrUInt(fRenderPass.Handle));
+ WriteLn(' done');
finally
FreeAndNil(RenderPassFactory);
end;
@@ -323,7 +421,9 @@ begin
for i := low(fFrameBuffers) to high(fFrameBuffers) do begin
FrameBufferFactory.Attachments[0] := fImageViews[i].Handle;
fFrameBuffers[i] := FrameBufferFactory.CreateFrameBuffer;
+ WriteLn(' handle: ', PtrUInt(fFrameBuffers[i].Handle));
end;
+ WriteLn(' done');
finally
FreeAndNil(FrameBufferFactory);
end;
@@ -343,6 +443,8 @@ begin
DescSetLayoutFactory.AllocHandler := fAllocHandler;
fDescSetLayout := DescSetLayoutFactory.CreateDescriptorSetLayout;
+ WriteLn(' handle: ', PtrUInt(fDescSetLayout.Handle));
+ WriteLn(' done');
finally
FreeAndNil(DescSetLayoutFactory);
end;
@@ -355,6 +457,8 @@ begin
PipelineLayoutFactory.SetLayouts.Length := 1;
PipelineLayoutFactory.SetLayouts[0] := fDescSetLayout.Handle;
fPipelineLayout := PipelineLayoutFactory.CreatePipelineLayout;
+ WriteLn(' handle: ', PtrUInt(fPipelineLayout.Handle));
+ WriteLn(' done');
finally
FreeAndNil(PipelineLayoutFactory);
end;
@@ -367,9 +471,12 @@ begin
ShaderModuleFactory.LoadGlslCode(ExtractFilePath(Application.ExeName) + '../../data/shaders/triangle.vert', [ VK_SHADER_STAGE_VERTEX_BIT ]);
fVertexShader := ShaderModuleFactory.CreateShaderModule;
+ WriteLn(' vertex handle: ', PtrUInt(fVertexShader.Handle));
ShaderModuleFactory.LoadGlslCode(ExtractFilePath(Application.ExeName) + '../../data/shaders/triangle.frag', [ VK_SHADER_STAGE_FRAGMENT_BIT ]);
fFragmentShader := ShaderModuleFactory.CreateShaderModule;
+ WriteLn(' fragment handle: ', PtrUInt(fFragmentShader.Handle));
+ WriteLn(' done');
finally
FreeAndNil(ShaderModuleFactory);
end;
@@ -379,7 +486,7 @@ begin
PipelineFactory := TvkuGraphicsPipelineFactory.Create(fDevice);
try
PipelineFactory.AllocHandler := fAllocHandler;
- fPipeline := PipelineFactory.CreateGraphicsPipeline(VK_INVALID_NDP_HANDLE);
+ // TODO fPipeline := PipelineFactory.CreateGraphicsPipeline(VK_INVALID_NDP_HANDLE);
finally
FreeAndNil(PipelineFactory);
end;
@@ -418,6 +525,7 @@ begin
FreeAndNil(fQueue);
FreeAndNil(fDevice);
FreeAndNil(fPhyDevice);
+ FreeAndNil(fDebugReporter);
FreeAndNil(fInstance);
FreeAndNil(fAllocHandler);
end;
diff --git a/projects/utils/VulkanUtils.pas b/projects/utils/VulkanUtils.pas
index c405f02..7142ce1 100644
--- a/projects/utils/VulkanUtils.pas
+++ b/projects/utils/VulkanUtils.pas
@@ -6,7 +6,7 @@ interface
uses
Classes, SysUtils,
- uvkuTypes, uvkuAllocationHandler,
+ uvkuTypes, uvkuAllocationHandler, uvkuDebugReporter,
uvkuInstance, uvkuInstanceFactory,
uvkuPhysicalDevice, uvkuDevice, uvkuDeviceFactory, uvkuDeviceMemory, uvkuQueue,
uvkuSurface, uvkuSurfaceFactory,
@@ -43,6 +43,9 @@ type
TvkuAllocationHandler = uvkuAllocationHandler.TvkuAllocationHandler;
+ TvkuDebugReporter = uvkuDebugReporter.TvkuDebugReporter;
+ TvkuConsoleDebugReporter = uvkuDebugReporter.TvkuConsoleDebugReporter;
+
{ Instance }
TvkuInstance = uvkuInstance.TvkuInstance;
TvkuInstanceFactory = uvkuInstanceFactory.TvkuInstanceFactory;
diff --git a/projects/utils/uvkuAllocationHandler.pas b/projects/utils/uvkuAllocationHandler.pas
index c66cc21..7e1512f 100644
--- a/projects/utils/uvkuAllocationHandler.pas
+++ b/projects/utils/uvkuAllocationHandler.pas
@@ -1,6 +1,7 @@
unit uvkuAllocationHandler;
{$mode objfpc}{$H+}
+{$I Vulkan.inc}
interface
@@ -25,32 +26,50 @@ type
implementation
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-function AllocateMemoryCallback(aUserData: PVkVoid; aSize: VkSize; aAlignment: VkSize; aScope: TVkSystemAllocationScope): PVkVoid; stdcall;
+function AllocateMemoryCallback(
+ aUserData: PVkVoid;
+ aSize: VkSize;
+ aAlignment: VkSize;
+ aScope: TVkSystemAllocationScope): PVkVoid; {$IFDEF VK_CDECL}cdecl{$ELSE}stdcall{$ENDIF};
begin
result := TvkuAllocationHandler(aUserData).AllocateMemory(aSize, aAlignment, aScope);
end;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-function ReallocateMemoryCallback(aUserData: PVkVoid; aOriginal: PVkVoid; aSize: VkSize;
- aAlignment: VkSize; aScope: TVkSystemAllocationScope): PVkVoid; stdcall;
+function ReallocateMemoryCallback(
+ aUserData: PVkVoid;
+ aOriginal: PVkVoid;
+ aSize: VkSize;
+ aAlignment: VkSize;
+ aScope: TVkSystemAllocationScope): PVkVoid; {$IFDEF VK_CDECL}cdecl{$ELSE}stdcall{$ENDIF};
begin
result := TvkuAllocationHandler(aUserData).ReallocateMemory(aOriginal, aSize, aAlignment, aScope);
end;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure FreeMemoryCallback(aUserData: PVkVoid; aMemory: PVkVoid); stdcall;
+procedure FreeMemoryCallback(
+ aUserData: PVkVoid;
+ aMemory: PVkVoid); {$IFDEF VK_CDECL}cdecl{$ELSE}stdcall{$ENDIF};
begin
TvkuAllocationHandler(aUserData).FreeMemory(aMemory);
end;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure InternalAllocationCallback(aUserData: PVkVoid; aSize: VkSize; aType: TVkInternalAllocationType; aScope: TVkSystemAllocationScope); stdcall;
+procedure InternalAllocationCallback(
+ aUserData: PVkVoid;
+ aSize: VkSize;
+ aType: TVkInternalAllocationType;
+ aScope: TVkSystemAllocationScope); {$IFDEF VK_CDECL}cdecl{$ELSE}stdcall{$ENDIF};
begin
TvkuAllocationHandler(aUserData).InternalAllocationNotification(aSize, aType, aScope);
end;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure InternalFreeCallback(aUserData: PVkVoid; aSize: VkSize; aType: TVkInternalAllocationType; aScope: TVkSystemAllocationScope); stdcall;
+procedure InternalFreeCallback(
+ aUserData: PVkVoid;
+ aSize: VkSize;
+ aType: TVkInternalAllocationType;
+ aScope: TVkSystemAllocationScope); {$IFDEF VK_CDECL}cdecl{$ELSE}stdcall{$ENDIF};
begin
TvkuAllocationHandler(aUserData).InternalFreeNotification(aSize, aType, aScope);
end;
diff --git a/projects/utils/uvkuCommandBuffer.pas b/projects/utils/uvkuCommandBuffer.pas
index 64aad9b..73f9138 100644
--- a/projects/utils/uvkuCommandBuffer.pas
+++ b/projects/utils/uvkuCommandBuffer.pas
@@ -20,6 +20,8 @@ type
property CommandPool: VkCommandPool read fCommandPool;
property DeviceCommands: TVkDeviceCommands read fDeviceCommands;
+ procedure BeginCommand;
+
constructor Create(
const aHandle: VkCommandBuffer;
const aOwnsHandle: Boolean;
@@ -30,8 +32,27 @@ type
implementation
+uses
+ uvkuUtils;
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TvkuCommandBuffer//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TvkuCommandBuffer.BeginCommand;
+var
+ Info: TVkCommandBufferBeginInfo;
+ err: TVkResult;
+begin
+ FillByte(Info, SizeOf(Info), 0);
+ Info.sType := VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ Info.pNext := nil;
+ Info.flags := []; // TODO
+ Info.pInheritanceInfo := nil; // TODO
+ err := DeviceCommands.vkBeginCommandBuffer(fHandle, @Info);
+ if (err < VK_SUCCESS) then
+ raise TvkuErrorException.Create('unable to begin command buffer', err);
+end;
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TvkuCommandBuffer.Create(const aHandle: VkCommandBuffer; const aOwnsHandle: Boolean;
const aCommandPool: VkCommandPool; const aDeviceCommands: TVkDeviceCommands);
diff --git a/projects/utils/uvkuCommandPoolFactory.pas b/projects/utils/uvkuCommandPoolFactory.pas
index 1aabfd0..4229ab8 100644
--- a/projects/utils/uvkuCommandPoolFactory.pas
+++ b/projects/utils/uvkuCommandPoolFactory.pas
@@ -15,6 +15,9 @@ type
fFlags: VkCommandPoolCreateFlags;
fQueueFamilyIndex: VkUint32;
public
+ property Flags: VkCommandPoolCreateFlags read fFlags write fFlags;
+ property QueueFamilyIndex: VkUint32 read fQueueFamilyIndex write fQueueFamilyIndex;
+
function GetStructure: TVkCommandPoolCreateInfo;
procedure SetStructure(const aData: TVkCommandPoolCreateInfo);
diff --git a/projects/utils/uvkuDebugReporter.pas b/projects/utils/uvkuDebugReporter.pas
new file mode 100644
index 0000000..498cc00
--- /dev/null
+++ b/projects/utils/uvkuDebugReporter.pas
@@ -0,0 +1,134 @@
+unit uvkuDebugReporter;
+
+{$mode objfpc}{$H+}
+{$I Vulkan.inc}
+
+interface
+
+uses
+ Classes, SysUtils,
+ Vulkan, uvkuBase, uvkuAllocationHandler;
+
+type
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ TvkuDebugReporter = class(TvkuAllocHandle)
+ private
+ fHandle: VkDebugReportCallbackEXT;
+ fInstanceCommands: TVkInstanceCommands;
+ protected
+ function DebugMessage(
+ aFlags: VkDebugReportFlagsEXT;
+ aObjectType: TVkDebugReportObjectTypeEXT;
+ aObject: VkUint64;
+ aLocation: VkSize;
+ aMessageCode: VkInt32;
+ aLayerPrefix: String;
+ aMessage: String): Boolean; virtual;
+ public
+ property Handle: VkDebugReportCallbackEXT read fHandle;
+
+ constructor Create(
+ const aInstanceCommands: TVkInstanceCommands;
+ const aAllocHandler: TvkuAllocationHandler = nil);
+ destructor Destroy; override;
+ end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ TvkuConsoleDebugReporter = class(TvkuDebugReporter)
+ protected
+ function DebugMessage(aFlags: VkDebugReportFlagsEXT; aObjectType: TVkDebugReportObjectTypeEXT; aObject: VkUint64;
+ aLocation: VkSize; aMessageCode: VkInt32; aLayerPrefix: String; aMessage: String): Boolean; override;
+ end;
+
+implementation
+
+uses
+ uvkuUtils;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function DebugReportCallback(
+ flags: VkDebugReportFlagsEXT;
+ objectType: TVkDebugReportObjectTypeEXT;
+ uObject: VkUint64;
+ location: VkSize;
+ messageCode: VkInt32;
+ pLayerPrefix: PVkChar;
+ pMessage: PVkChar;
+ pUserData: PVkVoid): VkBool32; {$IFDEF VK_CDECL}cdecl{$ELSE}stdcall{$ENDIF};
+var ret: Boolean;
+begin
+ ret := TvkuDebugReporter(pUserData).DebugMessage(
+ flags,
+ objectType,
+ uObject,
+ location,
+ messageCode,
+ String(pLayerPrefix),
+ String(pMessage));
+ if ret
+ then result := VK_TRUE
+ else result := VK_FALSE;
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TvkuDebugReporter//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TvkuDebugReporter.DebugMessage(aFlags: VkDebugReportFlagsEXT; aObjectType: TVkDebugReportObjectTypeEXT;
+ aObject: VkUint64; aLocation: VkSize; aMessageCode: VkInt32; aLayerPrefix: String; aMessage: String): Boolean;
+begin
+ result := true;
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TvkuDebugReporter.Create(
+ const aInstanceCommands: TVkInstanceCommands;
+ const aAllocHandler: TvkuAllocationHandler);
+var
+ CreateInfo: TVkDebugReportCallbackCreateInfoEXT;
+ err: TVkResult;
+begin
+ inherited Create;
+ if Assigned(aAllocHandler) then
+ SetAllocCallbacks(aAllocHandler.MakeStructure);
+ fInstanceCommands := aInstanceCommands;
+
+ FillByte(CreateInfo, SizeOf(CreateInfo), 0);
+ CreateInfo.sType := VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
+ CreateInfo.pNext := nil;
+ CreateInfo.pfnCallback := @DebugReportCallback;
+ CreateInfo.pUserData := self;
+ CreateInfo.flags := [
+ VK_DEBUG_REPORT_INFORMATION_BIT_EXT,
+ VK_DEBUG_REPORT_WARNING_BIT_EXT,
+ VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
+ VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ VK_DEBUG_REPORT_DEBUG_BIT_EXT
+ ];
+ err := fInstanceCommands.vkCreateDebugReportCallbackEXT(fInstanceCommands.Instance, @CreateInfo, AllocCallbacks, @fHandle);
+ if (err < VK_SUCCESS) then
+ raise TvkuErrorException.Create('unable to create debug report handle', err);
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+destructor TvkuDebugReporter.Destroy;
+begin
+ if (fHandle <> VK_INVALID_NDP_HANDLE) then
+ fInstanceCommands.vkDestroyDebugReportCallbackEXT(fInstanceCommands.Instance, fHandle, AllocCallbacks);
+ fHandle := VK_INVALID_NDP_HANDLE;
+ inherited Destroy;
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TvkuConsoleDebugReporter///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TvkuConsoleDebugReporter.DebugMessage(
+ aFlags: VkDebugReportFlagsEXT; aObjectType: TVkDebugReportObjectTypeEXT;
+ aObject: VkUint64; aLocation: VkSize; aMessageCode: VkInt32; aLayerPrefix: String; aMessage: String): Boolean;
+begin
+ WriteLn(Format(' DBG - [%03d] %10s: %s', [ Integer(aFlags), aLayerPrefix, aMessage ]));
+end;
+
+end.
+