layers: Validate mem ref counts in queueSubmit call
Grab and save max from GetGpuInfo, use this to validate count in
QueueSubmit call, warn if GetGpuInfo wasn't called beforehand.
diff --git a/layers/object_track.h b/layers/object_track.h
index b64e634..0ab7d44 100644
--- a/layers/object_track.h
+++ b/layers/object_track.h
@@ -39,6 +39,8 @@
OBJTRACK_COLOR_BLEND_NOT_BOUND, // Draw submitted with no color blend state object bound
OBJTRACK_DEPTH_STENCIL_NOT_BOUND, // Draw submitted with no depth-stencil state object bound
OBJTRACK_GPU_MEM_MAPPED, // Mem object ref'd in cmd buff is still mapped
+ OBJTRACK_GETGPUINFO_NOT_CALLED, // Gpu Information has not been requested before drawing
+ OBJTRACK_MEMREFCOUNT_MAX_EXCEEDED, // Number of QueueSubmit memory references exceeds GPU maximum
} OBJECT_TRACK_ERROR;
// Object Status -- used to track state of individual objects
@@ -163,9 +165,11 @@
uint64_t numUses;
OBJECT_STATUS status;
} OBJTRACK_NODE;
+
// prototype for extension functions
uint64_t objTrackGetObjectCount(XGL_OBJECT_TYPE type);
XGL_RESULT objTrackGetObjects(XGL_OBJECT_TYPE type, uint64_t objCount, OBJTRACK_NODE* pObjNodeArray);
+
// Func ptr typedefs
typedef uint64_t (*OBJ_TRACK_GET_OBJECT_COUNT)(XGL_OBJECT_TYPE);
typedef XGL_RESULT (*OBJ_TRACK_GET_OBJECTS)(XGL_OBJECT_TYPE, uint64_t, OBJTRACK_NODE*);
diff --git a/xgl-layer-generate.py b/xgl-layer-generate.py
index fd23635..bf17f68 100755
--- a/xgl-layer-generate.py
+++ b/xgl-layer-generate.py
@@ -641,6 +641,7 @@
if 'QueueSubmit' in proto.name:
using_line += ' set_status((void*)fence, XGL_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED);\n'
using_line += ' validate_memory_mapping_status(pMemRefs, memRefCount);\n'
+ using_line += ' validate_mem_ref_count(memRefCount);\n'
elif 'GetFenceStatus' in proto.name:
using_line += ' // Warn if submitted_flag is not set\n'
using_line += ' validate_status((void*)fence, XGL_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED, XGL_DBG_MSG_ERROR, OBJTRACK_INVALID_FENCE, "Status Requested for Unsubmitted Fence");\n'
@@ -714,6 +715,13 @@
'}' % (qual, decl, using_line, ret_val, proto.c_call(), create_line, destroy_line, stmt))
else:
c_call = proto.c_call().replace("(" + proto.params[0].name, "((XGL_PHYSICAL_GPU)gpuw->nextObject", 1)
+ gpu_state = ''
+ if 'GetGpuInfo' in proto.name:
+ gpu_state = ' if (infoType == XGL_INFO_TYPE_PHYSICAL_GPU_PROPERTIES) {\n'
+ gpu_state += ' if (pData != NULL) {\n'
+ gpu_state += ' setGpuInfoState(pData);\n'
+ gpu_state += ' }\n'
+ gpu_state += ' }\n'
funcs.append('%s%s\n'
'{\n'
' XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) %s;\n'
@@ -723,7 +731,8 @@
' %snextTable.%s;\n'
'%s%s'
'%s'
- '}' % (qual, decl, proto.params[0].name, using_line, ret_val, c_call, create_line, destroy_line, stmt))
+ '%s'
+ '}' % (qual, decl, proto.params[0].name, using_line, ret_val, c_call, create_line, destroy_line, gpu_state, stmt))
if 'WsiX11QueuePresent' == proto.name:
funcs.append("#endif")
elif "ParamChecker" == layer:
@@ -1194,6 +1203,7 @@
header_txt.append('static objNode *pGlobalHead = NULL;')
header_txt.append('static uint64_t numObjs[XGL_NUM_OBJECT_TYPE] = {0};')
header_txt.append('static uint64_t numTotalObjs = 0;')
+ header_txt.append('static uint32_t maxMemRefsPerSubmission = 0;')
header_txt.append('// Debug function to print global list and each individual object list')
header_txt.append('static void ll_print_lists()')
header_txt.append('{')
@@ -1425,6 +1435,24 @@
header_txt.append(' validate_status((void *)pMemRefs[i].mem, XGL_OBJECT_TYPE_GPU_MEMORY, OBJSTATUS_GPU_MEM_MAPPED, OBJSTATUS_NONE, XGL_DBG_MSG_ERROR, OBJTRACK_GPU_MEM_MAPPED, "A Mapped Memory Object was referenced in a command buffer");')
header_txt.append(' }')
header_txt.append('}')
+ header_txt.append('')
+ header_txt.append('static void validate_mem_ref_count(uint32_t numRefs) {')
+ header_txt.append(' if (maxMemRefsPerSubmission == 0) {')
+ header_txt.append(' char str[1024];')
+ header_txt.append(' sprintf(str, "xglQueueSubmit called before calling xglGetGpuInfo");')
+ header_txt.append(' layerCbMsg(XGL_DBG_MSG_WARNING, XGL_VALIDATION_LEVEL_0, NULL, 0, OBJTRACK_GETGPUINFO_NOT_CALLED, "OBJTRACK", str);')
+ header_txt.append(' } else {')
+ header_txt.append(' if (numRefs > maxMemRefsPerSubmission) {')
+ header_txt.append(' char str[1024];')
+ header_txt.append(' sprintf(str, "xglQueueSubmit Memory reference count (%d) exceeds allowable GPU limit (%d)", numRefs, maxMemRefsPerSubmission);')
+ header_txt.append(' layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, NULL, 0, OBJTRACK_MEMREFCOUNT_MAX_EXCEEDED, "OBJTRACK", str);')
+ header_txt.append(' }')
+ header_txt.append(' }')
+ header_txt.append('}')
+ header_txt.append('')
+ header_txt.append('static void setGpuInfoState(void *pData) {')
+ header_txt.append(' maxMemRefsPerSubmission = ((XGL_PHYSICAL_GPU_PROPERTIES *)pData)->maxMemRefsPerSubmission;')
+ header_txt.append('}')
return "\n".join(header_txt)
def generate_body(self):