KhronosGroup / SPIRV-Tools

Apache License 2.0
1.04k stars 545 forks source link

spirv-fuzz: Adding memory barrier instructions #4484

Open Mostafa-ashraf19 opened 3 years ago

Mostafa-ashraf19 commented 3 years ago

Part of issue #4420.

Main specifications

Mostafa-ashraf19 commented 3 years ago

Overview

The idea is to create a transformation that adds memory barrier instruction anywhere with some restrictions.

Implementation details

The initial structure of Transformation adding barrier instruction, the structure of the Protobuf followed by SPIR-V assembly example, before and after the transformation.


message TransformationAddMemoryBarrier {

  // Transformation is responsible for adding an OpMemoryBarrier.

  // The memory scope for the OpMemoryBarrier.
  uint32 memory_scope_id = 1;

  // The memory semantics for the OpMemoryBarrier.
  uint32 memory_semantics_id = 2;

  // A descriptor for instruction which the new OpMemoryBarrier instruction 
  // should be inserted before.
  InstructionDescriptor instruction_to_insert_before = 3;

}

SPIR-V example


  std::string shader = R"(
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint GLCompute %4 "main"
               OpExecutionMode %4 LocalSize 16 1 1
               OpSource ESSL 320
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeInt 32 0
         %15 = OpConstant %6 4 ; Scope Invocation
          %7 = OpConstant %6 2
         %26 = OpConstant %6 4
         %28 = OpConstant %6 64 ; None | UniformMemory
         %20 = OpTypePointer Function %6
          %4 = OpFunction %2 None %3
          %5 = OpLabel
         %21 = OpVariable %20 Function %7
          %9 = OpFunctionCall %2 %12
          %8 = OpCopyObject %6 %7
         %22 = OpLoad %6 %21
         %23 = OpFunctionCall %2 %12
         %24 = OpFunctionCall %2 %12
               OpReturn
               OpFunctionEnd
         %12 = OpFunction %2 None %3
         %13 = OpLabel
               OpReturn
               OpFunctionEnd
  )";

  std::string after_transformation = R"(
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint GLCompute %4 "main"
               OpExecutionMode %4 LocalSize 16 1 1
               OpSource ESSL 320
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeInt 32 0
         %15 = OpConstant %6 4 ; Scope Invocation
          %7 = OpConstant %6 2
         %26 = OpConstant %6 4
         %28 = OpConstant %6 64 ; None | UniformMemory
         %20 = OpTypePointer Function %6
          %4 = OpFunction %2 None %3
          %5 = OpLabel
         %21 = OpVariable %20 Function %7
          %9 = OpFunctionCall %2 %12
          %8 = OpCopyObject %6 %7
         %22 = OpLoad %6 %21
         %23 = OpFunctionCall %2 %12
               OpMemoryBarrier %15 %28
         %24 = OpFunctionCall %2 %12
               OpReturn
               OpFunctionEnd
         %12 = OpFunction %2 None %3
         %13 = OpLabel
               OpReturn
               OpFunctionEnd
  )";

What do you think @paulthomson?

paulthomson commented 3 years ago

Looks good to me!

paulthomson commented 3 years ago

Oh one thing: it looks like you have used AcquireRelease, but it should be Relaxed (i.e. None).