GLS.CUDA.Graphics.pas 30 KB

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