From 2d8516b2cae689d5e832bcd64cc05c8c47b90875 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 25 Mar 2019 19:44:46 +0100 Subject: [PATCH] - make shaderClipDistance optional --- src/rendering/vulkan/shaders/vk_shader.cpp | 2 ++ src/rendering/vulkan/system/vk_device.cpp | 22 +++++++------- src/rendering/vulkan/system/vk_device.h | 3 +- wadsrc/static/shaders/glsl/main.fp | 9 ++++++ wadsrc/static/shaders/glsl/main.vp | 34 ++++++++++++++++------ 5 files changed, 50 insertions(+), 20 deletions(-) diff --git a/src/rendering/vulkan/shaders/vk_shader.cpp b/src/rendering/vulkan/shaders/vk_shader.cpp index af9de97ce..c0fee6dbd 100644 --- a/src/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/rendering/vulkan/shaders/vk_shader.cpp @@ -220,6 +220,7 @@ std::unique_ptr VkShaderManager::LoadVertShader(FString shadername { FString code = GetTargetGlslVersion(); code << defines << shaderBindings; + if (!device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n"; code << "#line 1\n"; code << LoadPrivateShaderLump(vert_lump).GetChars() << "\n"; @@ -233,6 +234,7 @@ std::unique_ptr VkShaderManager::LoadFragShader(FString shadername FString code = GetTargetGlslVersion(); code << defines << shaderBindings; + if (!device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n"; if (!alphatest) code << "#define NO_ALPHATEST\n"; if (gbufferpass) code << "#define GBUFFER_PASS\n"; diff --git a/src/rendering/vulkan/system/vk_device.cpp b/src/rendering/vulkan/system/vk_device.cpp index 86fbe5645..29693e56e 100644 --- a/src/rendering/vulkan/system/vk_device.cpp +++ b/src/rendering/vulkan/system/vk_device.cpp @@ -75,13 +75,8 @@ VulkanDevice::VulkanDevice() InitVolk(); CreateInstance(); CreateSurface(); - - UsedDeviceFeatures.samplerAnisotropy = VK_TRUE; - UsedDeviceFeatures.fragmentStoresAndAtomics = VK_TRUE; - UsedDeviceFeatures.depthClamp = VK_TRUE; - UsedDeviceFeatures.shaderClipDistance = VK_TRUE; - SelectPhysicalDevice(); + SelectFeatures(); CreateDevice(); CreateAllocator(); } @@ -97,13 +92,20 @@ VulkanDevice::~VulkanDevice() ReleaseResources(); } -bool VulkanDevice::CheckFeatures(const VkPhysicalDeviceFeatures &f) +void VulkanDevice::SelectFeatures() +{ + UsedDeviceFeatures.samplerAnisotropy = PhysicalDevice.Features.samplerAnisotropy; + UsedDeviceFeatures.fragmentStoresAndAtomics = PhysicalDevice.Features.fragmentStoresAndAtomics; + UsedDeviceFeatures.depthClamp = PhysicalDevice.Features.depthClamp; + UsedDeviceFeatures.shaderClipDistance = PhysicalDevice.Features.shaderClipDistance; +} + +bool VulkanDevice::CheckRequiredFeatures(const VkPhysicalDeviceFeatures &f) { return f.samplerAnisotropy == VK_TRUE && f.fragmentStoresAndAtomics == VK_TRUE && - f.depthClamp == VK_TRUE && - f.shaderClipDistance == VK_TRUE; + f.depthClamp == VK_TRUE; } void VulkanDevice::SelectPhysicalDevice() @@ -114,7 +116,7 @@ void VulkanDevice::SelectPhysicalDevice() { const auto &info = AvailableDevices[idx]; - if (!CheckFeatures(info.Features)) + if (!CheckRequiredFeatures(info.Features)) continue; VulkanCompatibleDevice dev; diff --git a/src/rendering/vulkan/system/vk_device.h b/src/rendering/vulkan/system/vk_device.h index ce158332e..9ad9ba40d 100644 --- a/src/rendering/vulkan/system/vk_device.h +++ b/src/rendering/vulkan/system/vk_device.h @@ -87,7 +87,8 @@ private: void CreateAllocator(); void ReleaseResources(); - static bool CheckFeatures(const VkPhysicalDeviceFeatures &f); + void SelectFeatures(); + static bool CheckRequiredFeatures(const VkPhysicalDeviceFeatures &f); VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE; diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index 64a914461..80094c456 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -10,6 +10,11 @@ layout(location = 5) in vec4 vWorldNormal; layout(location = 6) in vec4 vEyeNormal; #endif +#ifdef NO_CLIPDISTANCE_SUPPORT +layout(location = 7) in vec4 ClipDistanceA; +layout(location = 8) in vec4 ClipDistanceB; +#endif + layout(location=0) out vec4 FragColor; #ifdef GBUFFER_PASS layout(location=1) out vec4 FragFog; @@ -542,6 +547,10 @@ vec3 AmbientOcclusionColor() void main() { +#ifdef NO_CLIPDISTANCE_SUPPORT + if (ClipDistanceA.x < 0 || ClipDistanceA.y < 0 || ClipDistanceA.z < 0 || ClipDistanceA.w < 0 || ClipDistanceB.x < 0) discard; +#endif + Material material = ProcessMaterial(); vec4 frag = material.Base; diff --git a/wadsrc/static/shaders/glsl/main.vp b/wadsrc/static/shaders/glsl/main.vp index f3e1c3d22..cc332ad95 100644 --- a/wadsrc/static/shaders/glsl/main.vp +++ b/wadsrc/static/shaders/glsl/main.vp @@ -18,6 +18,22 @@ layout(location = 5) out vec4 vWorldNormal; layout(location = 6) out vec4 vEyeNormal; #endif +#ifdef NO_CLIPDISTANCE_SUPPORT +layout(location = 7) out vec4 ClipDistanceA; +layout(location = 8) out vec4 ClipDistanceB; +#define ClipDistance0 ClipDistanceA.x +#define ClipDistance1 ClipDistanceA.y +#define ClipDistance2 ClipDistanceA.z +#define ClipDistance3 ClipDistanceA.w +#define ClipDistance4 ClipDistanceB.x +#else +#define ClipDistance0 gl_ClipDistance[0] +#define ClipDistance1 gl_ClipDistance[1] +#define ClipDistance2 gl_ClipDistance[2] +#define ClipDistance3 gl_ClipDistance[3] +#define ClipDistance4 gl_ClipDistance[4] +#endif + void main() { vec2 parmTexCoord; @@ -67,8 +83,8 @@ void main() if (uSplitBottomPlane.z != 0.0) { - gl_ClipDistance[3] = ((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y; - gl_ClipDistance[4] = worldcoord.y - ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z); + ClipDistance3 = ((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y; + ClipDistance4 = worldcoord.y - ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z); } #ifdef HAS_UNIFORM_VERTEX_DATA @@ -101,25 +117,25 @@ void main() if (uClipHeightDirection != 0.0) // clip planes used for reflective flats { - gl_ClipDistance[0] = (worldcoord.y - uClipHeight) * uClipHeightDirection; + ClipDistance0 = (worldcoord.y - uClipHeight) * uClipHeightDirection; } else if (uClipLine.x > -1000000.0) // and for line portals - this will never be active at the same time as the reflective planes clipping so it can use the same hardware clip plane. { - gl_ClipDistance[0] = -( (worldcoord.z - uClipLine.y) * uClipLine.z + (uClipLine.x - worldcoord.x) * uClipLine.w ) + 1.0/32768.0; // allow a tiny bit of imprecisions for colinear linedefs. + ClipDistance0 = -( (worldcoord.z - uClipLine.y) * uClipLine.z + (uClipLine.x - worldcoord.x) * uClipLine.w ) + 1.0/32768.0; // allow a tiny bit of imprecisions for colinear linedefs. } else { - gl_ClipDistance[0] = 1; + ClipDistance0 = 1; } // clip planes used for translucency splitting - gl_ClipDistance[1] = worldcoord.y - uClipSplit.x; - gl_ClipDistance[2] = uClipSplit.y - worldcoord.y; + ClipDistance1 = worldcoord.y - uClipSplit.x; + ClipDistance2 = uClipSplit.y - worldcoord.y; if (uSplitTopPlane == vec4(0.0)) { - gl_ClipDistance[3] = 1; - gl_ClipDistance[4] = 1; + ClipDistance3 = 1.0; + ClipDistance4 = 1.0; } gl_PointSize = 1.0;