anchor.diff:      }
   
   
  -type ComputeShader =
  +type internal ComputeShaderData =
       {
  -        csId            : string
  -        csMethod        : MethodBase
  -        csLocalSize     : V3i
           csBuffers       : Map<string, ComputeBuffer>
           csImages        : Map<string, ComputeImage>
           csSamplerStates : Map<string * int, SamplerState>
  
positive.code:                 )
              | None ->
                  failwithf "[FShade] cannot create compute shader using function: %A" f
  //
  //
  //        let signature = FunctionSignature.ofFunction f
  //
  //        cache.GetOrAdd((signature, maxLocalSize), fun (signature, maxLocalSize) ->
  //            let localSize = 
  //                match FunctionSignature.tryGetAttribute<LocalSizeAttribute> signature with
  //                    | Some size -> V3i(size.X, size.Y, size.Z)
  //                    | _ -> V3i(0, 0, 0)
  //
  //            let localSize =
  //                V3i(
  //                    (if localSize.X = MaxLocalSize then maxLocalSize.X else localSize.X),
  //                    (if localSize.Y = MaxLocalSize then maxLocalSize.Y else localSize.Y),
  //                    (if localSize.Z = MaxLocalSize then maxLocalSize.Z else localSize.Z)
  //                )
  //
  //            match tryExtractExpr f with
  //                | Some body ->
  //                    ofExpr localSize body
  //                | _ ->
  //                    failwithf "[FShade] cannot create compute shader using function: %A" f
  //        )
  
      let toEntryPoint (s : ComputeShader) =
          let bufferArguments = 
  
negative.code:                     try Invoker<'a, Expr>.Invoke f |> Some
                      with _ -> None
  
      let private ofExprInternal (meth : MethodBase) (hash : string) (localSize : V3i) (body0 : Expr) =
          let data =
              lazy (
                  let body1, state = Preprocessor.preprocess localSize body0
                  let body2 = Optimizer.ConstantFolding.evaluateConstants'' (fun m -> m.DeclaringType.FullName = "FShade.Primitives") body1
                  let body2 = Optimizer.liftInputs body2
  
                  let mutable buffers = Map.empty
                  let mutable images = Map.empty
                  let mutable uniforms = Map.empty
                  let mutable samplerStates = Map.empty
                  let mutable textureNames = Map.empty
  
                  let addImage (fmt : Type) (name : string) (t : Type) (dim : SamplerDimension) (isArray : bool) (isMS : bool) (contentType : Type) =
                      match Map.tryFind name images with
                          | Some oi ->
                              ()
                          | None ->
                              let img =
                                  {
                                      imageType = t
                                      formatType = fmt
                                      dimension = dim
                                      isArray = isArray
                                      isMS = isMS
                                      contentType = contentType
                                  }
                              images <- Map.add name img images
  
                  let addBuffer (name : string) (arrayType : Type) (read : bool) (write : bool) =
                      match Map.tryFind name buffers with
                          | Some b ->
                              buffers <- Map.add name { b with ComputeBuffer.read = b.read || read } buffers
                          | None ->
                              buffers <- Map.add name { ComputeBuffer.contentType = arrayType.GetElementType(); ComputeBuffer.read = read; ComputeBuffer.write = write } buffers
              
                  let setSamplerState (name : string) (index : int) (state : SamplerState) =
                      match Map.tryFind (name, index) samplerStates with
                          | Some _ -> ()
                          | None ->
                              samplerStates <- Map.add (name, index) state samplerStates
                      
                  let setTextureName (name : string) (index : int) (textureName : string) =
                      match Map.tryFind (name, index) textureNames with
                          | Some _ -> ()
                          | None ->
                              textureNames <- Map.add (name, index) textureName textureNames
  
  
                  for (name, p) in Map.toSeq state.inputs do
                      match p.paramType with
                          | ImageType(fmt, dim, isArr, isMS, valueType) ->
                              addImage fmt name p.paramType dim isArr isMS valueType
                          | t -> 
                              addBuffer name t true false
  
                  for (name, p) in Map.toSeq state.outputs do
                      addBuffer name p.paramType false true
  
  
  
                  for (name, p) in Map.toSeq state.uniforms do
                      let isArgument, name = 
                          if name.StartsWith "cs_" then true, name
                          else false, name
  
                      match p.uniformType with
                          | ImageType(fmt, dim, isArr, isMS, valueType) ->
                              addImage fmt name p.uniformType dim isArr isMS valueType
  
                          | SamplerType(dim, isArray, isShadow, isMS, valueType) ->
                              match p.uniformValue with
                                  | UniformValue.Sampler(texName, state) ->
                                      setSamplerState name 0 state
                                      setTextureName name 0 texName
  
                                  | UniformValue.SamplerArray arr ->
                                      for i in 0 .. arr.Length - 1 do
                                          let (texName, state) = arr.[i]
                                          setSamplerState name i state
                                          setTextureName name i texName
  
                                  | _ ->
                                      ()
  
                              uniforms <- Map.add name p uniforms
  
                          | _ ->
                              if isArgument then
                                  uniforms <- Map.add name { p with uniformValue = UniformValue.Attribute(uniform?Arguments, name) } uniforms
                              else
                                  uniforms <- Map.add name p uniforms
              
                      ()
  
                  {
                      csBuffers       = buffers
                      csImages        = images
                      csSamplerStates = samplerStates
                      csTextureNames  = textureNames
                      csUniforms      = uniforms
                      csBody          = body2
                      csShared        = Map.empty
                  }
              )
          
  
          ComputeShader(hash, meth, localSize, data)
  
      let private cache = System.Collections.Concurrent.ConcurrentDictionary<string * V3i, ComputeShader>()
      
  