diff --git a/WickedEngine/offlineshadercompiler.cpp b/WickedEngine/offlineshadercompiler.cpp index 6d78cc701..d77bf6f64 100644 --- a/WickedEngine/offlineshadercompiler.cpp +++ b/WickedEngine/offlineshadercompiler.cpp @@ -18,6 +18,7 @@ std::vector targets; std::unordered_map results; bool rebuild = false; bool shaderdump_enabled = false; +bool testmode = false; int main(int argc, char* argv[]) { @@ -28,6 +29,7 @@ int main(int argc, char* argv[]) std::cout << "\tspirv : \tCompile shaders to spirv (vulkan) format (using dxcompiler)" << std::endl; std::cout << "\trebuild : \tAll shaders will be rebuilt, regardless if they are outdated or not" << std::endl; std::cout << "\tshaderdump : \tShaders will be saved to wiShaderDump.h C++ header file (rebuild is assumed)" << std::endl; + std::cout << "\ttestmode : \tRebuild in an infinite loop, stress test" << std::endl; std::cout << "Command arguments used: "; wiStartupArguments::Parse(argc, argv); @@ -61,6 +63,12 @@ int main(int argc, char* argv[]) std::cout << "rebuild "; } + if (wiStartupArguments::HasArgument("testmode")) + { + testmode = true; + std::cout << "testmode "; + } + std::cout << std::endl; if (targets.empty()) @@ -391,117 +399,121 @@ int main(int argc, char* argv[]) std::string SHADERSOURCEPATH = wiRenderer::GetShaderSourcePath(); wiHelper::MakePathAbsolute(SHADERSOURCEPATH); - std::cout << "[Wicked Engine Offline Shader Compiler] Searching for outdated shaders..." << std::endl; - wiTimer timer; + do { - for (auto& target : targets) - { - std::string SHADERPATH = target.dir; - wiHelper::DirectoryCreate(SHADERPATH); + std::cout << "[Wicked Engine Offline Shader Compiler] Searching for outdated shaders..." << std::endl; + wiTimer timer; - for (int i = 0; i < wiGraphics::SHADERSTAGE_COUNT; ++i) + for (auto& target : targets) { - if (target.format == wiGraphics::SHADERFORMAT_HLSL5) + std::string SHADERPATH = target.dir; + wiHelper::DirectoryCreate(SHADERPATH); + + for (int i = 0; i < wiGraphics::SHADERSTAGE_COUNT; ++i) { - if ( - i == wiGraphics::MS || - i == wiGraphics::AS || - i == wiGraphics::LIB - ) + if (target.format == wiGraphics::SHADERFORMAT_HLSL5) { - // shader stage not applicable to HLSL5 - continue; + if ( + i == wiGraphics::MS || + i == wiGraphics::AS || + i == wiGraphics::LIB + ) + { + // shader stage not applicable to HLSL5 + continue; + } + } + + for (auto& shader : shaders[i]) + { + wiJobSystem::Execute(ctx, [=](wiJobArgs args) { + std::string shaderbinaryfilename = wiHelper::ReplaceExtension(SHADERPATH + shader, "cso"); + if (!rebuild && !wiShaderCompiler::IsShaderOutdated(shaderbinaryfilename)) + { + return; + } + + wiShaderCompiler::CompilerInput input; + input.format = target.format; + input.stage = (wiGraphics::SHADERSTAGE)i; + input.shadersourcefilename = SHADERSOURCEPATH + shader; + input.include_directories.push_back(SHADERSOURCEPATH); + + wiShaderCompiler::CompilerOutput output; + wiShaderCompiler::Compile(input, output); + + if (output.IsValid()) + { + wiShaderCompiler::SaveShaderAndMetadata(shaderbinaryfilename, output); + + locker.lock(); + if (!output.error_message.empty()) + { + std::cerr << output.error_message << std::endl; + } + std::cout << "shader compiled: " << shaderbinaryfilename << std::endl; + if (shaderdump_enabled) + { + results[shaderbinaryfilename] = output; + } + locker.unlock(); + } + else + { + locker.lock(); + std::cerr << "shader compile FAILED: " << shaderbinaryfilename << std::endl << output.error_message; + locker.unlock(); + std::exit(1); + } + + }); } } - - for (auto& shader : shaders[i]) - { - wiJobSystem::Execute(ctx, [=](wiJobArgs args) { - std::string shaderbinaryfilename = wiHelper::ReplaceExtension(SHADERPATH + shader, "cso"); - if (!rebuild && !wiShaderCompiler::IsShaderOutdated(shaderbinaryfilename)) - { - return; - } - - wiShaderCompiler::CompilerInput input; - input.format = target.format; - input.stage = (wiGraphics::SHADERSTAGE)i; - input.shadersourcefilename = SHADERSOURCEPATH + shader; - input.include_directories.push_back(SHADERSOURCEPATH); - - wiShaderCompiler::CompilerOutput output; - wiShaderCompiler::Compile(input, output); - - if (output.IsValid()) - { - wiShaderCompiler::SaveShaderAndMetadata(shaderbinaryfilename, output); - - locker.lock(); - if (!output.error_message.empty()) - { - std::cerr << output.error_message << std::endl; - } - std::cout << "shader compiled: " << shaderbinaryfilename << std::endl; - if (shaderdump_enabled) - { - results[shaderbinaryfilename] = output; - } - locker.unlock(); - } - else - { - locker.lock(); - std::cerr << "shader compile FAILED: " << shaderbinaryfilename << std::endl << output.error_message; - locker.unlock(); - std::exit(1); - } - - }); - } } - } - wiJobSystem::Wait(ctx); + wiJobSystem::Wait(ctx); - std::cout << "[Wicked Engine Offline Shader Compiler] Finished in " << std::setprecision(4) << timer.elapsed_seconds() << " seconds" << std::endl; + std::cout << "[Wicked Engine Offline Shader Compiler] Finished in " << std::setprecision(4) << timer.elapsed_seconds() << " seconds" << std::endl; - if (shaderdump_enabled) - { - std::cout << "[Wicked Engine Offline Shader Compiler] Creating ShaderDump..." << std::endl; - timer.record(); - std::stringstream ss; - ss << "namespace wiShaderDump {" << std::endl; - for (auto& x : results) + if (shaderdump_enabled) { - auto& name = x.first; - auto& output = x.second; - - std::string name_repl = name; - std::replace(name_repl.begin(), name_repl.end(), '/', '_'); - std::replace(name_repl.begin(), name_repl.end(), '.', '_'); - ss << "const uint8_t " << name_repl << "[] = {"; - for (size_t i = 0; i < output.shadersize; ++i) + std::cout << "[Wicked Engine Offline Shader Compiler] Creating ShaderDump..." << std::endl; + timer.record(); + std::stringstream ss; + ss << "namespace wiShaderDump {" << std::endl; + for (auto& x : results) { - ss << (uint32_t)output.shaderdata[i] << ","; - } - ss << "};" << std::endl; - } - ss << "struct ShaderDumpEntry{const uint8_t* data; size_t size;};" << std::endl; - ss << "const std::unordered_map shaderdump = {" << std::endl; - for (auto& x : results) - { - auto& name = x.first; - auto& output = x.second; + auto& name = x.first; + auto& output = x.second; - std::string name_repl = name; - std::replace(name_repl.begin(), name_repl.end(), '/', '_'); - std::replace(name_repl.begin(), name_repl.end(), '.', '_'); - ss << "std::pair(\"" << name << "\", {" << name_repl << ",sizeof(" << name_repl << ")})," << std::endl; + std::string name_repl = name; + std::replace(name_repl.begin(), name_repl.end(), '/', '_'); + std::replace(name_repl.begin(), name_repl.end(), '.', '_'); + ss << "const uint8_t " << name_repl << "[] = {"; + for (size_t i = 0; i < output.shadersize; ++i) + { + ss << (uint32_t)output.shaderdata[i] << ","; + } + ss << "};" << std::endl; + } + ss << "struct ShaderDumpEntry{const uint8_t* data; size_t size;};" << std::endl; + ss << "const std::unordered_map shaderdump = {" << std::endl; + for (auto& x : results) + { + auto& name = x.first; + auto& output = x.second; + + std::string name_repl = name; + std::replace(name_repl.begin(), name_repl.end(), '/', '_'); + std::replace(name_repl.begin(), name_repl.end(), '.', '_'); + ss << "std::pair(\"" << name << "\", {" << name_repl << ",sizeof(" << name_repl << ")})," << std::endl; + } + ss << "};" << std::endl; // map end + ss << "}" << std::endl; // namespace end + wiHelper::FileWrite("wiShaderDump.h", (uint8_t*)ss.str().c_str(), ss.str().length()); + std::cout << "[Wicked Engine Offline Shader Compiler] ShaderDump written to wiShaderDump.h in " << std::setprecision(4) << timer.elapsed_seconds() << " seconds" << std::endl; } - ss << "};" << std::endl; // map end - ss << "}" << std::endl; // namespace end - wiHelper::FileWrite("wiShaderDump.h", (uint8_t*)ss.str().c_str(), ss.str().length()); - std::cout << "[Wicked Engine Offline Shader Compiler] ShaderDump written to wiShaderDump.h in " << std::setprecision(4) << timer.elapsed_seconds() << " seconds" << std::endl; - } + + }while (testmode); return 0; } diff --git a/WickedEngine/shaders/ShaderInterop_Renderer.h b/WickedEngine/shaders/ShaderInterop_Renderer.h index 50620eef5..f0e9a37ab 100644 --- a/WickedEngine/shaders/ShaderInterop_Renderer.h +++ b/WickedEngine/shaders/ShaderInterop_Renderer.h @@ -9,6 +9,7 @@ static const uint SHADERMATERIAL_OPTION_BIT_OCCLUSION_PRIMARY = 1 << 2; static const uint SHADERMATERIAL_OPTION_BIT_OCCLUSION_SECONDARY = 1 << 3; static const uint SHADERMATERIAL_OPTION_BIT_USE_WIND = 1 << 4; static const uint SHADERMATERIAL_OPTION_BIT_RECEIVE_SHADOW = 1 << 5; +static const uint SHADERMATERIAL_OPTION_BIT_CAST_SHADOW = 1 << 6; struct ShaderMaterial { @@ -81,6 +82,7 @@ struct ShaderMaterial inline bool IsOcclusionEnabled_Secondary() { return options & SHADERMATERIAL_OPTION_BIT_OCCLUSION_SECONDARY; } inline bool IsUsingWind() { return options & SHADERMATERIAL_OPTION_BIT_USE_WIND; } inline bool IsReceiveShadow() { return options & SHADERMATERIAL_OPTION_BIT_RECEIVE_SHADOW; } + inline bool IsCastingShadow() { return options & SHADERMATERIAL_OPTION_BIT_CAST_SHADOW; } }; struct ShaderMesh diff --git a/WickedEngine/shaders/raytraceCS.hlsl b/WickedEngine/shaders/raytraceCS.hlsl index ff97f723f..4467ac65f 100644 --- a/WickedEngine/shaders/raytraceCS.hlsl +++ b/WickedEngine/shaders/raytraceCS.hlsl @@ -294,6 +294,8 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) // Add a new bounce iteration, otherwise the transparent effect can disappear: bounces++; + + continue; // skip light sampling } else { @@ -495,6 +497,11 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) ShaderMeshSubset subset = bindless_subsets[mesh.subsetbuffer][q.CandidateGeometryIndex()]; ShaderMaterial material = bindless_buffers[subset.material].Load(0); [branch] + if (!material.IsCastingShadow()) + { + continue; + } + [branch] if (material.texture_basecolormap_index < 0) { q.CommitNonOpaqueTriangleHit(); diff --git a/WickedEngine/shaders/rtaoLIB.hlsl b/WickedEngine/shaders/rtaoLIB.hlsl index 028e14fd2..7ad5ce704 100644 --- a/WickedEngine/shaders/rtaoLIB.hlsl +++ b/WickedEngine/shaders/rtaoLIB.hlsl @@ -73,6 +73,12 @@ void RTAO_AnyHit(inout RayPayload payload, in BuiltInTriangleIntersectionAttribu ShaderMeshSubset subset = bindless_subsets[mesh.subsetbuffer][GeometryIndex()]; ShaderMaterial material = bindless_buffers[subset.material].Load(0); [branch] + if (!material.IsCastingShadow()) + { + IgnoreHit(); + return; + } + [branch] if (material.texture_basecolormap_index < 0) { AcceptHitAndEndSearch(); diff --git a/WickedEngine/shaders/rtshadowLIB.hlsl b/WickedEngine/shaders/rtshadowLIB.hlsl index 5d2060f9a..2d9e41998 100644 --- a/WickedEngine/shaders/rtshadowLIB.hlsl +++ b/WickedEngine/shaders/rtshadowLIB.hlsl @@ -61,9 +61,6 @@ void RTShadow_Raygen() { uint bucket_bits = EntityTiles[flatTileIndex + bucket]; - // Bucket scalarizer - Siggraph 2017 - Improved Culling [Michal Drobot]: - bucket_bits = WaveReadLaneFirst(WaveActiveBitOr(bucket_bits)); - [loop] while (bucket_bits != 0 && shadow_index < MAX_RTSHADOWS) { @@ -238,6 +235,12 @@ void RTShadow_AnyHit(inout RayPayload payload, in BuiltInTriangleIntersectionAtt ShaderMeshSubset subset = bindless_subsets[mesh.subsetbuffer][GeometryIndex()]; ShaderMaterial material = bindless_buffers[subset.material].Load(0); [branch] + if (!material.IsCastingShadow()) + { + IgnoreHit(); + return; + } + [branch] if (material.texture_basecolormap_index < 0) { AcceptHitAndEndSearch(); diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 9a51df68a..2f0daaf75 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -289,6 +289,10 @@ namespace wiScene { dest->options |= SHADERMATERIAL_OPTION_BIT_RECEIVE_SHADOW; } + if (IsCastingShadow()) + { + dest->options |= SHADERMATERIAL_OPTION_BIT_CAST_SHADOW; + } GraphicsDevice* device = wiRenderer::GetDevice(); dest->texture_basecolormap_index = device->GetDescriptorIndex(textures[BASECOLORMAP].GetGPUResource(), SRV); @@ -2607,7 +2611,7 @@ namespace wiScene { auto& geometry = mesh.BLAS.desc.bottomlevel.geometries[subsetIndex]; uint32_t flags = geometry._flags; - if (material->IsAlphaTestEnabled() || (material->GetRenderTypes() & RENDERTYPE_TRANSPARENT)) + if (material->IsAlphaTestEnabled() || (material->GetRenderTypes() & RENDERTYPE_TRANSPARENT) || !material->IsCastingShadow()) { geometry._flags &= ~RaytracingAccelerationStructureDesc::BottomLevel::Geometry::FLAG_OPAQUE; } diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index c8f8d1455..7252a4380 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -239,7 +239,7 @@ namespace wiScene inline void SetDirty(bool value = true) { if (value) { _flags |= DIRTY; } else { _flags &= ~DIRTY; } } inline bool IsDirty() const { return _flags & DIRTY; } - inline void SetCastShadow(bool value) { if (value) { _flags |= CAST_SHADOW; } else { _flags &= ~CAST_SHADOW; } } + inline void SetCastShadow(bool value) { SetDirty(); if (value) { _flags |= CAST_SHADOW; } else { _flags &= ~CAST_SHADOW; } } inline void SetReceiveShadow(bool value) { SetDirty(); if (value) { _flags &= ~DISABLE_RECEIVE_SHADOW; } else { _flags |= DISABLE_RECEIVE_SHADOW; } } inline void SetOcclusionEnabled_Primary(bool value) { SetDirty(); if (value) { _flags |= OCCLUSION_PRIMARY; } else { _flags &= ~OCCLUSION_PRIMARY; } } inline void SetOcclusionEnabled_Secondary(bool value) { SetDirty(); if (value) { _flags |= OCCLUSION_SECONDARY; } else { _flags &= ~OCCLUSION_SECONDARY; } } diff --git a/WickedEngine/wiShaderCompiler.cpp b/WickedEngine/wiShaderCompiler.cpp index 020cee5df..1d5338950 100644 --- a/WickedEngine/wiShaderCompiler.cpp +++ b/WickedEngine/wiShaderCompiler.cpp @@ -68,7 +68,6 @@ namespace wiShaderCompiler { case wiGraphics::SHADERFORMAT_HLSL6: args.push_back(L"-D"); args.push_back(L"HLSL6"); - args.push_back(L"-D"); args.push_back(L"DISABLE_WAVE_INTRINSICS"); // random (as in only happening sometimes) validation fails with wave intrinsics :( break; case wiGraphics::SHADERFORMAT_SPIRV: args.push_back(L"-D"); args.push_back(L"SPIRV"); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 39ee73553..d47eba3ee 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates, breaking compatibility changes const int minor = 55; // minor bug fixes, alterations, refactors, updates - const int revision = 5; + const int revision = 6; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);