CUDA.Graphics.pas 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138
  1. //
  2. // The graphics platform GLScene https://github.com/glscene
  3. //
  4. unit CUDA.Graphics;
  5. (* CUDA Graphics for GLScene *)
  6. interface
  7. {$I GLScene.inc}
  8. uses
  9. Winapi.OpenGL,
  10. Winapi.OpenGLext,
  11. System.Classes,
  12. System.SysUtils,
  13. CUDA.Import,
  14. CUDA.APIComps,
  15. GLS.Context,
  16. GLS.State,
  17. GLS.Scene,
  18. GLS.Graphics,
  19. GLS.Material,
  20. GLS.Strings,
  21. GLS.TextureFormat,
  22. GLS.Texture,
  23. GLSL.Shader,
  24. GLSL.ShaderParameter,
  25. GLS.PersistentClasses,
  26. GLS.RenderContextInfo;
  27. type
  28. TGLVertexAttribute = class;
  29. TGLVertexAttributes = class;
  30. TOnBeforeKernelLaunch = procedure(Sender: TGLVertexAttribute) of object;
  31. TGLVertexAttribute = class(TCollectionItem)
  32. private
  33. FName: string;
  34. FType: TGLSLDataType;
  35. FFunc: TCUDAFunction;
  36. FLocation: Integer;
  37. FOnBeforeKernelLaunch: TOnBeforeKernelLaunch;
  38. procedure SetName(const AName: string);
  39. procedure SetType(AType: TGLSLDataType);
  40. procedure SetFunc(AFunc: TCUDAFunction);
  41. function GetLocation: Integer;
  42. function GetOwner: TGLVertexAttributes; reintroduce;
  43. public
  44. constructor Create(ACollection: TCollection); override;
  45. procedure NotifyChange(Sender: TObject);
  46. property Location: Integer read GetLocation;
  47. published
  48. property Name: string read FName write SetName;
  49. property GLSLType: TGLSLDataType read FType write SetType;
  50. property KernelFunction: TCUDAFunction read FFunc write SetFunc;
  51. property OnBeforeKernelLaunch: TOnBeforeKernelLaunch read
  52. FOnBeforeKernelLaunch write FOnBeforeKernelLaunch;
  53. end;
  54. TGLVertexAttributes = class(TOwnedCollection)
  55. private
  56. procedure SetItems(Index: Integer; const AValue: TGLVertexAttribute);
  57. function GetItems(Index: Integer): TGLVertexAttribute;
  58. public
  59. constructor Create(AOwner: TComponent);
  60. procedure NotifyChange(Sender: TObject);
  61. function MakeUniqueName(const ANameRoot: string): string;
  62. function GetAttributeByName(const AName: string): TGLVertexAttribute;
  63. function Add: TGLVertexAttribute;
  64. property Attributes[Index: Integer]: TGLVertexAttribute read GetItems
  65. write SetItems; default;
  66. end;
  67. TFeedBackMeshPrimitive = (fbmpPoint, fbmpLine, fbmpTriangle);
  68. TFeedBackMeshLaunching = (fblCommon, fblOnePerAtttribute);
  69. TCUDACustomFeedBackMesh = class(TGLBaseSceneObject)
  70. private
  71. FGeometryResource: TCUDAGraphicResource;
  72. FAttributes: TGLVertexAttributes;
  73. FVAO: TGLVertexArrayHandle;
  74. FVBO: TGLVBOArrayBufferHandle;
  75. FEBO: TGLVBOElementArrayHandle;
  76. FPrimitiveType: TFeedBackMeshPrimitive;
  77. FVertexNumber: Integer;
  78. FElementNumber: Integer;
  79. FShader: TGLSLShader;
  80. FCommonFunc: TCUDAFunction;
  81. FLaunching: TFeedBackMeshLaunching;
  82. FBlend: Boolean;
  83. procedure SetAttributes(AValue: TGLVertexAttributes);
  84. procedure SetPrimitiveType(AValue: TFeedBackMeshPrimitive);
  85. procedure SetVertexNumber(AValue: Integer);
  86. procedure SetElementNumber(AValue: Integer);
  87. procedure SetShader(AShader: TGLSLShader);
  88. procedure SetCommonFunc(AFunc: TCUDAFunction);
  89. protected
  90. procedure Notification(AComponent: TComponent;
  91. Operation: TOperation); override;
  92. procedure RefreshAttributes;
  93. procedure AllocateHandles;
  94. procedure LaunchKernels;
  95. protected
  96. property Attributes: TGLVertexAttributes read FAttributes write SetAttributes;
  97. // GLSL shader as material. If it absent or disabled - nothing be drawen.
  98. property Shader: TGLSLShader read FShader write SetShader;
  99. // Primitive type.
  100. property PrimitiveType: TFeedBackMeshPrimitive read FPrimitiveType
  101. write SetPrimitiveType default fbmpPoint;
  102. // Number of vertexes in array buffer.
  103. property VertexNumber: Integer read FVertexNumber
  104. write SetVertexNumber default 1;
  105. // Number of indexes in element buffer. Zero to disable.
  106. property ElementNumber: Integer read FElementNumber
  107. write SetElementNumber default 0;
  108. (* Used for all attributes and elements if Launching = fblCommon
  109. otherwise used own attribute function and this for elements. *)
  110. property CommonKernelFunction: TCUDAFunction read FCommonFunc
  111. write SetCommonFunc;
  112. (* Define mode of manufacturer launching:
  113. fblCommon - single launch for all,
  114. flOnePerAtttribute - one launch per attribute and elements *)
  115. property Launching: TFeedBackMeshLaunching read FLaunching
  116. write FLaunching default fblCommon;
  117. //Defines if the object uses blending for object sorting purposes.
  118. property Blend: Boolean read FBlend write FBlend default False;
  119. public
  120. constructor Create(AOwner: TComponent); override;
  121. destructor Destroy; override;
  122. procedure DoRender(var ARci: TGLRenderContextInfo;
  123. ARenderSelf, ARenderChildren: Boolean); override;
  124. property ArrayBufferHandle: TGLVBOArrayBufferHandle read FVBO;
  125. property ElementArrayHandle: TGLVBOElementArrayHandle read FEBO;
  126. end;
  127. TCUDAFeedbackMesh = class(TCUDACustomFeedBackMesh)
  128. published
  129. property Attributes;
  130. property Shader;
  131. property PrimitiveType;
  132. property VertexNumber;
  133. property ElementNumber;
  134. property CommonKernelFunction;
  135. property Launching;
  136. property Blend;
  137. property ObjectsSorting;
  138. property VisibilityCulling;
  139. property Direction;
  140. property PitchAngle;
  141. property Position;
  142. property RollAngle;
  143. property Scale;
  144. property ShowAxes;
  145. property TurnAngle;
  146. property Up;
  147. property Visible;
  148. property Pickable;
  149. property OnProgress;
  150. property OnPicked;
  151. property Behaviours;
  152. property Effects;
  153. end;
  154. TCUDAImageResource = class(TCUDAGraphicResource)
  155. private
  156. fMaterialLibrary: TGLMaterialLibrary;
  157. fTextureName: TGLLibMaterialName;
  158. procedure SetMaterialLibrary(const Value: TGLMaterialLibrary);
  159. procedure SetTextureName(const Value: TGLLibMaterialName);
  160. protected
  161. procedure AllocateHandles; override;
  162. procedure DestroyHandles; override;
  163. procedure Notification(AComponent: TComponent; Operation: TOperation);
  164. override;
  165. public
  166. constructor Create(AOwner: TComponent); override;
  167. destructor Destroy; override;
  168. procedure MapResources; override;
  169. procedure UnMapResources; override;
  170. procedure BindArrayToTexture(var cudaArray: TCUDAMemData;
  171. ALeyer, ALevel: LOngWord); override;
  172. published
  173. property TextureName: TGLLibMaterialName read fTextureName write
  174. SetTextureName;
  175. property MaterialLibrary: TGLMaterialLibrary read fMaterialLibrary write
  176. SetMaterialLibrary;
  177. property Mapping;
  178. end;
  179. TCUDAGeometryResource = class(TCUDAGraphicResource)
  180. private
  181. FFeedBackMesh: TCUDACustomFeedBackMesh;
  182. procedure SetFeedBackMesh(const Value: TCUDACustomFeedBackMesh);
  183. function GetAttribArraySize(AAttr: TGLVertexAttribute): LongWord;
  184. protected
  185. procedure AllocateHandles; override;
  186. procedure DestroyHandles; override;
  187. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  188. function GetAttributeArraySize(const AName: string): LongWord; override;
  189. function GetAttributeArrayAddress(const AName: string): Pointer; override;
  190. function GetElementArrayDataSize: LongWord; override;
  191. function GetElementArrayAddress: Pointer; override;
  192. public
  193. constructor Create(AOwner: TComponent); override;
  194. destructor Destroy; override;
  195. procedure MapResources; override;
  196. procedure UnMapResources; override;
  197. property AttributeDataSize[const AttribName: string]: LongWord read
  198. GetAttributeArraySize;
  199. property AttributeDataAddress[const AttribName: string]: Pointer read
  200. GetAttributeArrayAddress;
  201. property IndexDataSize: LongWord read GetElementArrayDataSize;
  202. property IndexDataAddress: Pointer read GetElementArrayAddress;
  203. published
  204. property FeedBackMesh: TCUDACustomFeedBackMesh read FFeedBackMesh write
  205. SetFeedBackMesh;
  206. property Mapping;
  207. end;
  208. //---------------------------------------------------------------------------
  209. implementation
  210. //---------------------------------------------------------------------------
  211. // ------------------
  212. // ------------------ TCUDAImageResource ------------------
  213. // ------------------
  214. constructor TCUDAImageResource.Create(AOwner: TComponent);
  215. begin
  216. inherited Create(AOwner);
  217. fHandle[0] := nil;
  218. fResourceType := rtTexture;
  219. FGLContextHandle := TGLVirtualHandle.Create;
  220. FGLContextHandle.OnAllocate := OnGLHandleAllocate;
  221. FGLContextHandle.OnDestroy := OnGLHandleDestroy;
  222. end;
  223. destructor TCUDAImageResource.Destroy;
  224. begin
  225. FGLContextHandle.Destroy;
  226. inherited;
  227. end;
  228. procedure TCUDAImageResource.SetMaterialLibrary(const Value:
  229. TGLMaterialLibrary);
  230. begin
  231. if fMaterialLibrary <> Value then
  232. begin
  233. if Assigned(fMaterialLibrary) then
  234. fMaterialLibrary.RemoveFreeNotification(Self);
  235. fMaterialLibrary := Value;
  236. if Assigned(fMaterialLibrary) then
  237. begin
  238. fMaterialLibrary.FreeNotification(Self);
  239. if fMaterialLibrary.TextureByName(fTextureName) <> nil then
  240. DestroyHandles;
  241. end;
  242. end;
  243. end;
  244. procedure TCUDAImageResource.SetTextureName(const Value: TGLLibMaterialName);
  245. begin
  246. if fTextureName <> Value then
  247. begin
  248. fTextureName := Value;
  249. DestroyHandles;
  250. end;
  251. end;
  252. procedure TCUDAImageResource.UnMapResources;
  253. begin
  254. if FMapCounter > 0 then
  255. Dec(FMapCounter);
  256. if FMapCounter = 0 then
  257. begin
  258. if Assigned(FHandle[0]) then
  259. begin
  260. Context.Requires;
  261. FStatus := cuGraphicsUnMapResources(1, @FHandle[0], nil);
  262. Context.Release;
  263. if FStatus <> CUDA_SUCCESS then
  264. Abort;
  265. end;
  266. end;
  267. end;
  268. procedure TCUDAImageResource.AllocateHandles;
  269. const
  270. cMapping: array[TCUDAMapping] of TCUgraphicsMapResourceFlags = (
  271. CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE,
  272. CU_GRAPHICS_MAP_RESOURCE_FLAGS_READ_ONLY,
  273. CU_GRAPHICS_MAP_RESOURCE_FLAGS_WRITE_DISCARD);
  274. var
  275. LTexture: TGLTexture;
  276. glHandle: Cardinal;
  277. begin
  278. FGLContextHandle.AllocateHandle;
  279. if FGLContextHandle.IsDataNeedUpdate
  280. and Assigned(FMaterialLibrary)
  281. and (Length(FTextureName) > 0) then
  282. begin
  283. inherited;
  284. LTexture := FMaterialLibrary.TextureByName(FTextureName);
  285. if Assigned(LTexture) then
  286. begin
  287. glHandle := LTexture.AllocateHandle;
  288. if glHandle = 0 then
  289. Abort;
  290. Context.Requires;
  291. DestroyHandles;
  292. FStatus := cuGraphicsGLRegisterImage(
  293. FHandle[0],
  294. glHandle,
  295. DecodeTextureTarget(LTexture.Image.NativeTextureTarget),
  296. cMapping[fMapping]);
  297. Context.Release;
  298. if FStatus <> CUDA_SUCCESS then
  299. Abort;
  300. FGLContextHandle.NotifyDataUpdated;
  301. end;
  302. end;
  303. end;
  304. procedure TCUDAImageResource.DestroyHandles;
  305. begin
  306. if Assigned(FHandle[0]) then
  307. begin
  308. inherited;
  309. Context.Requires;
  310. FStatus := cuGraphicsUnregisterResource(FHandle[0]);
  311. Context.Release;
  312. FHandle[0] := nil;
  313. FGLContextHandle.NotifyChangesOfData;
  314. end;
  315. end;
  316. procedure TCUDAImageResource.MapResources;
  317. begin
  318. AllocateHandles;
  319. if FMapCounter = 0 then
  320. begin
  321. if Assigned(FHandle[0]) then
  322. begin
  323. Context.Requires;
  324. FStatus := cuGraphicsMapResources(1, @FHandle[0], nil);
  325. Context.Release;
  326. if FStatus <> CUDA_SUCCESS then
  327. Abort;
  328. end;
  329. end;
  330. Inc(FMapCounter);
  331. end;
  332. procedure TCUDAImageResource.Notification(AComponent: TComponent; Operation:
  333. TOperation);
  334. begin
  335. inherited;
  336. if (AComponent = fMaterialLibrary) and (Operation = opRemove) then
  337. begin
  338. fMaterialLibrary := nil;
  339. fTextureName := '';
  340. DestroyHandles;
  341. end;
  342. end;
  343. procedure TCUDAImageResource.BindArrayToTexture(var cudaArray: TCUDAMemData;
  344. ALeyer, ALevel: LOngWord);
  345. var
  346. LTexture: TGLTexture;
  347. newArray: PCUarray;
  348. begin
  349. if FMapCounter = 0 then
  350. begin
  351. {$IFDEF USE_LOGGING}
  352. LogError(strFailToBindArrayToTex);
  353. {$ENDIF}
  354. Abort;
  355. end;
  356. Context.Requires;
  357. FStatus := cuGraphicsSubResourceGetMappedArray(
  358. newArray, FHandle[0], ALeyer, ALevel);
  359. Context.Release;
  360. if FStatus <> CUDA_SUCCESS then
  361. Abort;
  362. LTexture := FMaterialLibrary.TextureByName(FTextureName);
  363. SetArray(cudaArray, newArray, True, LTexture.TexDepth > 0);
  364. end;
  365. // ------------------
  366. // ------------------ TCUDAGeometryResource ------------------
  367. // ------------------
  368. constructor TCUDAGeometryResource.Create(AOwner: TComponent);
  369. begin
  370. inherited Create(AOwner);
  371. FHandle[0] := nil;
  372. FHandle[1] := nil;
  373. FResourceType := rtBuffer;
  374. FMapCounter := 0;
  375. FGLContextHandle := TGLVirtualHandle.Create;
  376. FGLContextHandle.OnAllocate := OnGLHandleAllocate;
  377. FGLContextHandle.OnDestroy := OnGLHandleDestroy;
  378. end;
  379. destructor TCUDAGeometryResource.Destroy;
  380. begin
  381. FeedBackMesh := nil;
  382. FGLContextHandle.Destroy;
  383. inherited;
  384. end;
  385. procedure TCUDAGeometryResource.SetFeedBackMesh(const Value:
  386. TCUDACustomFeedBackMesh);
  387. begin
  388. if FFeedBackMesh <> Value then
  389. begin
  390. if Assigned(FFeedBackMesh) then
  391. begin
  392. FFeedBackMesh.RemoveFreeNotification(Self);
  393. FFeedBackMesh.FGeometryResource := nil;
  394. end;
  395. FFeedBackMesh := Value;
  396. if Assigned(FFeedBackMesh) then
  397. begin
  398. FFeedBackMesh.FreeNotification(Self);
  399. FFeedBackMesh.FGeometryResource := Self;
  400. end;
  401. DestroyHandles;
  402. end;
  403. end;
  404. procedure TCUDAGeometryResource.AllocateHandles;
  405. const
  406. cMapping: array[TCUDAMapping] of TCUgraphicsMapResourceFlags = (
  407. CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE,
  408. CU_GRAPHICS_MAP_RESOURCE_FLAGS_READ_ONLY,
  409. CU_GRAPHICS_MAP_RESOURCE_FLAGS_WRITE_DISCARD);
  410. begin
  411. inherited;
  412. FGLContextHandle.AllocateHandle;
  413. if FGLContextHandle.IsDataNeedUpdate then
  414. begin
  415. if FFeedBackMesh.FVBO.IsDataNeedUpdate then
  416. FFeedBackMesh.AllocateHandles;
  417. Context.Requires;
  418. DestroyHandles;
  419. // Register vertex array
  420. FStatus := cuGraphicsGLRegisterBuffer(
  421. FHandle[0],
  422. FFeedBackMesh.FVBO.Handle,
  423. cMapping[FMapping]);
  424. // Register element array
  425. if FFeedBackMesh.ElementNumber > 0 then
  426. CollectStatus(
  427. cuGraphicsGLRegisterBuffer(
  428. FHandle[1],
  429. FFeedBackMesh.FEBO.Handle,
  430. cMapping[FMapping]));
  431. Context.Release;
  432. if FStatus <> CUDA_SUCCESS then
  433. Abort;
  434. FGLContextHandle.NotifyDataUpdated;
  435. end;
  436. end;
  437. procedure TCUDAGeometryResource.DestroyHandles;
  438. begin
  439. if Assigned(fHandle[0]) or Assigned(fHandle[1]) then
  440. begin
  441. inherited;
  442. Context.Requires;
  443. while FMapCounter > 0 do
  444. UnMapResources;
  445. FStatus := CUDA_SUCCESS;
  446. if Assigned(fHandle[0]) then
  447. begin
  448. CollectStatus(cuGraphicsUnregisterResource(fHandle[0]));
  449. fHandle[0] := nil;
  450. end;
  451. if Assigned(fHandle[1]) then
  452. begin
  453. CollectStatus(cuGraphicsUnregisterResource(fHandle[1]));
  454. fHandle[1] := nil;
  455. end;
  456. Context.Release;
  457. FGLContextHandle.NotifyChangesOfData;
  458. end;
  459. end;
  460. procedure TCUDAGeometryResource.Notification(AComponent: TComponent;
  461. Operation:
  462. TOperation);
  463. begin
  464. inherited;
  465. if (AComponent = FFeedBackMesh) and (Operation = opRemove) then
  466. begin
  467. FeedBackMesh := nil;
  468. DestroyHandles;
  469. end;
  470. end;
  471. procedure TCUDAGeometryResource.MapResources;
  472. var
  473. count: Integer;
  474. begin
  475. AllocateHandles;
  476. if FMapCounter = 0 then
  477. begin
  478. if Assigned(FHandle[0]) then
  479. begin
  480. count := 1;
  481. if Assigned(FHandle[1]) then
  482. Inc(count);
  483. Context.Requires;
  484. FStatus := cuGraphicsMapResources(count, @FHandle[0], nil);
  485. Context.Release;
  486. if FStatus <> CUDA_SUCCESS then
  487. Abort;
  488. end;
  489. end;
  490. Inc(FMapCounter);
  491. end;
  492. procedure TCUDAGeometryResource.UnMapResources;
  493. var
  494. count: Integer;
  495. begin
  496. if FMapCounter > 0 then
  497. Dec(FMapCounter);
  498. if FMapCounter = 0 then
  499. begin
  500. if Assigned(FHandle[0]) then
  501. begin
  502. count := 1;
  503. if Assigned(FHandle[1]) then
  504. Inc(count);
  505. Context.Requires;
  506. FStatus := cuGraphicsUnMapResources(count, @FHandle[0], nil);
  507. Context.Release;
  508. if FStatus <> CUDA_SUCCESS then
  509. Abort;
  510. end;
  511. end;
  512. end;
  513. function TCUDAGeometryResource.GetAttribArraySize(AAttr: TGLVertexAttribute): LongWord;
  514. var
  515. typeSize: LongWord;
  516. begin
  517. case AAttr.GLSLType of
  518. GLSLType1F: typeSize := SizeOf(Single);
  519. GLSLType2F: typeSize := 2 * SizeOf(Single);
  520. GLSLType3F: typeSize := 3 * SizeOf(Single);
  521. GLSLType4F: typeSize := 4 * SizeOf(Single);
  522. GLSLType1I: typeSize := SizeOf(Integer);
  523. GLSLType2I: typeSize := 2 * SizeOf(Integer);
  524. GLSLType3I: typeSize := 3 * SizeOf(Integer);
  525. GLSLType4I: typeSize := 4 * SizeOf(Integer);
  526. GLSLType1UI: typeSize := SizeOf(Integer);
  527. GLSLType2UI: typeSize := 2 * SizeOf(Integer);
  528. GLSLType3UI: typeSize := 3 * SizeOf(Integer);
  529. GLSLType4UI: typeSize := 4 * SizeOf(Integer);
  530. GLSLTypeMat2F: typeSize := 4 * SizeOf(Single);
  531. GLSLTypeMat3F: typeSize := 9 * SizeOf(Single);
  532. GLSLTypeMat4F: typeSize := 16 * SizeOf(Single);
  533. else
  534. begin
  535. Assert(False, strErrorEx + strUnknownType);
  536. typeSize := 0;
  537. end;
  538. end;
  539. Result := Cardinal(FFeedBackMesh.VertexNumber) * typeSize;
  540. end;
  541. function TCUDAGeometryResource.GetAttributeArraySize(
  542. const AName: string): LongWord;
  543. var
  544. LAttr: TGLVertexAttribute;
  545. begin
  546. Result := 0;
  547. LAttr := FFeedBackMesh.Attributes.GetAttributeByName(AName);
  548. if not Assigned(LAttr) then
  549. exit;
  550. if LAttr.GLSLType = GLSLTypeUndefined then
  551. exit;
  552. Result := GetAttribArraySize(LAttr);
  553. end;
  554. function TCUDAGeometryResource.GetAttributeArrayAddress(
  555. const AName: string): Pointer;
  556. var
  557. i: Integer;
  558. Size: Cardinal;
  559. MapPtr: Pointer;
  560. LAttr: TGLVertexAttribute;
  561. begin
  562. Result := nil;
  563. if FMapCounter = 0 then
  564. exit;
  565. LAttr := FFeedBackMesh.Attributes.GetAttributeByName(AName);
  566. if not Assigned(LAttr) then
  567. exit;
  568. for i := 0 to LAttr.Index - 1 do
  569. Inc(PByte(Result), GetAttribArraySize(FFeedBackMesh.Attributes[i]));
  570. Context.Requires;
  571. MapPtr := nil;
  572. FStatus := cuGraphicsResourceGetMappedPointer(
  573. MapPtr, Size, FHandle[0]);
  574. Context.Release;
  575. if FStatus <> CUDA_SUCCESS then
  576. Abort;
  577. if Cardinal(Result) + GetAttribArraySize(LAttr) > Size then
  578. begin
  579. {$IFDEF USE_LOGGING}
  580. LogError(strOutOfAttribSize);
  581. {$ENDIF}
  582. Abort;
  583. end;
  584. Inc(Pbyte(Result), Cardinal(MapPtr));
  585. end;
  586. function TCUDAGeometryResource.GetElementArrayDataSize: LongWord;
  587. begin
  588. Result := FFeedBackMesh.ElementNumber * SizeOf(Cardinal);
  589. end;
  590. function TCUDAGeometryResource.GetElementArrayAddress: Pointer;
  591. var
  592. Size: Cardinal;
  593. MapPtr: Pointer;
  594. begin
  595. Result := nil;
  596. if (FHandle[1] = nil) and (FMapCounter = 0) then
  597. exit;
  598. Context.Requires;
  599. MapPtr := nil;
  600. FStatus := cuGraphicsResourceGetMappedPointer(MapPtr, Size, FHandle[1]);
  601. Context.Release;
  602. if FStatus <> CUDA_SUCCESS then
  603. Abort;
  604. if GetElementArrayDataSize > Size then
  605. begin
  606. {$IFDEF USE_LOGGING}
  607. LogError(strOutOfElementSize);
  608. {$ENDIF}
  609. Abort;
  610. end;
  611. Inc(Pbyte(Result), Cardinal(MapPtr));
  612. end;
  613. // -----------------------
  614. // ----------------------- TGLVertexAttribute -------------------
  615. // -----------------------
  616. constructor TGLVertexAttribute.Create(ACollection: TCollection);
  617. begin
  618. inherited;
  619. FName := GetOwner.MakeUniqueName('Attrib');
  620. FType := GLSLTypeUndefined;
  621. FLocation := -1;
  622. end;
  623. procedure TGLVertexAttribute.SetFunc(AFunc: TCUDAFunction);
  624. var
  625. LMesh: TCUDACustomFeedBackMesh;
  626. begin
  627. LMesh := TCUDACustomFeedBackMesh(GetOwner.GetOwner);
  628. if Assigned(FFunc) then
  629. FFunc.RemoveFreeNotification(LMesh);
  630. FFunc := AFunc;
  631. if Assigned(FFunc) then
  632. FFunc.FreeNotification(LMesh);
  633. end;
  634. procedure TGLVertexAttribute.SetName(const AName: string);
  635. begin
  636. if AName <> FName then
  637. begin
  638. FName := '';
  639. FName := GetOwner.MakeUniqueName(AName);
  640. NotifyChange(Self);
  641. end;
  642. end;
  643. procedure TGLVertexAttribute.SetType(AType: TGLSLDataType);
  644. begin
  645. if AType <> FType then
  646. begin
  647. FType := AType;
  648. NotifyChange(Self);
  649. end;
  650. end;
  651. function TGLVertexAttribute.GetLocation: Integer;
  652. begin
  653. if FLocation < 0 then
  654. FLocation := gl.GetAttribLocation(
  655. CurrentGLContext.GLStates.CurrentProgram,
  656. PAnsiChar(AnsiString(FName)));
  657. Result := FLocation;
  658. end;
  659. function TGLVertexAttribute.GetOwner: TGLVertexAttributes;
  660. begin
  661. Result := TGLVertexAttributes(Collection);
  662. end;
  663. procedure TGLVertexAttribute.NotifyChange(Sender: TObject);
  664. begin
  665. GetOwner.NotifyChange(Self);
  666. end;
  667. // -----------------------
  668. // ----------------------- TGLVertexAttributes -------------------
  669. // -----------------------
  670. function TGLVertexAttributes.Add: TGLVertexAttribute;
  671. begin
  672. Result := (inherited Add) as TGLVertexAttribute;
  673. end;
  674. constructor TGLVertexAttributes.Create(AOwner: TComponent);
  675. begin
  676. inherited Create(AOwner, TGLVertexAttribute);
  677. end;
  678. function TGLVertexAttributes.GetAttributeByName(
  679. const AName: string): TGLVertexAttribute;
  680. var
  681. I: Integer;
  682. A: TGLVertexAttribute;
  683. begin
  684. // Brute-force, there no need optimization
  685. for I := 0 to Count - 1 do
  686. begin
  687. A := TGLVertexAttribute(Items[i]);
  688. if A.Name = AName then
  689. Exit(A);
  690. end;
  691. Result := nil;
  692. end;
  693. function TGLVertexAttributes.GetItems(Index: Integer): TGLVertexAttribute;
  694. begin
  695. Result := TGLVertexAttribute(inherited Items[index]);
  696. end;
  697. function TGLVertexAttributes.MakeUniqueName(const ANameRoot: string): string;
  698. var
  699. I: Integer;
  700. begin
  701. Result := ANameRoot;
  702. I := 1;
  703. while GetAttributeByName(Result) <> nil do
  704. begin
  705. Result := ANameRoot + IntToStr(I);
  706. Inc(I);
  707. end;
  708. end;
  709. procedure TGLVertexAttributes.NotifyChange(Sender: TObject);
  710. begin
  711. TCUDACustomFeedBackMesh(GetOwner).NotifyChange(Self);
  712. end;
  713. procedure TGLVertexAttributes.SetItems(Index: Integer;
  714. const AValue: TGLVertexAttribute);
  715. begin
  716. inherited Items[index] := AValue;
  717. end;
  718. // -----------------------
  719. // ----------------------- TCUDACustomFeedBackMesh -------------------
  720. // -----------------------
  721. procedure TCUDACustomFeedBackMesh.AllocateHandles;
  722. var
  723. I, L: Integer;
  724. Size, Offset: Cardinal;
  725. GR: TCUDAGeometryResource;
  726. EnabledLocations: array[0..GLS_VERTEX_ATTR_NUM - 1] of Boolean;
  727. begin
  728. FVAO.AllocateHandle;
  729. FVBO.AllocateHandle;
  730. FEBO.AllocateHandle;
  731. if Assigned(FGeometryResource) then
  732. begin
  733. GR := TCUDAGeometryResource(FGeometryResource);
  734. size := 0;
  735. for I := 0 to Attributes.Count - 1 do
  736. Inc(size, GR.GetAttribArraySize(Attributes[I]));
  737. FVAO.Bind;
  738. FVBO.BindBufferData(nil, size, GL_STREAM_DRAW);
  739. if FElementNumber > 0 then
  740. FEBO.BindBufferData(nil, GR.GetElementArrayDataSize, GL_STREAM_DRAW)
  741. else
  742. FEBO.UnBind; // Just in case
  743. // Predisable attributes
  744. for I := 0 to GLS_VERTEX_ATTR_NUM - 1 do
  745. EnabledLocations[I] := false;
  746. Offset := 0;
  747. for I := 0 to Attributes.Count - 1 do
  748. begin
  749. L := Attributes[I].Location;
  750. if L > -1 then
  751. begin
  752. EnabledLocations[I] := True;
  753. case Attributes[I].GLSLType of
  754. GLSLType1F: gl.VertexAttribPointer(L, 1, GL_FLOAT, false, 0, pointer(Offset));
  755. GLSLType2F: gl.VertexAttribPointer(L, 2, GL_FLOAT, false, 0, pointer(Offset));
  756. GLSLType3F: gl.VertexAttribPointer(L, 3, GL_FLOAT, false, 0, pointer(Offset));
  757. GLSLType4F: gl.VertexAttribPointer(L, 4, GL_FLOAT, false, 0, pointer(Offset));
  758. GLSLType1I: gl.VertexAttribIPointer(L, 1, GL_INT, 0, pointer(Offset));
  759. GLSLType2I: gl.VertexAttribIPointer(L, 2, GL_INT, 0, pointer(Offset));
  760. GLSLType3I: gl.VertexAttribIPointer(L, 3, GL_INT, 0, pointer(Offset));
  761. GLSLType4I: gl.VertexAttribIPointer(L, 4, GL_INT, 0, pointer(Offset));
  762. GLSLType1UI: gl.VertexAttribIPointer(L, 1, GL_UNSIGNED_INT, 0, pointer(Offset));
  763. GLSLType2UI: gl.VertexAttribIPointer(L, 2, GL_UNSIGNED_INT, 0, pointer(Offset));
  764. GLSLType3UI: gl.VertexAttribIPointer(L, 3, GL_UNSIGNED_INT, 0, pointer(Offset));
  765. GLSLType4UI: gl.VertexAttribIPointer(L, 4, GL_UNSIGNED_INT, 0, pointer(Offset));
  766. GLSLTypeMat2F: gl.VertexAttribPointer(L, 4, GL_FLOAT, false, 0, pointer(Offset));
  767. GLSLTypeMat3F: gl.VertexAttribPointer(L, 9, GL_FLOAT, false, 0, pointer(Offset));
  768. GLSLTypeMat4F: gl.VertexAttribPointer(L, 16, GL_FLOAT, false, 0, pointer(Offset));
  769. end; // of case
  770. end;
  771. Inc(Offset, GR.GetAttribArraySize(Attributes[I]));
  772. end;
  773. // Enable engagement attributes array
  774. begin
  775. for I := GLS_VERTEX_ATTR_NUM - 1 downto 0 do
  776. if EnabledLocations[I] then
  777. gl.EnableVertexAttribArray(I)
  778. else
  779. gl.DisableVertexAttribArray(I);
  780. end;
  781. FVAO.UnBind;
  782. FVAO.NotifyDataUpdated;
  783. end;
  784. end;
  785. constructor TCUDACustomFeedBackMesh.Create(AOwner: TComponent);
  786. begin
  787. inherited;
  788. ObjectStyle := ObjectStyle + [osDirectDraw];
  789. FAttributes := TGLVertexAttributes.Create(Self);
  790. FVAO := TGLVertexArrayHandle.Create;
  791. FVBO := TGLVBOArrayBufferHandle.Create;
  792. FEBO := TGLVBOElementArrayHandle.Create;
  793. FPrimitiveType := fbmpPoint;
  794. FLaunching := fblCommon;
  795. FVertexNumber := 1;
  796. FElementNumber := 0;
  797. FBlend := False;
  798. end;
  799. destructor TCUDACustomFeedBackMesh.Destroy;
  800. begin
  801. Shader := nil;
  802. FAttributes.Destroy;
  803. FVAO.Destroy;
  804. FVBO.Destroy;
  805. FEBO.Destroy;
  806. inherited;
  807. end;
  808. procedure TCUDACustomFeedBackMesh.LaunchKernels;
  809. var
  810. i: Integer;
  811. GeomRes: TCUDAGeometryResource;
  812. //IR: TCUDAImageResource;
  813. begin
  814. if Assigned(FGeometryResource) then
  815. begin
  816. // Produce geometry resource
  817. GeomRes := TCUDAGeometryResource(FGeometryResource);
  818. GeomRes.MapResources;
  819. // Produce vertex attributes
  820. case Launching of
  821. fblCommon:
  822. begin
  823. for I := 0 to FAttributes.Count - 1 do
  824. with FAttributes.Attributes[I] do
  825. if Assigned(OnBeforeKernelLaunch) then
  826. OnBeforeKernelLaunch(FAttributes.Attributes[I]);
  827. if Assigned(FCommonFunc) then
  828. FCommonFunc.Launch;
  829. end;
  830. fblOnePerAtttribute:
  831. begin
  832. for I := 0 to FAttributes.Count - 1 do
  833. with FAttributes.Attributes[I] do
  834. begin
  835. if Assigned(OnBeforeKernelLaunch) then
  836. OnBeforeKernelLaunch(FAttributes.Attributes[I]);
  837. if Assigned(KernelFunction) then
  838. KernelFunction.Launch;
  839. end;
  840. end;
  841. else
  842. Assert(False, strErrorEx + strUnknownType);
  843. end;
  844. // Produce indexes
  845. if (GeomRes.GetElementArrayDataSize > 0)
  846. and Assigned(FCommonFunc) then
  847. FCommonFunc.Launch;
  848. GeomRes.UnMapResources;
  849. end;
  850. end;
  851. // // Produce image resource
  852. // else if FGLResource is TCUDAImageResource then
  853. // begin
  854. // IR := TCUDAImageResource(FGLResource);
  855. // IR.MapResources;
  856. // if Assigned(FBeforeLaunch) then
  857. // FBeforeLaunch(Self, 0);
  858. // if Assigned(FManufacturer) then
  859. // FManufacturer.Launch;
  860. // IR.UnMapResources;
  861. // end;
  862. procedure TCUDACustomFeedBackMesh.DoRender(var ARci: TGLRenderContextInfo; ARenderSelf,
  863. ARenderChildren: Boolean);
  864. const
  865. cPrimitives: array[TFeedBackMeshPrimitive] of Cardinal =
  866. (GL_POINTS, GL_LINES, GL_TRIANGLES);
  867. begin
  868. if ARenderSelf
  869. and not (csDesigning in ComponentState)
  870. and Assigned(FShader)
  871. and Assigned(FGeometryResource) then
  872. try
  873. FShader.Apply(ARci, Self);
  874. if FVAO.IsDataNeedUpdate then
  875. AllocateHandles;
  876. // Produce mesh data
  877. LaunchKernels;
  878. // Draw mesh
  879. FVAO.Bind;
  880. // Multipass Shader Loop
  881. repeat
  882. // Render mesh
  883. if FElementNumber > 0 then
  884. begin
  885. gl.DrawElements(
  886. cPrimitives[FPrimitiveType],
  887. FElementNumber,
  888. GL_UNSIGNED_INT,
  889. nil);
  890. end
  891. else
  892. begin
  893. gl.DrawArrays(
  894. cPrimitives[FPrimitiveType],
  895. 0,
  896. FVertexNumber);
  897. end;
  898. until not FShader.UnApply(ARci);
  899. FVAO.UnBind;
  900. except
  901. Visible := False;
  902. end;
  903. if ARenderChildren then
  904. Self.RenderChildren(0, Count - 1, ARci);
  905. end;
  906. procedure TCUDACustomFeedBackMesh.Notification(AComponent: TComponent;
  907. Operation: TOperation);
  908. var
  909. I: Integer;
  910. begin
  911. if Operation = opRemove then
  912. begin
  913. if AComponent = Shader then
  914. Shader := nil
  915. else if AComponent = FCommonFunc then
  916. CommonKernelFunction := nil
  917. else if AComponent is TCUDAFunction then
  918. begin
  919. for I := 0 to FAttributes.Count - 1 do
  920. if FAttributes[I].KernelFunction = AComponent then
  921. FAttributes[I].KernelFunction := nil;
  922. end;
  923. end;
  924. inherited;
  925. end;
  926. procedure TCUDACustomFeedBackMesh.RefreshAttributes;
  927. var
  928. I: Integer;
  929. AttribInfo: TGLActiveAttribArray;
  930. begin
  931. if Assigned(FShader) and FShader.Enabled then
  932. begin
  933. FShader.FailedInitAction := fiaSilentDisable;
  934. Scene.CurrentBuffer.RenderingContext.Activate;
  935. try
  936. AttribInfo := FShader.GetActiveAttribs;
  937. except
  938. FShader.Enabled := False;
  939. Scene.CurrentBuffer.RenderingContext.Deactivate;
  940. exit;
  941. end;
  942. Scene.CurrentBuffer.RenderingContext.Deactivate;
  943. FAttributes.Clear;
  944. for I := 0 to High(AttribInfo) do
  945. begin
  946. with FAttributes.Add do
  947. begin
  948. Name := AttribInfo[I].Name;
  949. GLSLType := AttribInfo[I].AType;
  950. FLocation := AttribInfo[I].Location;
  951. end;
  952. end;
  953. FVAO.NotifyChangesOfData;
  954. end;
  955. end;
  956. procedure TCUDACustomFeedBackMesh.SetAttributes(AValue: TGLVertexAttributes);
  957. begin
  958. FAttributes.Assign(AValue);
  959. end;
  960. procedure TCUDACustomFeedBackMesh.SetCommonFunc(AFunc: TCUDAFunction);
  961. begin
  962. if AFunc <> FCommonFunc then
  963. begin
  964. if Assigned(FCommonFunc) then
  965. FCommonFunc.RemoveFreeNotification(Self);
  966. FCommonFunc := AFunc;
  967. if Assigned(FCommonFunc) then
  968. FCommonFunc.FreeNotification(Self);
  969. end;
  970. end;
  971. procedure TCUDACustomFeedBackMesh.SetElementNumber(AValue: Integer);
  972. begin
  973. if AValue < 0 then
  974. AValue := 0;
  975. FElementNumber := AValue;
  976. FVAO.NotifyChangesOfData;
  977. end;
  978. procedure TCUDACustomFeedBackMesh.SetPrimitiveType(AValue: TFeedBackMeshPrimitive);
  979. begin
  980. FPrimitiveType := AValue;
  981. end;
  982. procedure TCUDACustomFeedBackMesh.SetShader(AShader: TGLSLShader);
  983. begin
  984. if AShader <> FShader then
  985. begin
  986. if Assigned(FShader) then
  987. FShader.RemoveFreeNotification(Self);
  988. FShader := AShader;
  989. if Assigned(FShader) then
  990. FShader.FreeNotification(Self);
  991. if not (csLoading in ComponentState) then
  992. RefreshAttributes;
  993. end;
  994. end;
  995. procedure TCUDACustomFeedBackMesh.SetVertexNumber(AValue: Integer);
  996. begin
  997. if AValue < 1 then
  998. AValue := 1;
  999. FVertexNumber := AValue;
  1000. FVAO.NotifyChangesOfData;
  1001. end;
  1002. //------------------------------------------
  1003. initialization
  1004. //------------------------------------------
  1005. RegisterClasses([TCUDAImageResource, TCUDAGeometryResource,
  1006. TCUDACustomFeedBackMesh, TCUDAFeedbackMesh]);
  1007. end.