fpPS4/vulkan/vRender.pas
red-prig 4ce14d6c9d +
2022-06-29 22:02:50 +03:00

635 lines
18 KiB
ObjectPascal

unit vRender;
{$mode objfpc}{$H+}
interface
uses
Classes,
SysUtils,
RWLock,
sys_types,
g23tree,
ps4_libSceVideoOut,
si_ci_vi_merged_enum,
vulkan,
vDevice,
vMemory,
vShader,
vShaderExt,
vPipeline,
//vSetsPools,
vImage;
type
TvComputePipeline2=class(TvComputePipeline)
FRefs:ptruint;
Procedure Acquire(Sender:TObject);
Procedure Release(Sender:TOBject);
end;
TvRenderPass=class(vPipeline.TvRenderPass)
AtCount:TVkUInt32;
ColorAt:array[0..8] of TVkAttachmentDescription;
ColorRef:array[0..7] of TVkAttachmentReference; //subpass.colorAttachmentCount
pDepthStencilRef:TVkAttachmentReference;
subpass:TVkSubpassDescription;
dependency:TVkSubpassDependency;
Procedure Clear;
Procedure SetZorderStage(s:TVkPipelineStageFlags);
Procedure AddColorRef(id:TVkUInt32;IMAGE_USAGE:Byte);
Procedure SetDepthStencilRef(id:TVkUInt32;DEPTH_USAGE,STENCIL_USAGE:Byte);
Procedure AddColorAt(format:TVkFormat;IMAGE_USAGE:Byte;samples:TVkSampleCountFlagBits);
Procedure AddDepthAt(format:TVkFormat;DEPTH_USAGE,STENCIL_USAGE:Byte);
Function Compile:Boolean;
end;
TvGraphicsPipeline=class(TvPipeline)
FRenderPass:TvRenderPass;
Viewports:array[0..15] of TVkViewport; //viewportState.viewportCount
Scissors :array[0..15] of TVkRect2D; //viewportState.scissorCount
ColorBlends:array[0..7] of TVkPipelineColorBlendAttachmentState; //colorBlending.attachmentCount
FShaderGroup:TvShaderGroup;
dynamicStates:array[0..1] of TVkDynamicState; //dynamicState.dynamicStateCount
vertexInputInfo:TVkPipelineVertexInputStateCreateInfo;
inputAssembly:TVkPipelineInputAssemblyStateCreateInfo;
viewportState:TVkPipelineViewportStateCreateInfo;
rasterizer:TVkPipelineRasterizationStateCreateInfo;
multisampling:TVkPipelineMultisampleStateCreateInfo;
colorBlending:TVkPipelineColorBlendStateCreateInfo;
DepthStencil:TVkPipelineDepthStencilStateCreateInfo;
dynamicState:TVkPipelineDynamicStateCreateInfo;
emulate_primtype:Integer;
Procedure SetPrimType(t:TVkPrimitiveTopology);
Procedure AddVPort(const V:TVkViewport;const S:TVkRect2D);
Procedure AddBlend(const b:TVkPipelineColorBlendAttachmentState);
Procedure Clear;
procedure SetBlendColors(P:PSingle);
procedure SetRenderPass(RenderPass:TvRenderPass);
function Compile:Boolean;
end;
TvRenderTargets=class
FRenderPass:TvRenderPass;
FPipeline:TvGraphicsPipeline;
FFramebuffer:TvFramebuffer;
FRenderArea:TVkRect2D;
FClearValuesCount:TVkUInt32;
FClearValues:array[0..8] of TVkClearValue;
//
FRefs:ptruint;
//
Procedure AddClearColor(clr:TVkClearValue);
Function GetInfo:TVkRenderPassBeginInfo;
class function c(const a,b:TvRenderTargets):Integer;
Destructor Destroy; override;
Procedure Acquire(Sender:TObject);
Procedure Release(Sender:TOBject);
end;
TvRenderTargetsSet=specialize T23treeSet<TvRenderTargets,TvRenderTargets>;
Function GetDepthStencilLayout(DEPTH_USAGE,STENCIL_USAGE:Byte):TVkImageLayout;
Function GetDepthStencilAccessMask(DEPTH_USAGE,STENCIL_USAGE:Byte):TVkAccessFlags;
Function GetColorAccessMask(IMAGE_USAGE:Byte):TVkAccessFlags;
implementation
{
const
buf_ext:TVkExternalMemoryBufferCreateInfo=(
sType:VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO;
pNext:nil;
handleTypes:ord(VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT);
);
img_ext:TVkExternalMemoryImageCreateInfo=(
sType:VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
pNext:nil;
handleTypes:ord(VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT);
);
}
Procedure TvRenderPass.Clear;
begin
if (FHandle<>VK_NULL_HANDLE) then
begin
vkDestroyRenderPass(Device.FHandle,FHandle,nil);
FHandle:=VK_NULL_HANDLE;
end;
AtCount:=0;
FillChar(ColorAt,SizeOf(ColorAt),0);
FillChar(ColorRef,SizeOf(ColorRef),0);
subpass:=Default(TVkSubpassDescription);
subpass.pipelineBindPoint:=VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.inputAttachmentCount :=0;
subpass.pInputAttachments :=nil;
subpass.colorAttachmentCount:=0;
subpass.pColorAttachments :=@ColorRef;
subpass.pResolveAttachments :=nil; //colorAttachmentCount VK_ATTACHMENT_UNUSED
subpass.pDepthStencilAttachment:=nil; //1
subpass.preserveAttachmentCount:=0;
subpass.pPreserveAttachments :=nil;
dependency:=Default(TVkSubpassDependency);
dependency.srcSubpass :=VK_SUBPASS_EXTERNAL;
dependency.dstSubpass :=0;
dependency.srcStageMask :=0{ord(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)};
dependency.dstStageMask :=0{ord(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)};
dependency.srcAccessMask:=0;
dependency.dstAccessMask:=0{ord(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)};
end;
Procedure TvRenderPass.SetZorderStage(s:TVkPipelineStageFlags);
begin
dependency.srcStageMask:=dependency.srcStageMask or s;
dependency.dstStageMask:=dependency.dstStageMask or s;
end;
Procedure TvRenderPass.AddColorRef(id:TVkUInt32;IMAGE_USAGE:Byte);
var
am:TVkAccessFlags;
begin
if (subpass.colorAttachmentCount>7) then Exit;
ColorRef[subpass.colorAttachmentCount].attachment:=id;
ColorRef[subpass.colorAttachmentCount].layout :=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL{VK_IMAGE_LAYOUT_GENERAL};
Inc(subpass.colorAttachmentCount);
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);
am:=GetColorAccessMask(IMAGE_USAGE);
dependency.srcAccessMask:=dependency.srcAccessMask or am;
dependency.dstAccessMask:=dependency.dstAccessMask or am;
end;
Procedure TvRenderPass.SetDepthStencilRef(id:TVkUInt32;DEPTH_USAGE,STENCIL_USAGE:Byte);
var
am:TVkAccessFlags;
begin
subpass.pDepthStencilAttachment:=@pDepthStencilRef;
pDepthStencilRef.attachment :=id;
pDepthStencilRef.layout :=GetDepthStencilLayout(DEPTH_USAGE,STENCIL_USAGE);
am:=GetDepthStencilAccessMask(DEPTH_USAGE,STENCIL_USAGE);
dependency.srcAccessMask:=dependency.srcAccessMask or am;
dependency.dstAccessMask:=dependency.dstAccessMask or am;
end;
Procedure TvRenderPass.AddColorAt(format:TVkFormat;IMAGE_USAGE:Byte;samples:TVkSampleCountFlagBits);
begin
if (AtCount>8) then Exit;
ColorAt[AtCount]:=Default(TVkAttachmentDescription);
ColorAt[AtCount].format :=format;
ColorAt[AtCount].samples :=samples{VK_SAMPLE_COUNT_1_BIT};
With ColorAt[AtCount] 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 ColorAt[AtCount] 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;
ColorAt[AtCount].stencilLoadOp :=VK_ATTACHMENT_LOAD_OP_DONT_CARE;
ColorAt[AtCount].stencilStoreOp:=VK_ATTACHMENT_STORE_OP_DONT_CARE;
With ColorAt[AtCount] do
if (IMAGE_USAGE and TM_READ<>0) then
begin
initialLayout :=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
end else
begin
initialLayout :=VK_IMAGE_LAYOUT_UNDEFINED;
end;
With ColorAt[AtCount] do
finalLayout:=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
Inc(AtCount);
end;
Function GetDepthStencilLayout(DEPTH_USAGE,STENCIL_USAGE:Byte):TVkImageLayout;
begin
if ((DEPTH_USAGE or STENCIL_USAGE) and (TM_WRITE or TM_CLEAR)<>0) then
begin
Result:=VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
end else
begin
Result:=VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
end;
end;
Function GetDepthStencilAccessMask(DEPTH_USAGE,STENCIL_USAGE:Byte):TVkAccessFlags;
begin
Result:=(ord(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT) *ord((DEPTH_USAGE or STENCIL_USAGE) and TM_READ <>0) ) or
(ord(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)*ord((DEPTH_USAGE or STENCIL_USAGE) and (TM_WRITE or TM_CLEAR)<>0) );
end;
Function GetColorAccessMask(IMAGE_USAGE:Byte):TVkAccessFlags;
begin
Result:=(ord(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT) *ord(IMAGE_USAGE and TM_READ<>0) ) or
(ord(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)*ord(IMAGE_USAGE and (TM_WRITE or TM_CLEAR)<>0) );
end;
Procedure TvRenderPass.AddDepthAt(format:TVkFormat;DEPTH_USAGE,STENCIL_USAGE:Byte);
begin
if (AtCount>8) then Exit;
ColorAt[AtCount]:=Default(TVkAttachmentDescription);
ColorAt[AtCount].format :=format;
ColorAt[AtCount].samples :=VK_SAMPLE_COUNT_1_BIT;
With ColorAt[AtCount] 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 ColorAt[AtCount] 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 ColorAt[AtCount] 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 ColorAt[AtCount] 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 ColorAt[AtCount] do
if ((DEPTH_USAGE or STENCIL_USAGE) and TM_READ<>0) then
begin
initialLayout :=GetDepthStencilLayout(DEPTH_USAGE,STENCIL_USAGE);
end else
begin
initialLayout :=VK_IMAGE_LAYOUT_UNDEFINED;
end;
With ColorAt[AtCount] do
finalLayout:=GetDepthStencilLayout(DEPTH_USAGE,STENCIL_USAGE);
Inc(AtCount);
end;
Function TvRenderPass.Compile:Boolean;
var
r:TVkResult;
info:TVkRenderPassCreateInfo;
begin
Result:=False;
if (AtCount=0) then Exit;
if (FHandle<>VK_NULL_HANDLE) then Exit(True);
info:=Default(TVkRenderPassCreateInfo);
info.sType :=VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
info.attachmentCount:=AtCount;
info.pAttachments :=@ColorAt;
info.subpassCount :=1;
info.pSubpasses :=@subpass;
info.dependencyCount:=1;
info.pDependencies :=@dependency;
r:=vkCreateRenderPass(Device.FHandle,@info,nil,@FHandle);
if (r<>VK_SUCCESS) then
begin
Writeln('vkCreateRenderPass');
Exit;
end;
Result:=True;
end;
//
Procedure TvGraphicsPipeline.SetPrimType(t:TVkPrimitiveTopology);
begin
Case ord(t) of
ord(VK_PRIMITIVE_TOPOLOGY_POINT_LIST)..ord(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY):
begin
inputAssembly.topology:=t;
emulate_primtype:=0;
end;
DI_PT_RECTLIST:
begin
inputAssembly.topology:=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
emulate_primtype:=Integer(t);
end;
DI_PT_LINELOOP ,
DI_PT_QUADLIST ,
DI_PT_QUADSTRIP,
DI_PT_POLYGON :
begin
inputAssembly.topology:=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
emulate_primtype:=Integer(t);
end;
end;
end;
Procedure TvGraphicsPipeline.AddVPort(const V:TVkViewport;const S:TVkRect2D);
begin
if (s.extent.width=0) or (s.extent.height=0) then Assert(false);
if (viewportState.viewportCount>15) then Exit;
Viewports[viewportState.viewportCount]:=V;
Scissors [viewportState.viewportCount]:=S;
Inc(viewportState.viewportCount);
viewportState.scissorCount:=viewportState.viewportCount;
end;
Procedure TvGraphicsPipeline.AddBlend(const b:TVkPipelineColorBlendAttachmentState);
begin
if (colorBlending.attachmentCount>7) then Exit;
ColorBlends[colorBlending.attachmentCount]:=b;
Inc(colorBlending.attachmentCount);
end;
Procedure TvGraphicsPipeline.Clear;
begin
if (FHandle<>VK_NULL_HANDLE) then
begin
vkDestroyPipeline(Device.FHandle,FHandle,nil);
FHandle:=VK_NULL_HANDLE;
end;
vertexInputInfo:=Default(TVkPipelineVertexInputStateCreateInfo);
vertexInputInfo.sType :=VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
inputAssembly:=Default(TVkPipelineInputAssemblyStateCreateInfo);
inputAssembly.sType :=VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology :=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable:=VK_FALSE; //VGT_MULTI_PRIM_IB_RESET_EN
FillChar(Viewports ,SizeOf(Viewports),0);
FillChar(Scissors ,SizeOf(Scissors) ,0);
FillChar(ColorBlends,SizeOf(ColorBlends),0);
FShaderGroup:=nil;
viewportState:=Default(TVkPipelineViewportStateCreateInfo);
viewportState.sType :=VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount:=0;
viewportState.pViewports :=@Viewports;
viewportState.scissorCount :=0;
viewportState.pScissors :=@Scissors;
rasterizer:=Default(TVkPipelineRasterizationStateCreateInfo);
rasterizer.sType :=VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable:=VK_FALSE;
rasterizer.rasterizerDiscardEnable:=VK_FALSE; //DB_SHADER_CONTROL.KILL_ENABLE DB_RENDER_CONTROL.FORCE_COLOR_KILL
rasterizer.polygonMode :=VK_POLYGON_MODE_FILL; //PA_SU_SC_MODE_CNTL.POLY_MODE POLYMODE_FRONT_PTYPE POLYMODE_BACK_PTYPE
rasterizer.lineWidth :=1; //PA_SU_LINE_CNTL.WIDTH
rasterizer.cullMode :=ord(VK_CULL_MODE_NONE); //CULL_FRONT CULL_BACK
rasterizer.frontFace :=VK_FRONT_FACE_COUNTER_CLOCKWISE; //FACE
rasterizer.depthBiasEnable :=VK_FALSE;
rasterizer.depthBiasConstantFactor:=0;
rasterizer.depthBiasClamp :=0;
rasterizer.depthBiasSlopeFactor :=0;
multisampling:=Default(TVkPipelineMultisampleStateCreateInfo);
multisampling.sType :=VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable :=VK_FALSE;
multisampling.rasterizationSamples :=VK_SAMPLE_COUNT_1_BIT;
multisampling.minSampleShading :=1;
multisampling.pSampleMask :=nil;
multisampling.alphaToCoverageEnable:=VK_FALSE;
multisampling.alphaToOneEnable :=VK_FALSE;
colorBlending:=Default(TVkPipelineColorBlendStateCreateInfo);
colorBlending.sType :=VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable :=VK_FALSE;
colorBlending.logicOp :=VK_LOGIC_OP_COPY;
colorBlending.attachmentCount :=0;
colorBlending.pAttachments :=@ColorBlends;
DepthStencil:=Default(TVkPipelineDepthStencilStateCreateInfo);
DepthStencil.sType :=VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
DepthStencil.depthTestEnable :=VK_FALSE;
DepthStencil.depthWriteEnable :=VK_FALSE;
DepthStencil.depthCompareOp :=VK_COMPARE_OP_LESS;
DepthStencil.depthBoundsTestEnable:=VK_FALSE;
DepthStencil.stencilTestEnable :=VK_FALSE;
//DepthStencil.front :TVkStencilOpState;
//DepthStencil.back :TVkStencilOpState;
DepthStencil.minDepthBounds :=0;
DepthStencil.maxDepthBounds :=0;
dynamicState:=Default(TVkPipelineDynamicStateCreateInfo);
dynamicState.sType :=VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount:=0{2};
dynamicState.pDynamicStates :=@dynamicStates;
dynamicStates[0]:=VK_DYNAMIC_STATE_VIEWPORT;
dynamicStates[1]:=VK_DYNAMIC_STATE_LINE_WIDTH;
end;
type
PVec4f=^TVec4f;
TVec4f=array[0..3] of Single;
procedure TvGraphicsPipeline.SetBlendColors(P:PSingle);
begin
if (P=nil) then Exit;
colorBlending.blendConstants:=PVec4f(P)^;
end;
procedure TvGraphicsPipeline.SetRenderPass(RenderPass:TvRenderPass);
begin
if (FRenderPass<>RenderPass) then
begin
FRenderPass:=RenderPass;
end;
end;
function TvGraphicsPipeline.Compile:Boolean;
type
AVkPipelineShaderStageCreateInfo=array[0..6] of TVkPipelineShaderStageCreateInfo;
var
r:TVkResult;
Stages:AVkPipelineShaderStageCreateInfo; // info.stageCount
info:TVkGraphicsPipelineCreateInfo;
begin
Result:=False;
if (FShaderGroup=nil) then Exit;
if (FRenderPass=nil) then Exit;
if (viewportState.viewportCount=0) then Exit;
if (viewportState.scissorCount=0) then Exit;
info:=Default(TVkGraphicsPipelineCreateInfo);
Stages:=Default(AVkPipelineShaderStageCreateInfo);
FShaderGroup.FKey.ExportStages(@Stages,@info.stageCount);
if (info.stageCount=0) then Exit;
if (not FShaderGroup.Compile) then Exit;
if (not FRenderPass.Compile) then Exit;
info.sType :=VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
info.pStages :=@Stages;
info.pVertexInputState :=@vertexInputInfo;
info.pInputAssemblyState:=@inputAssembly;
info.pViewportState :=@viewportState;
info.pRasterizationState:=@rasterizer;
info.pMultisampleState :=@multisampling;
info.pDepthStencilState :=@DepthStencil;
info.pColorBlendState :=@colorBlending;
info.pDynamicState :=@dynamicState;
info.layout :=FShaderGroup.FLayout.FHandle;
info.renderPass :=FRenderPass.FHandle;
info.subpass :=0;
info.basePipelineHandle :=VK_NULL_HANDLE;
info.basePipelineIndex :=-1;
r:=vkCreateGraphicsPipelines(Device.FHandle,VK_NULL_HANDLE,1,@info,nil,@FHandle);
if (r<>VK_SUCCESS) then
begin
Writeln('failed to create graphics pipeline!');
exit;
end;
Result:=True;
end;
/////////
Procedure TvRenderTargets.AddClearColor(clr:TVkClearValue);
begin
if (FClearValuesCount>8) then Exit;
FClearValues[FClearValuesCount]:=clr;
Inc(FClearValuesCount);
end;
Function TvRenderTargets.GetInfo:TVkRenderPassBeginInfo;
begin
Result:=Default(TVkRenderPassBeginInfo);
Result.sType :=VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
Result.renderPass :=FRenderPass.FHandle;
Result.renderArea :=FRenderArea;
Result.clearValueCount:=FClearValuesCount;
Result.pClearValues :=FClearValues;
Result.framebuffer :=FFramebuffer.FHandle;
end;
class function TvRenderTargets.c(const a,b:TvRenderTargets):Integer;
begin
Result:=CompareByte(a,b,SizeOf(Pointer));
end;
Destructor TvRenderTargets.Destroy;
begin
FreeAndNil(FRenderPass);
FreeAndNil(FPipeline);
FreeAndNil(FFramebuffer);
inherited;
end;
Procedure TvRenderTargets.Acquire(Sender:TObject);
begin
System.InterlockedIncrement(Pointer(FRefs));
end;
Procedure TvRenderTargets.Release(Sender:TOBject);
begin
if System.InterlockedDecrement(Pointer(FRefs))=nil then
begin
Free;
end;
end;
Procedure TvComputePipeline2.Acquire(Sender:TObject);
begin
System.InterlockedIncrement(Pointer(FRefs));
end;
Procedure TvComputePipeline2.Release(Sender:TOBject);
begin
if System.InterlockedDecrement(Pointer(FRefs))=nil then
begin
Free;
end;
end;
//////////////
end.