FPPS4/vulkan/vCmdBuffer.pas

987 lines
23 KiB
Plaintext

unit vCmdBuffer;
{$mode objfpc}{$H+}
interface
uses
Classes,
SysUtils,
//ps4_types,
g23tree,
//ps4_libSceVideoOut,
si_ci_vi_merged_enum,
Vulkan,
vDependence,
vDevice,
vMemory,
//vShader,
vShaderExt,
vImage,
vPipeline,
//vSetsPools,
vRender;
type
TvCmdBuffer=class;
TvSemaphoreWait=record
FSemaphore:TvSemaphore;
FWaitStage:TVkPipelineStageFlags;
end;
TvSemaphoreWaitCompare=object
function c(a,b:TvSemaphoreWait):Integer; static;
end;
TvSemaphoreWaitSet=specialize T23treeSet<TvSemaphoreWait,TvSemaphoreWaitCompare>;
TvCustomCmdBuffer=class(TvDependenciesObject)
FRefs :ptruint;
FParent:TvCmdPool;
FQueue :TvQueue;
FCmdbuf:TVkCommandBuffer;
cmd_count:qword;
ret:Integer;
submit_id:ptruint;
FCurrPipeline:array[0..1] of TVkPipeline;
FCurrLayout :array[0..1] of TVkPipelineLayout;
FRenderPass:TVkRenderPass;
FWaitSemaphores:TvSemaphoreWaitSet;
FSignalSemaphore:TvSemaphore;
FFence:TvFence;
FCBState:Boolean;
Constructor Create(pool:TvCmdPool;Queue:TvQueue);
Destructor Destroy; override;
Procedure Acquire;
procedure Release;
procedure OnReleaseCmd(Sender:TObject);
function BeginCmdBuffer:Boolean;
Procedure EndCmdBuffer;
Procedure BindPipeline(BindPoint:TVkPipelineBindPoint;F:TVkPipeline);
Function IsRenderPass:Boolean;
Procedure EndRenderPass;
function QueueSubmit:TVkResult;
function Wait(timeout:TVkUInt64):TVkResult;
Procedure ReleaseResource;
Procedure AddWaitSemaphore(S:TvSemaphore;W:TVkPipelineStageFlags);
function GetSignaledSemaphore:TvSemaphore;
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 SetVertexInput(const FAttrBuilder:TvAttrBuilder);
Procedure BindVertexBuffer(Binding:TVkUInt32;
Buffer:TVkBuffer;
Offset:TVkDeviceSize);
Procedure ClearDepthStencilImage(
image:TVkImage;
imageLayout:TVkImageLayout;
const pDepthStencil:PVkClearDepthStencilValue;
rangeCount:TVkUInt32;
const pRanges:PVkImageSubresourceRange);
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);
end;
TvCmdBuffer=class(TvCustomCmdBuffer)
emulate_primtype:Integer;
instanceCount:DWORD;
function BeginRenderPass(RT:TvRenderTargets):Boolean;
function BindCompute(CP:TvComputePipeline2):Boolean;
Procedure BindSets(BindPoint:TVkPipelineBindPoint;F:TvDescriptorGroup);
//Procedure dmaData(src,dst:Pointer;byteCount:DWORD;isBlocking:Boolean);
//Procedure dmaData(src:DWORD;dst:Pointer;byteCount:DWORD;isBlocking:Boolean);
//Procedure writeAtEndOfShader(eventType:Byte;dst:Pointer;value:DWORD);
Procedure DrawIndexOffset2(Addr:Pointer;OFFSET,INDICES:DWORD;INDEX_TYPE:TVkIndexType);
Procedure DrawIndex2(Addr:Pointer;INDICES:DWORD;INDEX_TYPE:TVkIndexType);
Procedure DrawIndexAuto(INDICES:DWORD);
end;
implementation
uses
vBuffer,
vHostBufferManager;
function TvSemaphoreWaitCompare.c(a,b:TvSemaphoreWait):Integer;
begin
Result:=Integer(Pointer(a.FSemaphore)>Pointer(b.FSemaphore))-Integer(Pointer(a.FSemaphore)<Pointer(b.FSemaphore));
end;
Constructor TvCustomCmdBuffer.Create(pool:TvCmdPool;Queue:TvQueue);
begin
FParent:=pool;
FQueue:=Queue;
FCmdbuf:=pool.Alloc;
if (FCmdbuf=VK_NULL_HANDLE) then Exit;
FFence:=TvFence.Create(true);
FFence.Reset;
FSignalSemaphore:=TvSemaphore.Create;
FCBState:=False;
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;
Procedure TvCustomCmdBuffer.Acquire;
begin
System.InterlockedIncrement(Pointer(FRefs));
end;
procedure TvCustomCmdBuffer.Release;
begin
if System.InterlockedDecrement(Pointer(FRefs))=nil then
begin
Free;
end;
end;
procedure TvCustomCmdBuffer.OnReleaseCmd(Sender:TObject);
begin
Release;
end;
function TvCustomCmdBuffer.BeginCmdBuffer:Boolean;
var
r:TVkResult;
Info:TVkCommandBufferBeginInfo;
begin
Result:=False;
if (Self=nil) then Exit;
if FCBState then Exit(True);
if (FCmdbuf=VK_NULL_HANDLE) then Exit;
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:=True;
Result:=True;
end;
Procedure TvCustomCmdBuffer.EndCmdBuffer;
var
r:TVkResult;
begin
if (Self=nil) then Exit;
if FCBState then
begin
EndRenderPass;
FCurrLayout[0]:=VK_NULL_HANDLE;
FCurrLayout[1]:=VK_NULL_HANDLE;
FCurrPipeline[0]:=VK_NULL_HANDLE;
FCurrPipeline[1]:=VK_NULL_HANDLE;
r:=vkEndCommandBuffer(FCmdbuf);
if (r<>VK_SUCCESS) then
begin
Writeln(StdErr,'vkEndCommandBuffer:',r);
end;
FCBState:=False;
end;
end;
Procedure TvCustomCmdBuffer.BindPipeline(BindPoint:TVkPipelineBindPoint;F:TVkPipeline);
begin
if (Self=nil) then Exit;
if (FCurrPipeline[ord(BindPoint)]=F) then Exit;
if (not BeginCmdBuffer) then Exit;
Inc(cmd_count);
vkCmdBindPipeline(FCmdbuf,BindPoint,F);
FCurrPipeline[ord(BindPoint)]:=F;
end;
function TvCmdBuffer.BeginRenderPass(RT:TvRenderTargets):Boolean;
var
rinfo:TVkRenderPassBeginInfo;
ainfo:TVkRenderPassAttachmentBeginInfo;
begin
Result:=False;
if (Self=nil) then Exit;
if (RT=nil) then
begin
EndRenderPass;
Exit(True);
end;
if (RT.FRenderPass=nil) then Exit;
if (RT.FPipeline=nil) then Exit;
if (RT.FFramebuffer=nil) then Exit;
//if (not RT.FRenderPass.Compile) then Exit;
//if (not RT.FPipeline.Compile) then Exit;
//if (not RT.FFramebuffer.Compile) then Exit;
if (RT.FRenderPass.FHandle=FRenderPass) then Exit(True);
if (not BeginCmdBuffer) then Exit;
EndRenderPass;
rinfo:=RT.GetRInfo;
if RT.FFramebuffer.IsImageless then
begin
ainfo:=RT.GetAInfo;
rinfo.pNext:=@ainfo;
end;
FCurrPipeline[0]:=RT.FPipeline.FHandle;
FCurrLayout [0]:=RT.FPipeline.Key.FShaderGroup.FLayout.FHandle;
emulate_primtype:=RT.FPipeline.Key.emulate_primtype;
Inc(cmd_count);
vkCmdBeginRenderPass(FCmdbuf,@rinfo,VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline (FCmdbuf,VK_PIPELINE_BIND_POINT_GRAPHICS,FCurrPipeline[0]);
if AddDependence(@RT.Release) then
begin
RT.Acquire(Self);
end;
FRenderPass:=rinfo.renderPass;
Result:=True;
end;
Function TvCustomCmdBuffer.IsRenderPass:Boolean;
begin
Result:=False;
if (Self=nil) then Exit;
Result:=(FRenderPass<>VK_NULL_HANDLE);
end;
Procedure TvCustomCmdBuffer.EndRenderPass;
begin
if (Self=nil) then Exit;
if (FCmdbuf=VK_NULL_HANDLE) then Exit;
if (FRenderPass<>VK_NULL_HANDLE) then
begin
Inc(cmd_count);
vkCmdEndRenderPass(FCmdbuf);
FRenderPass:=VK_NULL_HANDLE;
end;
end;
function TvCmdBuffer.BindCompute(CP:TvComputePipeline2):Boolean;
begin
Result:=False;
if (Self=nil) or (CP=nil) then Exit;
BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE,CP.FHandle);
BindLayout (VK_PIPELINE_BIND_POINT_COMPUTE,CP.FLayout);
if AddDependence(@CP.Release) then
begin
CP.Acquire(Self);
end;
Result:=True;
end;
function TvCustomCmdBuffer.QueueSubmit:TVkResult;
var
info:TVkSubmitInfo;
FFenceHandle:TVkFence;
FHandles:array of TVkSemaphore;
FStages :array of TVkPipelineStageFlags;
i:Integer;
t:TvSemaphoreWaitSet.Iterator;
begin
Result:=VK_ERROR_UNKNOWN;
if (Self=nil) then Exit;
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 (FWaitSemaphores.Size<>0) then
begin
FHandles:=nil;
FStages :=nil;
SetLength(FHandles,FWaitSemaphores.Size);
SetLength(FStages ,FWaitSemaphores.Size);
i:=0;
t:=FWaitSemaphores.cbegin;
While (t.Item<>nil) do
begin
FHandles[i]:=t.Item^.FSemaphore.FHandle;
FStages [i]:=t.Item^.FWaitStage;
Inc(i);
t.Next;
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;
Result:=FQueue.Submit(1,@info,FFenceHandle);
ret:=Integer(Result);
if (Result<>VK_SUCCESS) then
begin
Writeln(StdErr,'vkQueueSubmit:',Result);
end;
end;
function TvCustomCmdBuffer.Wait(timeout:TVkUInt64):TVkResult;
begin
Result:=VK_ERROR_UNKNOWN;
if (Self=nil) then Exit;
if (FFence=nil) then Exit;
Result:=FFence.Wait(timeout);
end;
Procedure TvCustomCmdBuffer.ReleaseResource;
begin
if (Self=nil) then Exit;
ReleaseAllDependencies(Self);
FWaitSemaphores.Free;
cmd_count:=0;
ret:=0;
end;
Procedure TvCustomCmdBuffer.AddWaitSemaphore(S:TvSemaphore;W:TVkPipelineStageFlags);
Var
I:TvSemaphoreWaitSet.Iterator;
F:TvSemaphoreWait;
begin
if (S=nil) then Exit;
F:=Default(TvSemaphoreWait);
F.FSemaphore:=S;
F.FWaitStage:=W;
I:=FWaitSemaphores.find(F);
if (i.Item<>nil) then
begin
i.Item^.FWaitStage:=i.Item^.FWaitStage or W;
end else
begin
FWaitSemaphores.Insert(F);
end;
end;
function TvCustomCmdBuffer.GetSignaledSemaphore:TvSemaphore;
begin
Result:=FSignalSemaphore;
end;
Procedure TvCustomCmdBuffer.BindLayout(BindPoint:TVkPipelineBindPoint;F:TvPipelineLayout);
begin
if (Self=nil) then Exit;
if (F=nil) then Exit;
FCurrLayout[ord(BindPoint)]:=F.FHandle;
end;
Procedure TvCustomCmdBuffer.BindSet(BindPoint:TVkPipelineBindPoint;fset:TVkUInt32;FHandle:TVkDescriptorSet);
begin
if (Self=nil) then Exit;
if (FHandle=VK_NULL_HANDLE) then Exit;
if (FCmdbuf=VK_NULL_HANDLE) then Exit;
if (FCurrLayout[ord(BindPoint)]=VK_NULL_HANDLE) then Exit;
Inc(cmd_count);
vkCmdBindDescriptorSets(FCmdbuf,
BindPoint,
FCurrLayout[ord(BindPoint)],
fset,1,
@FHandle,
0,nil);
end;
Procedure TvCustomCmdBuffer.PushConstant(BindPoint:TVkPipelineBindPoint;stageFlags:TVkShaderStageFlags;offset,size:TVkUInt32;const pValues:PVkVoid);
begin
if (Self=nil) then Exit;
if (pValues=nil) or (size=0) then Exit;
if (FCurrLayout[ord(BindPoint)]=VK_NULL_HANDLE) then Exit;
if (not BeginCmdBuffer) then Exit;
Inc(cmd_count);
vkCmdPushConstants(FCmdbuf,
FCurrLayout[ord(BindPoint)],
stageFlags,
offset,size,
pValues);
end;
Procedure TvCustomCmdBuffer.DispatchDirect(X,Y,Z:TVkUInt32);
begin
if (Self=nil) then Exit;
if (FCurrPipeline[1]=VK_NULL_HANDLE) then Exit;
if (not BeginCmdBuffer) then Exit;
Inc(cmd_count);
vkCmdDispatch(FCmdbuf,X,Y,Z);
end;
Procedure TvCustomCmdBuffer.SetVertexInput(const FAttrBuilder:TvAttrBuilder);
var
input:TvVertexInputEXT;
begin
if (Self=nil) then Exit;
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.BindVertexBuffer(Binding:TVkUInt32;
Buffer:TVkBuffer;
Offset:TVkDeviceSize);
begin
if (Self=nil) then Exit;
if (not BeginCmdBuffer) then Exit;
vkCmdBindVertexBuffer(FCmdbuf,
binding,
Buffer,
Offset);
end;
Procedure TvCustomCmdBuffer.ClearDepthStencilImage(
image:TVkImage;
imageLayout:TVkImageLayout;
const pDepthStencil:PVkClearDepthStencilValue;
rangeCount:TVkUInt32;
const pRanges:PVkImageSubresourceRange);
begin
if (Self=nil) then Exit;
EndRenderPass;
if (not BeginCmdBuffer) then Exit;
Inc(cmd_count);
vkCmdClearDepthStencilImage(
FCmdbuf,
image,
imageLayout,
pDepthStencil,
rangeCount,
pRanges);
end;
Procedure TvCustomCmdBuffer.ClearColorImage(
image:TVkImage;
imageLayout:TVkImageLayout;
const pColor:PVkClearColorValue;
rangeCount:TVkUInt32;
const pRanges:PVkImageSubresourceRange);
begin
if (Self=nil) then Exit;
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 Exit;
EndRenderPass;
if (not BeginCmdBuffer) then Exit;
Inc(cmd_count);
vkCmdResolveImage(
FCmdbuf,
srcImage,
srcImageLayout,
dstImage,
dstImageLayout,
regionCount,
pRegions);
end;
Procedure TvCmdBuffer.BindSets(BindPoint:TVkPipelineBindPoint;F:TvDescriptorGroup);
var
i:Integer;
begin
if (F=nil) then Exit;
if (Self=nil) then Exit;
if (FCmdbuf=VK_NULL_HANDLE) then Exit;
if (FCurrLayout[ord(BindPoint)]=VK_NULL_HANDLE) then Exit;
if (Length(F.FSets)=0) then Exit;
For i:=0 to High(F.FSets) do
if F.FSets[i].IsValid then
begin
Inc(cmd_count);
vkCmdBindDescriptorSets(FCmdbuf,
BindPoint,
FCurrLayout[ord(BindPoint)],
i,1,
@F.FSets[i].FHandle,
0,nil);
end;
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.dmaData(src,dst:Pointer;byteCount:DWORD;isBlocking:Boolean);
var
srcb,dstb:TvHostBuffer;
info:TVkBufferCopy;
begin
if (Self=nil) then Exit;
EndRenderPass;
if (not BeginCmdBuffer) then Exit;
srcb:=FetchHostBuffer(Self,src,byteCount,ord(VK_BUFFER_USAGE_TRANSFER_SRC_BIT));
Assert(srcb<>nil);
if (srcb.Foffset+byteCount>srcb.FSize) then
begin
Assert(False,'FetchHostBuffer:Insufficient buffer size!');
end;
dstb:=FetchHostBuffer(Self,dst,byteCount,ord(VK_BUFFER_USAGE_TRANSFER_DST_BIT));
Assert(dstb<>nil);
if (dstb.Foffset+byteCount>dstb.FSize) then
begin
Assert(False,'FetchHostBuffer:Insufficient buffer size!');
end;
Inc(cmd_count);
vkBufferMemoryBarrier(cmdbuf,
srcb.FHandle,
VK_ACCESS_ANY,
ord(VK_ACCESS_TRANSFER_READ_BIT),
srcb.Foffset,byteCount,
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT),
ord(VK_PIPELINE_STAGE_TRANSFER_BIT));
Inc(cmd_count);
vkBufferMemoryBarrier(cmdbuf,
dstb.FHandle,
VK_ACCESS_ANY,
ord(VK_ACCESS_TRANSFER_WRITE_BIT),
dstb.Foffset,byteCount,
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT),
ord(VK_PIPELINE_STAGE_TRANSFER_BIT));
info:=Default(TVkBufferCopy);
info.srcOffset:=srcb.Foffset;
info.dstOffset:=dstb.Foffset;
info.size :=byteCount;
Inc(cmd_count);
vkCmdCopyBuffer(cmdbuf,
srcb.FHandle,
dstb.FHandle,
1,@info);
if isBlocking then
begin
Inc(cmd_count);
vkBarrier(cmdbuf,
ord(VK_PIPELINE_STAGE_TRANSFER_BIT),
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT));
end;
end;
Procedure TvCmdBuffer.dmaData(src:DWORD;dst:Pointer;byteCount:DWORD;isBlocking:Boolean);
var
dstb:TvHostBuffer;
begin
if (Self=nil) then Exit;
byteCount:=byteCount and (not 3); //4 byte align
EndRenderPass;
if (not BeginCmdBuffer) then Exit;
dstb:=FetchHostBuffer(Self,dst,byteCount,ord(VK_BUFFER_USAGE_TRANSFER_DST_BIT));
Assert(dstb<>nil);
Inc(cmd_count);
vkBufferMemoryBarrier(cmdbuf,
dstb.FHandle,
VK_ACCESS_ANY,
ord(VK_ACCESS_TRANSFER_WRITE_BIT),
dstb.Foffset,byteCount,
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT),
ord(VK_PIPELINE_STAGE_TRANSFER_BIT));
Inc(cmd_count);
vkCmdFillBuffer(cmdbuf,
dstb.FHandle,
dstb.Foffset,
byteCount,src);
if isBlocking then
begin
Inc(cmd_count);
vkBarrier(cmdbuf,
ord(VK_PIPELINE_STAGE_TRANSFER_BIT),
ord(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT));
end;
end;
Procedure TvCmdBuffer.writeAtEndOfShader(eventType:Byte;dst:Pointer;value:DWORD);
var
rb:TvHostBuffer;
begin
if (Self=nil) then Exit;
EndRenderPass;
if (not BeginCmdBuffer) then Exit;
Case eventType of
CS_DONE:
begin
Inc(cmd_count);
vkBarrier(cmdbuf,
ord(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT),
ord(VK_PIPELINE_STAGE_TRANSFER_BIT));
rb:=FetchHostBuffer(Self,dst,4,ord(VK_BUFFER_USAGE_TRANSFER_DST_BIT));
Assert(rb<>nil);
Inc(cmd_count);
vkCmdFillBuffer(cmdbuf,
rb.FHandle,
rb.Foffset,
4,value);
end;
PS_DONE:
begin
Inc(cmd_count);
vkBarrier(cmdbuf,
ord(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT),
ord(VK_PIPELINE_STAGE_TRANSFER_BIT));
rb:=FetchHostBuffer(Self,dst,4,ord(VK_BUFFER_USAGE_TRANSFER_DST_BIT));
Assert(rb<>nil);
Inc(cmd_count);
vkCmdFillBuffer(cmdbuf,
rb.FHandle,
rb.Foffset,
4,value);
end;
else
Assert(False);
end;
end;
}
function GET_INDEX_TYPE_SIZE(INDEX_TYPE:TVkIndexType):Byte;
begin
Case INDEX_TYPE of
VK_INDEX_TYPE_UINT16 :Result:=16;
VK_INDEX_TYPE_UINT32 :Result:=32;
VK_INDEX_TYPE_UINT8_EXT:Result:=8;
else Result:=0;
end;
end;
Procedure TvCmdBuffer.DrawIndexOffset2(Addr:Pointer;OFFSET,INDICES:DWORD;INDEX_TYPE:TVkIndexType);
var
rb:TvHostBuffer;
Size:TVkDeviceSize;
BufOffset:TVkDeviceSize;
i,h:DWORD;
begin
if (Self=nil) then Exit;
if (FCmdbuf=VK_NULL_HANDLE) then Exit;
if (FRenderPass=VK_NULL_HANDLE) then Exit;
if (FCurrPipeline[0]=VK_NULL_HANDLE) then Exit;
if (instanceCount=0) then instanceCount:=1;
Size:=(OFFSET+INDICES)*GET_INDEX_TYPE_SIZE(INDEX_TYPE);
rb:=FetchHostBuffer(Self,QWORD(Addr),Size,ord(VK_BUFFER_USAGE_INDEX_BUFFER_BIT));
Assert(rb<>nil);
Inc(cmd_count);
BufOffset:=QWORD(Addr)-rb.FAddr;
vkCmdBindIndexBuffer(
Fcmdbuf,
rb.FHandle,
BufOffset,
INDEX_TYPE);
Inc(cmd_count);
Case emulate_primtype of
0:
begin
vkCmdDrawIndexed(
Fcmdbuf,
INDICES, //indexCount
instanceCount, //instanceCount
OFFSET, //firstIndex
0, //vertexOffset
0); //firstInstance
end;
DI_PT_QUADLIST:
begin
Assert(instanceCount<=1,'instance DI_PT_QUADLIST');
Assert(OFFSET=0,'OFFSET DI_PT_QUADLIST');
h:=INDICES div 4;
if (h>0) then h:=h-1;
For i:=0 to h do
begin
vkCmdDrawIndexed(
Fcmdbuf,
4, //indexCount
1, //instanceCount
i*4, //firstIndex
0, //vertexOffset
0); //firstInstance
end;
end;
else
Assert(false,'TODO');
end;
end;
Procedure TvCmdBuffer.DrawIndex2(Addr:Pointer;INDICES:DWORD;INDEX_TYPE:TVkIndexType);
begin
DrawIndexOffset2(Addr,0,INDICES,INDEX_TYPE);
end;
Procedure TvCmdBuffer.DrawIndexAuto(INDICES:DWORD);
var
i,h:DWORD;
begin
if (Self=nil) then Exit;
if (FCmdbuf=VK_NULL_HANDLE) then Exit;
if (FRenderPass=VK_NULL_HANDLE) then Exit;
if (FCurrPipeline[0]=VK_NULL_HANDLE) then Exit;
if (instanceCount=0) then instanceCount:=1;
Case emulate_primtype of
0:
begin
vkCmdDraw(
FCmdbuf,
INDICES, //vertexCount
instanceCount, //instanceCount
0, //firstVertex
0); //firstInstance
end;
DI_PT_RECTLIST :
begin
Assert(instanceCount<=1,'instance DI_PT_RECTLIST');
{
0 3
1 2
}
//0 1 2
//0 2 3
h:=INDICES 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
0, //firstVertex
0); //firstInstance
end;
end;
//DI_PT_LINELOOP :;
DI_PT_QUADLIST :
begin
Assert(instanceCount<=1,'instance DI_PT_QUADLIST');
h:=INDICES 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
i*4, //firstVertex
0); //firstInstance
end;
end;
//DI_PT_QUADSTRIP:;
//DI_PT_POLYGON :;
else
begin
Assert(false,'TODO');
end;
end;
end;
end.