diff --git a/renderdoc/driver/gl/gl_shaderdebug.cpp b/renderdoc/driver/gl/gl_shaderdebug.cpp index b55201d7f..4d2047d56 100644 --- a/renderdoc/driver/gl/gl_shaderdebug.cpp +++ b/renderdoc/driver/gl/gl_shaderdebug.cpp @@ -1276,12 +1276,15 @@ public: return true; } - virtual bool QueueCalculateMathOp(rdcspv::GLSLstd450 op, + virtual bool QueueCalculateMathOp(rdcspv::Op opcode, rdcspv::GLSLstd450 glslop, const rdcarray ¶ms) override { CHECK_DEVICE_THREAD(); RDCASSERT(params.size() <= 3, params.size()); + // only support GLSL std450 ops + RDCASSERT(opcode == rdcspv::Op::ExtInst && glslop != rdcspv::GLSLstd450::Invalid, opcode, glslop); + RDCASSERTEQUAL(params[0].type, VarType::Float); GLMarkerRegion markerRegion("QueueCalculateMathOp"); @@ -1363,7 +1366,7 @@ public: } // push the operation afterwards - GL.glUniform1i(GL.glGetUniformLocation(mathProg, "op"), (int32_t)op); + GL.glUniform1i(GL.glGetUniformLocation(mathProg, "op"), (int32_t)glslop); GL.glDispatchCompute(1, 1, 1); diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.cpp b/renderdoc/driver/shaders/spirv/spirv_debug.cpp index ece9c144a..5924d9787 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug.cpp @@ -2938,6 +2938,34 @@ void ThreadState::StepNext(bool useDebugState, const uint32_t steps, break; } + case Op::FmaKHR: + { + OpFmaKHR fma(it); + + const DataType &resultType = debugger.GetType(fma.resultType); + + if(IsPendingResultReady()) + { + ShaderVariable result = GetPendingResult(); + result.rows = 1; + result.columns = RDCMAX(1U, resultType.vector().count) & 0xff; + + SetDst(fma.result, result); + break; + } + + rdcarray paramVars; + paramVars.push_back(GetSrc(fma.operand1)); + paramVars.push_back(GetSrc(fma.operand2)); + paramVars.push_back(GetSrc(fma.operand3)); + + ShaderVariable ret = paramVars[0]; + + QueueMathOp(Op::FmaKHR, GLSLstd450::Invalid, paramVars, ret); + + break; + } + ////////////////////////////////////////////////////////////////////////////// // // Subgroup opcodes @@ -5400,7 +5428,6 @@ void ThreadState::StepNext(bool useDebugState, const uint32_t steps, case Op::CompositeConstructCoopMatQCOM: case Op::CompositeExtractCoopMatQCOM: case Op::ExtractSubArrayQCOM: - case Op::FmaKHR: case Op::BufferPointerEXT: case Op::UntypedImageTexelPointerEXT: case Op::ConstantSizeOfEXT: @@ -5729,13 +5756,14 @@ void ThreadState::ExecuteMemoryBarrier(Id semanticsId) } } -void ThreadState::QueueMathOp(GLSLstd450 op, const rdcarray ¶mVars, - const ShaderVariable &result) +void ThreadState::QueueMathOp(Op opcode, GLSLstd450 glslop, + const rdcarray ¶mVars, const ShaderVariable &result) { SPIRV_DEBUG_RDCASSERT(!IsPendingResultPending()); pendingResultData = result; queuedGpuMathOp.workgroupIndex = workgroupIndex; - queuedGpuMathOp.op = op; + queuedGpuMathOp.opcode = opcode; + queuedGpuMathOp.glslop = glslop; queuedGpuMathOp.paramVars = paramVars; queuedGpuMathOp.result = &pendingResultData; SetStepNeedsGpuMathOp(); diff --git a/renderdoc/driver/shaders/spirv/spirv_debug.h b/renderdoc/driver/shaders/spirv/spirv_debug.h index 6054ed63b..c92553033 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug.h +++ b/renderdoc/driver/shaders/spirv/spirv_debug.h @@ -156,7 +156,8 @@ public: const ShaderVariable &compare, GatherChannel gatherChannel, const rdcspv::ImageOperandsAndParamDatas &operands, ShaderVariable &output, bool &hasResult) = 0; - virtual bool QueueCalculateMathOp(GLSLstd450 op, const rdcarray ¶ms) = 0; + virtual bool QueueCalculateMathOp(Op opcode, GLSLstd450 op, + const rdcarray ¶ms) = 0; virtual bool GetQueuedResults(rdcarray &mathOpResults, rdcarray &sampleGatherResults) = 0; virtual bool QueuedOpsHasSpace() = 0; @@ -285,7 +286,8 @@ private: struct GpuMathOperation { uint32_t workgroupIndex; - GLSLstd450 op; + Op opcode; + GLSLstd450 glslop; rdcarray paramVars; ShaderVariable *result; }; @@ -419,7 +421,7 @@ struct ThreadState Stepped, }; - void QueueMathOp(GLSLstd450 op, const rdcarray ¶mVars, + void QueueMathOp(Op opcode, GLSLstd450 op, const rdcarray ¶mVars, const ShaderVariable &result); void QueueSampleGather(Op opcode, DebugAPIWrapper::TextureType texType, const ShaderBindIndex &imageBind, const ShaderBindIndex &samplerBind, diff --git a/renderdoc/driver/shaders/spirv/spirv_debug_glsl450.cpp b/renderdoc/driver/shaders/spirv/spirv_debug_glsl450.cpp index bf3452569..7705ba57d 100644 --- a/renderdoc/driver/shaders/spirv/spirv_debug_glsl450.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_debug_glsl450.cpp @@ -1242,7 +1242,7 @@ ShaderVariable GPUOp(ThreadState &state, uint32_t instruction, const rdcarrayQueueCalculateMathOp(mathOp.op, mathOp.paramVars)) + if(apiWrapper->QueueCalculateMathOp(mathOp.opcode, mathOp.glslop, mathOp.paramVars)) { pendingGpuMathsOpsResults.push_back(mathOp.result); } diff --git a/renderdoc/driver/vulkan/extension_support.md b/renderdoc/driver/vulkan/extension_support.md index 9dbb945f0..72c231fb3 100644 --- a/renderdoc/driver/vulkan/extension_support.md +++ b/renderdoc/driver/vulkan/extension_support.md @@ -229,6 +229,7 @@ Maintainers can update this file by updating vk.xml in this folder and running ` * `VK_KHR_shader_float_controls` * `VK_KHR_shader_float_controls2` * `VK_KHR_shader_float16_int8` +* `VK_KHR_shader_fma` * `VK_KHR_shader_integer_dot_product` * `VK_KHR_shader_maximal_reconvergence` * `VK_KHR_shader_non_semantic_info` @@ -300,7 +301,6 @@ KHR extensions will definitely be implemented at some point, though KHR extensio * `VK_KHR_maintenance11` * `VK_KHR_opacity_micromap` * `VK_KHR_pipeline_binary` -* `VK_KHR_shader_fma` * `VK_KHR_shader_untyped_pointers` ## KHR Portability diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index 5e7c72eaf..53c8f7977 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -1836,6 +1836,7 @@ DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceShaderDrawParametersFeatures); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceShaderExpectAssumeFeatures); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceShaderFloat16Int8Features); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceShaderFloatControls2Features); +DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceShaderFmaFeaturesKHR); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceShaderImageFootprintFeaturesNV); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceShaderIntegerDotProductFeatures); @@ -2390,6 +2391,7 @@ DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceShaderDrawParametersFeatures); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceShaderExpectAssumeFeatures); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceShaderFloat16Int8Features); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceShaderFloatControls2Features); +DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceShaderFmaFeaturesKHR); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceShaderImageFootprintFeaturesNV); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceShaderIntegerDotProductFeatures); diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 3c608e6c0..79283ef42 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -1916,6 +1916,10 @@ static const VkExtensionProperties supportedExtensions[] = { VK_KHR_SHADER_FLOAT_CONTROLS_2_EXTENSION_NAME, VK_KHR_SHADER_FLOAT_CONTROLS_2_SPEC_VERSION, }, + { + VK_KHR_SHADER_FMA_EXTENSION_NAME, + VK_KHR_SHADER_FMA_SPEC_VERSION, + }, { VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME, VK_KHR_SHADER_INTEGER_DOT_PRODUCT_SPEC_VERSION, diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 8b635a943..664d7c485 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -547,6 +547,7 @@ private: bool m_Maintenance9 = false; bool m_DescriptorBuffers = false; bool m_MultiviewPerViewViewports = false; + uint32_t m_PreciseFMAMask = 0; uint32_t m_RTCaptureReplayHandleSize = 0; @@ -1516,6 +1517,7 @@ public: bool DescriptorBuffers() const { return m_DescriptorBuffers; } bool MultiViewGeometryShaders() const { return m_MultiViewGeometryShaders; } bool MultiviewPerViewViewports() const { return m_MultiviewPerViewViewports; } + uint32_t PreciseFMAMask() const { return m_PreciseFMAMask; } VulkanRenderState &GetRenderState() { return m_RenderState; } void SetActionCB(VulkanActionCallback *cb) { m_ActionCallback = cb; } void SetSubmitChain(void *submitChain) { m_SubmitChain = submitChain; } diff --git a/renderdoc/driver/vulkan/vk_next_chains.cpp b/renderdoc/driver/vulkan/vk_next_chains.cpp index 8c389ab7f..30537bb4b 100644 --- a/renderdoc/driver/vulkan/vk_next_chains.cpp +++ b/renderdoc/driver/vulkan/vk_next_chains.cpp @@ -576,6 +576,8 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, VkPhysicalDeviceShaderFloat16Int8Features); \ COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES, \ VkPhysicalDeviceShaderFloatControls2Features); \ + COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FMA_FEATURES_KHR, \ + VkPhysicalDeviceShaderFmaFeaturesKHR); \ COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT, \ VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT); \ COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV, \ @@ -1404,7 +1406,6 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_ARM: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT8_FEATURES_EXT: \ - case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FMA_FEATURES_KHR: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INSTRUMENTATION_FEATURES_ARM: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INSTRUMENTATION_PROPERTIES_ARM: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL: \ diff --git a/renderdoc/driver/vulkan/vk_serialise.cpp b/renderdoc/driver/vulkan/vk_serialise.cpp index ab2dad601..0b3ee6469 100644 --- a/renderdoc/driver/vulkan/vk_serialise.cpp +++ b/renderdoc/driver/vulkan/vk_serialise.cpp @@ -1546,6 +1546,10 @@ SERIALISE_VK_HANDLES(); PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES, \ VkPhysicalDeviceShaderFloatControls2Features) \ \ + /* VK_KHR_shader_fma */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FMA_FEATURES_KHR, \ + VkPhysicalDeviceShaderFmaFeaturesKHR) \ + \ /* VK_KHR_shader_integer_dot_product */ \ PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES, \ VkPhysicalDeviceShaderIntegerDotProductFeatures) \ @@ -2224,9 +2228,6 @@ SERIALISE_VK_HANDLES(); PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_DEVICE_PIPELINE_BINARY_INTERNAL_CACHE_CONTROL_KHR) \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PIPELINE_BINARY_HANDLES_INFO_KHR) \ \ - /* VK_KHR_shader_fma */ \ - PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FMA_FEATURES_KHR) \ - \ /* VK_KHR_shader_untyped_pointers */ \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_UNTYPED_POINTERS_FEATURES_KHR) \ \ @@ -12426,6 +12427,23 @@ void Deserialise(const VkPhysicalDeviceShaderFloat16Int8Features &el) DeserialiseNext(el.pNext); } +template +void DoSerialise(SerialiserType &ser, VkPhysicalDeviceShaderFmaFeaturesKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FMA_FEATURES_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(shaderFmaFloat16); + SERIALISE_MEMBER(shaderFmaFloat32); + SERIALISE_MEMBER(shaderFmaFloat64); +} + +template <> +void Deserialise(const VkPhysicalDeviceShaderFmaFeaturesKHR &el) +{ + DeserialiseNext(el.pNext); +} + template void DoSerialise(SerialiserType &ser, VkPhysicalDeviceShaderFloatControls2Features &el) { @@ -15708,6 +15726,7 @@ INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceShaderDrawParametersFeatures); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceShaderExpectAssumeFeatures) INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceShaderFloat16Int8Features); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceShaderFloatControls2Features); +INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceShaderFmaFeaturesKHR); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceShaderImageFootprintFeaturesNV); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceShaderIntegerDotProductFeatures); diff --git a/renderdoc/driver/vulkan/vk_shaderdebug.cpp b/renderdoc/driver/vulkan/vk_shaderdebug.cpp index 303d6be0c..9d84af885 100644 --- a/renderdoc/driver/vulkan/vk_shaderdebug.cpp +++ b/renderdoc/driver/vulkan/vk_shaderdebug.cpp @@ -1557,7 +1557,7 @@ public: return true; } - virtual bool QueueCalculateMathOp(rdcspv::GLSLstd450 op, + virtual bool QueueCalculateMathOp(rdcspv::Op opcode, rdcspv::GLSLstd450 glslop, const rdcarray ¶ms) override { CHECK_DEVICE_THREAD(); @@ -1645,8 +1645,16 @@ public: } // push the operation afterwards + + if(glslop == rdcspv::GLSLstd450::Invalid) + { + RDCCOMPILE_ASSERT(rdcspv::GLSLstd450::Max < (rdcspv::GLSLstd450)1000, + "GLSL std450 ops max is higher than expected"); + glslop = (rdcspv::GLSLstd450)(1000 + (uint32_t)opcode); + } + ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(m_DebugData.PipeLayout), VK_SHADER_STAGE_ALL, - sizeof(Vec4f) * 6, sizeof(uint32_t), &op); + sizeof(Vec4f) * 6, sizeof(uint32_t), &glslop); ObjDisp(cmd)->CmdDispatch(Unwrap(cmd), 1, 1, 1); @@ -2766,6 +2774,22 @@ private: cases.add(rdcspv::OpBranch(breakLabel)); } + // non-glsl opcodes + if(m_pDriver->PreciseFMAMask() & floatBitSize) + { + editor.AddCapability(rdcspv::Capability::FMAKHR); + + uint32_t op = 1000 + (uint32_t)rdcspv::Op::FmaKHR; + + rdcspv::Id label = editor.MakeId(); + targets.push_back({(uint32_t)op, label}); + + cases.add(rdcspv::OpLabel(label)); + rdcspv::Id result = cases.add(rdcspv::OpFmaKHR(vec4Type, editor.MakeId(), a, b, c)); + cases.add(rdcspv::OpStore(outVar, result)); + cases.add(rdcspv::OpBranch(breakLabel)); + } + func.add(rdcspv::OpSelectionMerge(breakLabel, rdcspv::SelectionControl::None)); func.add(rdcspv::OpSwitch32(opParam, defaultLabel, targets)); diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index ba00e8812..cefe5597a 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -3723,6 +3723,22 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi CHECK_PHYS_EXT_FEATURE(shaderAbort); } END_PHYS_EXT_CHECK(); + + BEGIN_PHYS_EXT_CHECK(VkPhysicalDeviceShaderFmaFeaturesKHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FMA_FEATURES_KHR); + { + CHECK_PHYS_EXT_FEATURE(shaderFmaFloat16); + CHECK_PHYS_EXT_FEATURE(shaderFmaFloat32); + CHECK_PHYS_EXT_FEATURE(shaderFmaFloat64); + + if(ext->shaderFmaFloat16) + m_PreciseFMAMask |= 16; + if(ext->shaderFmaFloat32) + m_PreciseFMAMask |= 32; + if(ext->shaderFmaFloat64) + m_PreciseFMAMask |= 64; + } + END_PHYS_EXT_CHECK(); } if(availFeatures.depthClamp)