GLS.CUDAGraphics.pas 31 KB

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