blob: 2cd851748138d79b5501bc02fc2ba91467faeeca [file] [log] [blame]
{{/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/}}
{{Global "module" ""}}
{{Include "go_common.tmpl"}}
{{$ | Macro "replay_writer.go" | GoFmt | Write "replay_writer.go"}}
{{define "replay_writer.go"}}
{{template "Go.GeneratedHeader" (Global "OutputDir")}}
import (
"fmt"
"io"
"io/ioutil"
"android.googlesource.com/platform/tools/gpu/atom"
"android.googlesource.com/platform/tools/gpu/binary"
"android.googlesource.com/platform/tools/gpu/database"
"android.googlesource.com/platform/tools/gpu/log"
"android.googlesource.com/platform/tools/gpu/memory"
"android.googlesource.com/platform/tools/gpu/replay/builder"
"android.googlesource.com/platform/tools/gpu/replay/protocol"
"android.googlesource.com/platform/tools/gpu/replay/value"
)
{{Global "Go.Statement.Override" "Statement"}}
{{Global "Go.Read.Override" "Read"}}
type postCall []func()
func (p *postCall) add(f func()) {
*p = append(*p, f)
}
func (p *postCall) exec() {
for _, f := range *p {
f()
}
}
func loadRemapb *builder.Builder, key interface{}, val value.Value) {
if ptr, found := ϟb.Remappings[key]; found {
ϟb.Load(val.Type(), ptr)
} else {
ptr = ϟb.AllocateMemory(uint64(val.Type().Sizeb.Architecture().PointerSize)))
ϟb.Push(val) // We have an input to an unknown id, use the unmapped value.
ϟb.Clone(0)
ϟb.Store(ptr)
ϟb.Remappings[key] = ptr
}
}
func storeRemapb *builder.Builder, key interface{}, val value.Pointer, ty protocol.Type) {
if ptr, found := ϟb.Remappings[key]; !found {
ptr = ϟb.AllocateMemory(uint64(ty.Sizeb.Architecture().PointerSize)))
ϟb.Load(ty, val)
ϟb.Store(ptr)
ϟb.Remappings[key] = ptr
}
}
{{Macro "DeclareBuilderFunctionInfos" $}}
{{ForEach $.Pseudonyms "DeclarePseudonymValue" | JoinWith "\n"}}
{{ForEach (AllCommands $) "DeclareCommandReplay" | JoinWith "\n"}}
{{ForEach $.Pointers "PointerReplayMethods" | JoinWith "\n"}}
{{ForEach $.Slices "SliceReplayMethods" | JoinWith "\n"}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the replay function for the specified command
-------------------------------------------------------------------------------
*/}}
{{define "DeclareCommandReplay"}}
{{AssertType $ "Function"}}
{{if not (GetAnnotation $ "no_replay")}}
{{$name := Macro "Go.CmdName" $}}
var _ = replay.Replayer(&{{$name}}{}) // interface compliance check
func a *{{$name}}) {{if GetAnnotation $ "replay_custom"}}default{{end}}Replay
ϟi atom.ID, ϟs *gfxapi.State, ϟd database.Database, ϟl log.Logger, ϟb *builder.Builder) {
ϟc := getStates)
ϟp := &postCall{}
_ = ϟc
ϟa.observations.ApplyReadss.Memory[memory.ApplicationPool])
{{/* Simulate the call */}}
{{Macro "Go.Block" $.Block}}
ϟa.observations.ApplyWritess.Memory[memory.ApplicationPool])
{{/* Push all the parameters on the stack */}}
{{range $p := $.CallParameters}}
{{$type := TypeOf $p}}
{{$name := print "ϟa." (Macro "Go.Parameter" $p)}}
{{Macro "PushInput" "Type" $type "Name" $name}}
{{end}}
{{/* Call the function */}}
ϟb.Call({{Macro "BuilderFunctionInfo" $}})
{{/* Perform post-call actions*/}}
ϟp.exec()
}
{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits logic to push the specified input variable to the VM's stack.
-------------------------------------------------------------------------------
*/}}
{{define "PushInput"}}
{{AssertType $.Type "Type"}}
{{AssertType $.Name "string"}}
{{if (GetAnnotation $.Type "replay_remap")}}
if key, remap := {{$.Name}}.remapa, ϟs); remap {
loadRemapb, key, {{Macro "Value" "Type" $.Type "Name" $.Name}})
} else {
ϟb.Push({{Macro "Value" "Type" $.Type "Name" $.Name}})
}
{{else}}
ϟb.Push({{Macro "Value" "Type" $.Type "Name" $.Name}})
{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Returns the builder.Value holding the specified variable.
-------------------------------------------------------------------------------
*/}}
{{define "Value"}}
{{AssertType $.Type "Type"}}
{{AssertType $.Name "string"}}
{{if (GetAnnotation $.Type "replay_custom_value")}}{{$.Name}}.valueb, ϟa, ϟs)
{{else if IsBool $.Type}}value.Bool({{$.Name}})
{{else if IsS8 $.Type}}value.S8({{$.Name}})
{{else if IsU8 $.Type}}value.U8({{$.Name}})
{{else if IsS16 $.Type}}value.S16({{$.Name}})
{{else if IsU16 $.Type}}value.U16({{$.Name}})
{{else if IsF32 $.Type}}value.F32({{$.Name}})
{{else if IsU32 $.Type}}value.U32({{$.Name}})
{{else if IsS32 $.Type}}value.S32({{$.Name}})
{{else if IsF64 $.Type}}value.F64({{$.Name}})
{{else if IsU64 $.Type}}value.U64({{$.Name}})
{{else if IsS64 $.Type}}value.S64({{$.Name}})
{{else if IsInt $.Type}}value.S64({{$.Name}})
{{else if IsUint $.Type}}value.U64({{$.Name}})
{{else if IsString $.Type}}ϟb.String({{$.Name}})
{{else if IsPointer $.Type}}{{$.Name}}.value()
{{else if IsEnum $.Type}}value.U32({{$.Name}})
{{else if IsStaticArray $.Type}}{{$.Name}}.valueb, ϟa, ϟs)
{{else if IsPseudonym $.Type}}{{$.Name}}.valueb, ϟa, ϟs)
{{else if IsClass $.Type}}{{$.Name}}.valueb, ϟa, ϟs)
{{else }}{{Error "macro Value '%v' called with unsupported type: %s" $.Name $.Type.Name}}
{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Declares the value method for a given pseudonym type.
-------------------------------------------------------------------------------
*/}}
{{define "DeclarePseudonymValue"}}
{{AssertType $ "Pseudonym"}}
{{if not (GetAnnotation $ "replay_custom_value")}}
{{$v := print (Macro "Go.Type" $.To) "(c)"}}
func (c {{$.Name}}) valueb *builder.Builder, ϟa atom.Atom, ϟs *gfxapi.State) value.Value { return {{Macro "Value" "Type" $.To "Name" $v}} }
{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Declares the value method for the given static array type.
-------------------------------------------------------------------------------
*/}}
{{define "DeclareArrayValue"}}
{{AssertType $ "Array" "StaticArray"}}
{{if not (or (Macro "IsInternal" $.ValueType) (IsAny $.ValueType))}}
func (arr {{Macro "Go.Type" $}}) valueb *builder.Builder, ϟa atom.Atom, ϟs *gfxapi.State) value.Pointer {
if len(arr) > 0 {
for _, e := range arr {
{{Macro "PushInput" "Type" $.ValueType "Name" "e"}}
}
return ϟb.Buffer(len(arr))
} else {
return value.AbsolutePointer(0)
}
}
{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits a function info definition for each of the commands.
-------------------------------------------------------------------------------
*/}}
{{define "DeclareBuilderFunctionInfos"}}
{{AssertType $ "API"}}
{{range $i, $c := AllCommands $}}
var {{Macro "BuilderFunctionInfo" $c}} = builder.FunctionInfo
ID: {{$i}},§
ReturnType: {{Macro "BuilderType" $c.Return.Type}},§
Parameters: {{len $c.CallParameters}},§
}
{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the name of the variable holding the specified command's function id.
-------------------------------------------------------------------------------
*/}}
{{define "BuilderFunctionInfo"}}{{AssertType $ "Function"}}funcInfo{{Macro "Go.CmdName" $}}{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the replay builder type for the given command return type.
-------------------------------------------------------------------------------
*/}}
{{define "BuilderType"}}
{{AssertType $ "Type"}}
{{ if IsPseudonym $}}{{Macro "BuilderType" $.To}}
{{else if IsEnum $}}protocol.TypeUint32
{{else if IsBool $}}protocol.TypeBool
{{else if IsInt $}}protocol.TypeInt64
{{else if IsUint $}}protocol.TypeUint64
{{else if IsS8 $}}protocol.TypeInt8
{{else if IsU8 $}}protocol.TypeUint8
{{else if IsS16 $}}protocol.TypeInt16
{{else if IsU16 $}}protocol.TypeUint16
{{else if IsS32 $}}protocol.TypeInt32
{{else if IsU32 $}}protocol.TypeUint32
{{else if IsF32 $}}protocol.TypeFloat
{{else if IsS64 $}}protocol.TypeInt64
{{else if IsU64 $}}protocol.TypeUint64
{{else if IsF64 $}}protocol.TypeDouble
{{else if IsVoid $}}protocol.TypeVoid
{{else if IsString $}}protocol.TypeVolatilePointer
{{else if IsPointer $}}protocol.TypeVolatilePointer {{/* TODO: Might be absolute... */}}
{{else}}{{Error "macro BuilderType called with unsupported type: %s" $.Name}}
{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
An override for the "Go.Statement" macro.
-------------------------------------------------------------------------------
*/}}
{{define "Statement"}}
{{if IsRead $}}
{{Macro "Go.Read" $.Slice}}.onReplayReada, ϟs, ϟd, ϟl, ϟb)
{{else if IsWrite $}}
{{Macro "Go.Read" $.Slice}}.onReplayWritea, ϟs, ϟd, ϟl, ϟb, ϟp)
{{else if IsCopy $}}
{{Macro "Go.Read" $.Dst}}.replayCopy({{Macro "Go.Read" $.Src}}, ϟa, ϟs, ϟd, ϟl, ϟb, ϟp)
{{else if IsSliceAssign $}}
{{if ne $.Operator "="}}{{Error "Compound assignments to pointers are not supported (%s)" $.Operator}}{{end}}
{{Macro "Go.Read" $.To.Slice}}.Index({{Macro "Go.Read" $.To.Index}}, ϟs).replayWrite({{Macro "Go.Read" $.Value}}, ϟa, ϟs, ϟd, ϟl, ϟb, ϟp)
{{else}}
{{Macro "Go.Statement.Default" $}}
{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
An override for the "Go.Read" macro.
-------------------------------------------------------------------------------
*/}}
{{define "Read"}}
{{if IsSliceIndex $}}
{{Macro "Go.Read" $.Slice}}.Index({{Macro "Go.Read" $.Index}}, ϟs).§
{{if Global "Go.InferredExpression"}}
replayMapa, ϟs, ϟd, ϟl, ϟb)
{{else}}
replayReada, ϟs, ϟd, ϟl, ϟb)
{{end}}
{{else}}
{{Macro "Go.Read.Default" $}}
{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits additional methods used for replay generation for the Pointer type or
indirect type (Pseudonym) to Pointer.
-------------------------------------------------------------------------------
*/}}
{{define "PointerReplayMethods"}}
{{AssertType $ "Pointer" "Pseudonym"}}
{{$p := $ | Underlying | Unpack }}
{{$ptr_ty := Macro "Go.Type" $ }}
{{$el_ty := Macro "Go.Type" $p.To }}
{{$el_is_void := IsVoid ($p.To | Underlying | Unpack)}}
{{if not $el_is_void}}
func (p {{$ptr_ty}}) replayMapa atom.Atom, ϟs *gfxapi.State, ϟd database.Database, ϟl log.Logger, ϟb *builder.Builder) {{$el_ty}} {
p.Slice(0, 1, ϟs).replayMapa, ϟs, ϟd, ϟl, ϟb)
return p.Reads, ϟd, ϟl)
}
func (p {{$ptr_ty}}) replayReada atom.Atom, ϟs *gfxapi.State, ϟd database.Database, ϟl log.Logger, ϟb *builder.Builder) {{$el_ty}} {
p.Slice(0, 1, ϟs).onReplayReada, ϟs, ϟd, ϟl, ϟb)
return p.Reads, ϟd, ϟl)
}
func (p {{$ptr_ty}}) replayWrite(value {{$el_ty}}, ϟa atom.Atom, ϟs *gfxapi.State, ϟd database.Database, ϟl log.Logger, ϟb *builder.Builder, ϟp *postCall) {
p.Write(value, ϟs)
p.Slice(0, 1, ϟs).onReplayWritea, ϟs, ϟd, ϟl, ϟb, ϟp)
}
{{end}}
func (p {{$ptr_ty}}) value() value.Pointer {
if p.Address != 0 {
return value.VolatileCapturePointer(p.Address)
} else {
return value.AbsolutePointer(0)
}
}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits additional methods used for replay generation for the Slice type or
indirect type (Pseudonym) to Slice.
-------------------------------------------------------------------------------
*/}}
{{define "SliceReplayMethods"}}
{{AssertType $ "Slice" "Pseudonym"}}
{{$s := $ | Underlying | Unpack }}
{{$slice_ty := Macro "Go.Type" $ }}
{{$el_ty := Macro "Go.Type" $s.To }}
{{$el_is_void := IsVoid ($s.To | Underlying | Unpack)}}
func (s {{$slice_ty}}) onReplayReada atom.Atom, ϟs *gfxapi.State, ϟd database.Database, ϟl log.Logger, ϟb *builder.Builder) {
if s.Pool == memory.ApplicationPool {
s.replayMapa, ϟs, ϟd, ϟl, ϟb)
{{if (GetAnnotation $s.To "replay_remap")}}
ptr, step := value.VolatileCapturePointer(s.Base), value.VolatileCapturePointer(s.ElementSizes))
for _, v := range s.Reads, ϟd, ϟl) {
if key, remap := v.remapa, ϟs); remap {
loadRemapb, key, {{Macro "Value" "Type" $s.To "Name" "v"}})
} else {
ϟb.Push({{Macro "Value" "Type" $s.To "Name" "v"}})
}
ϟb.Store(ptr)
ptr += step
}
{{else}}
ϟb.Write(s.Ranges), s.ResourceIDs, ϟd, ϟl))
{{end}}
}
}
func (s {{$slice_ty}}) onReplayWritea atom.Atom, ϟs *gfxapi.State, ϟd database.Database, ϟl log.Logger, ϟb *builder.Builder, ϟp *postCall) {
if s.Pool == memory.ApplicationPool {
ϟb.MapMemory(s.Root.Range(uint64(s.Ranges).End() - s.Root)))
{{if (GetAnnotation $s.To "replay_remap")}}
ϟp.add(func() {
ptr, step := value.VolatileCapturePointer(s.Base), value.VolatileCapturePointer(s.ElementSizes))
for _, v := range s.Reads, ϟd, ϟl) {
if key, remap := v.remapa, ϟs); remap {
storeRemapb, key, ptr, {{Macro "BuilderType" $s.To}})
}
ptr += step
}
})
{{end}}
}
}
func (s {{$slice_ty}}) replayMapa atom.Atom, ϟs *gfxapi.State, ϟd database.Database, ϟl log.Logger, ϟb *builder.Builder) {
if s.Pool == memory.ApplicationPool {
rng := s.Ranges)
ϟb.MapMemory(s.Root.Range(uint64(rng.End() - s.Root)))
}
}
{{if not $el_is_void}}
func (s {{$slice_ty}}) replayReada atom.Atom, ϟs *gfxapi.State, ϟd database.Database, ϟl log.Logger, ϟb *builder.Builder) []{{$el_ty}} {
s.onReplayReada, ϟs, ϟd, ϟl, ϟb)
return s.Reads, ϟd, ϟl)
}
func (dst {{$slice_ty}}) replayCopy(src {{$slice_ty}}, ϟa atom.Atom, ϟs *gfxapi.State, ϟd database.Database, ϟl log.Logger, ϟb *builder.Builder, ϟp *postCall) {
dst, src = dst.Copy(src, ϟs, ϟd, ϟl)
src.onReplayReada, ϟs, ϟd, ϟl, ϟb)
dst.onReplayWritea, ϟs, ϟd, ϟl, ϟb, ϟp)
}
{{end}}
{{end}}