swr: [rasterizer] add archrast instrumentation
authorTim Rowley <timothy.o.rowley@intel.com>
Mon, 29 Aug 2016 19:56:03 +0000 (14:56 -0500)
committerTim Rowley <timothy.o.rowley@intel.com>
Tue, 30 Aug 2016 15:32:36 +0000 (10:32 -0500)
Statistics measurement system

12 files changed:
src/gallium/drivers/swr/Makefile.am
src/gallium/drivers/swr/Makefile.sources
src/gallium/drivers/swr/rasterizer/archrast/archrast.cpp [new file with mode: 0644]
src/gallium/drivers/swr/rasterizer/archrast/archrast.h [new file with mode: 0644]
src/gallium/drivers/swr/rasterizer/archrast/eventmanager.h [new file with mode: 0644]
src/gallium/drivers/swr/rasterizer/archrast/events.proto [new file with mode: 0644]
src/gallium/drivers/swr/rasterizer/core/api.cpp
src/gallium/drivers/swr/rasterizer/core/context.h
src/gallium/drivers/swr/rasterizer/scripts/gen_archrast.py [new file with mode: 0644]
src/gallium/drivers/swr/rasterizer/scripts/templates/ar_event_cpp.template [new file with mode: 0644]
src/gallium/drivers/swr/rasterizer/scripts/templates/ar_event_h.template [new file with mode: 0644]
src/gallium/drivers/swr/rasterizer/scripts/templates/ar_eventhandler_h.template [new file with mode: 0644]

index 33664d6b8dd5829153fd4bf35de470790f96e583..154f0ca8202786ce3f086ee767bc32be97d95b0c 100644 (file)
@@ -35,13 +35,16 @@ COMMON_CXXFLAGS = \
        $(SWR_CXX11_CXXFLAGS) \
        -I$(builddir)/rasterizer/scripts \
        -I$(builddir)/rasterizer/jitter \
+       -I$(builddir)/rasterizer/archrast \
        -I$(srcdir)/rasterizer \
        -I$(srcdir)/rasterizer/core \
        -I$(srcdir)/rasterizer/scripts \
-       -I$(srcdir)/rasterizer/jitter
+       -I$(srcdir)/rasterizer/jitter \
+       -I$(srcdir)/rasterizer/archrast
 
 COMMON_SOURCES = \
        $(CXX_SOURCES) \
+       $(ARCHRAST_CXX_SOURCES) \
        $(COMMON_CXX_SOURCES) \
        $(CORE_CXX_SOURCES) \
        $(JITTER_CXX_SOURCES) \
@@ -54,7 +57,10 @@ BUILT_SOURCES = \
        rasterizer/scripts/gen_knobs.h \
        rasterizer/jitter/state_llvm.h \
        rasterizer/jitter/builder_x86.h \
-       rasterizer/jitter/builder_x86.cpp
+       rasterizer/jitter/builder_x86.cpp \
+       rasterizer/archrast/gen_ar_event.h \
+       rasterizer/archrast/gen_ar_event.cpp \
+       rasterizer/archrast/gen_ar_eventhandler.h
 
 MKDIR_GEN = $(AM_V_at)$(MKDIR_P) $(@D)
 PYTHON_GEN = $(AM_V_GEN)$(PYTHON2) $(PYTHON_FLAGS)
@@ -107,6 +113,29 @@ rasterizer/jitter/builder_x86.cpp: rasterizer/jitter/scripts/gen_llvm_ir_macros.
                --output rasterizer/jitter/builder_x86.cpp \
                --gen_x86_cpp
 
+rasterizer/archrast/gen_ar_event.h: rasterizer/scripts/gen_archrast.py rasterizer/scripts/templates/ar_event_h.template rasterizer/archrast/events.proto
+       $(MKDIR_GEN)
+       $(PYTHON_GEN) \
+               $(srcdir)/rasterizer/scripts/gen_archrast.py \
+               --proto $(srcdir)/rasterizer/archrast/events.proto \
+               --output rasterizer/archrast/gen_ar_event.h \
+               --gen_event_h
+
+rasterizer/archrast/gen_ar_event.cpp: rasterizer/scripts/gen_archrast.py rasterizer/scripts/templates/ar_event_cpp.template rasterizer/archrast/events.proto
+       $(MKDIR_GEN)
+       $(PYTHON_GEN) \
+               $(srcdir)/rasterizer/scripts/gen_archrast.py \
+               --proto $(srcdir)/rasterizer/archrast/events.proto \
+               --output rasterizer/archrast/gen_ar_event.cpp \
+               --gen_event_cpp
+
+rasterizer/archrast/gen_ar_eventhandler.h: rasterizer/scripts/gen_archrast.py rasterizer/scripts/templates/ar_eventhandler_h.template rasterizer/archrast/events.proto
+       $(MKDIR_GEN)
+       $(PYTHON_GEN) \
+               $(srcdir)/rasterizer/scripts/gen_archrast.py \
+               --proto $(srcdir)/rasterizer/archrast/events.proto \
+               --output rasterizer/archrast/gen_ar_eventhandler.h \
+               --gen_eventhandler_h
 
 COMMON_LIBADD = \
        $(top_builddir)/src/gallium/auxiliary/libgallium.la \
@@ -197,8 +226,10 @@ libswrAVX2_la_LDFLAGS = \
 include $(top_srcdir)/install-gallium-links.mk
 
 EXTRA_DIST = \
+       rasterizer/archrast/events.proto \
        rasterizer/jitter/scripts/gen_llvm_ir_macros.py \
        rasterizer/jitter/scripts/gen_llvm_types.py \
+       rasterizer/scripts/gen_archrast.py \
        rasterizer/scripts/gen_knobs.py \
        rasterizer/scripts/knob_defs.py \
        rasterizer/scripts/mako/ast.py \
@@ -218,4 +249,7 @@ EXTRA_DIST = \
        rasterizer/scripts/mako/runtime.py \
        rasterizer/scripts/mako/template.py \
        rasterizer/scripts/mako/util.py \
-       rasterizer/scripts/templates/knobs.template
+       rasterizer/scripts/templates/knobs.template \
+       rasterizer/scripts/templates/ar_event_h.template \
+       rasterizer/scripts/templates/ar_event_cpp.template \
+       rasterizer/scripts/templates/ar_eventhandler_h.template
index 99b3900b57c81e95f114cad327360284ef5f9daf..e0ea161ee5d1e0f635dd99247562851d7b260f98 100644 (file)
@@ -45,6 +45,11 @@ CXX_SOURCES := \
        swr_query.h \
        swr_query.cpp
 
+ARCHRAST_CXX_SOURCES := \
+       rasterizer/archrast/archrast.cpp \
+       rasterizer/archrast/archrast.h \
+       rasterizer/archrast/eventmanager.h
+
 COMMON_CXX_SOURCES := \
        rasterizer/common/formats.cpp \
        rasterizer/common/formats.h \
diff --git a/src/gallium/drivers/swr/rasterizer/archrast/archrast.cpp b/src/gallium/drivers/swr/rasterizer/archrast/archrast.cpp
new file mode 100644 (file)
index 0000000..48dec28
--- /dev/null
@@ -0,0 +1,72 @@
+/****************************************************************************
+* Copyright (C) 2016 Intel Corporation.   All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice (including the next
+* paragraph) shall be included in all copies or substantial portions of the
+* Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+* IN THE SOFTWARE.
+*
+* @file archrast.h
+*
+* @brief Definitions for archrast.
+*
+******************************************************************************/
+#include "common/os.h"
+#include "archrast/archrast.h"
+#include "archrast/eventmanager.h"
+
+namespace ArchRast
+{
+    static EventManager* FromHandle(HANDLE hThreadContext)
+    {
+        return reinterpret_cast<EventManager*>(hThreadContext);
+    }
+
+    // Construct an event manager and associate a handler with it.
+    HANDLE CreateThreadContext()
+    {
+        EventManager* pManager = new EventManager();
+        EventHandler* pHandler = new EventHandler();
+
+        if (pManager && pHandler)
+        {
+            pManager->attach(pHandler);
+
+            return pManager;
+        }
+
+        SWR_ASSERT(0, "Failed to register thread.");
+        return nullptr;
+    }
+
+    void DestroyThreadContext(HANDLE hThreadContext)
+    {
+        EventManager* pManager = FromHandle(hThreadContext);
+        SWR_ASSERT(pManager != nullptr);
+
+        delete pManager;
+    }
+
+    // Dispatch event for this thread.
+    void dispatch(HANDLE hThreadContext, Event& event)
+    {
+        EventManager* pManager = FromHandle(hThreadContext);
+        SWR_ASSERT(pManager != nullptr);
+
+        pManager->dispatch(event);
+    }
+}
diff --git a/src/gallium/drivers/swr/rasterizer/archrast/archrast.h b/src/gallium/drivers/swr/rasterizer/archrast/archrast.h
new file mode 100644 (file)
index 0000000..bdb3afb
--- /dev/null
@@ -0,0 +1,41 @@
+/****************************************************************************
+* Copyright (C) 2016 Intel Corporation.   All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice (including the next
+* paragraph) shall be included in all copies or substantial portions of the
+* Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+* IN THE SOFTWARE.
+*
+* @file archrast.h
+*
+* @brief Definitions for archrast.
+*
+******************************************************************************/
+#pragma once
+
+#include "common/os.h"
+#include "gen_ar_event.h"
+
+namespace ArchRast
+{
+    HANDLE CreateThreadContext();
+    void DestroyThreadContext(HANDLE hThreadContext);
+
+    // Dispatch event for this thread.
+    void dispatch(HANDLE hThreadContext, Event& event);
+};
+
diff --git a/src/gallium/drivers/swr/rasterizer/archrast/eventmanager.h b/src/gallium/drivers/swr/rasterizer/archrast/eventmanager.h
new file mode 100644 (file)
index 0000000..d162ca8
--- /dev/null
@@ -0,0 +1,68 @@
+/****************************************************************************
+* Copyright (C) 2016 Intel Corporation.   All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice (including the next
+* paragraph) shall be included in all copies or substantial portions of the
+* Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+* IN THE SOFTWARE.
+*
+* @file archrast.h
+*
+* @brief Definitions for the event manager.
+*
+******************************************************************************/
+#pragma once
+
+#include "common/os.h"
+
+#include "gen_ar_event.h"
+#include "gen_ar_eventhandler.h"
+
+#include <vector>
+
+namespace ArchRast
+{
+    //////////////////////////////////////////////////////////////////////////
+    /// EventManager - interface to dispatch events to handlers.
+    /// Event handling occurs only on a single thread.
+    //////////////////////////////////////////////////////////////////////////
+    class EventManager
+    {
+    public:
+        void attach(EventHandler* pHandler)
+        {
+            mHandlers.push_back(pHandler);
+        }
+
+        void dispatch(Event& event)
+        {
+            ///@todo Add event filter check here.
+
+            for (auto pHandler : mHandlers)
+            {
+                event.accept(pHandler);
+            }
+        }
+    private:
+
+        // Handlers stay registered for life
+        void detach(EventHandler* pHandler) { SWR_ASSERT(0); }
+
+        std::vector<EventHandler*> mHandlers;
+    };
+};
+
diff --git a/src/gallium/drivers/swr/rasterizer/archrast/events.proto b/src/gallium/drivers/swr/rasterizer/archrast/events.proto
new file mode 100644 (file)
index 0000000..4c2e7dc
--- /dev/null
@@ -0,0 +1,108 @@
+# Copyright (C) 2016 Intel Corporation.   All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# Provides definitions for events.
+
+enum GroupType
+{
+    APIClearRenderTarget,
+    APIDraw,
+    APIDrawWakeAllThreads,
+    APIDrawIndexed,
+    APIDispatch,
+    APIStoreTiles,
+    APIGetDrawContext,
+    APISync,
+    APIWaitForIdle,
+    FEProcessDraw,
+    FEProcessDrawIndexed,
+    FEFetchShader,
+    FEVertexShader,
+    FEHullShader,
+    FETessellation,
+    FEDomainShader,
+    FEGeometryShader,
+    FEStreamout,
+    FEPAAssemble,
+    FEBinPoints,
+    FEBinLines,
+    FEBinTriangles,
+    FETriangleSetup,
+    FEViewportCull,
+    FEGuardbandClip,
+    FEClipPoints,
+    FEClipLines,
+    FEClipTriangles,
+    FECullZeroAreaAndBackface,
+    FECullBetweenCenters,
+    FEProcessStoreTiles,
+    FEProcessInvalidateTiles,
+    WorkerWorkOnFifoBE,
+    WorkerFoundWork,
+    BELoadTiles,
+    BEDispatch,
+    BEClear,
+    BERasterizeLine,
+    BERasterizeTriangle,
+    BETriangleSetup,
+    BEStepSetup,
+    BECullZeroArea,
+    BEEmptyTriangle,
+    BETrivialAccept,
+    BETrivialReject,
+    BERasterizePartial,
+    BEPixelBackend,
+    BESetup,
+    BEBarycentric,
+    BEEarlyDepthTest,
+    BEPixelShader,
+    BESingleSampleBackend,
+    BEPixelRateBackend,
+    BESampleRateBackend,
+    BENullBackend,
+    BELateDepthTest,
+    BEOutputMerger,
+    BEStoreTiles,
+    BEEndTile,
+    WorkerWaitForThreadEvent,
+};
+
+event Start
+{
+    GroupType type;
+    uint32_t id;
+};
+
+event End
+{
+    GroupType type;
+    uint32_t count;
+};
+
+event DrawIndexedInstance
+{
+    PRIMITIVE_TOPOLOGY topology;
+    uint32_t numIndices;
+    int32_t  indexOffset;
+    int32_t  baseVertex;
+    uint32_t numInstances;
+    uint32_t startInstance;
+};
index 089ef0f5c495682bbd88dbed58e10e5bacd97403..6bdb8f4b41041214a8fd55d0951e42b80101b6f5 100644 (file)
@@ -46,6 +46,8 @@
 #include "common/simdintrin.h"
 #include "common/os.h"
 
+#include "archrast/archrast.h"
+
 static const SWR_RECT g_MaxScissorRect = { 0, 0, KNOB_MAX_SCISSOR_X, KNOB_MAX_SCISSOR_Y };
 
 void SetupDefaultState(SWR_CONTEXT *pContext);
@@ -107,6 +109,10 @@ HANDLE SwrCreateContext(
     pContext->ppScratch = new uint8_t*[pContext->NumWorkerThreads];
     pContext->pStats = new SWR_STATS[pContext->NumWorkerThreads];
 
+    // Setup ArchRast thread contexts which includes +1 for API thread.
+    pContext->pArContext = new HANDLE[pContext->NumWorkerThreads+1];
+    pContext->pArContext[pContext->NumWorkerThreads] = ArchRast::CreateThreadContext();
+
     // Allocate scratch space for workers.
     ///@note We could lazily allocate this but its rather small amount of memory.
     for (uint32_t i = 0; i < pContext->NumWorkerThreads; ++i)
@@ -121,6 +127,9 @@ HANDLE SwrCreateContext(
 #else
         pContext->ppScratch[i] = (uint8_t*)AlignedMalloc(32 * sizeof(KILOBYTE), KNOB_SIMD_WIDTH * 4);
 #endif
+
+        // Initialize worker thread context for ArchRast.
+        pContext->pArContext[i] = ArchRast::CreateThreadContext();
     }
 
     // State setup AFTER context is fully initialized
@@ -176,9 +185,12 @@ void SwrDestroyContext(HANDLE hContext)
 #else
         AlignedFree(pContext->ppScratch[i]);
 #endif
+
+        ArchRast::DestroyThreadContext(pContext->pArContext[i]);
     }
 
     delete [] pContext->ppScratch;
+    delete [] pContext->pArContext;
     delete [] pContext->pStats;
 
     delete(pContext->pHotTileMgr);
@@ -1194,6 +1206,9 @@ void DrawIndexedInstance(
     DRAW_CONTEXT* pDC = GetDrawContext(pContext);
     API_STATE* pState = &pDC->pState->state;
 
+    AR_BEGIN(AR_API_CTX, APIDrawIndexed, pDC->drawId);
+    AR_EVENT(AR_API_CTX, DrawIndexedInstance(topology, numIndices, indexOffset, baseVertex, numInstances, startInstance));
+
     uint32_t maxIndicesPerDraw = MaxVertsPerDraw(pDC, numIndices, topology);
     uint32_t primsPerDraw = GetNumPrims(topology, maxIndicesPerDraw);
     uint32_t remainingIndices = numIndices;
@@ -1265,6 +1280,7 @@ void DrawIndexedInstance(
     pDC = GetDrawContext(pContext);
     pDC->pState->state.rastState.cullMode = oldCullMode;
 
+    AR_END(AR_API_CTX, APIDrawIndexed, numIndices * numInstances);
     RDTSC_STOP(APIDrawIndexed, numIndices * numInstances, 0);
 }
 
index f24b8f0d4c2c87f78893abcaebc3ae5c63287de1..6d63e087bcd534571aa3a34567135e147bec1f72 100644 (file)
@@ -506,7 +506,24 @@ struct SWR_CONTEXT
     uint32_t lastFrameChecked;
     uint64_t lastDrawChecked;
     TileSet singleThreadLockedTiles;
+
+    // ArchRast thread contexts.
+    HANDLE* pArContext;
 };
 
 #define UPDATE_STAT(name, count) if (GetApiState(pDC).enableStats) { pDC->dynState.pStats[workerId].name += count; }
 #define UPDATE_STAT_FE(name, count) if (GetApiState(pDC).enableStats) { pDC->dynState.statsFE.name += count; }
+
+// ArchRast instrumentation framework
+#ifdef KNOB_ENABLE_AR
+#define AR_WORKER_CTX  pDC->pContext->pArContext[workerId]
+#define AR_API_CTX     pDC->pContext->pArContext[pContext->NumWorkerThreads]
+
+#define AR_BEGIN(ctx, type, id)    ArchRast::dispatch(ctx, ArchRast::Start(ArchRast::type, id))
+#define AR_END(ctx, type, count)   ArchRast::dispatch(ctx, ArchRast::End(ArchRast::type, count))
+#define AR_EVENT(ctx, event)       ArchRast::dispatch(ctx, ArchRast::event)
+#else
+#define AR_BEGIN(ctx, type, id)
+#define AR_END(ctx, type, id)
+#define AR_EVENT(ctx, event)
+#endif
\ No newline at end of file
diff --git a/src/gallium/drivers/swr/rasterizer/scripts/gen_archrast.py b/src/gallium/drivers/swr/rasterizer/scripts/gen_archrast.py
new file mode 100644 (file)
index 0000000..deb16be
--- /dev/null
@@ -0,0 +1,195 @@
+# Copyright (C) 2014-2016 Intel Corporation.   All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+# Python source
+from __future__ import print_function
+import os
+import sys
+import re
+import argparse
+from mako.template import Template
+from mako.exceptions import RichTraceback
+
+def write_template_to_string(template_filename, **kwargs):
+    try:
+        template = Template(filename=template_filename)
+        # Split + Join fixes line-endings for whatever platform you are using
+        return '\n'.join(template.render(**kwargs).splitlines())
+    except:
+        traceback = RichTraceback()
+        for (filename, lineno, function, line) in traceback.traceback:
+            print("File %s, line %s, in %s" % (filename, lineno, function))
+            print(line, "\n")
+        print("%s: %s" % (str(traceback.error.__class__.__name__), traceback.error))
+
+def write_template_to_file(template_filename, output_filename, **kwargs):
+    with open(output_filename, "w") as outfile:
+        print(write_template_to_string(template_filename, **kwargs), file=outfile)
+
+def parse_event_fields(lines, idx, event_dict):
+    field_names = []
+    field_types = []
+    end_of_event = False
+
+    # record all fields in event definition.
+    # note: we don't check if there's a leading brace.
+    while not end_of_event and idx < len(lines):
+        line = lines[idx].rstrip()
+        idx += 1
+
+        field = re.match(r"(\s*)(\w+)(\s*)(\w+)", line)
+
+        if field:
+            field_types.append(field.group(2))
+            field_names.append(field.group(4))
+
+        end_of_event = re.match(r"(\s*)};", line)
+
+    event_dict['field_types'] = field_types
+    event_dict['field_names'] = field_names
+    return idx
+
+def parse_enums(lines, idx, event_dict):
+    enum_names = []
+    end_of_enum = False
+
+    # record all enum values in enumeration
+    # note: we don't check if there's a leading brace.
+    while not end_of_enum and idx < len(lines):
+        line = lines[idx].rstrip()
+        idx += 1
+
+        preprocessor = re.search(r"#if|#endif", line)
+
+        if not preprocessor:
+            enum = re.match(r"(\s*)(\w+)(\s*)", line)
+
+            if enum:
+                enum_names.append(line)
+
+            end_of_enum = re.match(r"(\s*)};", line)
+
+    event_dict['names'] = enum_names
+    return idx
+
+def parse_protos(filename):
+    protos = {}
+
+    with open(filename, 'r') as f:
+        lines=f.readlines()
+
+        idx = 0
+
+        protos['events'] = {}       # event dictionary containing events with their fields
+        protos['event_names'] = []  # needed to keep events in order parsed. dict is not ordered.
+        protos['enums'] = {}
+        protos['enum_names'] = []
+
+        raw_text = []
+        while idx < len(lines):
+            line = lines[idx].rstrip()
+            idx += 1
+
+            # search for event definitions.
+            match = re.match(r"(\s*)event(\s*)(\w+)", line)
+
+            if match:
+                event_name = match.group(3)
+                protos['event_names'].append(event_name)
+
+                protos['events'][event_name] = {}
+                idx = parse_event_fields(lines, idx, protos['events'][event_name])
+
+            # search for enums.
+            match = re.match(r"(\s*)enum(\s*)(\w+)", line)
+
+            if match:
+                enum_name = match.group(3)
+                protos['enum_names'].append(enum_name)
+
+                protos['enums'][enum_name] = {}
+                idx = parse_enums(lines, idx, protos['enums'][enum_name])
+
+    return protos
+
+def main():
+
+    # Parse args...
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--proto", "-p", help="Path to proto file", required=True)
+    parser.add_argument("--output", "-o", help="Output filename (i.e. event.h)", required=True)
+    parser.add_argument("--gen_event_h", "-geh", help="Generate event header", action="store_true", default=False)
+    parser.add_argument("--gen_event_cpp", "-gec", help="Generate event cpp", action="store_true", default=False)
+    parser.add_argument("--gen_eventhandler_h", "-gehh", help="Generate eventhandler header", action="store_true", default=False)
+    args = parser.parse_args()
+
+    proto_filename = args.proto
+
+    (output_dir, output_filename) = os.path.split(args.output)
+
+    if not output_dir:
+        output_dir = "."
+
+    #print("output_dir = %s" % output_dir, file=sys.stderr)
+    #print("output_filename = %s" % output_filename, file=sys.stderr)
+
+    if not os.path.exists(proto_filename):
+        print("Error: Could not find proto file %s" % proto_filename, file=sys.stderr)
+        return 1
+
+    protos = parse_protos(proto_filename)
+
+    # Generate event header
+    if args.gen_event_h:
+        curdir = os.path.dirname(os.path.abspath(__file__))
+        template_file = os.sep.join([curdir, 'templates', 'ar_event_h.template'])
+        output_fullpath = os.sep.join([output_dir, output_filename])
+
+        write_template_to_file(template_file, output_fullpath,
+                filename=output_filename,
+                protos=protos)
+
+    # Generate event implementation
+    if args.gen_event_cpp:
+        curdir = os.path.dirname(os.path.abspath(__file__))
+        template_file = os.sep.join([curdir, 'templates', 'ar_event_cpp.template'])
+        output_fullpath = os.sep.join([output_dir, output_filename])
+
+        write_template_to_file(template_file, output_fullpath,
+                filename=output_filename,
+                protos=protos)
+
+    # Generate event handler header
+    if args.gen_eventhandler_h:
+        curdir = os.path.dirname(os.path.abspath(__file__))
+        template_file = os.sep.join([curdir, 'templates', 'ar_eventhandler_h.template'])
+        output_fullpath = os.sep.join([output_dir, output_filename])
+
+        write_template_to_file(template_file, output_fullpath,
+                filename=output_filename,
+                event_header="gen_ar_event.h",   # todo: fix this!
+                protos=protos)
+
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(main())
+
diff --git a/src/gallium/drivers/swr/rasterizer/scripts/templates/ar_event_cpp.template b/src/gallium/drivers/swr/rasterizer/scripts/templates/ar_event_cpp.template
new file mode 100644 (file)
index 0000000..d033d93
--- /dev/null
@@ -0,0 +1,41 @@
+/****************************************************************************
+* Copyright (C) 2016 Intel Corporation.   All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice (including the next
+* paragraph) shall be included in all copies or substantial portions of the
+* Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+* IN THE SOFTWARE.
+*
+* @file ${filename}
+*
+* @brief Implementation for events.  auto-generated file
+* 
+* DO NOT EDIT
+*
+******************************************************************************/
+#include "common/os.h"
+#include "gen_ar_event.h"
+#include "gen_ar_eventhandler.h"
+
+using namespace ArchRast;
+% for name in protos['event_names']:
+
+void ${name}::accept(EventHandler* pHandler)
+{
+    pHandler->handle(*this);
+}
+% endfor
diff --git a/src/gallium/drivers/swr/rasterizer/scripts/templates/ar_event_h.template b/src/gallium/drivers/swr/rasterizer/scripts/templates/ar_event_h.template
new file mode 100644 (file)
index 0000000..c1576f7
--- /dev/null
@@ -0,0 +1,89 @@
+/****************************************************************************
+* Copyright (C) 2016 Intel Corporation.   All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice (including the next
+* paragraph) shall be included in all copies or substantial portions of the
+* Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+* IN THE SOFTWARE.
+*
+* @file ${filename}
+*
+* @brief Definitions for events.  auto-generated file
+* 
+* DO NOT EDIT
+* 
+******************************************************************************/
+#pragma once
+
+#include "common/os.h"
+#include "core/state.h"
+
+namespace ArchRast
+{
+% for name in protos['enum_names']:
+    enum ${name}
+    {<% names = protos['enums'][name]['names'] %>
+        % for i in range(len(names)):
+        ${names[i].lstrip()}
+        % endfor
+    };
+% endfor
+
+    //Forward decl
+    class EventHandler;
+
+    //////////////////////////////////////////////////////////////////////////
+    /// Event - interface for handling events.
+    //////////////////////////////////////////////////////////////////////////
+    struct Event
+    {
+        virtual void accept(EventHandler* pHandler) = 0;
+    };
+% for name in protos['event_names']:
+
+    //////////////////////////////////////////////////////////////////////////
+    /// ${name}
+    //////////////////////////////////////////////////////////////////////////
+    struct ${name} : Event
+    {<%
+        field_names = protos['events'][name]['field_names']
+        field_types = protos['events'][name]['field_types'] %>
+        // Fields
+        % for i in range(len(field_names)):
+        ${field_types[i]} ${field_names[i]};
+        % endfor
+
+        // Constructor
+        ${name}(
+        % for i in range(len(field_names)):
+            % if i < len(field_names)-1:
+            ${field_types[i]} ${field_names[i]},
+            % endif
+            % if i == len(field_names)-1:
+            ${field_types[i]} ${field_names[i]})
+            % endif
+        % endfor
+        {
+        % for i in range(len(field_names)):
+            this->${field_names[i]} = ${field_names[i]};
+        % endfor
+        }
+
+        virtual void accept(EventHandler* pHandler);
+    };
+% endfor
+}
\ No newline at end of file
diff --git a/src/gallium/drivers/swr/rasterizer/scripts/templates/ar_eventhandler_h.template b/src/gallium/drivers/swr/rasterizer/scripts/templates/ar_eventhandler_h.template
new file mode 100644 (file)
index 0000000..53e5a19
--- /dev/null
@@ -0,0 +1,46 @@
+/****************************************************************************
+* Copyright (C) 2016 Intel Corporation.   All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice (including the next
+* paragraph) shall be included in all copies or substantial portions of the
+* Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+* IN THE SOFTWARE.
+*
+* @file ${filename}
+*
+* @brief Event handler interface.  auto-generated file
+* 
+* DO NOT EDIT
+* 
+******************************************************************************/
+#pragma once
+
+#include "${event_header}"
+
+namespace ArchRast
+{
+    //////////////////////////////////////////////////////////////////////////
+    /// EventHandler - interface for handling events.
+    //////////////////////////////////////////////////////////////////////////
+    class EventHandler
+    {
+    public:
+% for name in protos['event_names']:
+        virtual void handle(${name}& event) {}
+% endfor
+    };
+}