mirror of https://github.com/red-prig/fpPS4.git
1880 lines
42 KiB
Plaintext
1880 lines
42 KiB
Plaintext
unit vCmdBuffer;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes,
|
|
SysUtils,
|
|
g_node_splay,
|
|
si_ci_vi_merged_enum,
|
|
|
|
kern_proc,
|
|
vm_map,
|
|
vm_tracking_map,
|
|
|
|
Vulkan,
|
|
vDependence,
|
|
vDevice,
|
|
vMemory,
|
|
//vShader,
|
|
vShaderExt,
|
|
vImage,
|
|
vPipeline,
|
|
vPipelineManager,
|
|
vSetsPoolManager,
|
|
vDescriptorSet,
|
|
vRender;
|
|
|
|
type
|
|
TvCmdBuffer=class;
|
|
|
|
PvSemaphoreWait=^TvSemaphoreWait;
|
|
TvSemaphoreWait=object
|
|
//
|
|
FSemaphore:TvSemaphore; //Must be the first element in memory
|
|
FWaitStage:TVkPipelineStageFlags;
|
|
//
|
|
pLeft :PvSemaphoreWait;
|
|
pRight:PvSemaphoreWait;
|
|
//
|
|
function c(a,b:PvSemaphoreWait):Integer; static;
|
|
end;
|
|
|
|
TvSemaphoreWaitSet=specialize TNodeSplay<TvSemaphoreWait>;
|
|
|
|
p_cmd_track_deferred=^t_cmd_track_deferred;
|
|
t_cmd_track_deferred=object
|
|
//
|
|
start :QWORD;
|
|
__end :QWORD;
|
|
exclude:Pointer;
|
|
//
|
|
pLeft :p_cmd_track_deferred;
|
|
pRight:p_cmd_track_deferred;
|
|
//
|
|
function c(a,b:p_cmd_track_deferred):Integer; static;
|
|
end;
|
|
|
|
t_cmd_track_deferred_set=specialize TNodeSplay<t_cmd_track_deferred>;
|
|
|
|
const
|
|
BP_GRAPHICS=VK_PIPELINE_BIND_POINT_GRAPHICS;
|
|
BP_COMPUTE =VK_PIPELINE_BIND_POINT_COMPUTE;
|
|
|
|
type
|
|
TvCustomCmdBuffer=class(TvDependenciesObject)
|
|
|
|
FParent:TvCustomCmdPool;
|
|
FQueue :TvQueue;
|
|
FCmdbuf:TVkCommandBuffer;
|
|
|
|
cmd_count:qword;
|
|
ret:Integer;
|
|
|
|
submit_id:ptruint;
|
|
|
|
FCurrPipeline:array[BP_GRAPHICS..BP_COMPUTE] of TVkPipeline;
|
|
FCurrLayout :array[BP_GRAPHICS..BP_COMPUTE] of TvPipelineLayout;
|
|
FCurrBinds :array[BP_GRAPHICS..BP_COMPUTE] of PvDescriptorCache;
|
|
FCurrGroup :array[BP_GRAPHICS..BP_COMPUTE] of TvDescriptorGroup;
|
|
|
|
FDescriptorCacheSet:TvDescriptorCacheSet;
|
|
|
|
FRenderPass:TVkRenderPass;
|
|
|
|
FWaitSemaphores:TvSemaphoreWaitSet;
|
|
FWaitSemaphoresCount:Integer;
|
|
|
|
FSignalSemaphore:TvSemaphore;
|
|
|
|
FFence:TvFence;
|
|
|
|
FCBState:(cbFree,cbInit,cbBegin,cbEnd,cbSubmit);
|
|
|
|
FPlannedTriggers:t_cmd_track_deferred_set;
|
|
|
|
Constructor Create(pool:TvCustomCmdPool;Queue:TvQueue);
|
|
Destructor Destroy; override;
|
|
|
|
function AllocCmdBuffer:Boolean;
|
|
Function IsAllocated:Boolean;
|
|
function BeginCmdBuffer:Boolean;
|
|
Procedure EndCmdBuffer;
|
|
Procedure BindPipeline(BindPoint:TVkPipelineBindPoint;F:TVkPipeline);
|
|
Function IsRenderPass:Boolean;
|
|
Procedure EndRenderPass;
|
|
function BeforePushBarrier:TVkCommandBuffer;
|
|
|
|
function QueueSubmit:TVkResult;
|
|
function Wait(timeout:TVkUInt64):TVkResult;
|
|
function Status:TVkResult;
|
|
|
|
Procedure ReleaseResource;
|
|
Procedure FreeAllSemaphores;
|
|
Procedure AddWaitSemaphore(S:TvSemaphore;W:TVkPipelineStageFlags);
|
|
function GetSignaledSemaphore:TvSemaphore;
|
|
|
|
Procedure ReleaseAllPlannedTriggers;
|
|
Procedure AddPlannedTrigger(start,__end:QWORD;exclude:Pointer);
|
|
|
|
Procedure FreeAllDescriptorCache;
|
|
|
|
Procedure BindLayout(BindPoint:TVkPipelineBindPoint;F:TvPipelineLayout);
|
|
Procedure BindSet(BindPoint:TVkPipelineBindPoint;fset:TVkUInt32;FHandle:TVkDescriptorSet);
|
|
Procedure PushConstant(BindPoint:TVkPipelineBindPoint;stageFlags:TVkShaderStageFlags;offset,size:TVkUInt32;const pValues:PVkVoid);
|
|
Procedure DispatchDirect(X,Y,Z:TVkUInt32);
|
|
|
|
Procedure BindVertexBuffers(const FAttrBuilder:TvAttrBuilder);
|
|
Procedure SetVertexInput(const FAttrBuilder:TvAttrBuilder);
|
|
|
|
Procedure ClearDepthStencilImage(image:TVkImage;
|
|
imageLayout:TVkImageLayout;
|
|
const pDepthStencil:PVkClearDepthStencilValue;
|
|
rangeCount:TVkUInt32;
|
|
const pRanges:PVkImageSubresourceRange);
|
|
|
|
Procedure ClearDepthStencilImage(image:TVkImage;
|
|
imageLayout:TVkImageLayout;
|
|
const pDepthStencil:PVkClearDepthStencilValue;
|
|
const range:TVkImageSubresourceRange);
|
|
|
|
Procedure ClearColorImage(image:TVkImage;
|
|
imageLayout:TVkImageLayout;
|
|
const pColor:PVkClearColorValue;
|
|
rangeCount:TVkUInt32;
|
|
const pRanges:PVkImageSubresourceRange);
|
|
|
|
Procedure ResolveImage(srcImage:TVkImage;
|
|
srcImageLayout:TVkImageLayout;
|
|
dstImage:TVkImage;
|
|
dstImageLayout:TVkImageLayout;
|
|
regionCount:TVkUInt32;
|
|
const pRegions:PVkImageResolve);
|
|
|
|
procedure CopyBufferToImage(srcBuffer:TVkBuffer;
|
|
dstImage:TVkImage;
|
|
dstImageLayout:
|
|
TVkImageLayout;
|
|
regionCount:TVkUInt32;
|
|
const pRegions:PVkBufferImageCopy);
|
|
|
|
procedure CopyImageToBuffer(srcImage:TVkImage;
|
|
srcImageLayout:TVkImageLayout;
|
|
dstBuffer:TVkBuffer;
|
|
regionCount:TVkUInt32;
|
|
const pRegions:PVkBufferImageCopy);
|
|
|
|
procedure BufferMemoryBarrier(buffer:TVkBuffer;
|
|
srcAccessMask:TVkAccessFlags;
|
|
dstAccessMask:TVkAccessFlags;
|
|
offset,size:TVkDeviceSize;
|
|
srcStageMask:TVkPipelineStageFlags;
|
|
dstStageMask:TVkPipelineStageFlags);
|
|
|
|
Procedure InsertLabel(pLabelName:PVkChar);
|
|
Procedure BeginLabel(pLabelName:PVkChar);
|
|
Procedure EndLabel();
|
|
|
|
function FetchDescriptorCache(layout:TvPipelineLayout):PvDescriptorCache;
|
|
function FetchDescriptorCache(BindPoint:TVkPipelineBindPoint):PvDescriptorCache;
|
|
function FetchDescriptorInterface(BindPoint:TVkPipelineBindPoint):TvDescriptorInterface;
|
|
Procedure ApplyDescriptorCache(BindPoint:TVkPipelineBindPoint);
|
|
|
|
Procedure BindSets(BindPoint:TVkPipelineBindPoint;F:TvDescriptorGroup);
|
|
end;
|
|
|
|
TvCmdBuffer=class(TvCustomCmdBuffer)
|
|
|
|
FRender:TvRenderPassBeginInfo;
|
|
|
|
Femulate_primtype:SmallInt;
|
|
Fshader_primtype :SmallInt;
|
|
FinstanceCount:DWORD;
|
|
FINDEX_TYPE:TVkIndexType;
|
|
|
|
function BeginRenderPass(RT:PvRenderPassBeginInfo;GP:TvGraphicsPipeline2):Boolean;
|
|
|
|
function BindCompute(CP:TvComputePipeline2):Boolean;
|
|
|
|
Procedure dmaData1(src,dst:Pointer;byteCount:DWORD;isBlocking:Boolean);
|
|
Procedure dmaData2(src:DWORD;dst:Pointer;byteCount:DWORD;isBlocking:Boolean);
|
|
Procedure WriteEos(eventType:Byte;dst:Pointer;value:DWORD;isBlocking:Boolean);
|
|
Procedure WriteEvent(eventType:Byte);
|
|
|
|
Procedure DrawIndexOffset2(IndexBase:Pointer;indexOffset,vertexOffset,indexCount:DWORD);
|
|
Procedure DrawIndexAuto (vertexOffset,indexCount:DWORD);
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
vBuffer,
|
|
vHostBufferManager;
|
|
|
|
function TvSemaphoreWait.c(a,b:PvSemaphoreWait):Integer;
|
|
begin
|
|
Result:=Integer(Pointer(a^.FSemaphore)>Pointer(b^.FSemaphore))-Integer(Pointer(a^.FSemaphore)<Pointer(b^.FSemaphore));
|
|
end;
|
|
|
|
function t_cmd_track_deferred.c(a,b:p_cmd_track_deferred):Integer;
|
|
begin
|
|
//start
|
|
Result:=Integer(a^.start>b^.start)-Integer(a^.start<b^.start);
|
|
if (Result<>0) then Exit;
|
|
//__end
|
|
Result:=Integer(a^.__end>b^.__end)-Integer(a^.__end<b^.__end);
|
|
if (Result<>0) then Exit;
|
|
//exclude
|
|
Result:=Integer(a^.exclude>b^.exclude)-Integer(a^.exclude<b^.exclude);
|
|
if (Result<>0) then Exit;
|
|
end;
|
|
|
|
//
|
|
|
|
Constructor TvCustomCmdBuffer.Create(pool:TvCustomCmdPool;Queue:TvQueue);
|
|
begin
|
|
FParent:=pool;
|
|
FQueue:=Queue;
|
|
|
|
FFence:=TvFence.Create(False);
|
|
|
|
FSignalSemaphore:=TvSemaphore.Create;
|
|
|
|
FCBState:=cbFree;
|
|
end;
|
|
|
|
Destructor TvCustomCmdBuffer.Destroy;
|
|
begin
|
|
ReleaseResource;
|
|
|
|
FreeAndNil(FFence);
|
|
FreeAndNil(FSignalSemaphore);
|
|
|
|
if (FParent<>nil) and (FCmdbuf<>VK_NULL_HANDLE) then
|
|
begin
|
|
FParent.Free(FCmdbuf);
|
|
end;
|
|
inherited;
|
|
end;
|
|
|
|
function TvCustomCmdBuffer.AllocCmdBuffer:Boolean;
|
|
begin
|
|
if (FCmdbuf<>VK_NULL_HANDLE) then Exit(True);
|
|
|
|
FCmdbuf:=FParent.Alloc;
|
|
if (FCmdbuf=VK_NULL_HANDLE) then Exit(False);
|
|
|
|
FCBState:=cbInit;
|
|
|
|
Result:=True;
|
|
end;
|
|
|
|
Function TvCustomCmdBuffer.IsAllocated:Boolean;
|
|
begin
|
|
Result:=False;
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
Result:=(FCmdbuf<>VK_NULL_HANDLE);
|
|
end;
|
|
|
|
function TvCustomCmdBuffer.BeginCmdBuffer:Boolean;
|
|
var
|
|
r:TVkResult;
|
|
Info:TVkCommandBufferBeginInfo;
|
|
begin
|
|
Result:=False;
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (not AllocCmdBuffer) then Exit;
|
|
|
|
case FCBState of
|
|
cbInit:; //need start
|
|
cbBegin:
|
|
begin
|
|
//is started
|
|
Exit(True);
|
|
end;
|
|
else
|
|
//idk why it called in this state
|
|
Exit(False);
|
|
end;
|
|
|
|
Info:=Default(TVkCommandBufferBeginInfo);
|
|
Info.sType:=VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
|
Info.flags:=ord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
|
Info.pInheritanceInfo:=nil;
|
|
r:=vkBeginCommandBuffer(FCmdbuf,@Info);
|
|
if (r<>VK_SUCCESS) then
|
|
begin
|
|
Writeln(StdErr,'vkBeginCommandBuffer:',r);
|
|
Exit;
|
|
end;
|
|
FCBState:=cbBegin;
|
|
Result:=True;
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.EndCmdBuffer;
|
|
var
|
|
r:TVkResult;
|
|
begin
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (FCBState<>cbBegin) then Exit;
|
|
|
|
EndRenderPass;
|
|
|
|
FCurrLayout[BP_GRAPHICS]:=nil;
|
|
FCurrLayout[BP_COMPUTE ]:=nil;
|
|
|
|
FCurrBinds[BP_GRAPHICS]:=nil;
|
|
FCurrBinds[BP_COMPUTE ]:=nil;
|
|
|
|
FCurrGroup[BP_GRAPHICS]:=nil;
|
|
FCurrGroup[BP_COMPUTE ]:=nil;
|
|
|
|
FCurrPipeline[BP_GRAPHICS]:=VK_NULL_HANDLE;
|
|
FCurrPipeline[BP_COMPUTE ]:=VK_NULL_HANDLE;
|
|
|
|
r:=vkEndCommandBuffer(FCmdbuf);
|
|
if (r<>VK_SUCCESS) then
|
|
begin
|
|
Writeln(StdErr,'vkEndCommandBuffer:',r);
|
|
end;
|
|
|
|
FCBState:=cbEnd;
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.BindPipeline(BindPoint:TVkPipelineBindPoint;F:TVkPipeline);
|
|
begin
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (FCurrPipeline[BindPoint]=F) then Exit;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkCmdBindPipeline(FCmdbuf,BindPoint,F);
|
|
FCurrPipeline[BindPoint]:=F;
|
|
end;
|
|
|
|
function TvCmdBuffer.BeginRenderPass(RT:PvRenderPassBeginInfo;GP:TvGraphicsPipeline2):Boolean;
|
|
var
|
|
rinfo:TVkRenderPassBeginInfo;
|
|
ainfo:TVkRenderPassAttachmentBeginInfo;
|
|
begin
|
|
Result:=False;
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (RT=nil) then Exit;
|
|
|
|
if (RT^.FRenderPass =nil) then Exit;
|
|
if (RT^.FFramebuffer=nil) then Exit;
|
|
if (GP=nil) then Exit;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
if (FRenderPass=VK_NULL_HANDLE) or
|
|
(CompareByte(FRender,RT^,SizeOf(TvRenderPassBeginInfo))<>0) then
|
|
begin
|
|
//reset render pass
|
|
EndRenderPass;
|
|
|
|
FRender:=RT^;
|
|
|
|
rinfo:=FRender.GetRInfo;
|
|
|
|
if FRender.FFramebuffer.IsImageless then
|
|
begin
|
|
ainfo:=FRender.GetAInfo;
|
|
rinfo.pNext:=@ainfo;
|
|
end;
|
|
|
|
Inc(cmd_count);
|
|
|
|
//start render pass
|
|
vkCmdBeginRenderPass(FCmdbuf,@rinfo,VK_SUBPASS_CONTENTS_INLINE);
|
|
FRenderPass:=rinfo.renderPass;
|
|
end;
|
|
|
|
Femulate_primtype:=GP.Key.emulate_primtype;
|
|
Fshader_primtype :=GP.Key.shader_primtype;
|
|
|
|
BindPipeline(BP_GRAPHICS,GP.FHandle);
|
|
BindLayout (BP_GRAPHICS,GP.Key.FShaderGroup.FLayout);
|
|
|
|
RefTo(FRender.FRenderPass );
|
|
RefTo(FRender.FFramebuffer);
|
|
RefTo(GP);
|
|
|
|
Result:=True;
|
|
end;
|
|
|
|
Function TvCustomCmdBuffer.IsRenderPass:Boolean;
|
|
begin
|
|
Result:=False;
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
Result:=(FRenderPass<>VK_NULL_HANDLE);
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.EndRenderPass;
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (FCmdbuf=VK_NULL_HANDLE) then Exit;
|
|
if (FRenderPass<>VK_NULL_HANDLE) then
|
|
begin
|
|
Inc(cmd_count);
|
|
vkCmdEndRenderPass(FCmdbuf);
|
|
FRenderPass:=VK_NULL_HANDLE;
|
|
//
|
|
FCurrLayout[BP_GRAPHICS]:=nil;
|
|
FCurrBinds [BP_GRAPHICS]:=nil;
|
|
FCurrGroup [BP_GRAPHICS]:=nil;
|
|
//
|
|
FCurrPipeline[BP_GRAPHICS]:=VK_NULL_HANDLE;
|
|
end;
|
|
end;
|
|
|
|
function TvCustomCmdBuffer.BeforePushBarrier:TVkCommandBuffer;
|
|
begin
|
|
Result:=0;
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
EndRenderPass;
|
|
|
|
Result:=FCmdbuf;
|
|
end;
|
|
|
|
function TvCmdBuffer.BindCompute(CP:TvComputePipeline2):Boolean;
|
|
begin
|
|
Result:=False;
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (CP=nil) then Exit;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
BindPipeline(BP_COMPUTE,CP.FHandle);
|
|
BindLayout (BP_COMPUTE,CP.Key.FShaderGroup.FLayout);
|
|
|
|
RefTo(CP);
|
|
|
|
Result:=True;
|
|
end;
|
|
|
|
function TvCustomCmdBuffer.QueueSubmit:TVkResult;
|
|
var
|
|
info:TVkSubmitInfo;
|
|
|
|
FFenceHandle:TVkFence;
|
|
|
|
FHandles:array of TVkSemaphore;
|
|
FStages :array of TVkPipelineStageFlags;
|
|
|
|
i:Integer;
|
|
t:PvSemaphoreWait;
|
|
begin
|
|
Result:=VK_ERROR_UNKNOWN;
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
case FCBState of
|
|
cbFree,
|
|
cbInit:
|
|
begin
|
|
//zero cmd buffer
|
|
Exit(VK_SUCCESS);
|
|
end;
|
|
cbSubmit:
|
|
begin
|
|
//cmd buffer submitted
|
|
Exit(VK_SUCCESS);
|
|
end;
|
|
else;
|
|
end;
|
|
|
|
if (FCmdbuf=VK_NULL_HANDLE) then Exit;
|
|
|
|
EndCmdBuffer;
|
|
|
|
info:=Default(TVkSubmitInfo);
|
|
info.sType :=VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
info.commandBufferCount :=1;
|
|
info.pCommandBuffers :=@FCmdbuf;
|
|
|
|
if (FWaitSemaphoresCount<>0) then
|
|
begin
|
|
FHandles:=nil;
|
|
FStages :=nil;
|
|
SetLength(FHandles,FWaitSemaphoresCount);
|
|
SetLength(FStages ,FWaitSemaphoresCount);
|
|
|
|
i:=0;
|
|
t:=FWaitSemaphores.Min;
|
|
While (t<>nil) do
|
|
begin
|
|
FHandles[i]:=t^.FSemaphore.FHandle;
|
|
FStages [i]:=t^.FWaitStage;
|
|
Inc(i);
|
|
//
|
|
t:=FWaitSemaphores.Next(t);
|
|
end;
|
|
|
|
info.waitSemaphoreCount:=i;
|
|
info.pWaitSemaphores :=@FHandles[0];
|
|
info.pWaitDstStageMask :=@FStages[0];
|
|
|
|
end;
|
|
|
|
if (FSignalSemaphore<>nil) then
|
|
begin
|
|
info.signalSemaphoreCount:=1;
|
|
info.pSignalSemaphores :=@FSignalSemaphore.FHandle;
|
|
end;
|
|
|
|
FFenceHandle:=VK_NULL_HANDLE;
|
|
if (FFence<>nil) then
|
|
begin
|
|
FFenceHandle:=FFence.FHandle;
|
|
end;
|
|
|
|
//Writeln('vkQueueSubmit>');
|
|
|
|
Result:=FQueue.Submit(1,@info,FFenceHandle);
|
|
|
|
//Writeln('vkQueueSubmit<');
|
|
|
|
ret:=Integer(Result);
|
|
if (Result<>VK_SUCCESS) then
|
|
begin
|
|
Writeln(StdErr,'vkQueueSubmit:',Result);
|
|
end;
|
|
|
|
FCBState:=cbSubmit;
|
|
end;
|
|
|
|
function TvCustomCmdBuffer.Wait(timeout:TVkUInt64):TVkResult;
|
|
begin
|
|
Result:=VK_ERROR_UNKNOWN;
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (FFence=nil) then Exit;
|
|
|
|
case FCBState of
|
|
cbFree,
|
|
cbInit:
|
|
begin
|
|
//zero cmd buffer
|
|
Exit(VK_SUCCESS);
|
|
end;
|
|
cbSubmit:
|
|
begin
|
|
//cmd buffer submitted
|
|
Result:=FFence.Wait(timeout);
|
|
end;
|
|
else
|
|
//idk why it called in this state
|
|
Exit(VK_ERROR_UNKNOWN);
|
|
end;
|
|
|
|
end;
|
|
|
|
function TvCustomCmdBuffer.Status:TVkResult;
|
|
begin
|
|
Result:=VK_ERROR_UNKNOWN;
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (FFence=nil) then Exit;
|
|
|
|
case FCBState of
|
|
cbFree,
|
|
cbInit:
|
|
begin
|
|
//zero cmd buffer
|
|
Exit(VK_SUCCESS);
|
|
end;
|
|
cbSubmit:
|
|
begin
|
|
//cmd buffer submitted
|
|
Result:=FFence.Status;
|
|
end;
|
|
else
|
|
//idk why it called in this state
|
|
Exit(VK_ERROR_UNKNOWN);
|
|
end;
|
|
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.ReleaseResource;
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
ReleaseAllDependencies(Self);
|
|
|
|
ReleaseAllPlannedTriggers;
|
|
|
|
FreeAllDescriptorCache;
|
|
|
|
FreeAllSemaphores;
|
|
|
|
cmd_count:=0;
|
|
ret:=0;
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.FreeAllSemaphores;
|
|
var
|
|
node:PvSemaphoreWait;
|
|
begin
|
|
if IsLinearAlloc then
|
|
begin
|
|
FWaitSemaphores:=Default(TvSemaphoreWaitSet);
|
|
end else
|
|
begin
|
|
node:=FWaitSemaphores.Min;
|
|
|
|
while (node<>nil) do
|
|
begin
|
|
FWaitSemaphores.delete(node);
|
|
OnFree(node);
|
|
|
|
node:=FWaitSemaphores.Min;
|
|
end;
|
|
end;
|
|
|
|
FWaitSemaphoresCount:=0;
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.AddWaitSemaphore(S:TvSemaphore;W:TVkPipelineStageFlags);
|
|
Var
|
|
node:PvSemaphoreWait;
|
|
begin
|
|
if (S=nil) then Exit;
|
|
|
|
node:=FWaitSemaphores.Find(@S);
|
|
|
|
if (node=nil) then
|
|
begin
|
|
node:=OnAlloc(SizeOf(TvSemaphoreWait));
|
|
node^.FSemaphore:=S;
|
|
node^.FWaitStage:=W;
|
|
//
|
|
FWaitSemaphores.Insert(node);
|
|
//
|
|
Inc(FWaitSemaphoresCount);
|
|
end;
|
|
|
|
end;
|
|
|
|
function TvCustomCmdBuffer.GetSignaledSemaphore:TvSemaphore;
|
|
begin
|
|
Result:=FSignalSemaphore;
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.ReleaseAllPlannedTriggers;
|
|
var
|
|
node:p_cmd_track_deferred;
|
|
begin
|
|
node:=FPlannedTriggers.Min;
|
|
|
|
while (node<>nil) do
|
|
begin
|
|
|
|
//deffered trigger
|
|
vm_map_track_trigger(p_proc.p_vmspace,node^.start,node^.__end,node^.exclude,M_GPU_APPLY);
|
|
|
|
if IsLinearAlloc then
|
|
begin
|
|
node:=FPlannedTriggers.Next(node);
|
|
end else
|
|
begin
|
|
FPlannedTriggers.delete(node);
|
|
OnFree(node);
|
|
//
|
|
node:=FPlannedTriggers.Min;
|
|
end;
|
|
|
|
end;
|
|
|
|
if IsLinearAlloc then
|
|
begin
|
|
FPlannedTriggers:=Default(t_cmd_track_deferred_set);
|
|
end;
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.AddPlannedTrigger(start,__end:QWORD;exclude:Pointer);
|
|
Var
|
|
tmp:t_cmd_track_deferred;
|
|
node:p_cmd_track_deferred;
|
|
begin
|
|
//planned trigger
|
|
vm_map_track_trigger(p_proc.p_vmspace,start,__end,exclude,M_GPU_PLANNED);
|
|
|
|
tmp:=Default(t_cmd_track_deferred);
|
|
tmp.start :=start;
|
|
tmp. __end :=__end;
|
|
tmp.exclude:=exclude;
|
|
|
|
node:=FPlannedTriggers.Find(@tmp);
|
|
|
|
if (node=nil) then
|
|
begin
|
|
node:=OnAlloc(SizeOf(t_cmd_track_deferred));
|
|
node^:=tmp;
|
|
//
|
|
FPlannedTriggers.Insert(node);
|
|
end;
|
|
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.FreeAllDescriptorCache;
|
|
var
|
|
node:PvDescriptorCache;
|
|
begin
|
|
if IsLinearAlloc then
|
|
begin
|
|
FDescriptorCacheSet:=Default(TvDescriptorCacheSet);
|
|
end else
|
|
begin
|
|
node:=FDescriptorCacheSet.Min;
|
|
|
|
while (node<>nil) do
|
|
begin
|
|
FDescriptorCacheSet.delete(node);
|
|
OnFree(node);
|
|
|
|
node:=FDescriptorCacheSet.Min;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.BindLayout(BindPoint:TVkPipelineBindPoint;F:TvPipelineLayout);
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (F=nil) then Exit;
|
|
|
|
if (FCurrLayout[BindPoint]<>F) then
|
|
begin
|
|
FCurrLayout[BindPoint]:=F;
|
|
FCurrBinds [BindPoint]:=nil;
|
|
FCurrGroup [BindPoint]:=nil;
|
|
end;
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.BindSet(BindPoint:TVkPipelineBindPoint;fset:TVkUInt32;FHandle:TVkDescriptorSet);
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (FHandle=VK_NULL_HANDLE) then Exit;
|
|
if (FCurrLayout[BindPoint]=nil) then Exit;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkCmdBindDescriptorSets(FCmdbuf,
|
|
BindPoint,
|
|
FCurrLayout[BindPoint].FHandle,
|
|
fset,1,
|
|
@FHandle,
|
|
0,nil);
|
|
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.PushConstant(BindPoint:TVkPipelineBindPoint;stageFlags:TVkShaderStageFlags;offset,size:TVkUInt32;const pValues:PVkVoid);
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (pValues=nil) or (size=0) then Exit;
|
|
if (FCurrLayout[BindPoint]=nil) then Exit;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkCmdPushConstants(FCmdbuf,
|
|
FCurrLayout[BindPoint].FHandle,
|
|
stageFlags,
|
|
offset,size,
|
|
pValues);
|
|
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.DispatchDirect(X,Y,Z:TVkUInt32);
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (FCurrPipeline[BP_COMPUTE]=VK_NULL_HANDLE) then Exit;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
ApplyDescriptorCache(BP_COMPUTE);
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkCmdDispatch(FCmdbuf,X,Y,Z);
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.BindVertexBuffers(const FAttrBuilder:TvAttrBuilder);
|
|
var
|
|
i,c:Integer;
|
|
|
|
rb:TvHostBuffer;
|
|
|
|
Buffers:array[0..31] of TVkBuffer;
|
|
Offsets:array[0..31] of TVkDeviceSize;
|
|
|
|
last_binding:TVkUInt32;
|
|
last_size :TVkUInt32;
|
|
|
|
diff:TVkDeviceSize;
|
|
begin
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
c:=FAttrBuilder.FBindDescsCount;
|
|
if (c=0) then Exit;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
rb:=nil;
|
|
last_binding:=0;
|
|
last_size :=0;
|
|
For i:=0 to c-1 do
|
|
With FAttrBuilder.FBindVBufs[i] do
|
|
begin
|
|
|
|
rb:=FetchHostBuffer(Self,QWORD(min_addr),GetSize);
|
|
|
|
if (last_binding<>binding) then
|
|
begin
|
|
//flush
|
|
if (last_size<>0) then
|
|
begin
|
|
vkCmdBindVertexBuffers(FCmdbuf,last_binding,last_size,@Buffers,@Offsets);
|
|
last_size:=0;
|
|
end;
|
|
//
|
|
last_binding:=binding;
|
|
end;
|
|
|
|
diff:=QWORD(min_addr)-rb.FAddr;
|
|
|
|
Buffers[last_size]:=rb.FHandle;
|
|
Offsets[last_size]:=diff;
|
|
|
|
Inc(last_size);
|
|
end;
|
|
|
|
//flush
|
|
if (last_size<>0) then
|
|
begin
|
|
vkCmdBindVertexBuffers(FCmdbuf,last_binding,last_size,@Buffers,@Offsets);
|
|
end;
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.SetVertexInput(const FAttrBuilder:TvAttrBuilder);
|
|
var
|
|
input:TvVertexInputEXT;
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if not limits.VK_EXT_vertex_input_dynamic_state then Exit;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
FAttrBuilder.Export2(input);
|
|
|
|
if (vkCmdSetVertexInputEXT=nil) then
|
|
begin
|
|
TPFN_vkVoidFunction(vkCmdSetVertexInputEXT):=vkGetInstanceProcAddr(VulkanApp.FInstance,'vkCmdSetVertexInputEXT');
|
|
end;
|
|
|
|
vkCmdSetVertexInputEXT(FCmdbuf,
|
|
input.vertexBindingDescriptionCount,
|
|
@input.VertexBindingDescriptions[0],
|
|
input.vertexAttributeDescriptionCount,
|
|
@input.VertexAttributeDescriptions[0]);
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.ClearDepthStencilImage(image:TVkImage;
|
|
imageLayout:TVkImageLayout;
|
|
const pDepthStencil:PVkClearDepthStencilValue;
|
|
rangeCount:TVkUInt32;
|
|
const pRanges:PVkImageSubresourceRange);
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
EndRenderPass;
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkCmdClearDepthStencilImage(
|
|
FCmdbuf,
|
|
image,
|
|
imageLayout,
|
|
pDepthStencil,
|
|
rangeCount,
|
|
pRanges);
|
|
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.ClearDepthStencilImage(image:TVkImage;
|
|
imageLayout:TVkImageLayout;
|
|
const pDepthStencil:PVkClearDepthStencilValue;
|
|
const range:TVkImageSubresourceRange);
|
|
begin
|
|
ClearDepthStencilImage(image,
|
|
imageLayout,
|
|
pDepthStencil,
|
|
1,
|
|
@range);
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.ClearColorImage(image:TVkImage;
|
|
imageLayout:TVkImageLayout;
|
|
const pColor:PVkClearColorValue;
|
|
rangeCount:TVkUInt32;
|
|
const pRanges:PVkImageSubresourceRange);
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
EndRenderPass;
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkCmdClearColorImage(
|
|
FCmdbuf,
|
|
image,
|
|
imageLayout,
|
|
pColor,
|
|
rangeCount,
|
|
pRanges);
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.ResolveImage(srcImage:TVkImage;
|
|
srcImageLayout:TVkImageLayout;
|
|
dstImage:TVkImage;
|
|
dstImageLayout:TVkImageLayout;
|
|
regionCount:TVkUInt32;
|
|
const pRegions:PVkImageResolve);
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
EndRenderPass;
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkCmdResolveImage(
|
|
FCmdbuf,
|
|
srcImage,
|
|
srcImageLayout,
|
|
dstImage,
|
|
dstImageLayout,
|
|
regionCount,
|
|
pRegions);
|
|
end;
|
|
|
|
procedure TvCustomCmdBuffer.CopyBufferToImage(srcBuffer:TVkBuffer;
|
|
dstImage:TVkImage;
|
|
dstImageLayout:
|
|
TVkImageLayout;
|
|
regionCount:TVkUInt32;
|
|
const pRegions:PVkBufferImageCopy);
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
EndRenderPass;
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkCmdCopyBufferToImage(
|
|
FCmdbuf,
|
|
srcBuffer,
|
|
dstImage,
|
|
dstImageLayout,
|
|
regionCount,
|
|
pRegions);
|
|
end;
|
|
|
|
procedure TvCustomCmdBuffer.CopyImageToBuffer(srcImage:TVkImage;
|
|
srcImageLayout:TVkImageLayout;
|
|
dstBuffer:TVkBuffer;
|
|
regionCount:TVkUInt32;
|
|
const pRegions:PVkBufferImageCopy);
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
EndRenderPass;
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkCmdCopyImageToBuffer(
|
|
FCmdbuf,
|
|
srcImage,
|
|
srcImageLayout,
|
|
dstBuffer,
|
|
regionCount,
|
|
pRegions);
|
|
end;
|
|
|
|
procedure TvCustomCmdBuffer.BufferMemoryBarrier(buffer:TVkBuffer;
|
|
srcAccessMask:TVkAccessFlags;
|
|
dstAccessMask:TVkAccessFlags;
|
|
offset,size:TVkDeviceSize;
|
|
srcStageMask:TVkPipelineStageFlags;
|
|
dstStageMask:TVkPipelineStageFlags);
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkBufferMemoryBarrier(FCmdbuf,
|
|
buffer,
|
|
srcAccessMask,
|
|
dstAccessMask,
|
|
offset,size,
|
|
srcStageMask,
|
|
dstStageMask);
|
|
end;
|
|
|
|
Const
|
|
VK_ACCESS_ANY=
|
|
ord(VK_ACCESS_INDIRECT_COMMAND_READ_BIT ) or
|
|
ord(VK_ACCESS_INDEX_READ_BIT ) or
|
|
ord(VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT ) or
|
|
ord(VK_ACCESS_UNIFORM_READ_BIT ) or
|
|
ord(VK_ACCESS_INPUT_ATTACHMENT_READ_BIT ) or
|
|
ord(VK_ACCESS_SHADER_READ_BIT ) or
|
|
ord(VK_ACCESS_SHADER_WRITE_BIT ) or
|
|
ord(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT ) or
|
|
ord(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ) or
|
|
ord(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT ) or
|
|
ord(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT) or
|
|
ord(VK_ACCESS_TRANSFER_READ_BIT ) or
|
|
ord(VK_ACCESS_TRANSFER_WRITE_BIT ) or
|
|
ord(VK_ACCESS_HOST_READ_BIT ) or
|
|
ord(VK_ACCESS_HOST_WRITE_BIT ) or
|
|
ord(VK_ACCESS_MEMORY_READ_BIT ) or
|
|
ord(VK_ACCESS_MEMORY_WRITE_BIT );
|
|
|
|
Procedure TvCmdBuffer.dmaData1(src,dst:Pointer;byteCount:DWORD;isBlocking:Boolean);
|
|
var
|
|
srcb,dstb:TvHostBuffer;
|
|
info:TVkBufferCopy;
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
EndRenderPass;
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
DebugReport.CmdBeginLabel(FCmdbuf,'dmaData');
|
|
|
|
srcb:=FetchHostBuffer(Self,QWORD(src),byteCount);
|
|
Assert(srcb<>nil);
|
|
|
|
dstb:=FetchHostBuffer(Self,QWORD(dst),byteCount);
|
|
Assert(dstb<>nil);
|
|
|
|
info:=Default(TVkBufferCopy);
|
|
info.srcOffset:=QWORD(src)-srcb.FAddr;
|
|
info.dstOffset:=QWORD(dst)-dstb.FAddr;
|
|
info.size :=byteCount;
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkBufferMemoryBarrier(FCmdbuf,
|
|
srcb.FHandle,
|
|
VK_ACCESS_ANY,
|
|
ord(VK_ACCESS_TRANSFER_READ_BIT),
|
|
info.srcOffset,byteCount,
|
|
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT),
|
|
ord(VK_PIPELINE_STAGE_TRANSFER_BIT));
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkBufferMemoryBarrier(FCmdbuf,
|
|
dstb.FHandle,
|
|
VK_ACCESS_ANY,
|
|
ord(VK_ACCESS_TRANSFER_WRITE_BIT),
|
|
info.dstOffset,byteCount,
|
|
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT),
|
|
ord(VK_PIPELINE_STAGE_TRANSFER_BIT));
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkCmdCopyBuffer(FCmdbuf,
|
|
srcb.FHandle,
|
|
dstb.FHandle,
|
|
1,@info);
|
|
|
|
if isBlocking then
|
|
begin
|
|
Inc(cmd_count);
|
|
|
|
vkMemoryBarrier(FCmdbuf,
|
|
ord(VK_ACCESS_TRANSFER_WRITE_BIT), //srcAccessMask
|
|
VK_ACCESS_ANY, //dstAccessMask
|
|
ord(VK_PIPELINE_STAGE_TRANSFER_BIT), //srcStageMask
|
|
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)); //dstStageMask
|
|
end;
|
|
|
|
DebugReport.CmdEndLabel(FCmdbuf);
|
|
|
|
AddPlannedTrigger(QWORD(dst),QWORD(dst)+byteCount,nil);
|
|
end;
|
|
|
|
Procedure TvCmdBuffer.dmaData2(src:DWORD;dst:Pointer;byteCount:DWORD;isBlocking:Boolean);
|
|
var
|
|
dstb:TvHostBuffer;
|
|
dstOffset:TVkDeviceSize;
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
byteCount:=byteCount and (not 3); //4 byte align
|
|
|
|
EndRenderPass;
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
DebugReport.CmdBeginLabel(FCmdbuf,'dmaData');
|
|
|
|
dstb:=FetchHostBuffer(Self,QWORD(dst),byteCount);
|
|
Assert(dstb<>nil);
|
|
|
|
dstOffset:=QWORD(dst)-dstb.FAddr;
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkBufferMemoryBarrier(FCmdbuf,
|
|
dstb.FHandle,
|
|
VK_ACCESS_ANY,
|
|
ord(VK_ACCESS_TRANSFER_WRITE_BIT),
|
|
dstOffset,byteCount,
|
|
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT),
|
|
ord(VK_PIPELINE_STAGE_TRANSFER_BIT));
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkCmdFillBuffer(FCmdbuf,
|
|
dstb.FHandle,
|
|
dstOffset,
|
|
byteCount,
|
|
src);
|
|
|
|
if isBlocking then
|
|
begin
|
|
Inc(cmd_count);
|
|
|
|
vkMemoryBarrier(FCmdbuf,
|
|
ord(VK_ACCESS_TRANSFER_WRITE_BIT), //srcAccessMask
|
|
VK_ACCESS_ANY, //dstAccessMask
|
|
ord(VK_PIPELINE_STAGE_TRANSFER_BIT), //srcStageMask
|
|
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)); //dstStageMask
|
|
end;
|
|
|
|
DebugReport.CmdEndLabel(FCmdbuf);
|
|
|
|
AddPlannedTrigger(QWORD(dst),QWORD(dst)+byteCount,nil);
|
|
end;
|
|
|
|
const
|
|
VK_ACCESS_CS=
|
|
ord(VK_ACCESS_UNIFORM_READ_BIT) or
|
|
ord(VK_ACCESS_SHADER_READ_BIT ) or
|
|
ord(VK_ACCESS_SHADER_WRITE_BIT);
|
|
|
|
VK_ACCESS_PS=
|
|
ord(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT ) or
|
|
ord(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
|
|
|
|
Procedure TvCmdBuffer.WriteEos(eventType:Byte;dst:Pointer;value:DWORD;isBlocking:Boolean);
|
|
var
|
|
rb:TvHostBuffer;
|
|
BufOffset:TVkDeviceSize;
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
EndRenderPass;
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
DebugReport.CmdBeginLabel(FCmdbuf,'WriteEos');
|
|
|
|
Case eventType of
|
|
CS_DONE:
|
|
begin
|
|
Inc(cmd_count);
|
|
|
|
DebugReport.CmdInsertLabel(FCmdbuf,'CS_DONE');
|
|
|
|
vkMemoryBarrier(FCmdbuf,
|
|
VK_ACCESS_CS, //srcAccessMask
|
|
ord(VK_ACCESS_TRANSFER_WRITE_BIT), //dstAccessMask
|
|
ord(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT), //srcStageMask
|
|
ord(VK_PIPELINE_STAGE_TRANSFER_BIT)); //dstStageMask
|
|
end;
|
|
PS_DONE:
|
|
begin
|
|
Inc(cmd_count);
|
|
|
|
DebugReport.CmdInsertLabel(FCmdbuf,'PS_DONE');
|
|
|
|
vkMemoryBarrier(FCmdbuf,
|
|
VK_ACCESS_PS, //srcAccessMask
|
|
ord(VK_ACCESS_TRANSFER_WRITE_BIT), //dstAccessMask
|
|
ord(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT), //srcStageMask
|
|
ord(VK_PIPELINE_STAGE_TRANSFER_BIT)); //dstStageMask
|
|
end;
|
|
else
|
|
Assert(false,'WriteEos.eventType');
|
|
end;
|
|
|
|
rb:=FetchHostBuffer(Self,QWORD(dst),4);
|
|
Assert(rb<>nil);
|
|
|
|
BufOffset:=QWORD(dst)-rb.FAddr;
|
|
|
|
Inc(cmd_count);
|
|
|
|
vkCmdFillBuffer(FCmdbuf,
|
|
rb.FHandle,
|
|
BufOffset,
|
|
4,value);
|
|
|
|
if isBlocking then
|
|
begin
|
|
Inc(cmd_count);
|
|
|
|
vkMemoryBarrier(FCmdbuf,
|
|
ord(VK_ACCESS_TRANSFER_WRITE_BIT), //srcAccessMask
|
|
VK_ACCESS_ANY, //dstAccessMask
|
|
ord(VK_PIPELINE_STAGE_TRANSFER_BIT), //srcStageMask
|
|
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)); //dstStageMask
|
|
end;
|
|
|
|
DebugReport.CmdEndLabel(FCmdbuf);
|
|
|
|
AddPlannedTrigger(QWORD(dst),QWORD(dst)+4,nil);
|
|
end;
|
|
|
|
const
|
|
VK_ACCESS_DB=
|
|
ord(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT ) or
|
|
ord(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
|
|
|
|
VK_STAGE_DB=
|
|
ord(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) or
|
|
ord(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT) or
|
|
ord(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
|
|
|
|
Procedure TvCmdBuffer.WriteEvent(eventType:Byte);
|
|
begin
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
EndRenderPass;
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
Case eventType of
|
|
CS_PARTIAL_FLUSH:
|
|
begin
|
|
Inc(cmd_count);
|
|
|
|
DebugReport.CmdInsertLabel(FCmdbuf,'CS_PARTIAL_FLUSH');
|
|
|
|
vkMemoryBarrier(FCmdbuf,
|
|
VK_ACCESS_CS, //srcAccessMask
|
|
VK_ACCESS_ANY, //dstAccessMask
|
|
ord(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT), //srcStageMask
|
|
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)); //dstStageMask
|
|
end;
|
|
DB_CACHE_FLUSH_AND_INV: //DB
|
|
begin
|
|
Inc(cmd_count);
|
|
|
|
DebugReport.CmdInsertLabel(FCmdbuf,'DB_CACHE_FLUSH_AND_INV');
|
|
|
|
vkMemoryBarrier(FCmdbuf,
|
|
VK_ACCESS_DB, //srcAccessMask
|
|
VK_ACCESS_ANY, //dstAccessMask
|
|
VK_STAGE_DB, //srcStageMask
|
|
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)); //dstStageMask
|
|
|
|
end;
|
|
|
|
FLUSH_AND_INV_DB_META: //HTILE
|
|
begin
|
|
Inc(cmd_count);
|
|
|
|
DebugReport.CmdInsertLabel(FCmdbuf,'FLUSH_AND_INV_DB_META');
|
|
|
|
vkMemoryBarrier(FCmdbuf,
|
|
VK_ACCESS_DB, //srcAccessMask
|
|
VK_ACCESS_ANY, //dstAccessMask
|
|
VK_STAGE_DB, //srcStageMask
|
|
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)); //dstStageMask
|
|
|
|
end;
|
|
FLUSH_AND_INV_CB_META: //CMASK
|
|
begin
|
|
Inc(cmd_count);
|
|
|
|
DebugReport.CmdInsertLabel(FCmdbuf,'FLUSH_AND_INV_CB_META');
|
|
|
|
vkMemoryBarrier(FCmdbuf,
|
|
VK_ACCESS_PS, //srcAccessMask
|
|
ord(VK_ACCESS_TRANSFER_WRITE_BIT), //dstAccessMask
|
|
ord(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT), //srcStageMask
|
|
ord(VK_PIPELINE_STAGE_TRANSFER_BIT)); //dstStageMask
|
|
|
|
end;
|
|
FLUSH_AND_INV_CB_PIXEL_DATA: //CB
|
|
begin
|
|
Inc(cmd_count);
|
|
|
|
DebugReport.CmdInsertLabel(FCmdbuf,'FLUSH_AND_INV_CB_PIXEL_DATA');
|
|
|
|
vkMemoryBarrier(FCmdbuf,
|
|
VK_ACCESS_PS, //srcAccessMask
|
|
ord(VK_ACCESS_TRANSFER_WRITE_BIT), //dstAccessMask
|
|
ord(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT), //srcStageMask
|
|
ord(VK_PIPELINE_STAGE_TRANSFER_BIT)); //dstStageMask
|
|
|
|
end;
|
|
CACHE_FLUSH_AND_INV_EVENT: //CB,DB
|
|
begin
|
|
Inc(cmd_count);
|
|
|
|
vkMemoryBarrier(FCmdbuf,
|
|
VK_ACCESS_PS or VK_ACCESS_DB, //srcAccessMask
|
|
VK_ACCESS_ANY, //dstAccessMask
|
|
VK_STAGE_DB or ord(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT), //srcStageMask
|
|
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)); //dstStageMask
|
|
end;
|
|
else
|
|
Assert(false,'WriteEvent.eventType');
|
|
end;
|
|
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.InsertLabel(pLabelName:PVkChar);
|
|
begin
|
|
if (Self=nil) then Exit;
|
|
if (DebugReport.FCmdInsertDebugUtilsLabel=nil) then Exit;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
DebugReport.CmdInsertLabel(FCmdbuf,pLabelName);
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.BeginLabel(pLabelName:PVkChar);
|
|
begin
|
|
if (Self=nil) then Exit;
|
|
if (DebugReport.FCmdBeginDebugUtilsLabel=nil) then Exit;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
DebugReport.CmdBeginLabel(FCmdbuf,pLabelName);
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.EndLabel();
|
|
begin
|
|
if (Self=nil) then Exit;
|
|
|
|
if (not IsAllocated) then Exit;
|
|
|
|
DebugReport.CmdEndLabel(FCmdbuf);
|
|
end;
|
|
|
|
function GET_INDEX_TYPE_SIZE(INDEX_TYPE:TVkIndexType):Byte; inline;
|
|
const
|
|
_s:array[0..1] of Byte=(2,4);
|
|
begin
|
|
Result:=_s[ord(INDEX_TYPE) and 1];
|
|
end;
|
|
|
|
Procedure TvCmdBuffer.DrawIndexOffset2(IndexBase:Pointer;indexOffset,vertexOffset,indexCount:DWORD);
|
|
var
|
|
rb:TvHostBuffer;
|
|
Size:TVkDeviceSize;
|
|
BufOffset:TVkDeviceSize;
|
|
i,h:DWORD;
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (FRenderPass=VK_NULL_HANDLE) then Exit;
|
|
if (FCurrPipeline[BP_GRAPHICS]=VK_NULL_HANDLE) then Exit;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
ApplyDescriptorCache(BP_GRAPHICS);
|
|
|
|
if (FinstanceCount=0) then FinstanceCount:=1;
|
|
|
|
Size:=(indexOffset+indexCount)*GET_INDEX_TYPE_SIZE(FINDEX_TYPE);
|
|
|
|
rb:=FetchHostBuffer(Self,QWORD(IndexBase),Size);
|
|
Assert(rb<>nil);
|
|
|
|
Inc(cmd_count);
|
|
|
|
BufOffset:=QWORD(IndexBase)-rb.FAddr;
|
|
|
|
vkCmdBindIndexBuffer(
|
|
Fcmdbuf,
|
|
rb.FHandle,
|
|
BufOffset,
|
|
FINDEX_TYPE);
|
|
|
|
Inc(cmd_count);
|
|
|
|
Case Femulate_primtype of
|
|
0:
|
|
begin
|
|
vkCmdDrawIndexed(
|
|
Fcmdbuf,
|
|
indexCount, //indexCount
|
|
FinstanceCount, //instanceCount
|
|
indexOffset, //firstIndex
|
|
vertexOffset, //vertexOffset
|
|
0); //firstInstance
|
|
end;
|
|
DI_PT_QUADLIST:
|
|
begin
|
|
InsertLabel('DI_PT_QUADLIST');
|
|
|
|
Assert(FinstanceCount<=1,'instance DI_PT_QUADLIST');
|
|
|
|
h:=indexCount div 4;
|
|
if (h>0) then h:=h-1;
|
|
For i:=0 to h do
|
|
begin
|
|
vkCmdDrawIndexed(
|
|
Fcmdbuf,
|
|
4, //indexCount
|
|
1, //instanceCount
|
|
indexOffset+i*4, //firstIndex
|
|
vertexOffset, //vertexOffset
|
|
0); //firstInstance
|
|
end;
|
|
end;
|
|
else
|
|
Assert(false,'TODO');
|
|
end;
|
|
|
|
end;
|
|
|
|
Procedure TvCmdBuffer.DrawIndexAuto(vertexOffset,indexCount:DWORD);
|
|
var
|
|
i,h:DWORD;
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (FRenderPass=VK_NULL_HANDLE) then Exit;
|
|
if (FCurrPipeline[BP_GRAPHICS]=VK_NULL_HANDLE) then Exit;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
ApplyDescriptorCache(BP_GRAPHICS);
|
|
|
|
if (FinstanceCount=0) then FinstanceCount:=1;
|
|
|
|
Case Femulate_primtype of
|
|
0:
|
|
begin
|
|
Inc(cmd_count);
|
|
vkCmdDraw(
|
|
FCmdbuf,
|
|
indexCount, //vertexCount
|
|
FinstanceCount, //instanceCount
|
|
vertexOffset, //firstVertex
|
|
0); //firstInstance
|
|
end;
|
|
|
|
DI_PT_RECTLIST:
|
|
begin
|
|
InsertLabel('DI_PT_RECTLIST');
|
|
|
|
Assert(FinstanceCount<=1,'instance DI_PT_RECTLIST');
|
|
{
|
|
VK_EXT_primitive_topology_list_restart ???
|
|
|
|
0 3
|
|
1 2
|
|
}
|
|
//0 1 2
|
|
//0 2 3
|
|
|
|
if (Fshader_primtype=-1) then
|
|
begin
|
|
|
|
h:=indexCount div 3;
|
|
if (h>0) then h:=h-1;
|
|
For i:=0 to h do
|
|
begin
|
|
Inc(cmd_count);
|
|
vkCmdDraw(
|
|
FCmdbuf,
|
|
4, //vertexCount
|
|
1, //instanceCount
|
|
vertexOffset+i*3, //firstVertex
|
|
0); //firstInstance
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
//geom shader emulate
|
|
|
|
Inc(cmd_count);
|
|
vkCmdDraw(
|
|
FCmdbuf,
|
|
indexCount, //vertexCount
|
|
FinstanceCount, //instanceCount
|
|
vertexOffset, //firstVertex
|
|
0); //firstInstance
|
|
end;
|
|
|
|
end;
|
|
//DI_PT_LINELOOP :;
|
|
DI_PT_QUADLIST:
|
|
begin
|
|
InsertLabel('DI_PT_QUADLIST');
|
|
|
|
Assert(FinstanceCount<=1,'instance DI_PT_QUADLIST');
|
|
|
|
h:=indexCount div 4;
|
|
if (h>0) then h:=h-1;
|
|
For i:=0 to h do
|
|
begin
|
|
Inc(cmd_count);
|
|
vkCmdDraw(
|
|
FCmdbuf,
|
|
4, //vertexCount
|
|
1, //instanceCount
|
|
vertexOffset+i*4, //firstVertex
|
|
0); //firstInstance
|
|
end;
|
|
end;
|
|
//DI_PT_QUADSTRIP:;
|
|
//DI_PT_POLYGON :;
|
|
else
|
|
begin
|
|
Assert(false,'TODO');
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
//
|
|
|
|
function TvCustomCmdBuffer.FetchDescriptorCache(layout:TvPipelineLayout):PvDescriptorCache;
|
|
begin
|
|
Result:=FDescriptorCacheSet.Find(@layout);
|
|
|
|
if (Result=nil) then
|
|
begin
|
|
Result:=AllocDescriptorCache(Self,layout);
|
|
FDescriptorCacheSet.Insert(Result);
|
|
end;
|
|
end;
|
|
|
|
function TvCustomCmdBuffer.FetchDescriptorCache(BindPoint:TVkPipelineBindPoint):PvDescriptorCache;
|
|
begin
|
|
Result:=nil;
|
|
|
|
if (FCurrLayout[BindPoint]=nil) then Exit;
|
|
|
|
Result:=FCurrBinds[BindPoint];
|
|
|
|
if (Result=nil) then
|
|
begin
|
|
Result:=FetchDescriptorCache(FCurrLayout[BindPoint]);
|
|
//
|
|
FCurrBinds[BindPoint]:=Result;
|
|
//
|
|
Result^.SetAllChange;
|
|
end;
|
|
end;
|
|
|
|
function TvCustomCmdBuffer.FetchDescriptorInterface(BindPoint:TVkPipelineBindPoint):TvDescriptorInterface;
|
|
begin
|
|
Result:=Default(TvDescriptorInterface);
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
Result:=TvDescriptorInterface(FetchDescriptorCache(BindPoint));
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.ApplyDescriptorCache(BindPoint:TVkPipelineBindPoint);
|
|
var
|
|
Cache:PvDescriptorCache;
|
|
Group:TvDescriptorGroup;
|
|
begin
|
|
if (FCurrLayout[BindPoint]=nil) then Exit;
|
|
|
|
Cache:=FCurrBinds[BindPoint];
|
|
if (Cache=nil) then Exit;
|
|
|
|
if (Cache^.p_count_all=0) then Exit; //no sets
|
|
|
|
Group:=FCurrGroup[BindPoint];
|
|
|
|
if (Cache^.p_change_any) or
|
|
(Group=nil) then
|
|
begin
|
|
Group:=FetchDescriptorGroup(Self,FCurrLayout[BindPoint]);
|
|
//
|
|
FCurrGroup[BindPoint]:=Group;
|
|
//
|
|
Group.Bind(Cache);
|
|
//
|
|
BindSets(BindPoint,Group);
|
|
//
|
|
Cache^.ClearAllChange;
|
|
end;
|
|
|
|
//VK_KHR_push_descriptor vkCmdPushDescriptorSetKHR TODO
|
|
end;
|
|
|
|
Procedure TvCustomCmdBuffer.BindSets(BindPoint:TVkPipelineBindPoint;F:TvDescriptorGroup);
|
|
var
|
|
A:array[0..6] of TVkDescriptorSet;
|
|
i,start,pos:Integer;
|
|
|
|
procedure Flush; inline;
|
|
begin
|
|
Inc(cmd_count);
|
|
|
|
vkCmdBindDescriptorSets(FCmdbuf,
|
|
BindPoint,
|
|
FCurrLayout[BindPoint].FHandle,
|
|
start,pos,
|
|
@A[0],
|
|
0,nil);
|
|
|
|
pos:=0;
|
|
end;
|
|
|
|
begin
|
|
|
|
if (Self=nil) then
|
|
begin
|
|
Writeln(stderr,'Self=nil,',{$I %LINE%});
|
|
Exit;
|
|
end;
|
|
|
|
if (F=nil) then Exit;
|
|
if (FCurrLayout[BindPoint]=nil) then Exit;
|
|
if (Length(F.FSets)=0) then Exit;
|
|
|
|
if (not BeginCmdBuffer) then Exit;
|
|
|
|
pos:=0;
|
|
|
|
For i:=0 to High(F.FSets) do
|
|
begin
|
|
if F.FSets[i].IsValid then
|
|
begin
|
|
|
|
if (pos=0) then
|
|
begin
|
|
start:=i;
|
|
end;
|
|
|
|
A[pos]:=F.FSets[i].FHandle;
|
|
Inc(pos);
|
|
|
|
if (pos=7) then
|
|
begin
|
|
Flush;
|
|
end;
|
|
|
|
end else
|
|
if (pos<>0) then
|
|
begin
|
|
Flush;
|
|
end;
|
|
end;
|
|
|
|
if (pos<>0) then
|
|
begin
|
|
Flush;
|
|
end;
|
|
end;
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
end.
|
|
|
|
|
|
|
|
|