209 void drawDeferredLighting()
override;
217 uint32_t gpuDrivenMeshRecord(
Mesh *
mesh)
override;
231 void gpuDrivenCullEmit(
const glm::mat4&
viewProj,
const glm::vec3&
eye,
float fovYDeg,
float nearZ,
232 float farZ)
override;
234 void gpuDrivenDrawOpaque()
override;
236 bool gpuDrivenResolveWanted()
const override;
238 void gpuDrivenRecordVisPass()
override;
240 void gpuDrivenResolve()
override;
244 uint32_t gpuDrivenVgAssetId(
Mesh *
mesh)
const override;
246 bool gpuDrivenVgAttachToMesh(
Mesh *
mesh, uint32_t vgAssetId)
override;
249 bool gpuDrivenVgSetInstance(uint32_t vgAssetId,
const glm::mat4&
model, uint32_t materialId)
override;
251 void gpuDrivenVgComputeSection(
const glm::mat4&
viewProj,
const glm::vec3&
eye,
float fovYDeg,
float nearZ,
252 float farZ)
override;
260 uint32_t debugGpuDrivenGpuVisibleCount();
268 uint32_t debugGpuDrivenVgGpuVisibleCount();
272 [[nodiscard]]
Result<void> debugValidatePbrVariantBaseSources();
280 void initWithWindow(
void *nativeWindow)
override;
282 void present()
override;
284 void pushValidationScope()
override;
286 void popValidationScope()
override;
288 void setMsaaSamples(
int samples)
override;
292 void setVSync(
bool enabled)
override;
296 void setViewportSize(
int width,
int height,
int pixelwidth,
int pixelheight)
override;
298 void drawSolidRect(
float x,
float y,
float w,
float h,
const Color &
color,
303 void drawSolidRectRotated(
float cx,
float cy,
float w,
float h,
float degrees,
309 bool repeatV =
false)
override;
313#if !defined(__EMSCRIPTEN__)
318 std::span<const uint8_t> rgba)
override;
323 std::span<const uint16_t> rgbaHalf)
override;
328 std::span<const uint8_t> rgba)
override;
331 Texture *newCubemap(
int faceSize,
const uint8_t *rgbaFaces)
override;
333 Texture *newCubemap(
int faceSize,
const uint8_t *rgbaFaces,
337 Texture *newHDRCubemap(
int faceSize)
override;
342 bool copyHDRCanvasesToCubemap(
Canvas *
const *sources,
int faceCount,
346 bool filterHDRReflectionCubemap(
Texture *cubemap,
int sampleCount = 64)
override;
356 float getMaxAnisotropy()
const override;
358 Texture *newTextureFromFile(
const std::string &filename)
override;
360 bool reloadTextureFromFile(
const std::string &filename)
override;
364 bool releaseTexture(
Texture *texture)
override;
367 const uint8_t *rgba)
override;
370 int height, std::span<const std::uint8_t> rgba,
371 std::size_t bytesPerRow = 0)
override;
374 Texture *texture, std::span<const TextureRegionUpload> regions)
override;
377 void drawTexturedRect(
Texture *texture,
float x,
float y,
float w,
float h,
383 void drawTexturedRectUV(
Texture *texture,
float x,
float y,
float w,
float h,
float u0,
float v0,
384 float u1,
float v1,
const Color &
color)
override;
387 float h,
float u0,
float v0,
float u1,
float v1,
392 float w,
float h,
float degrees,
float u0,
float v0,
394 bool rotatedUV =
false,
422 Shader *newShaderFromSpv(
const std::vector<uint32_t> &vertSpv,
423 const std::vector<uint32_t> &fragSpv)
override;
425 Shader *newShaderFromSpvFile(
const std::string &vertPath,
const std::string &fragPath)
override;
427 Shader *newShaderFromWgsl(
const std::string &vertWgsl,
428 const std::string &fragWgsl)
override;
432 const std::vector<uint32_t> &fragSpv)
override;
436 const std::string &fragWgsl)
override;
440 const std::string &fragGlsl)
override;
442 Shader *newShader(
const std::string &vertGlsl,
const std::string &fragGlsl)
override;
444 Shader *newMeshShaderFromSpv(
const std::vector<uint32_t> &vertSpv,
445 const std::vector<uint32_t> &fragSpv)
override;
447 Shader *newMeshShaderFromWgsl(
const std::string &vertWgsl,
448 const std::string &fragWgsl)
override;
453 Shader *newMeshShader(
const std::string &vertGlsl,
const std::string &fragGlsl)
override;
455 Shader *newHairShaderFromSpv(
const std::vector<uint32_t> &vertSpv,
456 const std::vector<uint32_t> &fragSpv)
override;
458 Shader *newHairShaderFromWgsl(
const std::string &vertWgsl,
459 const std::string &fragWgsl)
override;
464 Mesh *newMeshFromAssimp(const ::aiMesh &
mesh)
override;
466 Mesh *newMeshFromAssimp(const ::aiMesh &
mesh,
const aiMatrix4x4 &worldTransform)
override;
468 Mesh *newMeshFromArrays(
const float *posXYZ,
const float *nrmXYZ,
const float *uvST,
477 Mesh *newMeshFromArraysColored(
const float *posXYZ,
const float *nrmXYZ,
const float *uvST,
481 [[nodiscard]] std::optional<eve::graphics::MeshBackendDescriptor> describeMesh(
Mesh *
mesh)
const override;
482 bool bakeMeshMorph(
Mesh *
mesh)
override;
484 bool updateMeshVertices(
Mesh *
mesh,
const float *posXYZ,
const float *nrmXYZ,
const float *uvST,
487 bool setMeshSkinningData(
Mesh *
mesh,
const uint16_t *joints4,
const float *weights4,
490 Mesh *newMeshSphere(
int slices = 32,
int stacks = 16)
override;
492 Mesh *newMeshCylinder(
int slices = 32,
int stacks = 1,
bool caps =
true)
override;
494 bool releaseMesh(
Mesh *
mesh)
override;
497 void begin3DFrame()
override;
499 void begin3DFrameToCanvas(
Canvas *canvas)
override;
501 void end3DFrameToCanvas()
override;
506 return completedOffscreenTimestampMs.exchange(0.f);
509 void setMesh3DViewProj(
const glm::mat4 &
viewProj)
override;
511 void setMesh3DView(
const glm::mat4 &
view)
override;
513 void setMesh3DClip(
float nearZ,
float farZ)
override;
515 Texture *getSceneColorTexture()
override;
521 Texture *getSceneLinearDepthTexture()
override;
528 void drawVoxelFaceInstances(
const uint32_t *packed,
int count,
float originX,
float originY,
529 float originZ,
const std::string &faceDir,
Texture *atlas,
530 int tilesPerRow = 16,
const uint32_t *ao =
nullptr)
override;
534 void setMesh3DPackedNormalMask(
bool enabled)
override;
538 void setMesh3DVirtualTexture(
bool enabled,
int pageCountX,
int pageCountY,
539 int atlasSlotsX,
int atlasSlotsY,
540 float borderFraction)
override;
546 [[nodiscard]] Mesh3DSceneColorCaptureStatus captureMesh3DSceneColor()
override;
554 const std::string &alphaTechnique =
"cutoff")
override;
556 void setMesh3DTexCellBomb(
float cellScale,
float strength,
float rotAmount = 1.f)
override;
558 void setMesh3DParallax(
float scale,
float minLayers = 8.f,
float maxLayers = 32.f)
override;
560 void setMesh3DLodDither(
float weight,
bool reverse,
bool enabled)
override;
564 void setCloudShadows(
float strength,
float worldCell,
float time,
float windSpeed,
float windAngle,
float coverage,
569 void setMesh3DClusteredActive(
bool active)
override;
571 void setMesh3DSSAO(
float intensity)
override;
573 void setMesh3DLight(
const glm::vec3 &
dir,
const glm::vec3 &
color)
override;
575 void setMesh3DCameraPos(
const glm::vec3 &
eye)
override;
577 void setMesh3DEnv(
Texture *cube,
float intensity)
override;
579 void setMesh3DEnvProbe(
const glm::vec3 &
center,
const glm::vec3 &extent)
override;
583 void setSceneExposure(
float exposure)
override { sceneExposure = std::max(exposure, 0.f); }
593 sceneInverseGamma = glm::max(inverseGamma, glm::vec3(0.001F));
604 float lensScale)
override {
605 sceneTransitionVignette = std::clamp(vignette, 0.0F, 1.0F);
606 sceneTransitionVignetteSmoothness = std::clamp(vignetteSmoothness, 0.01F, 1.0F);
607 sceneTransitionLensDistortion = std::clamp(lensDistortion, 0.0F, 1.0F);
608 sceneTransitionLensScale = std::clamp(lensScale, 0.01F, 5.0F);
621 sceneAutoExposureMinEV = minEV;
622 sceneAutoExposureMaxEV = maxEV;
632 sceneBloomIntensity = intensity;
633 sceneBloomThreshold = threshold;
641 float farZ)
override {
642 sceneDofFocusDistance = focusDistance;
643 sceneDofMaxBlurPx = maxBlurPx;
644 sceneDofFocusRange = focusRange;
645 sceneDofNearZ = nearZ;
659 void setMesh3DShadows(
const ShadowUpload &upload)
override;
661 void setMesh3DShadowReceive(
bool receive)
override;
665 void beginShadowPass(
int cascadeIndex)
override;
667 void drawMeshShadow(
Mesh *
mesh,
const glm::mat4 &lightMVP,
bool doubleSided =
true)
override;
673 void endShadowPass()
override;
676 void beginGBufferPass(
int width,
int height)
override;
678 void drawMeshGBuffer(
Mesh*
mesh,
const glm::mat4&
mvp,
const glm::mat4&
model,
float nearZ,
float farZ,
679 Texture*
albedo =
nullptr,
float tintR = 1.f,
float tintG = 1.f,
float tintB = 1.f,
680 float motionX = 0.f,
float motionY = 0.f,
float roughness = 0.45f,
683 void drawMeshGBufferAlpha(
Mesh*
mesh,
const glm::mat4&
mvp,
const glm::mat4&
model,
float nearZ,
float farZ,
684 Texture*
albedo =
nullptr,
float tintR = 1.f,
float tintG = 1.f,
float tintB = 1.f,
685 float motionX = 0.f,
float motionY = 0.f,
float roughness = 0.45f,
688 void endGBufferPass()
override;
690 image::ImageData *readGBufferToImageData(
const std::string &attachment)
override;
695 void beginDecalPass(
int width,
int height)
override;
697 void setDecalCamera(
const glm::mat4 &
viewProj,
float nearZ,
float farZ)
override;
700 const float uvRect[4],
float fade,
float normalStrength,
float roughnessStrength,
701 float metalStrength,
float emissiveStrength,
int blendMode = 0,
702 int projectionMode = 0,
float blendSharpness = 4.f,
703 float parallaxScale = 0.f,
float parallaxMinLayers = 8.f,
704 float parallaxMaxLayers = 24.f,
float edgeFadeWidth = 0.06f)
override;
706 void endDecalPass()
override;
708 image::ImageData *readDecalLayerToImageData(
const std::string &attachment)
override;
716 void setCanvas(
Canvas *canvas)
override;
718 bool isCanvasActive()
const override;
720 Canvas *getCanvas()
const override;
723 Texture *getTexture()
override;
727 bool beginFrameReadback(
const std::string &
path)
override;
729 int frameReadbackStatus()
const override;
735 void draw(
Canvas *C,
const glm::mat4 &matrix)
const override;
737 void clear(std::optional<Color>
color, std::optional<int> stencil, std::optional<double>
depth)
override;
739 Color getPixel(
int x,
int y)
override;
798 Texture *normalTexture =
nullptr;
799 Texture *heightTexture =
nullptr;
800 glm::vec4 virtualTexture{0.f};
801 glm::vec4 virtualAtlas{0.f};
802 glm::mat4
model{1.f};
806 BlendMode surfaceBlend = BlendMode::Alpha;
807 bool depthWrite =
false;
809 bool shadowReceive =
true;
816 ShadowUpload shadows{};
817 Texture *environment =
nullptr;
818 float environmentIntensity = 0.f;
821 std::string alphaTechnique =
"cutoff";
822 glm::vec4 lodFade{1.f, 0.f, 0.f, 0.f};
823 std::optional<PbrSurface> pbrSurface;
824 wgpu::Buffer skinBuffer;
825 uint32_t frameUboOffset = 0;
826 uint32_t pushUboOffset = 0;
827 uint32_t shadowUboOffset = 0;
828 uint32_t clusteredUboOffset = 0;
834 bool alphaTest =
false;
836 glm::vec4 lodFade{1.f, 0.f, 0.f, 0.f};
843 glm::mat4
model{1.f};
847 glm::vec2 motion{0.f};
850 bool alphaTest =
false;
852 uint32_t pushUboOffset = 0;
855 uint32_t instanceBufferOffset = 0;
856 uint32_t aoBufferOffset = 0;
858 GpuTexture *atlas =
nullptr;
860 glm::vec4 chunkOrigin{0.f};
861 glm::vec4 atlasInfo{16.f, 0.f, 0.f, 0.f};
863 uint32_t pushUboOffset = 0;
866 glm::mat4
model{1.f};
870 glm::vec4 uvRect{0.f, 0.f, 1.f, 1.f};
871 glm::vec4 fadeParams{1.f, 0.f, 0.f, 0.f};
872 glm::vec4 extraParams{0.f};
873 glm::vec4 surfaceParams{0.f, 8.f, 24.f, 0.06f};
877 void createDefaultTextures();
878 void createPipelineResources();
879 void create2DPipelines();
880 void createMesh3DPipelines();
881 wgpu::RenderPipeline get2DColorPipeline(BlendMode
blend,
bool offscreen);
882 wgpu::RenderPipeline get2DTexturedPipeline(BlendMode
blend,
bool offscreen);
883 wgpu::RenderPipeline get2DLitPipeline(BlendMode
blend, WGPUTextureFormat format);
884 wgpu::RenderPipeline getMesh3DPipeline(BlendMode
blend,
bool depthWrite,
bool doubleSided,
bool canvasTarget);
885 void createMesh3DClusteredPipeline();
886 void createShadowPipelines();
887 void createGbufferPipelines();
888 void createDecalPipeline();
889 void createVoxelPipelines();
890 void ensureGpuDrivenResources(uint32_t
instanceCount, uint32_t bucketCount);
891 void recordGpuDrivenCompute(wgpu::CommandEncoder encoder);
892 void flushGpuDrivenDraws(wgpu::RenderPassEncoder pass,
bool canvasTarget,
893 bool hdrCanvas =
false);
894 void ensureGpuDrivenVisibilityResources();
895 void recordGpuDrivenVisibility(wgpu::CommandEncoder encoder);
896 void flushGpuDrivenResolve(wgpu::RenderPassEncoder pass);
897 void ensureGpuDrivenVgResources();
898 void recordGpuDrivenVgCompute(wgpu::CommandEncoder encoder);
899 void recordGpuDrivenVgVisibility(wgpu::CommandEncoder encoder);
900 void flushGpuDrivenVgResolve(wgpu::RenderPassEncoder pass);
901 void createSceneColorResources(
int width,
int height);
902 void destroySceneColorResources();
903 void createShadowResources();
904 void destroyShadowResources();
905 void createGbufferResources(
int width,
int height);
906 void destroyGbufferResources();
908 void destroyDecalResources();
910 wgpu::RenderPipeline createPipelineForShader(GpuShader* gs, wgpu::TextureFormat format,
bool depth,
bool mesh3d,
911 bool hair,
bool shadow,
bool gbuffer, wgpu::PipelineLayout
layout);
912 wgpu::BindGroupLayout make2DBindGroupLayout();
913 wgpu::BindGroupLayout makeMesh3DBindGroupLayout();
914 wgpu::BindGroupLayout makeMesh3DClusteredBindGroupLayout();
915 wgpu::BindGroupLayout makeShadowBindGroupLayout();
916 wgpu::BindGroupLayout makeGbufferBindGroupLayout();
917 wgpu::BindGroupLayout makeDecalBindGroupLayout();
918 wgpu::BindGroupLayout makeVoxelBindGroupLayout();
919 wgpu::PipelineLayout make2DPipelineLayout();
920 wgpu::PipelineLayout makeMesh3DPipelineLayout();
921 wgpu::PipelineLayout makeMesh3DClusteredPipelineLayout();
922 wgpu::PipelineLayout makeShadowPipelineLayout();
923 wgpu::PipelineLayout makeGbufferPipelineLayout();
924 wgpu::PipelineLayout makeDecalPipelineLayout();
925 wgpu::PipelineLayout makeVoxelPipelineLayout();
927 GpuTexture *gpuForTexture(Texture *
t)
const;
928 GpuTexture *gpuForTextureOrWhite(Texture *
t)
const;
929 wgpu::BindGroup makeTex2DBindGroup(GpuTexture *
color, GpuTexture *
depth,
930 GpuTexture *motion =
nullptr, GpuTexture *extra =
nullptr,
931 GpuTexture *specular =
nullptr);
932 wgpu::BindGroup makeMeshBindGroup(GpuTexture*
albedo, GpuTexture*
normal, GpuTexture* env, GpuTexture*
height,
933 GpuTexture*
depth, GpuTexture* sceneColor, uint32_t frameUboOffset,
934 uint32_t shadowUboOffset, uint32_t pushUboOffset,
const wgpu::Buffer& skinBuffer);
935 wgpu::BindGroup makeMesh3DClusteredBindGroup(GpuTexture *
albedo, GpuTexture *
normal,
936 GpuTexture *env, GpuTexture *
height,
937 GpuTexture *
depth, wgpu::TextureView aoView,
938 uint32_t frameUboOffset, uint32_t shadowUboOffset);
939 void uploadClusteredLighting(
const ClusteredLightingUpload &upload);
940 void ensureMeshBindGroupsForDraw(Mesh3dDraw &
d);
941 wgpu::Sampler makeSampler(
const TextureSampler &
sampler, uint32_t mipLevels)
const;
943 void uploadTexturePixels(GpuTexture *gt,
const uint8_t *rgba,
int w,
int h,
944 const TextureCreateInfo &
info);
945 void uploadTexturePixelsMips(GpuTexture *gt,
const uint8_t *rgba,
int w,
int h);
946 void flush2D(wgpu::RenderPassEncoder pass,
int viewW,
int viewH, WGPUTextureFormat format);
947 void drawTexturedBatch(wgpu::RenderPassEncoder pass, TexturedBatch &
tb,
int viewW,
int viewH,
948 WGPUTextureFormat format,
bool offscreen);
949 void drawLitBatch(wgpu::RenderPassEncoder pass, LitBatch &lb,
int viewW,
int viewH,
950 WGPUTextureFormat format);
951 void flushMesh3D(wgpu::RenderPassEncoder pass, WGPUTextureFormat format,
952 bool canvasTarget =
false);
953 bool drawPbrMesh(wgpu::RenderPassEncoder pass, WGPUTextureFormat format,
954 bool canvasTarget, Mesh3dDraw &
draw, GpuMesh &
mesh);
955 void flushPrimitive3D(wgpu::RenderPassEncoder pass, WGPUTextureFormat format, uint32_t sampleCount);
956 wgpu::RenderPipeline getPrimitive3DPipeline(PrimitiveDepthMode
depth, BlendMode
blend, PrimitiveCullMode cull,
957 WGPUTextureFormat format, uint32_t sampleCount);
958 void flushShadowPass(wgpu::RenderPassEncoder pass,
int cascade);
959 void flushGbufferPass(wgpu::RenderPassEncoder pass);
960 void flushDecalPass(wgpu::RenderPassEncoder pass);
961 void submitPendingDeferredPasses();
962 void createDeferredLightingPipeline();
963 void destroyDeferredLightingResources();
964 void ensureDeferredLightingClusteredUpload();
966 void flushDeferredLighting(wgpu::RenderPassEncoder pass);
972 bool flushGBufferPassInto(wgpu::CommandEncoder& encoder,
bool runAo);
973 void flushVoxelDraws(wgpu::RenderPassEncoder pass, WGPUTextureFormat format);
981 uint32_t alloc(uint64_t
size, uint64_t alignment);
982 std::vector<wgpu::Buffer> palettes;
983 size_t paletteIndex = 0;
990 wgpu::Buffer uploadSkinPalette(Mesh*
mesh);
991 UboArena ¤tUboArena();
992 void ensureUboArena(UboArena &arena, uint64_t
bytes);
1000 uint64_t alloc(uint64_t
bytes);
1002 void reset() { used = 0; }
1004 VertexArena ¤tVertexArena();
1005 void ensureVertexArena(VertexArena &arena, uint64_t
bytes);
1007 uint32_t frameSlotCount()
const {
return kFramesInFlight; }
1008 uint32_t currentFrameSlot()
const {
return frameIndex % kFramesInFlight; }
1011 VertexArena voxelInstanceArena;
1013 VertexArena voxelAoArena;
1016 bool initialized =
false;
1017 bool deviceInitDone =
false;
1018 bool headless_ =
false;
1019 void *sdlWindow =
nullptr;
1020 int logicalW = 0, logicalH = 0;
1021 int pixelW = 0, pixelH = 0;
1022 float maxSamplerAnisotropy = 1.f;
1024 wgpu::Instance instance;
1028 wgpu::Surface surface;
1030 WGPUTextureFormat surfaceFormat = WGPUTextureFormat_BGRA8Unorm;
1031 std::atomic<bool> surfaceNeedsRecreate{
false};
1032 bool swapchainConfigured =
false;
1035 uint32_t frameIndex = 0;
1037 uint32_t lastPresentSlot = 0;
1038 bool sceneColorHistoryValid =
false;
1039 std::optional<size_t> mesh3dSceneColorCaptureIndex;
1040 static constexpr uint32_t kFramesInFlight = 2;
1041 std::vector<UboArena> uboArenas;
1042 std::vector<VertexArena> vertexArenas;
1043 wgpu::Buffer mesh3dFrameUboPool;
1044 uint32_t mesh3dFrameUboSlots[kFramesInFlight]{};
1045 wgpu::Buffer shadowUboPool;
1046 uint32_t shadowUboSlots[kFramesInFlight]{};
1047 wgpu::Buffer pushUboPool;
1048 uint32_t pushUboSlots[kFramesInFlight]{};
1051 GpuTexture *whiteTexture =
nullptr;
1052 GpuTexture *flatNormalTexture =
nullptr;
1053 GpuTexture *flatNormalTexture3D =
nullptr;
1054 GpuTexture *flatHeightTexture3D =
nullptr;
1055 GpuTexture *flatDepthTexture3D =
nullptr;
1056 GpuTexture *defaultEnvCubemap =
nullptr;
1057 wgpu::BindGroupLayout reflectionProbeFilterSetLayout;
1058 wgpu::PipelineLayout reflectionProbeFilterPipelineLayout;
1059 wgpu::RenderPipeline reflectionProbeFilterPipeline;
1060 GpuTexture *shadowDepthArray =
nullptr;
1064 GpuTexture *defaultShadowTex =
nullptr;
1067 wgpu::PipelineLayout tex2DPipelineLayout;
1068 wgpu::PipelineLayout mesh3dPipelineLayout;
1069 wgpu::RenderPipeline mesh3dCanvasPipeline;
1070 wgpu::BindGroupLayout mesh3dClusteredSetLayout;
1071 wgpu::PipelineLayout mesh3dClusteredPipelineLayout;
1072 wgpu::RenderPipeline mesh3dClusteredPipeline;
1075 struct ClusteredStorage {
1079 uint64_t lightsCap = 0;
1080 uint64_t tableCap = 0;
1081 uint64_t indicesCap = 0;
1082 } clusteredStorage[kFramesInFlight];
1083 wgpu::PipelineLayout shadowPipelineLayout;
1084 wgpu::PipelineLayout gbufferPipelineLayout;
1085 wgpu::PipelineLayout decalPipelineLayout;
1086 wgpu::PipelineLayout voxelPipelineLayout;
1087 wgpu::BindGroupLayout tex2DSetLayout;
1088 wgpu::BindGroupLayout mesh3dSetLayout;
1089 wgpu::BindGroupLayout shadowSetLayout;
1090 wgpu::BindGroupLayout gbufferSetLayout;
1091 wgpu::BindGroupLayout decalSetLayout;
1092 wgpu::BindGroupLayout voxelSetLayout;
1094 wgpu::BindGroupLayout deferredLightingSetLayout;
1095 wgpu::PipelineLayout deferredLightingPipelineLayout;
1096 wgpu::RenderPipeline deferredLightingPipeline;
1097 wgpu::Sampler deferredLightingNearestSampler;
1098 bool deferredLightingPending_ =
false;
1103 wgpu::PipelineLayout aoPipelineLayout;
1104 wgpu::RenderPipeline aoPipeline;
1105 wgpu::BindGroupLayout aoSetLayout;
1106 wgpu::Texture aoTex[2];
1107 wgpu::TextureView aoView[2];
1108 uint32_t aoWriteIndex = 0;
1109 bool aoReady =
false;
1112 wgpu::BindGroup makeAOBindGroup(wgpu::TextureView depthView);
1115 wgpu::Sampler mainSampler;
1116 wgpu::RenderPipeline colorPipeline;
1117 wgpu::RenderPipeline texturedPipeline;
1118 wgpu::RenderPipeline colorAdditivePipeline;
1119 wgpu::RenderPipeline texturedAdditivePipeline;
1120 wgpu::RenderPipeline colorPremultipliedPipeline;
1121 wgpu::RenderPipeline texturedPremultipliedPipeline;
1122 wgpu::RenderPipeline colorMultiplyPipeline;
1123 wgpu::RenderPipeline texturedMultiplyPipeline;
1124 wgpu::RenderPipeline colorOpaquePipeline;
1125 wgpu::RenderPipeline texturedOpaquePipeline;
1126 wgpu::RenderPipeline sceneTonemapPipeline;
1127 float sceneExposure = 1.f;
1128 glm::vec3 sceneColorFilter{1.f};
1129 glm::vec3 sceneLift{0.f};
1130 glm::vec3 sceneInverseGamma{1.f};
1131 glm::vec3 sceneGain{1.f};
1132 float sceneTransitionVignette = 0.0F;
1133 float sceneTransitionVignetteSmoothness = 0.2F;
1134 float sceneTransitionLensDistortion = 0.0F;
1135 float sceneTransitionLensScale = 1.0F;
1136 bool sceneAutoExposure =
false;
1137 float sceneAutoExposureMinEV = -8.f;
1138 float sceneAutoExposureMaxEV = 8.f;
1139 float sceneBloomIntensity = 0.f;
1140 float sceneBloomThreshold = 1.f;
1141 float sceneDofFocusDistance = 0.f;
1142 float sceneDofMaxBlurPx = 0.f;
1143 float sceneDofFocusRange = 8.f;
1144 float sceneDofNearZ = 0.1f;
1145 float sceneDofFarZ = 100.f;
1146 wgpu::RenderPipeline mesh3dPipeline;
1147 wgpu::RenderPipeline mesh3dTransparentPipeline;
1148 static constexpr size_t kMeshPipelineVariants = 20;
1149 std::array<wgpu::RenderPipeline, kMeshPipelineVariants> mesh3dPipelines;
1150 std::array<wgpu::RenderPipeline, kMeshPipelineVariants> mesh3dCanvasPipelines;
1151 wgpu::RenderPipeline mesh3dShadowPipeline;
1152 wgpu::RenderPipeline mesh3dShadowSingleSidedPipeline;
1153 wgpu::RenderPipeline mesh3dShadowAlphaPipeline;
1154 wgpu::RenderPipeline mesh3dShadowAlphaSingleSidedPipeline;
1155 wgpu::RenderPipeline mesh3dGbufferPipeline;
1156 wgpu::RenderPipeline mesh3dGbufferAlphaPipeline;
1157 wgpu::RenderPipeline decalPipeline;
1158 wgpu::RenderPipeline voxelRectPipeline;
1159 wgpu::RenderPipeline lit2dPipeline;
1160 wgpu::RenderPipeline lit2dAdditivePipeline;
1161 wgpu::RenderPipeline lit2dPremultipliedPipeline;
1162 wgpu::RenderPipeline lit2dMultiplyPipeline;
1163 wgpu::RenderPipeline lit2dOpaquePipeline;
1165 wgpu::RenderPipeline offscreenColorPipeline;
1166 wgpu::RenderPipeline offscreenTexturedPipeline;
1167 wgpu::RenderPipeline offscreenColorAdditivePipeline;
1168 wgpu::RenderPipeline offscreenTexturedAdditivePipeline;
1169 wgpu::RenderPipeline offscreenColorPremultipliedPipeline;
1170 wgpu::RenderPipeline offscreenTexturedPremultipliedPipeline;
1171 wgpu::RenderPipeline offscreenColorMultiplyPipeline;
1172 wgpu::RenderPipeline offscreenTexturedMultiplyPipeline;
1173 wgpu::RenderPipeline offscreenColorOpaquePipeline;
1174 wgpu::RenderPipeline offscreenTexturedOpaquePipeline;
1175 wgpu::RenderPipeline hdrOffscreenTexturedPipeline;
1176 wgpu::RenderPipeline hdrOffscreenTexturedOpaquePipeline;
1177 wgpu::RenderPipeline offscreenLitPipeline;
1178 wgpu::RenderPipeline offscreenLitAdditivePipeline;
1179 wgpu::RenderPipeline offscreenLitPremultipliedPipeline;
1180 wgpu::RenderPipeline offscreenLitMultiplyPipeline;
1181 wgpu::RenderPipeline offscreenLitOpaquePipeline;
1182 wgpu::RenderPipeline hdrOffscreenLitPipeline;
1183 wgpu::RenderPipeline hdrOffscreenLitAdditivePipeline;
1184 wgpu::RenderPipeline hdrOffscreenLitPremultipliedPipeline;
1185 wgpu::RenderPipeline hdrOffscreenLitMultiplyPipeline;
1186 wgpu::RenderPipeline hdrOffscreenLitOpaquePipeline;
1188 wgpu::Buffer fullscreenQuadVb;
1189 wgpu::Buffer toneMapQuadVb;
1190 wgpu::Buffer fullscreenQuadIb;
1191 bool fullscreenQuadReady =
false;
1194 std::vector<SolidBatch> solidBatches;
1195 std::vector<TexturedBatch> texturedBatches;
1196 std::vector<LitBatch> litBatches;
1197 Lighting2DUBO lighting2dFrame{};
1198 enum class OverlayKind : uint8_t {
Solid, Textured, Lit };
1199 struct OverlaySpan {
1200 OverlayKind
kind = OverlayKind::Solid;
1202 uint32_t vertBegin = 0;
1203 uint32_t vertCount = 0;
1205 std::vector<OverlaySpan> overlaySpans;
1206 bool sceneColorComposited =
false;
1207 void noteSolidOverlay(uint32_t batchIndex);
1208 void noteTexturedOverlay(Texture *tex, uint32_t batchIndex);
1209 void noteLitOverlay(uint32_t batchIndex);
1210 void clear2DBatches();
1213 bool frame3DStarted =
false;
1214 bool sceneColorPassOpen =
false;
1217 OffscreenCanvas *active3DCanvas =
nullptr;
1218 bool offscreenTimestampSupported =
false;
1219 wgpu::QuerySet offscreenTimestampQuerySet;
1220 wgpu::Buffer offscreenTimestampResolveBuffer;
1221 struct OffscreenTimestampReadback {
1226 std::array<OffscreenTimestampReadback, 3> offscreenTimestampReadbacks{};
1227 size_t offscreenTimestampReadbackCursor = 0;
1228 mutable std::atomic<float> completedOffscreenTimestampMs{0.f};
1232 wgpu::Texture presentedReadback;
1233 int presentedReadbackW = 0, presentedReadbackH = 0;
1234 WGPUTextureFormat presentedReadbackFormat = WGPUTextureFormat_Undefined;
1235 bool surfaceCanCopySrc =
false;
1236 void recordPresentedReadback(wgpu::CommandEncoder &encoder,
const wgpu::Texture &surfaceTexture);
1237 wgpu::Texture lastReadbackTex;
1238 int lastReadbackW = 0;
1239 int lastReadbackH = 0;
1240 glm::mat4 mesh3dViewProj{1.f};
1241 glm::mat4 mesh3dView{1.f};
1242 float mesh3dNear = 0.1f, mesh3dFar = 100.f;
1243 struct Primitive3DVertex {
1244 glm::vec4 clipPosition{0.f};
1245 glm::vec4
color{1.f};
1247 struct Primitive3DDraw {
1248 ScenePrimitivePaint paint;
1249 float averageDepth = 0.f;
1251 std::vector<Primitive3DVertex>
vertices;
1253 std::vector<Primitive3DDraw> primitive3DDraws;
1254 std::unordered_map<std::uint64_t, wgpu::RenderPipeline> primitive3DPipelines;
1255 Texture *sceneColorTexture =
nullptr;
1256 Texture *mesh3dNormalTexture =
nullptr;
1257 Texture *mesh3dHeightTexture =
nullptr;
1258 Texture *mesh3dEnvTexture =
nullptr;
1259 Texture *mesh3dSceneDepthTexture =
nullptr;
1260 Texture *mesh3dSceneColorTexture =
nullptr;
1261 float mesh3dEnvIntensity = 0.f;
1262 glm::vec3 mesh3dEnvProbeCenter{0.f};
1263 glm::vec3 mesh3dEnvProbeExtent{0.f};
1264 ReflectionProbeUpload mesh3dReflectionProbes{};
1265 float mesh3dMetallic = 0.f;
1266 float mesh3dRoughness = 0.45f;
1267 SurfaceMode mesh3dSurfaceMode = SurfaceMode::Opaque;
1268 BlendMode mesh3dSurfaceBlend = BlendMode::Alpha;
1269 bool mesh3dSurfaceDepthWrite =
false;
1270 bool mesh3dSurfaceDoubleSided =
false;
1271 float mesh3dAlphaCutoff = 0.5f;
1272 std::string mesh3dAlphaTechnique =
"cutoff";
1273 glm::vec4 mesh3dLodFade{1.f, 0.f, 0.f, 0.f};
1274 float mesh3dTexBombScale = 4.f, mesh3dTexBombStrength = 0.f, mesh3dTexBombRot = 1.f;
1275 float mesh3dParallaxScale = 0.f, mesh3dParallaxMin = 8.f, mesh3dParallaxMax = 32.f;
1276 glm::vec4 mesh3dVirtualTexture{0.f};
1277 glm::vec4 mesh3dVirtualAtlas{0.f};
1278 float mesh3dSsaoIntensity = 1.f;
1279 glm::vec4 mesh3dCloud{0.f, 1.5f, 0.f, 0.f};
1280 glm::vec4 mesh3dCloudWind{4.f, 0.f, 0.55f, 0.5f};
1281 Lighting3DPack mesh3dLighting{};
1282 ShadowUpload mesh3dShadows{};
1283 bool mesh3dShadowReceive =
true;
1284 int mesh3dSkinInfluenceLimit = 4;
1285 bool mesh3dClusteredActive =
false;
1286 ClusteredLightingUpload mesh3dClustered{};
1287 glm::vec3 mesh3dCameraPos{0.f, 0.f, 3.f};
1288 bool frameHad3DThisFrame =
false;
1289 std::vector<Mesh3dDraw> mesh3dDraws;
1290 std::optional<PbrSurface> mesh3dPbrSurface;
1291 struct PbrResources;
1292 static void deletePbrResources(PbrResources *
resources);
1293 std::unique_ptr<PbrResources, void (*)(PbrResources *)> pbrResources_{
1294 nullptr, &deletePbrResources};
1296 bool hasPendingClear =
true;
1299 int shadowPassCascade = -1;
1300 std::vector<ShadowDraw> shadowPassDraws;
1301 std::vector<ShadowDraw> shadowCascadeDraws[ShadowConfig::kTotalLayers];
1304 bool gbufferPassActive =
false;
1305 bool gbufferPassPending =
false;
1306 std::vector<GbufferDraw> gbufferPassDraws;
1309 std::vector<VoxelDraw> voxelDraws;
1310 wgpu::Buffer voxelUnitQuadVerts;
1311 wgpu::Buffer voxelUnitQuadIndices;
1313 struct SceneColorSlot {
1314 wgpu::Texture msaaColor;
1315 wgpu::TextureView msaaView;
1316 wgpu::Texture
color;
1317 wgpu::TextureView colorView;
1318 wgpu::Texture
depth;
1319 wgpu::TextureView depthView;
1320 GpuTexture colorGpu;
1322 uint32_t sampleCount = 1;
1324 int sceneColorWidth = 0, sceneColorHeight = 0;
1327 WGPUTextureFormat sceneColorFormat = WGPUTextureFormat_RGBA8Unorm;
1328 uint32_t sceneColorSamples = 1;
1329 std::vector<SceneColorSlot> sceneColorSlots;
1332 struct ShadowMapSlot {
1333 wgpu::Texture texture;
1334 wgpu::TextureView
view;
1336 std::vector<ShadowMapSlot> shadowMaps;
1337 int shadowMapSize = ShadowConfig::kMapSize;
1340 struct GbufferSlot {
1342 wgpu::TextureView normalView;
1343 wgpu::Texture depthColor;
1344 wgpu::TextureView depthColorView;
1346 wgpu::TextureView albedoView;
1347 wgpu::Texture pbrParams;
1348 wgpu::TextureView pbrParamsView;
1349 wgpu::Texture emissive;
1350 wgpu::TextureView emissiveView;
1351 wgpu::Texture
depth;
1352 wgpu::TextureView depthView;
1353 wgpu::Texture visID;
1354 wgpu::TextureView visIDView;
1355 wgpu::Texture visBary;
1356 wgpu::TextureView visBaryView;
1357 GpuTexture normalGpu;
1358 GpuTexture depthColorGpu;
1359 GpuTexture albedoGpu;
1360 GpuTexture pbrParamsGpu;
1361 GpuTexture emissiveGpu;
1362 GpuTexture depthGpu;
1370 int gbufferWidth = 0, gbufferHeight = 0;
1371 std::vector<GbufferSlot> gbufferSlots;
1372 uint32_t lastGbufferSlot = 0;
1373 bool gbufferDepthValid_ =
false;
1377 wgpu::TextureView albedoView;
1379 wgpu::TextureView normalView;
1381 wgpu::TextureView paramsView;
1383 int decalWidth = 0, decalHeight = 0;
1384 std::vector<DecalSlot> decalSlots;
1385 std::vector<DecalDraw> decalPassDraws;
1386 glm::mat4 decalViewProj{1.f};
1387 bool decalPassActive =
false;
1388 bool decalPassPending =
false;
1389 bool decalReady =
false;
1390 uint32_t lastDecalSlot = 0;
1391 Texture *decalFlatAlbedo =
nullptr;
1392 Texture *decalFlatNormal =
nullptr;
1393 Texture *decalFlatParams =
nullptr;
1396 Canvas *activeCanvas =
nullptr;
1397 std::vector<std::unique_ptr<eve::graphics::Canvas>> ownedCanvases;
1400 std::vector<std::unique_ptr<Texture>> ownedTextures;
1401 std::vector<std::unique_ptr<GpuTexture>> ownedGpuTextures;
1402 std::unordered_map<std::string, Texture *> texturesByPath;
1403 std::unordered_map<std::string, Texture *> sharedTexturesByContent;
1404 std::vector<std::unique_ptr<Mesh>> ownedMeshes;
1405 std::vector<std::unique_ptr<GpuMesh>> ownedGpuMeshes;
1406 std::vector<std::unique_ptr<Shader>> ownedShaders;
1407 std::vector<std::unique_ptr<GpuShader>> ownedGpuShaders;
1412 bool gpuDrivenEnabled_ =
false;
1413 std::vector<Mesh *> gpuDrivenMeshes_;
1414 std::vector<Material *> gpuDrivenMaterials_;
1415 std::vector<uint32_t> gpuDrivenMaterialFree_;
1416 std::unordered_map<Mesh *, uint32_t> gpuDrivenMeshIds_;
1417 std::unordered_map<Material *, uint32_t> gpuDrivenMaterialIds_;
1418 std::vector<GpuInstance> gpuDrivenPending_;
1420 std::vector<GpuInstance> gpuDrivenVisible_;
1421 struct GpuDrivenBucket {
1425 uint32_t inputCount = 0;
1427 std::vector<GpuDrivenBucket> gpuDrivenBuckets_;
1428 wgpu::BindGroupLayout gpuDrivenComputeSetLayout_;
1429 wgpu::BindGroupLayout gpuDrivenRenderSetLayout_;
1430 wgpu::PipelineLayout gpuDrivenComputePipelineLayout_;
1431 wgpu::PipelineLayout gpuDrivenRenderPipelineLayout_;
1432 wgpu::ComputePipeline gpuDrivenCullPipeline_;
1433 wgpu::BindGroupLayout gpuDrivenHzbSetLayout_;
1434 wgpu::PipelineLayout gpuDrivenHzbPipelineLayout_;
1435 wgpu::ComputePipeline gpuDrivenHzbPipeline_;
1436 wgpu::Buffer gpuDrivenHzbBuffer_;
1437 wgpu::Buffer gpuDrivenHzbParamsBuffer_;
1438 wgpu::BindGroup gpuDrivenHzbBindGroup_;
1439 std::vector<uint32_t> gpuDrivenHzbOffsets_;
1440 uint32_t gpuDrivenHzbWidth_ = 0;
1441 uint32_t gpuDrivenHzbHeight_ = 0;
1442 uint64_t gpuDrivenHzbCapacity_ = 0;
1443 wgpu::RenderPipeline gpuDrivenRenderPipeline_;
1444 wgpu::RenderPipeline gpuDrivenCanvasPipeline_;
1445 wgpu::RenderPipeline gpuDrivenHdrCanvasPipeline_;
1446 wgpu::RenderPipeline gpuDrivenResidentRenderPipeline_;
1447 wgpu::RenderPipeline gpuDrivenResidentCanvasPipeline_;
1448 wgpu::RenderPipeline gpuDrivenResidentHdrCanvasPipeline_;
1449 wgpu::Buffer gpuDrivenParamsBuffer_;
1450 wgpu::Buffer gpuDrivenInputBuffer_;
1451 wgpu::Buffer gpuDrivenVisibleBuffer_;
1452 wgpu::Buffer gpuDrivenIndirectBuffer_;
1453 wgpu::Buffer gpuDrivenVisIndirectBuffer_;
1454 wgpu::BindGroup gpuDrivenComputeBindGroup_;
1455 wgpu::BindGroup gpuDrivenRenderBindGroup_;
1456 uint64_t gpuDrivenInputCapacity_ = 0;
1457 uint64_t gpuDrivenVisibleCapacity_ = 0;
1458 uint64_t gpuDrivenIndirectCapacity_ = 0;
1459 uint64_t gpuDrivenVisIndirectCapacity_ = 0;
1460 uint32_t gpuDrivenDispatchCount_ = 0;
1461 uint32_t gpuDrivenLastIndirectDrawCount_ = 0;
1462 uint32_t gpuDrivenLastBucketCount_ = 0;
1463 bool gpuDrivenComputePending_ =
false;
1464 bool gpuDrivenDrawPending_ =
false;
1465 bool gpuDrivenResidentDrawPending_ =
false;
1466 WGPUBuffer gpuDrivenResidentBuffer_ =
nullptr;
1467 uint64_t gpuDrivenResidentOffset_ = 0;
1468 uint64_t gpuDrivenResidentSize_ = 0;
1469 bool gpuDrivenVisPending_ =
false;
1470 bool gpuDrivenResolvePending_ =
false;
1471 wgpu::BindGroupLayout gpuDrivenVisSetLayout_;
1472 wgpu::BindGroupLayout gpuDrivenResolveSetLayout_;
1473 wgpu::PipelineLayout gpuDrivenVisPipelineLayout_;
1474 wgpu::PipelineLayout gpuDrivenResolvePipelineLayout_;
1475 wgpu::RenderPipeline gpuDrivenVisPipeline_;
1476 wgpu::RenderPipeline gpuDrivenResolvePipeline_;
1478 struct GpuDrivenVgAsset {
1481 wgpu::Buffer clusters;
1482 wgpu::Buffer indirect;
1485 uint32_t triangleCount = 0;
1486 uint32_t clusterCount = 0;
1488 glm::mat4
model{1.f};
1492 std::vector<GpuDrivenVgAsset> gpuDrivenVgAssets_;
1493 std::unordered_map<Mesh *, uint32_t> gpuDrivenVgMeshIds_;
1494 wgpu::BindGroupLayout gpuDrivenVgComputeSetLayout_;
1495 wgpu::BindGroupLayout gpuDrivenVgVisSetLayout_;
1496 wgpu::BindGroupLayout gpuDrivenVgResolveSetLayout_;
1497 wgpu::PipelineLayout gpuDrivenVgComputePipelineLayout_;
1498 wgpu::PipelineLayout gpuDrivenVgVisPipelineLayout_;
1499 wgpu::PipelineLayout gpuDrivenVgResolvePipelineLayout_;
1500 wgpu::ComputePipeline gpuDrivenVgCullPipeline_;
1501 wgpu::RenderPipeline gpuDrivenVgVisPipeline_;
1502 wgpu::RenderPipeline gpuDrivenVgResolvePipeline_;
1503 glm::mat4 gpuDrivenVgViewProj_{1.f};
1504 glm::vec3 gpuDrivenVgCameraPos_{0.f};
1505 float gpuDrivenVgFovYDeg_ = 60.f;
1506 float gpuDrivenVgNear_ = 0.1f;
1507 float gpuDrivenVgFar_ = 100.f;
1508 glm::vec4 gpuDrivenVgPlanes_[6]{};
1509 uint32_t gpuDrivenVgVisibleDiagnostic_ = 0;
1510 uint32_t gpuDrivenVgLastIndirectDrawCount_ = 0;
1511 bool gpuDrivenVgComputePending_ =
false;
1512 bool gpuDrivenVgVisPending_ =
false;
1513 bool gpuDrivenVgResolvePending_ =
false;
1517 struct PendingReadback {
1520 uint64_t bytesPerRow = 0;
1522 bool mapped =
false, done =
false,
ok =
false;
1523 bool hdr =
false, bgra =
false;
1525 std::unique_ptr<PendingReadback> pendingReadback_;
1531 using MeshBindGroupKey =
1532 std::tuple<uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t,
1533 uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t>;
1534 std::map<MeshBindGroupKey, wgpu::BindGroup> meshBindGroupCache_;
1535 static constexpr size_t kMaxMeshBindGroupCache = 128;
1536 void clearMeshBindGroupCache() { meshBindGroupCache_.clear(); }
1538 void markSwapchainDirty()
override { swapchainConfigured =
false; }
1539 void rebuildSwapchainIfNeeded();
1540 bool acquireSurfaceTexture(wgpu::TextureView &
view, wgpu::Texture &texture);