mirror of https://github.com/red-prig/fpPS4.git
398 lines
8.5 KiB
Plaintext
398 lines
8.5 KiB
Plaintext
unit vRenderPassManager;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils,
|
|
g23tree,
|
|
Vulkan,
|
|
vDevice,
|
|
vDependence,
|
|
vPipeline,
|
|
vImage{,
|
|
vCmdBuffer};
|
|
|
|
type
|
|
PvRenderPassKey=^TvRenderPassKey;
|
|
TvRenderPassKey=packed object
|
|
AtdCount:Byte;
|
|
RefCount:Byte; //VkSubpassDescription.colorAttachmentCount
|
|
DepCount:Byte; //DepthRef
|
|
_align:Byte;
|
|
ColorAtd:array[0..8] of TVkAttachmentDescription;
|
|
ColorRef:array[0..7] of TVkAttachmentReference;
|
|
DepthRef:TVkAttachmentReference;
|
|
Dependency:TVkSubpassDependency;
|
|
Procedure Clear;
|
|
Procedure SetZorderStage(s:TVkPipelineStageFlags);
|
|
Procedure _AddColorRef(id:TVkUInt32;IMAGE_USAGE:Byte);
|
|
Procedure _SetDepthRef(id:TVkUInt32;DEPTH_USAGE,STENCIL_USAGE:Byte);
|
|
Procedure AddColorAt(id:TVkUInt32;aformat:TVkFormat;IMAGE_USAGE,asamples:Byte);
|
|
Procedure AddDepthAt(id:TVkUInt32;aformat:TVkFormat;DEPTH_USAGE,STENCIL_USAGE,asamples:Byte);
|
|
end;
|
|
|
|
TvRenderPass2=class(TvRenderPass)
|
|
Key:TvRenderPassKey;
|
|
//
|
|
Function Compile:Boolean;
|
|
end;
|
|
|
|
function FetchRenderPass(cmd:TvDependenciesObject;P:PvRenderPassKey):TvRenderPass2;
|
|
|
|
implementation
|
|
|
|
uses
|
|
kern_rwlock;
|
|
|
|
type
|
|
TvRenderPassKey2Compare=object
|
|
function c(a,b:PvRenderPassKey):Integer; static;
|
|
end;
|
|
|
|
_TvRenderPass2Set=specialize T23treeSet<PvRenderPassKey,TvRenderPassKey2Compare>;
|
|
TvRenderPass2Set=object(_TvRenderPass2Set)
|
|
lock:Pointer;
|
|
Procedure Lock_wr;
|
|
Procedure Unlock_wr;
|
|
end;
|
|
|
|
var
|
|
FRenderPass2Set:TvRenderPass2Set;
|
|
|
|
function TvRenderPassKey2Compare.c(a,b:PvRenderPassKey):Integer;
|
|
begin
|
|
Result:=CompareByte(a^,b^,SizeOf(TvRenderPassKey));
|
|
end;
|
|
|
|
Procedure TvRenderPass2Set.Lock_wr;
|
|
begin
|
|
rw_wlock(lock);
|
|
end;
|
|
|
|
Procedure TvRenderPass2Set.Unlock_wr;
|
|
begin
|
|
rw_wunlock(lock);
|
|
end;
|
|
|
|
//
|
|
|
|
Procedure TvRenderPassKey.Clear;
|
|
begin
|
|
Self:=Default(TvRenderPassKey);
|
|
Dependency.srcSubpass:=VK_SUBPASS_EXTERNAL;
|
|
end;
|
|
|
|
Procedure TvRenderPassKey.SetZorderStage(s:TVkPipelineStageFlags);
|
|
begin
|
|
Dependency.srcStageMask:=Dependency.srcStageMask or s;
|
|
Dependency.dstStageMask:=Dependency.dstStageMask or s;
|
|
end;
|
|
|
|
Procedure TvRenderPassKey._AddColorRef(id:TVkUInt32;IMAGE_USAGE:Byte);
|
|
var
|
|
am:TVkAccessFlags;
|
|
begin
|
|
if (RefCount>7) then Exit;
|
|
|
|
if (id<>VK_ATTACHMENT_UNUSED) then
|
|
begin
|
|
with ColorRef[RefCount] do
|
|
begin
|
|
attachment:=id;
|
|
layout:=GetColorSendLayout(IMAGE_USAGE);
|
|
end;
|
|
end else
|
|
begin
|
|
with ColorRef[RefCount] do
|
|
begin
|
|
attachment:=VK_ATTACHMENT_UNUSED;
|
|
layout:=VK_IMAGE_LAYOUT_GENERAL;
|
|
end;
|
|
end;
|
|
|
|
Inc(RefCount);
|
|
|
|
//add on unused also
|
|
Dependency.srcStageMask :=Dependency.srcStageMask or ord(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
|
Dependency.dstStageMask :=Dependency.dstStageMask or ord(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
|
|
|
if (id<>VK_ATTACHMENT_UNUSED) then
|
|
begin
|
|
am:=GetColorAccessAttachMask(IMAGE_USAGE);
|
|
|
|
Dependency.srcAccessMask:=Dependency.srcAccessMask or am;
|
|
Dependency.dstAccessMask:=Dependency.dstAccessMask or am;
|
|
end;
|
|
end;
|
|
|
|
Procedure TvRenderPassKey._SetDepthRef(id:TVkUInt32;DEPTH_USAGE,STENCIL_USAGE:Byte);
|
|
var
|
|
am:TVkAccessFlags;
|
|
begin
|
|
DepCount:=1;
|
|
|
|
DepthRef.attachment:=id;
|
|
DepthRef.layout :=GetDepthStencilSendLayout(DEPTH_USAGE,STENCIL_USAGE);
|
|
|
|
am:=GetDepthStencilAccessAttachMask(DEPTH_USAGE,STENCIL_USAGE);
|
|
|
|
Dependency.srcAccessMask:=Dependency.srcAccessMask or am;
|
|
Dependency.dstAccessMask:=Dependency.dstAccessMask or am;
|
|
end;
|
|
|
|
Procedure TvRenderPassKey.AddColorAt(id:TVkUInt32;aformat:TVkFormat;IMAGE_USAGE,asamples:Byte);
|
|
begin
|
|
if (AtdCount>8) then Exit;
|
|
|
|
if (aformat=VK_FORMAT_R10G11B11_UFLOAT_FAKE32) then
|
|
begin
|
|
aformat:=VK_FORMAT_B10G11R11_UFLOAT_PACK32;
|
|
end;
|
|
|
|
ColorAtd[AtdCount]:=Default(TVkAttachmentDescription);
|
|
|
|
With ColorAtd[AtdCount] do
|
|
begin
|
|
format :=aformat;
|
|
samples:=TVkSampleCountFlagBits(asamples);
|
|
|
|
stencilLoadOp :=VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
stencilStoreOp:=VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
end;
|
|
|
|
if (id<>VK_ATTACHMENT_UNUSED) then
|
|
begin
|
|
With ColorAtd[AtdCount] do
|
|
if ((IMAGE_USAGE and TM_CLEAR)<>0) then
|
|
begin
|
|
loadOp:=VK_ATTACHMENT_LOAD_OP_CLEAR;
|
|
end else
|
|
if ((IMAGE_USAGE and TM_READ)<>0) then
|
|
begin
|
|
loadOp:=VK_ATTACHMENT_LOAD_OP_LOAD;
|
|
end else
|
|
begin
|
|
loadOp:=VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
end;
|
|
|
|
With ColorAtd[AtdCount] do
|
|
if ((IMAGE_USAGE and TM_WRITE)<>0) then
|
|
begin
|
|
storeOp:=VK_ATTACHMENT_STORE_OP_STORE;
|
|
end else
|
|
begin
|
|
storeOp:=VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
end;
|
|
|
|
With ColorAtd[AtdCount] do
|
|
if ((IMAGE_USAGE and TM_READ)<>0) then
|
|
begin
|
|
initialLayout:=GetColorSendLayout(IMAGE_USAGE);
|
|
end else
|
|
begin
|
|
initialLayout:=VK_IMAGE_LAYOUT_UNDEFINED;
|
|
end;
|
|
|
|
With ColorAtd[AtdCount] do
|
|
begin
|
|
finalLayout:=GetColorSendLayout(IMAGE_USAGE);
|
|
end;
|
|
end else
|
|
begin
|
|
With ColorAtd[AtdCount] do
|
|
begin
|
|
loadOp :=VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
storeOp:=VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
|
|
initialLayout:=VK_IMAGE_LAYOUT_UNDEFINED;
|
|
finalLayout :=VK_IMAGE_LAYOUT_GENERAL;
|
|
end;
|
|
end;
|
|
|
|
Inc(AtdCount);
|
|
|
|
_AddColorRef(id,IMAGE_USAGE);
|
|
end;
|
|
|
|
Procedure TvRenderPassKey.AddDepthAt(id:TVkUInt32;aformat:TVkFormat;DEPTH_USAGE,STENCIL_USAGE,asamples:Byte);
|
|
begin
|
|
if (AtdCount>8) then Exit;
|
|
|
|
ColorAtd[AtdCount]:=Default(TVkAttachmentDescription);
|
|
|
|
With ColorAtd[AtdCount] do
|
|
begin
|
|
format :=aformat;
|
|
samples:=TVkSampleCountFlagBits(asamples);
|
|
end;
|
|
|
|
With ColorAtd[AtdCount] do
|
|
if ((DEPTH_USAGE and TM_CLEAR)<>0) then
|
|
begin
|
|
loadOp:=VK_ATTACHMENT_LOAD_OP_CLEAR;
|
|
end else
|
|
if ((DEPTH_USAGE and TM_READ)<>0) then
|
|
begin
|
|
loadOp:=VK_ATTACHMENT_LOAD_OP_LOAD;
|
|
end else
|
|
begin
|
|
loadOp:=VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
end;
|
|
|
|
With ColorAtd[AtdCount] do
|
|
if ((DEPTH_USAGE and TM_WRITE)<>0) then
|
|
begin
|
|
storeOp:=VK_ATTACHMENT_STORE_OP_STORE;
|
|
end else
|
|
begin
|
|
storeOp:=VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
end;
|
|
|
|
With ColorAtd[AtdCount] do
|
|
if ((STENCIL_USAGE and TM_CLEAR)<>0) then
|
|
begin
|
|
stencilLoadOp:=VK_ATTACHMENT_LOAD_OP_CLEAR;
|
|
end else
|
|
if ((STENCIL_USAGE and TM_READ)<>0) then
|
|
begin
|
|
stencilLoadOp:=VK_ATTACHMENT_LOAD_OP_LOAD;
|
|
end else
|
|
begin
|
|
stencilLoadOp:=VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
end;
|
|
|
|
With ColorAtd[AtdCount] do
|
|
if ((STENCIL_USAGE and TM_WRITE)<>0) then
|
|
begin
|
|
stencilStoreOp:=VK_ATTACHMENT_STORE_OP_STORE;
|
|
end else
|
|
begin
|
|
stencilStoreOp:=VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
end;
|
|
|
|
With ColorAtd[AtdCount] do
|
|
begin
|
|
initialLayout:=GetDepthStencilInitLayout(DEPTH_USAGE,STENCIL_USAGE);
|
|
end;
|
|
|
|
With ColorAtd[AtdCount] do
|
|
begin
|
|
finalLayout:=GetDepthStencilSendLayout(DEPTH_USAGE,STENCIL_USAGE);
|
|
end;
|
|
|
|
Inc(AtdCount);
|
|
|
|
_SetDepthRef(id,DEPTH_USAGE,STENCIL_USAGE);
|
|
end;
|
|
|
|
///
|
|
|
|
Function TvRenderPass2.Compile:Boolean;
|
|
var
|
|
r:TVkResult;
|
|
subpass:TVkSubpassDescription;
|
|
info:TVkRenderPassCreateInfo;
|
|
begin
|
|
Result:=False;
|
|
if (Key.AtdCount=0) and (Key.DepCount=0) then Exit;
|
|
|
|
if (FHandle<>VK_NULL_HANDLE) then Exit(True);
|
|
|
|
subpass:=Default(TVkSubpassDescription);
|
|
subpass.pipelineBindPoint:=VK_PIPELINE_BIND_POINT_GRAPHICS;
|
|
|
|
subpass.inputAttachmentCount :=0;
|
|
subpass.pInputAttachments :=nil;
|
|
|
|
subpass.colorAttachmentCount :=Key.RefCount;
|
|
subpass.pColorAttachments :=@Key.ColorRef;
|
|
|
|
subpass.pResolveAttachments :=nil; //colorAttachmentCount VK_ATTACHMENT_UNUSED
|
|
|
|
if (Key.DepCount<>0) then
|
|
begin
|
|
subpass.pDepthStencilAttachment:=@Key.DepthRef; //1
|
|
end;
|
|
|
|
subpass.preserveAttachmentCount:=0;
|
|
subpass.pPreserveAttachments :=nil;
|
|
|
|
info:=Default(TVkRenderPassCreateInfo);
|
|
info.sType :=VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
|
info.attachmentCount:=Key.AtdCount;
|
|
info.pAttachments :=@Key.ColorAtd;
|
|
info.subpassCount :=1;
|
|
info.pSubpasses :=@subpass;
|
|
info.dependencyCount:=1;
|
|
info.pDependencies :=@Key.Dependency;
|
|
|
|
r:=vkCreateRenderPass(Device.FHandle,@info,nil,@FHandle);
|
|
if (r<>VK_SUCCESS) then
|
|
begin
|
|
Writeln(StdErr,'vkCreateRenderPass:',r);
|
|
Exit;
|
|
end;
|
|
|
|
Result:=True;
|
|
end;
|
|
|
|
function _Find(P:PvRenderPassKey):TvRenderPass2;
|
|
var
|
|
i:TvRenderPass2Set.Iterator;
|
|
begin
|
|
Result:=nil;
|
|
i:=FRenderPass2Set.find(P);
|
|
if (i.Item<>nil) then
|
|
begin
|
|
Result:=TvRenderPass2(ptruint(i.Item^)-ptruint(@TvRenderPass2(nil).key));
|
|
end;
|
|
end;
|
|
|
|
function _FetchRenderPass(P:PvRenderPassKey):TvRenderPass2;
|
|
var
|
|
t:TvRenderPass2;
|
|
begin
|
|
Result:=nil;
|
|
|
|
t:=_Find(P);
|
|
|
|
if (t=nil) then
|
|
begin
|
|
|
|
t:=TvRenderPass2.Create;
|
|
t.key:=P^;
|
|
|
|
if not t.Compile then
|
|
begin
|
|
FreeAndNil(t);
|
|
end else
|
|
begin
|
|
t.Acquire(nil); //map ref
|
|
FRenderPass2Set.Insert(@t.key);
|
|
end;
|
|
end;
|
|
|
|
Result:=t;
|
|
end;
|
|
|
|
function FetchRenderPass(cmd:TvDependenciesObject;P:PvRenderPassKey):TvRenderPass2;
|
|
begin
|
|
Result:=nil;
|
|
if (P=nil) then Exit;
|
|
|
|
FRenderPass2Set.Lock_wr;
|
|
|
|
Result:=_FetchRenderPass(P);
|
|
|
|
cmd.RefTo(Result);
|
|
|
|
FRenderPass2Set.Unlock_wr;
|
|
end;
|
|
|
|
|
|
|
|
end.
|
|
|