diff --git a/src/dawn_native/d3d12/ShaderModuleD3D12.cpp b/src/dawn_native/d3d12/ShaderModuleD3D12.cpp index 718e0c169f..d60132549f 100644 --- a/src/dawn_native/d3d12/ShaderModuleD3D12.cpp +++ b/src/dawn_native/d3d12/ShaderModuleD3D12.cpp @@ -28,10 +28,227 @@ #include #include +#include +#include +#include namespace dawn_native { namespace d3d12 { namespace { + ResultOrError GetDXCompilerVersion(ComPtr dxcValidator) { + ComPtr versionInfo; + DAWN_TRY(CheckHRESULT(dxcValidator.As(&versionInfo), + "D3D12 QueryInterface IDxcValidator to IDxcVersionInfo")); + + uint32_t compilerMajor, compilerMinor; + DAWN_TRY(CheckHRESULT(versionInfo->GetVersion(&compilerMajor, &compilerMinor), + "IDxcVersionInfo::GetVersion")); + + // Pack both into a single version number. + return (uint64_t(compilerMajor) << uint64_t(32)) + compilerMinor; + } + + uint64_t GetD3DCompilerVersion() { + return D3D_COMPILER_VERSION; + } + + struct CompareBindingPoint { + constexpr bool operator()(const tint::transform::BindingPoint& lhs, + const tint::transform::BindingPoint& rhs) const { + if (lhs.group != rhs.group) { + return lhs.group < rhs.group; + } else { + return lhs.binding < rhs.binding; + } + } + }; + + void Serialize(std::stringstream& output, const tint::ast::Access& access) { + output << access; + } + + void Serialize(std::stringstream& output, + const tint::transform::BindingPoint& binding_point) { + output << "(BindingPoint"; + output << " group=" << binding_point.group; + output << " binding=" << binding_point.binding; + output << ")"; + } + + template + void Serialize(std::stringstream& output, + const std::unordered_map& map) { + output << "(map"; + + std::map sorted(map.begin(), + map.end()); + for (auto& entry : sorted) { + output << " "; + Serialize(output, entry.first); + output << "="; + Serialize(output, entry.second); + } + output << ")"; + } + + // The inputs to a shader compilation. These have been intentionally isolated from the + // device to help ensure that the pipeline cache key contains all inputs for compilation. + struct ShaderCompilationRequest { + enum Compiler { FXC, DXC }; + + // Common inputs + Compiler compiler; + const tint::Program* program; + const char* entryPointName; + SingleShaderStage stage; + uint32_t compileFlags; + bool disableSymbolRenaming; + tint::transform::BindingRemapper::BindingPoints bindingPoints; + tint::transform::BindingRemapper::AccessControls accessControls; + bool isRobustnessEnabled; + + // FXC/DXC common inputs + bool disableWorkgroupInit; + + // FXC inputs + uint64_t fxcVersion; + + // DXC inputs + uint64_t dxcVersion; + const D3D12DeviceInfo* deviceInfo; + bool hasShaderFloat16Extension; + + static ResultOrError Create( + const char* entryPointName, + SingleShaderStage stage, + const PipelineLayout* layout, + uint32_t compileFlags, + const Device* device, + const tint::Program* program, + const BindingInfoArray& moduleBindingInfo) { + Compiler compiler; + uint64_t dxcVersion = 0; + if (device->IsToggleEnabled(Toggle::UseDXC)) { + compiler = Compiler::DXC; + DAWN_TRY_ASSIGN(dxcVersion, GetDXCompilerVersion(device->GetDxcValidator())); + } else { + compiler = Compiler::FXC; + } + + using tint::transform::BindingPoint; + using tint::transform::BindingRemapper; + + BindingRemapper::BindingPoints bindingPoints; + BindingRemapper::AccessControls accessControls; + + // d3d12::BindGroupLayout packs the bindings per HLSL register-space. We modify the + // Tint AST to make the "bindings" decoration match the offset chosen by + // d3d12::BindGroupLayout so that Tint produces HLSL with the correct registers + // assigned to each interface variable. + for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) { + const BindGroupLayout* bgl = ToBackend(layout->GetBindGroupLayout(group)); + const auto& groupBindingInfo = moduleBindingInfo[group]; + for (const auto& it : groupBindingInfo) { + BindingNumber binding = it.first; + auto const& bindingInfo = it.second; + BindingIndex bindingIndex = bgl->GetBindingIndex(binding); + BindingPoint srcBindingPoint{static_cast(group), + static_cast(binding)}; + BindingPoint dstBindingPoint{static_cast(group), + bgl->GetShaderRegister(bindingIndex)}; + if (srcBindingPoint != dstBindingPoint) { + bindingPoints.emplace(srcBindingPoint, dstBindingPoint); + } + + // Declaring a read-only storage buffer in HLSL but specifying a storage + // buffer in the BGL produces the wrong output. Force read-only storage + // buffer bindings to be treated as UAV instead of SRV. Internal storage + // buffer is a storage buffer used in the internal pipeline. + const bool forceStorageBufferAsUAV = + (bindingInfo.buffer.type == wgpu::BufferBindingType::ReadOnlyStorage && + (bgl->GetBindingInfo(bindingIndex).buffer.type == + wgpu::BufferBindingType::Storage || + bgl->GetBindingInfo(bindingIndex).buffer.type == + kInternalStorageBufferBinding)); + if (forceStorageBufferAsUAV) { + accessControls.emplace(srcBindingPoint, tint::ast::Access::kReadWrite); + } + } + } + + ShaderCompilationRequest request; + request.compiler = compiler; + request.program = program; + request.entryPointName = entryPointName; + request.stage = stage; + request.compileFlags = compileFlags; + request.disableSymbolRenaming = + device->IsToggleEnabled(Toggle::DisableSymbolRenaming); + request.bindingPoints = std::move(bindingPoints); + request.accessControls = std::move(accessControls); + request.isRobustnessEnabled = device->IsRobustnessEnabled(); + request.disableWorkgroupInit = + device->IsToggleEnabled(Toggle::DisableWorkgroupInit); + request.fxcVersion = compiler == Compiler::FXC ? GetD3DCompilerVersion() : 0; + request.dxcVersion = compiler == Compiler::DXC ? dxcVersion : 0; + request.deviceInfo = &device->GetDeviceInfo(); + request.hasShaderFloat16Extension = + device->IsExtensionEnabled(Extension::ShaderFloat16); + return std::move(request); + } + + ResultOrError CreateCacheKey() const { + // Generate the WGSL from the Tint program so it's normalized. + // TODO(tint:1180): Consider using a binary serialization of the tint AST for a more + // compact representation. + auto result = tint::writer::wgsl::Generate(program, tint::writer::wgsl::Options{}); + if (!result.success) { + std::ostringstream errorStream; + errorStream << "Tint WGSL failure:" << std::endl; + errorStream << "Generator: " << result.error << std::endl; + return DAWN_INTERNAL_ERROR(errorStream.str().c_str()); + } + + std::stringstream stream; + + // Prefix the key with the type to avoid collisions from another type that could + // have the same key. + stream << static_cast(PersistentKeyType::Shader); + stream << "\n"; + + stream << result.wgsl.length(); + stream << "\n"; + + stream << result.wgsl; + stream << "\n"; + + stream << "(ShaderCompilationRequest"; + stream << " compiler=" << compiler; + stream << " entryPointName=" << entryPointName; + stream << " stage=" << uint32_t(stage); + stream << " compileFlags=" << compileFlags; + stream << " disableSymbolRenaming=" << disableSymbolRenaming; + + stream << " bindingPoints="; + Serialize(stream, bindingPoints); + + stream << " accessControls="; + Serialize(stream, accessControls); + + stream << " shaderModel=" << deviceInfo->shaderModel; + stream << " disableWorkgroupInit=" << disableWorkgroupInit; + stream << " isRobustnessEnabled=" << isRobustnessEnabled; + stream << " fxcVersion=" << fxcVersion; + stream << " dxcVersion=" << dxcVersion; + stream << " hasShaderFloat16Extension=" << hasShaderFloat16Extension; + stream << ")"; + stream << "\n"; + + return PersistentCacheKey(std::istreambuf_iterator{stream}, + std::istreambuf_iterator{}); + } + }; + std::vector GetDXCArguments(uint32_t compileFlags, bool enable16BitTypes) { std::vector arguments; if (compileFlags & D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY) { @@ -83,85 +300,173 @@ namespace dawn_native { namespace d3d12 { return arguments; } + ResultOrError> CompileShaderDXC(IDxcLibrary* dxcLibrary, + IDxcCompiler* dxcCompiler, + const ShaderCompilationRequest& request, + const std::string& hlslSource) { + ComPtr sourceBlob; + DAWN_TRY( + CheckHRESULT(dxcLibrary->CreateBlobWithEncodingOnHeapCopy( + hlslSource.c_str(), hlslSource.length(), CP_UTF8, &sourceBlob), + "DXC create blob")); + + std::wstring entryPointW; + DAWN_TRY_ASSIGN(entryPointW, ConvertStringToWstring(request.entryPointName)); + + std::vector arguments = + GetDXCArguments(request.compileFlags, request.hasShaderFloat16Extension); + + ComPtr result; + DAWN_TRY(CheckHRESULT( + dxcCompiler->Compile(sourceBlob.Get(), nullptr, entryPointW.c_str(), + request.deviceInfo->shaderProfiles[request.stage].c_str(), + arguments.data(), arguments.size(), nullptr, 0, nullptr, + &result), + "DXC compile")); + + HRESULT hr; + DAWN_TRY(CheckHRESULT(result->GetStatus(&hr), "DXC get status")); + + if (FAILED(hr)) { + ComPtr errors; + DAWN_TRY(CheckHRESULT(result->GetErrorBuffer(&errors), "DXC get error buffer")); + + std::string message = std::string("DXC compile failed with ") + + static_cast(errors->GetBufferPointer()); + return DAWN_VALIDATION_ERROR(message); + } + + ComPtr compiledShader; + DAWN_TRY(CheckHRESULT(result->GetResult(&compiledShader), "DXC get result")); + return std::move(compiledShader); + } + + ResultOrError> CompileShaderFXC(const PlatformFunctions* functions, + const ShaderCompilationRequest& request, + const std::string& hlslSource) { + const char* targetProfile = nullptr; + switch (request.stage) { + case SingleShaderStage::Vertex: + targetProfile = "vs_5_1"; + break; + case SingleShaderStage::Fragment: + targetProfile = "ps_5_1"; + break; + case SingleShaderStage::Compute: + targetProfile = "cs_5_1"; + break; + } + + ComPtr compiledShader; + ComPtr errors; + + if (FAILED(functions->d3dCompile(hlslSource.c_str(), hlslSource.length(), nullptr, + nullptr, nullptr, request.entryPointName, + targetProfile, request.compileFlags, 0, + &compiledShader, &errors))) { + std::string message = std::string("D3D compile failed with ") + + static_cast(errors->GetBufferPointer()); + return DAWN_VALIDATION_ERROR(message); + } + + return std::move(compiledShader); + } + + ResultOrError TranslateToHLSL(const ShaderCompilationRequest& request, + std::string* remappedEntryPointName) { + std::ostringstream errorStream; + errorStream << "Tint HLSL failure:" << std::endl; + + tint::transform::Manager transformManager; + tint::transform::DataMap transformInputs; + + if (request.isRobustnessEnabled) { + transformManager.Add(); + } + transformManager.Add(); + + transformManager.Add(); + + if (request.disableSymbolRenaming) { + // We still need to rename HLSL reserved keywords + transformInputs.Add( + tint::transform::Renamer::Target::kHlslKeywords); + } + + // D3D12 registers like `t3` and `c3` have the same bindingOffset number in + // the remapping but should not be considered a collision because they have + // different types. + const bool mayCollide = true; + transformInputs.Add( + std::move(request.bindingPoints), std::move(request.accessControls), mayCollide); + + tint::Program transformedProgram; + tint::transform::DataMap transformOutputs; + DAWN_TRY_ASSIGN(transformedProgram, + RunTransforms(&transformManager, request.program, transformInputs, + &transformOutputs, nullptr)); + + if (auto* data = transformOutputs.Get()) { + auto it = data->remappings.find(request.entryPointName); + if (it != data->remappings.end()) { + *remappedEntryPointName = it->second; + } else { + if (request.disableSymbolRenaming) { + *remappedEntryPointName = request.entryPointName; + } else { + return DAWN_VALIDATION_ERROR( + "Could not find remapped name for entry point."); + } + } + } else { + return DAWN_VALIDATION_ERROR("Transform output missing renamer data."); + } + + tint::writer::hlsl::Options options; + options.disable_workgroup_init = request.disableWorkgroupInit; + auto result = tint::writer::hlsl::Generate(&transformedProgram, options); + if (!result.success) { + errorStream << "Generator: " << result.error << std::endl; + return DAWN_VALIDATION_ERROR(errorStream.str().c_str()); + } + + return std::move(result.hlsl); + } + + template + MaybeError CompileShader(const PlatformFunctions* functions, + IDxcLibrary* dxcLibrary, + IDxcCompiler* dxcCompiler, + ShaderCompilationRequest&& request, + bool dumpShaders, + F&& DumpShadersEmitLog, + CompiledShader* compiledShader) { + // Compile the source shader to HLSL. + std::string hlslSource; + std::string remappedEntryPoint; + DAWN_TRY_ASSIGN(hlslSource, TranslateToHLSL(request, &remappedEntryPoint)); + if (dumpShaders) { + std::ostringstream dumpedMsg; + dumpedMsg << "/* Dumped generated HLSL */" << std::endl << hlslSource; + DumpShadersEmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str()); + } + request.entryPointName = remappedEntryPoint.c_str(); + switch (request.compiler) { + case ShaderCompilationRequest::Compiler::DXC: + DAWN_TRY_ASSIGN(compiledShader->compiledDXCShader, + CompileShaderDXC(dxcLibrary, dxcCompiler, request, hlslSource)); + break; + case ShaderCompilationRequest::Compiler::FXC: + DAWN_TRY_ASSIGN(compiledShader->compiledFXCShader, + CompileShaderFXC(functions, request, hlslSource)); + break; + } + + return {}; + } + } // anonymous namespace - ResultOrError> CompileShaderDXC(Device* device, - SingleShaderStage stage, - const std::string& hlslSource, - const char* entryPoint, - uint32_t compileFlags) { - ComPtr dxcLibrary = device->GetDxcLibrary(); - - ComPtr sourceBlob; - DAWN_TRY(CheckHRESULT(dxcLibrary->CreateBlobWithEncodingOnHeapCopy( - hlslSource.c_str(), hlslSource.length(), CP_UTF8, &sourceBlob), - "DXC create blob")); - - ComPtr dxcCompiler = device->GetDxcCompiler(); - - std::wstring entryPointW; - DAWN_TRY_ASSIGN(entryPointW, ConvertStringToWstring(entryPoint)); - - std::vector arguments = - GetDXCArguments(compileFlags, device->IsExtensionEnabled(Extension::ShaderFloat16)); - - ComPtr result; - DAWN_TRY(CheckHRESULT( - dxcCompiler->Compile(sourceBlob.Get(), nullptr, entryPointW.c_str(), - device->GetDeviceInfo().shaderProfiles[stage].c_str(), - arguments.data(), arguments.size(), nullptr, 0, nullptr, &result), - "DXC compile")); - - HRESULT hr; - DAWN_TRY(CheckHRESULT(result->GetStatus(&hr), "DXC get status")); - - if (FAILED(hr)) { - ComPtr errors; - DAWN_TRY(CheckHRESULT(result->GetErrorBuffer(&errors), "DXC get error buffer")); - - std::string message = std::string("DXC compile failed with ") + - static_cast(errors->GetBufferPointer()); - return DAWN_VALIDATION_ERROR(message); - } - - ComPtr compiledShader; - DAWN_TRY(CheckHRESULT(result->GetResult(&compiledShader), "DXC get result")); - return std::move(compiledShader); - } - - ResultOrError> CompileShaderFXC(Device* device, - SingleShaderStage stage, - const std::string& hlslSource, - const char* entryPoint, - uint32_t compileFlags) { - const char* targetProfile = nullptr; - switch (stage) { - case SingleShaderStage::Vertex: - targetProfile = "vs_5_1"; - break; - case SingleShaderStage::Fragment: - targetProfile = "ps_5_1"; - break; - case SingleShaderStage::Compute: - targetProfile = "cs_5_1"; - break; - } - - ComPtr compiledShader; - ComPtr errors; - - const PlatformFunctions* functions = device->GetFunctions(); - if (FAILED(functions->d3dCompile(hlslSource.c_str(), hlslSource.length(), nullptr, nullptr, - nullptr, entryPoint, targetProfile, compileFlags, 0, - &compiledShader, &errors))) { - std::string message = std::string("D3D compile failed with ") + - static_cast(errors->GetBufferPointer()); - return DAWN_VALIDATION_ERROR(message); - } - - return std::move(compiledShader); - } - // static ResultOrError> ShaderModule::Create(Device* device, const ShaderModuleDescriptor* descriptor, @@ -180,120 +485,13 @@ namespace dawn_native { namespace d3d12 { return InitializeBase(parseResult); } - ResultOrError ShaderModule::TranslateToHLSL( - const tint::Program* program, - const char* entryPointName, - SingleShaderStage stage, - PipelineLayout* layout, - std::string* remappedEntryPointName) const { - ASSERT(!IsError()); - - ScopedTintICEHandler scopedICEHandler(GetDevice()); - - using BindingRemapper = tint::transform::BindingRemapper; - using BindingPoint = tint::transform::BindingPoint; - BindingRemapper::BindingPoints bindingPoints; - BindingRemapper::AccessControls accessControls; - - const BindingInfoArray& moduleBindingInfo = GetEntryPoint(entryPointName).bindings; - - // d3d12::BindGroupLayout packs the bindings per HLSL register-space. - // We modify the Tint AST to make the "bindings" decoration match the - // offset chosen by d3d12::BindGroupLayout so that Tint produces HLSL - // with the correct registers assigned to each interface variable. - for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) { - const BindGroupLayout* bgl = ToBackend(layout->GetBindGroupLayout(group)); - const auto& groupBindingInfo = moduleBindingInfo[group]; - for (const auto& it : groupBindingInfo) { - BindingNumber binding = it.first; - auto const& bindingInfo = it.second; - BindingIndex bindingIndex = bgl->GetBindingIndex(binding); - BindingPoint srcBindingPoint{static_cast(group), - static_cast(binding)}; - BindingPoint dstBindingPoint{static_cast(group), - bgl->GetShaderRegister(bindingIndex)}; - if (srcBindingPoint != dstBindingPoint) { - bindingPoints.emplace(srcBindingPoint, dstBindingPoint); - } - - // Declaring a read-only storage buffer in HLSL but specifying a - // storage buffer in the BGL produces the wrong output. - // Force read-only storage buffer bindings to be treated as UAV - // instead of SRV. - // Internal storage buffer is a storage buffer used in the internal pipeline. - const bool forceStorageBufferAsUAV = - (bindingInfo.buffer.type == wgpu::BufferBindingType::ReadOnlyStorage && - (bgl->GetBindingInfo(bindingIndex).buffer.type == - wgpu::BufferBindingType::Storage || - bgl->GetBindingInfo(bindingIndex).buffer.type == - kInternalStorageBufferBinding)); - if (forceStorageBufferAsUAV) { - accessControls.emplace(srcBindingPoint, tint::ast::Access::kReadWrite); - } - } - } - - std::ostringstream errorStream; - errorStream << "Tint HLSL failure:" << std::endl; - - tint::transform::Manager transformManager; - tint::transform::DataMap transformInputs; - - if (GetDevice()->IsRobustnessEnabled()) { - transformManager.Add(); - } - transformManager.Add(); - - transformManager.Add(); - - if (GetDevice()->IsToggleEnabled(Toggle::DisableSymbolRenaming)) { - // We still need to rename HLSL reserved keywords - transformInputs.Add( - tint::transform::Renamer::Target::kHlslKeywords); - } - - // D3D12 registers like `t3` and `c3` have the same bindingOffset number in the - // remapping but should not be considered a collision because they have different types. - const bool mayCollide = true; - transformInputs.Add(std::move(bindingPoints), - std::move(accessControls), mayCollide); - - tint::Program transformedProgram; - tint::transform::DataMap transformOutputs; - DAWN_TRY_ASSIGN( - transformedProgram, - RunTransforms(&transformManager, program, transformInputs, &transformOutputs, nullptr)); - - if (auto* data = transformOutputs.Get()) { - auto it = data->remappings.find(entryPointName); - if (it != data->remappings.end()) { - *remappedEntryPointName = it->second; - } else { - if (GetDevice()->IsToggleEnabled(Toggle::DisableSymbolRenaming)) { - *remappedEntryPointName = entryPointName; - } else { - return DAWN_VALIDATION_ERROR("Could not find remapped name for entry point."); - } - } - } else { - return DAWN_VALIDATION_ERROR("Transform output missing renamer data."); - } - - tint::writer::hlsl::Options options; - options.disable_workgroup_init = GetDevice()->IsToggleEnabled(Toggle::DisableWorkgroupInit); - auto result = tint::writer::hlsl::Generate(&transformedProgram, options); - if (!result.success) { - errorStream << "Generator: " << result.error << std::endl; - return DAWN_VALIDATION_ERROR(errorStream.str().c_str()); - } - - return std::move(result.hlsl); - } - ResultOrError ShaderModule::Compile(const char* entryPointName, SingleShaderStage stage, PipelineLayout* layout, uint32_t compileFlags) { + ASSERT(!IsError()); + ScopedTintICEHandler scopedICEHandler(GetDevice()); + Device* device = ToBackend(GetDevice()); CompiledShader compiledShader = {}; @@ -333,47 +531,33 @@ namespace dawn_native { namespace d3d12 { program = GetTintProgram(); } - // Compile the source shader to HLSL. - std::string hlslSource; - std::string remappedEntryPoint; - DAWN_TRY_ASSIGN(hlslSource, TranslateToHLSL(program, entryPointName, stage, layout, - &remappedEntryPoint)); - entryPointName = remappedEntryPoint.c_str(); + ShaderCompilationRequest request; + DAWN_TRY_ASSIGN(request, ShaderCompilationRequest::Create( + entryPointName, stage, layout, compileFlags, device, program, + GetEntryPoint(entryPointName).bindings)); - if (device->IsToggleEnabled(Toggle::DumpShaders)) { - std::ostringstream dumpedMsg; - dumpedMsg << "/* Dumped generated HLSL */" << std::endl << hlslSource; - GetDevice()->EmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str()); - } - - // Use HLSL source as the input for the key since it does need to know about the pipeline - // layout. The pipeline layout is only required if we key from WGSL: two different pipeline - // layouts could be used to produce different shader blobs and the wrong shader blob could - // be loaded since the pipeline layout was missing from the key. - // The compiler flags or version used could also produce different HLSL source. HLSL key - // needs both to ensure the shader cache key is unique to the HLSL source. - // TODO(dawn:549): Consider keying from WGSL and serialize the pipeline layout it used. PersistentCacheKey shaderCacheKey; - DAWN_TRY_ASSIGN(shaderCacheKey, - CreateHLSLKey(entryPointName, stage, hlslSource, compileFlags)); + DAWN_TRY_ASSIGN(shaderCacheKey, request.CreateCacheKey()); - DAWN_TRY_ASSIGN(compiledShader.cachedShader, - device->GetPersistentCache()->GetOrCreate( - shaderCacheKey, [&](auto doCache) -> MaybeError { - if (device->IsToggleEnabled(Toggle::UseDXC)) { - DAWN_TRY_ASSIGN(compiledShader.compiledDXCShader, - CompileShaderDXC(device, stage, hlslSource, - entryPointName, compileFlags)); - } else { - DAWN_TRY_ASSIGN(compiledShader.compiledFXCShader, - CompileShaderFXC(device, stage, hlslSource, - entryPointName, compileFlags)); - } - const D3D12_SHADER_BYTECODE shader = - compiledShader.GetD3D12ShaderBytecode(); - doCache(shader.pShaderBytecode, shader.BytecodeLength); - return {}; - })); + DAWN_TRY_ASSIGN( + compiledShader.cachedShader, + device->GetPersistentCache()->GetOrCreate( + shaderCacheKey, [&](auto doCache) -> MaybeError { + DAWN_TRY(CompileShader( + device->GetFunctions(), + device->IsToggleEnabled(Toggle::UseDXC) ? device->GetDxcLibrary().Get() + : nullptr, + device->IsToggleEnabled(Toggle::UseDXC) ? device->GetDxcCompiler().Get() + : nullptr, + std::move(request), device->IsToggleEnabled(Toggle::DumpShaders), + [&](WGPULoggingType loggingType, const char* message) { + GetDevice()->EmitLog(loggingType, message); + }, + &compiledShader)); + const D3D12_SHADER_BYTECODE shader = compiledShader.GetD3D12ShaderBytecode(); + doCache(shader.pShaderBytecode, shader.BytecodeLength); + return {}; + })); return std::move(compiledShader); } @@ -389,69 +573,4 @@ namespace dawn_native { namespace d3d12 { UNREACHABLE(); return {}; } - - ResultOrError ShaderModule::CreateHLSLKey(const char* entryPointName, - SingleShaderStage stage, - const std::string& hlslSource, - uint32_t compileFlags) const { - std::stringstream stream; - - // Prefix the key with the type to avoid collisions from another type that could have the - // same key. - stream << static_cast(PersistentKeyType::Shader); - - // Provide "guard" strings that the user cannot provide to help ensure the generated HLSL - // used to create this key is not being manufactured by the user to load the wrong shader - // blob. - // These strings can be HLSL comments because Tint does not emit HLSL comments. - // TODO(dawn:549): Replace guards strings with something more secure. - constexpr char kStartGuard[] = "// Start shader autogenerated by Dawn."; - constexpr char kEndGuard[] = "// End shader autogenerated by Dawn."; - ASSERT(hlslSource.find(kStartGuard) == std::string::npos); - ASSERT(hlslSource.find(kEndGuard) == std::string::npos); - - stream << kStartGuard << "\n"; - stream << hlslSource; - stream << "\n" << kEndGuard; - - stream << compileFlags; - - // Add the HLSL compiler version for good measure. - // Prepend the compiler name to ensure the version is always unique. - if (GetDevice()->IsToggleEnabled(Toggle::UseDXC)) { - uint64_t dxCompilerVersion; - DAWN_TRY_ASSIGN(dxCompilerVersion, GetDXCompilerVersion()); - stream << "DXC" << dxCompilerVersion; - } else { - stream << "FXC" << GetD3DCompilerVersion(); - } - - // If the source contains multiple entry points, ensure they are cached seperately - // per stage since DX shader code can only be compiled per stage using the same - // entry point. - stream << static_cast(stage); - stream << entryPointName; - - return PersistentCacheKey(std::istreambuf_iterator{stream}, - std::istreambuf_iterator{}); - } - - ResultOrError ShaderModule::GetDXCompilerVersion() const { - ComPtr dxcValidator = ToBackend(GetDevice())->GetDxcValidator(); - - ComPtr versionInfo; - DAWN_TRY(CheckHRESULT(dxcValidator.As(&versionInfo), - "D3D12 QueryInterface IDxcValidator to IDxcVersionInfo")); - - uint32_t compilerMajor, compilerMinor; - DAWN_TRY(CheckHRESULT(versionInfo->GetVersion(&compilerMajor, &compilerMinor), - "IDxcVersionInfo::GetVersion")); - - // Pack both into a single version number. - return (uint64_t(compilerMajor) << uint64_t(32)) + compilerMinor; - } - - uint64_t ShaderModule::GetD3DCompilerVersion() const { - return D3D_COMPILER_VERSION; - } }} // namespace dawn_native::d3d12 diff --git a/src/dawn_native/d3d12/ShaderModuleD3D12.h b/src/dawn_native/d3d12/ShaderModuleD3D12.h index 436d7bdd37..880a35cf45 100644 --- a/src/dawn_native/d3d12/ShaderModuleD3D12.h +++ b/src/dawn_native/d3d12/ShaderModuleD3D12.h @@ -58,20 +58,6 @@ namespace dawn_native { namespace d3d12 { ShaderModule(Device* device, const ShaderModuleDescriptor* descriptor); ~ShaderModule() override = default; MaybeError Initialize(ShaderModuleParseResult* parseResult); - - ResultOrError TranslateToHLSL(const tint::Program* program, - const char* entryPointName, - SingleShaderStage stage, - PipelineLayout* layout, - std::string* remappedEntryPointName) const; - - ResultOrError CreateHLSLKey(const char* entryPointName, - SingleShaderStage stage, - const std::string& hlslSource, - uint32_t compileFlags) const; - - ResultOrError GetDXCompilerVersion() const; - uint64_t GetD3DCompilerVersion() const; }; }} // namespace dawn_native::d3d12