mirror of
https://github.com/Nexoniarz/Fry3DX.git
synced 2026-11-03 04:24:26 +00:00
Vulkan: a compute shader the driver can't build is left out, not a crash
The Galaxy S22 (Xclipse 920) says it has ray queries but can't build the ray-traced light and fog shaders; Fry3DX crashed on start there. Android builds use a current glslc (not the NDK's 2022 one). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NMSrd5oe1GpUD7E6d825KP
This commit is contained in:
parent
39a11e401e
commit
5d4ff6338a
3 changed files with 20 additions and 11 deletions
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
|
@ -62,7 +62,7 @@ jobs:
|
||||||
- name: SDK
|
- name: SDK
|
||||||
run: |
|
run: |
|
||||||
yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" "ndk;27.2.12479018" "build-tools;35.0.0" "platforms;android-35" > /dev/null
|
yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" "ndk;27.2.12479018" "build-tools;35.0.0" "platforms;android-35" > /dev/null
|
||||||
sudo apt-get install -y ninja-build
|
sudo apt-get install -y ninja-build glslc
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
env:
|
||||||
ANDROID_NDK_ROOT: ${{ env.ANDROID_HOME }}/ndk/27.2.12479018
|
ANDROID_NDK_ROOT: ${{ env.ANDROID_HOME }}/ndk/27.2.12479018
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,12 @@ def main():
|
||||||
llvm = os.path.join(ndk, "toolchains", "llvm", "prebuilt", "linux-x86_64", "bin")
|
llvm = os.path.join(ndk, "toolchains", "llvm", "prebuilt", "linux-x86_64", "bin")
|
||||||
|
|
||||||
if not os.path.isdir(BUILD):
|
if not os.path.isdir(BUILD):
|
||||||
glslc = os.environ.get("GLSLC") or os.path.join(ndk, "shader-tools", "linux-x86_64", "glslc") # (the NDK's own, if none's given)
|
# A current glslc: $GLSLC, or the one on PATH. (Not the NDK's: its 2022 shaderc makes compute
|
||||||
run("cmake", "--preset", "android", *([f"-DGLSLC={glslc}"] if os.path.exists(glslc) else []), cwd=ROOT)
|
# shaders some phone drivers can't build, e.g. the Galaxy S22's.)
|
||||||
|
glslc = os.environ.get("GLSLC") or shutil.which("glslc")
|
||||||
|
if not glslc:
|
||||||
|
sys.exit("No glslc: install shaderc (or the Vulkan SDK), or set GLSLC")
|
||||||
|
run("cmake", "--preset", "android", f"-DGLSLC={glslc}", cwd=ROOT)
|
||||||
run("cmake", "--build", "--preset", "android", cwd=ROOT)
|
run("cmake", "--build", "--preset", "android", cwd=ROOT)
|
||||||
|
|
||||||
stage = os.path.join(BUILD, "apk")
|
stage = os.path.join(BUILD, "apk")
|
||||||
|
|
|
||||||
|
|
@ -671,7 +671,7 @@ private:
|
||||||
Texture hzbMips_[kHzbLevels]; // [0] unused (that's hzb_)
|
Texture hzbMips_[kHzbLevels]; // [0] unused (that's hzb_)
|
||||||
uint32_t gpuCulled_ = 0;
|
uint32_t gpuCulled_ = 0;
|
||||||
const vk::Buffer* cullFor_ = nullptr; // this frame's commands, while the opaque lists are drawn
|
const vk::Buffer* cullFor_ = nullptr; // this frame's commands, while the opaque lists are drawn
|
||||||
bool gpuCulling() const override { return true; }
|
bool gpuCulling() const override { return cullPipeline_ != VK_NULL_HANDLE; }
|
||||||
// The fog grid (froxel.comp): two cell buffers (this frame's, last frame's) and the integrated one.
|
// The fog grid (froxel.comp): two cell buffers (this frame's, last frame's) and the integrated one.
|
||||||
struct FroxelPush { VkDeviceAddress frame, cur, prev, integrated; glm::vec4 proj, prevPos, prevFwd; uint32_t mode, frameIndex; VkDeviceAddress tlas, smoke, smokeSky; glm::vec4 smokeOrigin; };
|
struct FroxelPush { VkDeviceAddress frame, cur, prev, integrated; glm::vec4 proj, prevPos, prevFwd; uint32_t mode, frameIndex; VkDeviceAddress tlas, smoke, smokeSky; glm::vec4 smokeOrigin; };
|
||||||
struct SmokeSkyPush { VkDeviceAddress frame, sky; };
|
struct SmokeSkyPush { VkDeviceAddress frame, sky; };
|
||||||
|
|
@ -685,7 +685,7 @@ private:
|
||||||
VkPipeline froxelPipeline_ = VK_NULL_HANDLE, froxelRtPipeline_ = VK_NULL_HANDLE; // (rays: sky seen from each cell)
|
VkPipeline froxelPipeline_ = VK_NULL_HANDLE, froxelRtPipeline_ = VK_NULL_HANDLE; // (rays: sky seen from each cell)
|
||||||
uint32_t froxelFrame_ = 0;
|
uint32_t froxelFrame_ = 0;
|
||||||
glm::vec4 froxelPrevPos_{0.0f}, froxelPrevFwd_{0.0f};
|
glm::vec4 froxelPrevPos_{0.0f}, froxelPrevFwd_{0.0f};
|
||||||
bool froxelFog() const override { return true; }
|
bool froxelFog() const override { return froxelPipeline_ != VK_NULL_HANDLE; }
|
||||||
// Real-time GI (gi.comp): the scene for rays (per frame in flight), and the probes (this
|
// Real-time GI (gi.comp): the scene for rays (per frame in flight), and the probes (this
|
||||||
// frame's, last frame's).
|
// frame's, last frame's).
|
||||||
struct Tlas {
|
struct Tlas {
|
||||||
|
|
@ -924,8 +924,10 @@ void VulkanBackend::createPipelines() {
|
||||||
adaptPipeline_ = makePipeline(dev, layout_, {kFullscreenVert, sizeof kFullscreenVert, kAdaptFrag, sizeof kAdaptFrag, kSceneFormat, false});
|
adaptPipeline_ = makePipeline(dev, layout_, {kFullscreenVert, sizeof kFullscreenVert, kAdaptFrag, sizeof kAdaptFrag, kSceneFormat, false});
|
||||||
ssrPipeline_ = makePipeline(dev, layout_, {kFullscreenVert, sizeof kFullscreenVert, kSsrFrag, sizeof kSsrFrag, kSceneFormat, false});
|
ssrPipeline_ = makePipeline(dev, layout_, {kFullscreenVert, sizeof kFullscreenVert, kSsrFrag, sizeof kSsrFrag, kSceneFormat, false});
|
||||||
shadowMeshPipeline_ = makePipeline(dev, layout_, {kMeshVert, sizeof kMeshVert, nullptr, 0, VK_FORMAT_UNDEFINED, true, true});
|
shadowMeshPipeline_ = makePipeline(dev, layout_, {kMeshVert, sizeof kMeshVert, nullptr, 0, VK_FORMAT_UNDEFINED, true, true});
|
||||||
// Compute pipelines (GPU culling, the fog grid), on the same layout.
|
// Compute pipelines (GPU culling, the fog grid, ray-traced light), on the same layout. All of
|
||||||
auto compute = [&](const uint32_t* code, size_t size, VkPipeline& out) {
|
// them are extras: one a driver can't build is left out (and what it does is off). (The
|
||||||
|
// Galaxy S22's driver says it has ray queries but can't build gi.comp or froxel_rt.comp.)
|
||||||
|
auto compute = [&](const char* name, const uint32_t* code, size_t size, VkPipeline& out) {
|
||||||
VkShaderModuleCreateInfo ci{VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO};
|
VkShaderModuleCreateInfo ci{VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO};
|
||||||
ci.codeSize = size;
|
ci.codeSize = size;
|
||||||
ci.pCode = code;
|
ci.pCode = code;
|
||||||
|
|
@ -934,12 +936,15 @@ void VulkanBackend::createPipelines() {
|
||||||
VkComputePipelineCreateInfo pi{VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO};
|
VkComputePipelineCreateInfo pi{VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO};
|
||||||
pi.stage = {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0, VK_SHADER_STAGE_COMPUTE_BIT, m, "main", nullptr};
|
pi.stage = {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0, VK_SHADER_STAGE_COMPUTE_BIT, m, "main", nullptr};
|
||||||
pi.layout = layout_;
|
pi.layout = layout_;
|
||||||
VK_CHECK(vkCreateComputePipelines(dev, VK_NULL_HANDLE, 1, &pi, nullptr, &out));
|
if (const VkResult res = vkCreateComputePipelines(dev, VK_NULL_HANDLE, 1, &pi, nullptr, &out); res != VK_SUCCESS) {
|
||||||
|
log::warn("The graphics driver couldn't build the {} shader (VkResult {}): it's off", name, int(res));
|
||||||
|
out = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
vkDestroyShaderModule(dev, m, nullptr);
|
vkDestroyShaderModule(dev, m, nullptr);
|
||||||
};
|
};
|
||||||
compute(kCullComp, sizeof kCullComp, cullPipeline_);
|
compute("GPU culling", kCullComp, sizeof kCullComp, cullPipeline_);
|
||||||
compute(kFroxelComp, sizeof kFroxelComp, froxelPipeline_);
|
compute("fog grid", kFroxelComp, sizeof kFroxelComp, froxelPipeline_);
|
||||||
if (device_.rayQuery()) compute(kGiComp, sizeof kGiComp, giPipeline_), compute(kFroxelRtComp, sizeof kFroxelRtComp, froxelRtPipeline_);
|
if (device_.rayQuery()) compute("ray-traced light", kGiComp, sizeof kGiComp, giPipeline_), compute("ray-traced fog", kFroxelRtComp, sizeof kFroxelRtComp, froxelRtPipeline_);
|
||||||
// Depth pre-pass, and the scene's opaque meshes after it.
|
// Depth pre-pass, and the scene's opaque meshes after it.
|
||||||
depthMeshPipeline_ = makePipeline(dev, layout_, {kMeshVert, sizeof kMeshVert, kDepthFrag, sizeof kDepthFrag, VK_FORMAT_UNDEFINED, true});
|
depthMeshPipeline_ = makePipeline(dev, layout_, {kMeshVert, sizeof kMeshVert, kDepthFrag, sizeof kDepthFrag, VK_FORMAT_UNDEFINED, true});
|
||||||
depthSkinnedPipeline_ = makePipeline(dev, layout_, {kSkinnedVert, sizeof kSkinnedVert, kDepthFrag, sizeof kDepthFrag, VK_FORMAT_UNDEFINED, true});
|
depthSkinnedPipeline_ = makePipeline(dev, layout_, {kSkinnedVert, sizeof kSkinnedVert, kDepthFrag, sizeof kDepthFrag, VK_FORMAT_UNDEFINED, true});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue