Beispiel #1
0
ReplayCreateStatus ReplayRenderer::CreateDevice(const wchar_t *logfile)
{
	RDCLOG("Creating replay device for %ls", logfile);

	RDCDriver driverType = RDC_Unknown;
	wstring driverName = L"";
	auto status = RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, NULL);

	if(driverType == RDC_Unknown || driverName == L"" || status != eReplayCreate_Success)
	{
		RDCERR("Couldn't get device type from log");
		return status;
	}

	IReplayDriver *driver = NULL;
	status = RenderDoc::Inst().CreateReplayDriver(driverType, logfile, &driver);

	if(driver && status == eReplayCreate_Success)
	{
		RDCLOG("Created replay driver.");
		return PostCreateInit(driver);
	}
	
	RDCERR("Couldn't create a replay device :(.");
	return status;
}
Beispiel #2
0
  TargetControl(Network::Socket *sock, string clientName, bool forceConnection, bool localhost)
      : m_Socket(sock), m_Local(localhost)
  {
    PacketType type;
    vector<byte> payload;

    m_PID = 0;

    {
      Serialiser ser("", Serialiser::WRITING, false);

      ser.SerialiseString("", clientName);
      ser.Serialise("", forceConnection);

      if(!SendPacket(m_Socket, ePacket_Handshake, ser))
      {
        SAFE_DELETE(m_Socket);
        return;
      }
    }

    Serialiser *ser = NULL;
    GetPacket(type, ser);

    // failed handshaking
    if(m_Socket == NULL || ser == NULL)
      return;

    RDCASSERT(type == ePacket_Handshake || type == ePacket_Busy);

    if(type == ePacket_Handshake)
    {
      ser->Serialise("", m_Target);
      ser->Serialise("", m_API);
      ser->Serialise("", m_PID);

      RDCLOG("Got remote handshake: %s (%s) [%u]", m_Target.c_str(), m_API.c_str(), m_PID);
    }
    else if(type == ePacket_Busy)
    {
      ser->Serialise("", m_Target);
      ser->Serialise("", m_API);
      ser->Serialise("", m_BusyClient);

      RDCLOG("Got remote busy signal: %s (%s) owned by %s", m_Target.c_str(), m_API.c_str(),
             m_BusyClient.c_str());
    }

    SAFE_DELETE(ser);
  }
Beispiel #3
0
extern "C" RENDERDOC_API int RENDERDOC_CC RENDERDOC_GetAPI(RENDERDOC_Version version, void **outAPIPointers)
{
	if(outAPIPointers == NULL)
	{
		RDCERR("Invalid call to RENDERDOC_GetAPI with NULL outAPIPointers");
		return 0;
	}

	int ret = 0;
	int major = 0, minor = 0, patch = 0;

#define API_VERSION_HANDLE(enumver, actualver) \
	if(version == CONCAT(eRENDERDOC_API_Version_, enumver)) \
	{ \
		CONCAT(Init_, actualver)(); \
		*outAPIPointers = &CONCAT(api_, actualver); \
		CONCAT(api_, actualver).GetAPIVersion(&major, &minor, &patch); \
		ret = 1; \
	}

	API_VERSION_HANDLE(1_0_0, 1_0_1);
	API_VERSION_HANDLE(1_0_1, 1_0_1);

#undef API_VERSION_HANDLE

	if(ret)
	{
		RDCLOG("Initialising RenderDoc API version %d.%d.%d for requested version %d", major, minor, patch, version);
		return 1;
	}

	RDCERR("Unrecognised API version '%d'", version);
	return 0;
}
Beispiel #4
0
extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_TriggerExceptionHandler(void *exceptionPtrs,
                                                                             bool32 crashed)
{
  if(RenderDoc::Inst().GetCrashHandler() == NULL)
    return;

  if(exceptionPtrs)
  {
    RenderDoc::Inst().GetCrashHandler()->WriteMinidump(exceptionPtrs);
  }
  else
  {
    if(!crashed)
    {
      RDCLOG("Writing crash log");
    }

    RenderDoc::Inst().GetCrashHandler()->WriteMinidump();

    if(!crashed)
    {
      RenderDoc::Inst().RecreateCrashHandler();
    }
  }
}
Beispiel #5
0
ReplayCreateStatus ReplayRenderer::SetDevice(IReplayDriver *device)
{
	if(device)
	{
		RDCLOG("Got replay driver.");
		return PostCreateInit(device);
	}
	
	RDCERR("Given invalid replay driver.");
	return eReplayCreate_InternalError;
}
Beispiel #6
0
static void GPA_LoggingCallback(GPA_Logging_Type messageType, const char *pMessage)
{
  if(messageType == GPA_LOGGING_ERROR)
  {
    RDCWARN(pMessage);
  }
  else
  {
    RDCLOG(pMessage);
  }
}
    static int WSAAPI WSACleanup_hook()
    {
        // don't let the application murder our sockets with a mismatched WSACleanup() call
        if(syshooks.m_WSARefCount == 1)
        {
            RDCLOG("WSACleanup called with (to the application) no WSAStartup! Ignoring.");
            SetLastError(WSANOTINITIALISED);
            return SOCKET_ERROR;
        }

        // decrement refcount and call the real thing
        syshooks.m_WSARefCount--;
        return syshooks.WSACleanup()();
    }
Beispiel #8
0
BOOL add_hooks()
{
	wchar_t curFile[512];
	GetModuleFileNameW(NULL, curFile, 512);

	wstring f = strlower(wstring(curFile));

	// bail immediately if we're in a system process. We don't want to hook, log, anything -
	// this instance is being used for a shell extension.
	if(f.find(L"dllhost.exe") != wstring::npos ||
		f.find(L"explorer.exe") != wstring::npos)
	{
#ifndef _RELEASE
		OutputDebugStringA("Hosting renderdoc.dll in shell process\n");
#endif
		return TRUE;
	}

	if(f.find(L"renderdoccmd.exe") != wstring::npos ||
		 f.find(L"renderdocui.exe") != wstring::npos)
	{
		RDCDEBUG("Not creating hooks - in replay app");

		RenderDoc::Inst().SetReplayApp(true);
	
		RenderDoc::Inst().Initialise();

		return true;
	}
	
	RenderDoc::Inst().Initialise();

	RDCLOG("Loading into %ls", curFile);

	const wchar_t *appFilter = NULL; //L"MyApplication";

	if(appFilter != NULL)
	{
		if(wcsstr(curFile, appFilter) == 0)
		{
			RDCDEBUG("Not app I want. Exiting");
			return TRUE;
		}
	}

	LibraryHooks::GetInstance().CreateHooks();

	return TRUE;
}
Beispiel #9
0
// DllMain equivalent
void library_loaded()
{
	string curfile;
	FileIO::GetExecutableFilename(curfile);
	
	if(curfile.find("/renderdoccmd") != string::npos ||
	   curfile.find("/renderdocui") != string::npos ||
	   curfile.find("/qrenderdoc") != string::npos)
	{
		RDCDEBUG("Not creating hooks - in replay app");
		
		RenderDoc::Inst().SetReplayApp(true);
		
		RenderDoc::Inst().Initialise();
		
		return;
	}
	else
	{
		RenderDoc::Inst().Initialise();

		char *logfile = getenv("RENDERDOC_LOGFILE");
		char *opts = getenv("RENDERDOC_CAPTUREOPTS");

		if(opts)
		{
			string optstr = opts;

			CaptureOptions optstruct;
			readCapOpts(optstr.c_str(), &optstruct);

			RenderDoc::Inst().SetCaptureOptions(optstruct);
		}

		if(logfile)
		{
			RenderDoc::Inst().SetLogFile(logfile);
		}
	
		RDCLOG("Loading into %s", curfile.c_str());
	
		LibraryHooks::GetInstance().CreateHooks();
	}
}
Beispiel #10
0
static BOOL add_hooks()
{
    wchar_t curFile[512];
    GetModuleFileNameW(NULL, curFile, 512);

    wstring f = strlower(wstring(curFile));

    // bail immediately if we're in a system process. We don't want to hook, log, anything -
    // this instance is being used for a shell extension.
    if(f.find(L"dllhost.exe") != wstring::npos || f.find(L"explorer.exe") != wstring::npos)
    {
#ifndef _RELEASE
        OutputDebugStringA("Hosting " STRINGIZE(RDOC_DLL_FILE) ".dll in shell process\n");
#endif
        return TRUE;
    }

    if(f.find(CONCAT(L, STRINGIZE(RDOC_DLL_FILE)) L"cmd.exe") != wstring::npos ||
            f.find(CONCAT(L, STRINGIZE(RDOC_DLL_FILE)) L"ui.vshost.exe") != wstring::npos ||
            f.find(L"q" CONCAT(L, STRINGIZE(RDOC_DLL_FILE)) L".exe") != wstring::npos ||
            f.find(CONCAT(L, STRINGIZE(RDOC_DLL_FILE)) L"ui.exe") != wstring::npos)
    {
        RDCDEBUG("Not creating hooks - in replay app");

        RenderDoc::Inst().SetReplayApp(true);

        RenderDoc::Inst().Initialise();

        return true;
    }

    RenderDoc::Inst().Initialise();

    RDCLOG("Loading into %ls", curFile);

    LibraryHooks::GetInstance().CreateHooks();

    return TRUE;
}
Beispiel #11
0
static BOOL add_hooks()
{
  wchar_t curFile[512];
  GetModuleFileNameW(NULL, curFile, 512);

  wstring f = strlower(wstring(curFile));

  // bail immediately if we're in a system process. We don't want to hook, log, anything -
  // this instance is being used for a shell extension.
  if(f.find(L"dllhost.exe") != wstring::npos || f.find(L"explorer.exe") != wstring::npos)
  {
#ifndef _RELEASE
    OutputDebugStringA("Hosting " STRINGIZE(RDOC_DLL_FILE) ".dll in shell process\n");
#endif
    return TRUE;
  }

  // search for an exported symbol with this name, typically renderdoc__replay__marker
  if(HOOKS_IDENTIFY(STRINGIZE(RDOC_DLL_FILE) "__replay__marker"))
  {
    RDCDEBUG("Not creating hooks - in replay app");

    RenderDoc::Inst().SetReplayApp(true);

    RenderDoc::Inst().Initialise();

    return true;
  }

  RenderDoc::Inst().Initialise();

  RDCLOG("Loading into %ls", curFile);

  LibraryHooks::GetInstance().CreateHooks();

  return TRUE;
}
Beispiel #12
0
bool WrappedVulkan::Serialise_vkCreateDevice(
		Serialiser*                                 localSerialiser,
		VkPhysicalDevice                            physicalDevice,
		const VkDeviceCreateInfo*                   pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
		VkDevice*                                   pDevice)
{
	SERIALISE_ELEMENT(ResourceId, physId, GetResID(physicalDevice));
	SERIALISE_ELEMENT(VkDeviceCreateInfo, serCreateInfo, *pCreateInfo);
	SERIALISE_ELEMENT(ResourceId, devId, GetResID(*pDevice));

	if(m_State == READING)
	{
		// we must make any modifications locally, so the free of pointers
		// in the serialised VkDeviceCreateInfo don't double-free
		VkDeviceCreateInfo createInfo = serCreateInfo;
		
		std::vector<string> Extensions;
		for(uint32_t i=0; i < createInfo.enabledExtensionCount; i++)
		{
			// don't include the debug marker extension
			if(strcmp(createInfo.ppEnabledExtensionNames[i], VK_EXT_DEBUG_MARKER_EXTENSION_NAME))
				Extensions.push_back(createInfo.ppEnabledExtensionNames[i]);
		}

		std::vector<string> Layers;
		for(uint32_t i=0; i < createInfo.enabledLayerCount; i++)
			Layers.push_back(createInfo.ppEnabledLayerNames[i]);

		StripUnwantedLayers(Layers);

		AddRequiredExtensions(false, Extensions);
		
#if defined(FORCE_VALIDATION_LAYERS)
		Layers.push_back("VK_LAYER_LUNARG_standard_validation");
#endif

		createInfo.enabledLayerCount = (uint32_t)Layers.size();

		const char **layerArray = NULL;
		if(!Layers.empty())
		{
			layerArray = new const char *[createInfo.enabledLayerCount];
			
			for(uint32_t i=0; i < createInfo.enabledLayerCount; i++)
				layerArray[i] = Layers[i].c_str();

			createInfo.ppEnabledLayerNames = layerArray;
		}

		createInfo.enabledExtensionCount = (uint32_t)Extensions.size();

		const char **extArray = NULL;
		if(!Extensions.empty())
		{
			extArray = new const char *[createInfo.enabledExtensionCount];
			
			for(uint32_t i=0; i < createInfo.enabledExtensionCount; i++)
				extArray[i] = Extensions[i].c_str();

			createInfo.ppEnabledExtensionNames = extArray;
		}

		physicalDevice = GetResourceManager()->GetLiveHandle<VkPhysicalDevice>(physId);

		VkDevice device;

		uint32_t qCount = 0;
		ObjDisp(physicalDevice)->GetPhysicalDeviceQueueFamilyProperties(Unwrap(physicalDevice), &qCount, NULL);

		VkQueueFamilyProperties *props = new VkQueueFamilyProperties[qCount];
		ObjDisp(physicalDevice)->GetPhysicalDeviceQueueFamilyProperties(Unwrap(physicalDevice), &qCount, props);

		bool found = false;
		uint32_t qFamilyIdx = 0;
		VkQueueFlags search = (VK_QUEUE_GRAPHICS_BIT);

		// for queue priorities, if we need it
		float one = 1.0f;

		// if we need to change the requested queues, it will point to this
		VkDeviceQueueCreateInfo *modQueues = NULL;

		for(uint32_t i=0; i < createInfo.queueCreateInfoCount; i++)
		{
			uint32_t idx = createInfo.pQueueCreateInfos[i].queueFamilyIndex;
			RDCASSERT(idx < qCount);

			// this requested queue is one we can use too
			if((props[idx].queueFlags & search) == search && createInfo.pQueueCreateInfos[i].queueCount > 0)
			{
				qFamilyIdx = idx;
				found = true;
				break;
			}
		}

		// if we didn't find it, search for which queue family we should add a request for
		if(!found)
		{
			RDCDEBUG("App didn't request a queue family we can use - adding our own");

			for(uint32_t i=0; i < qCount; i++)
			{
				if((props[i].queueFlags & search) == search)
				{
					qFamilyIdx = i;
					found = true;
					break;
				}
			}

			if(!found)
			{
				SAFE_DELETE_ARRAY(props);
				RDCERR("Can't add a queue with required properties for RenderDoc! Unsupported configuration");
			}
			else
			{
				// we found the queue family, add it
				modQueues = new VkDeviceQueueCreateInfo[createInfo.queueCreateInfoCount + 1];
				for(uint32_t i=0; i < createInfo.queueCreateInfoCount; i++)
					modQueues[i] = createInfo.pQueueCreateInfos[i];

				modQueues[createInfo.queueCreateInfoCount].queueFamilyIndex = qFamilyIdx;
				modQueues[createInfo.queueCreateInfoCount].queueCount = 1;
				modQueues[createInfo.queueCreateInfoCount].pQueuePriorities = &one;

				createInfo.pQueueCreateInfos = modQueues;
				createInfo.queueCreateInfoCount++;
			}
		}
		
		SAFE_DELETE_ARRAY(props);

		VkPhysicalDeviceFeatures enabledFeatures = {0};
		if(createInfo.pEnabledFeatures != NULL) enabledFeatures = *createInfo.pEnabledFeatures;
		createInfo.pEnabledFeatures = &enabledFeatures;

		VkPhysicalDeviceFeatures availFeatures = {0};
		ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures(Unwrap(physicalDevice), &availFeatures);

		if(availFeatures.fillModeNonSolid)
			enabledFeatures.fillModeNonSolid = true;
		else
			RDCWARN("fillModeNonSolid = false, wireframe overlay will be solid");
		
		if(availFeatures.robustBufferAccess)
			enabledFeatures.robustBufferAccess = true;
		else
			RDCWARN("robustBufferAccess = false, out of bounds access due to bugs in application or RenderDoc may cause crashes");

		if(availFeatures.vertexPipelineStoresAndAtomics)
			enabledFeatures.vertexPipelineStoresAndAtomics = true;
		else
			RDCWARN("vertexPipelineStoresAndAtomics = false, output mesh data will not be available");

		uint32_t numExts = 0;

		VkResult vkr = ObjDisp(physicalDevice)->EnumerateDeviceExtensionProperties(Unwrap(physicalDevice), NULL, &numExts, NULL);
		RDCASSERTEQUAL(vkr, VK_SUCCESS);

		VkExtensionProperties *exts = new VkExtensionProperties[numExts];

		vkr = ObjDisp(physicalDevice)->EnumerateDeviceExtensionProperties(Unwrap(physicalDevice), NULL, &numExts, exts);
		RDCASSERTEQUAL(vkr, VK_SUCCESS);

		for(uint32_t i=0; i < numExts; i++)
			RDCLOG("Ext %u: %s (%u)", i, exts[i].extensionName, exts[i].specVersion);

		SAFE_DELETE_ARRAY(exts);

		// PORTABILITY check that extensions and layers supported in capture (from createInfo) are supported in replay

		vkr = GetDeviceDispatchTable(NULL)->CreateDevice(Unwrap(physicalDevice), &createInfo, NULL, &device);
		RDCASSERTEQUAL(vkr, VK_SUCCESS);

		GetResourceManager()->WrapResource(device, device);
		GetResourceManager()->AddLiveResource(devId, device);
		
		InitDeviceReplayTables(Unwrap(device));

		RDCASSERT(m_Device == VK_NULL_HANDLE); // MULTIDEVICE
		
		m_PhysicalDevice = physicalDevice;
		m_Device = device;

		m_QueueFamilyIdx = qFamilyIdx;

		if(m_InternalCmds.cmdpool == VK_NULL_HANDLE)
		{
			VkCommandPoolCreateInfo poolInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, NULL, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, qFamilyIdx };
			vkr = ObjDisp(device)->CreateCommandPool(Unwrap(device), &poolInfo, NULL, &m_InternalCmds.cmdpool);
			RDCASSERTEQUAL(vkr, VK_SUCCESS);

			GetResourceManager()->WrapResource(Unwrap(device), m_InternalCmds.cmdpool);
		}
		
		ObjDisp(physicalDevice)->GetPhysicalDeviceProperties(Unwrap(physicalDevice), &m_PhysicalDeviceData.props);
		
		ObjDisp(physicalDevice)->GetPhysicalDeviceMemoryProperties(Unwrap(physicalDevice), &m_PhysicalDeviceData.memProps);

		ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures(Unwrap(physicalDevice), &m_PhysicalDeviceData.features);

		for(int i=VK_FORMAT_BEGIN_RANGE+1; i < VK_FORMAT_END_RANGE; i++)
			ObjDisp(physicalDevice)->GetPhysicalDeviceFormatProperties(Unwrap(physicalDevice), VkFormat(i), &m_PhysicalDeviceData.fmtprops[i]);

		m_PhysicalDeviceData.readbackMemIndex = m_PhysicalDeviceData.GetMemoryIndex(~0U, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 0);
		m_PhysicalDeviceData.uploadMemIndex = m_PhysicalDeviceData.GetMemoryIndex(~0U, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 0);
		m_PhysicalDeviceData.GPULocalMemIndex = m_PhysicalDeviceData.GetMemoryIndex(~0U, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);

		for(size_t i=0; i < m_PhysicalDevices.size(); i++)
		{
			if(physicalDevice == m_PhysicalDevices[i])
			{
				m_PhysicalDeviceData.memIdxMap = m_MemIdxMaps[i];
				break;
			}
		}

		m_DebugManager = new VulkanDebugManager(this, device);

		SAFE_DELETE_ARRAY(modQueues);
		SAFE_DELETE_ARRAY(layerArray);
		SAFE_DELETE_ARRAY(extArray);
	}

	return true;
}
Beispiel #13
0
bool WrappedVulkan::Serialise_vkEnumeratePhysicalDevices(
		Serialiser*                                 localSerialiser,
		VkInstance                                  instance,
		uint32_t*                                   pPhysicalDeviceCount,
		VkPhysicalDevice*                           pPhysicalDevices)
{
	SERIALISE_ELEMENT(ResourceId, inst, GetResID(instance));
	SERIALISE_ELEMENT(uint32_t, physIndex, *pPhysicalDeviceCount);
	SERIALISE_ELEMENT(ResourceId, physId, GetResID(*pPhysicalDevices));

	uint32_t memIdxMap[32] = {0};
	if(m_State >= WRITING)
		memcpy(memIdxMap, GetRecord(*pPhysicalDevices)->memIdxMap, sizeof(memIdxMap));

	localSerialiser->SerialisePODArray<32>("memIdxMap", memIdxMap);

	// not used at the moment but useful for reference and might be used
	// in the future
	VkPhysicalDeviceProperties physProps;
	VkPhysicalDeviceMemoryProperties memProps;
	VkPhysicalDeviceFeatures physFeatures;
	
	if(m_State >= WRITING)
	{
		ObjDisp(instance)->GetPhysicalDeviceProperties(Unwrap(*pPhysicalDevices), &physProps);
		ObjDisp(instance)->GetPhysicalDeviceMemoryProperties(Unwrap(*pPhysicalDevices), &memProps);
		ObjDisp(instance)->GetPhysicalDeviceFeatures(Unwrap(*pPhysicalDevices), &physFeatures);
	}

	localSerialiser->Serialise("physProps", physProps);
	localSerialiser->Serialise("memProps", memProps);
	localSerialiser->Serialise("physFeatures", physFeatures);

	VkPhysicalDevice pd = VK_NULL_HANDLE;

	if(m_State >= WRITING)
	{
		pd = *pPhysicalDevices;
	}
	else
	{
		uint32_t count;
		VkPhysicalDevice *devices;

		instance = GetResourceManager()->GetLiveHandle<VkInstance>(inst);
		VkResult vkr = ObjDisp(instance)->EnumeratePhysicalDevices(Unwrap(instance), &count, NULL);
		RDCASSERTEQUAL(vkr, VK_SUCCESS);

		RDCASSERT(count > physIndex);
		devices = new VkPhysicalDevice[count];

		if(physIndex >= m_PhysicalDevices.size())
		{
			m_PhysicalDevices.resize(physIndex+1);
			m_MemIdxMaps.resize(physIndex+1);
		}

		vkr = ObjDisp(instance)->EnumeratePhysicalDevices(Unwrap(instance), &count, devices);
		RDCASSERTEQUAL(vkr, VK_SUCCESS);

		// PORTABILITY match up physical devices to those available on replay

		pd = devices[physIndex];

		for(size_t i=0; i < m_PhysicalDevices.size(); i++)
		{
			// physical devices might be re-created inside EnumeratePhysicalDevices every time, so
			// we need to re-wrap any previously enumerated physical devices
			if(m_PhysicalDevices[i] != VK_NULL_HANDLE)
			{
				RDCASSERTNOTEQUAL(i, physIndex);
				GetWrapped(m_PhysicalDevices[i])->RewrapObject(devices[i]);
			}
		}

		SAFE_DELETE_ARRAY(devices);

		GetResourceManager()->WrapResource(instance, pd);
		GetResourceManager()->AddLiveResource(physId, pd);

		m_PhysicalDevices[physIndex] = pd;

		uint32_t *storedMap = new uint32_t[32];
		memcpy(storedMap, memIdxMap, sizeof(memIdxMap));
		m_MemIdxMaps[physIndex] = storedMap;

		RDCLOG("Captured log describes physical device %u:", physIndex);
		RDCLOG("   - %s (ver %x) - %04x:%04x", physProps.deviceName, physProps.driverVersion, physProps.vendorID, physProps.deviceID);

		ObjDisp(pd)->GetPhysicalDeviceProperties(Unwrap(pd), &physProps);
		ObjDisp(pd)->GetPhysicalDeviceMemoryProperties(Unwrap(pd), &memProps);
		ObjDisp(pd)->GetPhysicalDeviceFeatures(Unwrap(pd), &physFeatures);
		
		RDCLOG("Replaying on physical device %u:", physIndex);
		RDCLOG("   - %s (ver %x) - %04x:%04x", physProps.deviceName, physProps.driverVersion, physProps.vendorID, physProps.deviceID);

	}

	return true;
}
Beispiel #14
0
VkResult WrappedVulkan::vkCreateInstance(
		const VkInstanceCreateInfo*                 pCreateInfo,
		const VkAllocationCallbacks*                pAllocator,
		VkInstance*                                 pInstance)
{
	RDCASSERT(pCreateInfo);

	// don't support any extensions for this createinfo
	RDCASSERT(pCreateInfo->pApplicationInfo == NULL || pCreateInfo->pApplicationInfo->pNext == NULL);

	VkLayerInstanceCreateInfo *layerCreateInfo = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext;

	// step through the chain of pNext until we get to the link info
	while(layerCreateInfo &&
				(layerCreateInfo->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO || 
				 layerCreateInfo->function != VK_LAYER_LINK_INFO)
			)
	{
		layerCreateInfo = (VkLayerInstanceCreateInfo *)layerCreateInfo->pNext;
	}
	RDCASSERT(layerCreateInfo);

	PFN_vkGetInstanceProcAddr gpa = layerCreateInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr;
	// move chain on for next layer
	layerCreateInfo->u.pLayerInfo = layerCreateInfo->u.pLayerInfo->pNext;

	PFN_vkCreateInstance createFunc = (PFN_vkCreateInstance)gpa(VK_NULL_HANDLE, "vkCreateInstance");

	VkInstanceCreateInfo modifiedCreateInfo;
	modifiedCreateInfo = *pCreateInfo;

	const char **addedExts = new const char *[modifiedCreateInfo.enabledExtensionCount+1];

	for(uint32_t i=0; i < modifiedCreateInfo.enabledExtensionCount; i++)
		addedExts[i] = modifiedCreateInfo.ppEnabledExtensionNames[i];

	if(RenderDoc::Inst().GetCaptureOptions().APIValidation)
		addedExts[modifiedCreateInfo.enabledExtensionCount++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME;

	modifiedCreateInfo.ppEnabledExtensionNames = addedExts;
	
	VkResult ret = createFunc(&modifiedCreateInfo, pAllocator, pInstance);

	m_Instance = *pInstance;

	InitInstanceTable(m_Instance, gpa);

	GetResourceManager()->WrapResource(m_Instance, m_Instance);

	*pInstance = m_Instance;

	// should only be called during capture
	RDCASSERT(m_State >= WRITING);

	m_InitParams.Set(pCreateInfo, GetResID(m_Instance));
	VkResourceRecord *record = GetResourceManager()->AddResourceRecord(m_Instance);

	record->instDevInfo = new InstanceDeviceInfo();
	
#undef CheckExt
#define CheckExt(name) if(!strcmp(modifiedCreateInfo.ppEnabledExtensionNames[i], STRINGIZE(name))) { record->instDevInfo->name = true; }

	for(uint32_t i=0; i < modifiedCreateInfo.enabledExtensionCount; i++)
	{
		CheckInstanceExts();
	}

	delete[] addedExts;

	InitInstanceExtensionTables(m_Instance);

	RenderDoc::Inst().AddDeviceFrameCapturer(LayerDisp(m_Instance), this);
	
	m_DbgMsgCallback = VK_NULL_HANDLE;
	m_PhysicalDevice = VK_NULL_HANDLE;
	m_Device = VK_NULL_HANDLE;
	m_QueueFamilyIdx = ~0U;
	m_Queue = VK_NULL_HANDLE;
	m_InternalCmds.Reset();

	if(RenderDoc::Inst().GetCaptureOptions().APIValidation && ObjDisp(m_Instance)->CreateDebugReportCallbackEXT)
	{
		VkDebugReportCallbackCreateInfoEXT debugInfo = {};
		debugInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
		debugInfo.pNext = NULL;
		debugInfo.pfnCallback = &DebugCallbackStatic;
		debugInfo.pUserData = this;
		debugInfo.flags = VK_DEBUG_REPORT_WARNING_BIT_EXT|VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT|VK_DEBUG_REPORT_ERROR_BIT_EXT;

		ObjDisp(m_Instance)->CreateDebugReportCallbackEXT(Unwrap(m_Instance), &debugInfo, NULL, &m_DbgMsgCallback);
	}

	if(ret == VK_SUCCESS)
	{
		RDCLOG("Initialised capture layer in Vulkan instance.");
	}

	return ret;
}
Beispiel #15
0
VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount,
                                      const VkSubmitInfo *pSubmits, VkFence fence)
{
  SCOPED_DBG_SINK();

  size_t tempmemSize = sizeof(VkSubmitInfo) * submitCount;

  // need to count how many semaphore and command buffer arrays to allocate for
  for(uint32_t i = 0; i < submitCount; i++)
  {
    tempmemSize += pSubmits[i].commandBufferCount * sizeof(VkCommandBuffer);
    tempmemSize += pSubmits[i].signalSemaphoreCount * sizeof(VkSemaphore);
    tempmemSize += pSubmits[i].waitSemaphoreCount * sizeof(VkSemaphore);
  }

  byte *memory = GetTempMemory(tempmemSize);

  VkSubmitInfo *unwrappedSubmits = (VkSubmitInfo *)memory;
  VkSemaphore *unwrappedWaitSems = (VkSemaphore *)(unwrappedSubmits + submitCount);

  for(uint32_t i = 0; i < submitCount; i++)
  {
    RDCASSERT(pSubmits[i].sType == VK_STRUCTURE_TYPE_SUBMIT_INFO && pSubmits[i].pNext == NULL);
    unwrappedSubmits[i] = pSubmits[i];

    unwrappedSubmits[i].pWaitSemaphores =
        unwrappedSubmits[i].waitSemaphoreCount ? unwrappedWaitSems : NULL;
    for(uint32_t o = 0; o < unwrappedSubmits[i].waitSemaphoreCount; o++)
      unwrappedWaitSems[o] = Unwrap(pSubmits[i].pWaitSemaphores[o]);
    unwrappedWaitSems += unwrappedSubmits[i].waitSemaphoreCount;

    VkCommandBuffer *unwrappedCommandBuffers = (VkCommandBuffer *)unwrappedWaitSems;

    unwrappedSubmits[i].pCommandBuffers =
        unwrappedSubmits[i].commandBufferCount ? unwrappedCommandBuffers : NULL;
    for(uint32_t o = 0; o < unwrappedSubmits[i].commandBufferCount; o++)
      unwrappedCommandBuffers[o] = Unwrap(pSubmits[i].pCommandBuffers[o]);
    unwrappedCommandBuffers += unwrappedSubmits[i].commandBufferCount;

    VkSemaphore *unwrappedSignalSems = (VkSemaphore *)unwrappedCommandBuffers;

    unwrappedSubmits[i].pSignalSemaphores =
        unwrappedSubmits[i].signalSemaphoreCount ? unwrappedSignalSems : NULL;
    for(uint32_t o = 0; o < unwrappedSubmits[i].signalSemaphoreCount; o++)
      unwrappedSignalSems[o] = Unwrap(pSubmits[i].pSignalSemaphores[o]);
  }

  VkResult ret =
      ObjDisp(queue)->QueueSubmit(Unwrap(queue), submitCount, unwrappedSubmits, Unwrap(fence));

  bool capframe = false;
  set<ResourceId> refdIDs;

  for(uint32_t s = 0; s < submitCount; s++)
  {
    for(uint32_t i = 0; i < pSubmits[s].commandBufferCount; i++)
    {
      ResourceId cmd = GetResID(pSubmits[s].pCommandBuffers[i]);

      VkResourceRecord *record = GetRecord(pSubmits[s].pCommandBuffers[i]);

      {
        SCOPED_LOCK(m_ImageLayoutsLock);
        GetResourceManager()->ApplyBarriers(record->bakedCommands->cmdInfo->imgbarriers,
                                            m_ImageLayouts);
      }

      // need to lock the whole section of code, not just the check on
      // m_State, as we also need to make sure we don't check the state,
      // start marking dirty resources then while we're doing so the
      // state becomes capframe.
      // the next sections where we mark resources referenced and add
      // the submit chunk to the frame record don't have to be protected.
      // Only the decision of whether we're inframe or not, and marking
      // dirty.
      {
        SCOPED_LOCK(m_CapTransitionLock);
        if(m_State == WRITING_CAPFRAME)
        {
          for(auto it = record->bakedCommands->cmdInfo->dirtied.begin();
              it != record->bakedCommands->cmdInfo->dirtied.end(); ++it)
            GetResourceManager()->MarkPendingDirty(*it);

          capframe = true;
        }
        else
        {
          for(auto it = record->bakedCommands->cmdInfo->dirtied.begin();
              it != record->bakedCommands->cmdInfo->dirtied.end(); ++it)
            GetResourceManager()->MarkDirtyResource(*it);
        }
      }

      if(capframe)
      {
        // for each bound descriptor set, mark it referenced as well as all resources currently
        // bound to it
        for(auto it = record->bakedCommands->cmdInfo->boundDescSets.begin();
            it != record->bakedCommands->cmdInfo->boundDescSets.end(); ++it)
        {
          GetResourceManager()->MarkResourceFrameReferenced(GetResID(*it), eFrameRef_Read);

          VkResourceRecord *setrecord = GetRecord(*it);

          for(auto refit = setrecord->descInfo->bindFrameRefs.begin();
              refit != setrecord->descInfo->bindFrameRefs.end(); ++refit)
          {
            refdIDs.insert(refit->first);
            GetResourceManager()->MarkResourceFrameReferenced(refit->first, refit->second.second);

            if(refit->second.first & DescriptorSetData::SPARSE_REF_BIT)
            {
              VkResourceRecord *sparserecord = GetResourceManager()->GetResourceRecord(refit->first);

              GetResourceManager()->MarkSparseMapReferenced(sparserecord->sparseInfo);
            }
          }
        }

        for(auto it = record->bakedCommands->cmdInfo->sparse.begin();
            it != record->bakedCommands->cmdInfo->sparse.end(); ++it)
          GetResourceManager()->MarkSparseMapReferenced(*it);

        // pull in frame refs from this baked command buffer
        record->bakedCommands->AddResourceReferences(GetResourceManager());
        record->bakedCommands->AddReferencedIDs(refdIDs);

        // ref the parent command buffer by itself, this will pull in the cmd buffer pool
        GetResourceManager()->MarkResourceFrameReferenced(record->GetResourceID(), eFrameRef_Read);

        for(size_t sub = 0; sub < record->bakedCommands->cmdInfo->subcmds.size(); sub++)
        {
          record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->AddResourceReferences(
              GetResourceManager());
          record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->AddReferencedIDs(refdIDs);
          GetResourceManager()->MarkResourceFrameReferenced(
              record->bakedCommands->cmdInfo->subcmds[sub]->GetResourceID(), eFrameRef_Read);

          record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->AddRef();
        }

        GetResourceManager()->MarkResourceFrameReferenced(GetResID(queue), eFrameRef_Read);

        if(fence != VK_NULL_HANDLE)
          GetResourceManager()->MarkResourceFrameReferenced(GetResID(fence), eFrameRef_Read);

        {
          SCOPED_LOCK(m_CmdBufferRecordsLock);
          m_CmdBufferRecords.push_back(record->bakedCommands);
          for(size_t sub = 0; sub < record->bakedCommands->cmdInfo->subcmds.size(); sub++)
            m_CmdBufferRecords.push_back(record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands);
        }

        record->bakedCommands->AddRef();
      }

      record->cmdInfo->dirtied.clear();
    }
  }

  if(capframe)
  {
    vector<VkResourceRecord *> maps;
    {
      SCOPED_LOCK(m_CoherentMapsLock);
      maps = m_CoherentMaps;
    }

    for(auto it = maps.begin(); it != maps.end(); ++it)
    {
      VkResourceRecord *record = *it;
      MemMapState &state = *record->memMapState;

      // potential persistent map
      if(state.mapCoherent && state.mappedPtr && !state.mapFlushed)
      {
        // only need to flush memory that could affect this submitted batch of work
        if(refdIDs.find(record->GetResourceID()) == refdIDs.end())
        {
          RDCDEBUG("Map of memory %llu not referenced in this queue - not flushing",
                   record->GetResourceID());
          continue;
        }

        size_t diffStart = 0, diffEnd = 0;
        bool found = true;

// enabled as this is necessary for programs with very large coherent mappings
// (> 1GB) as otherwise more than a couple of vkQueueSubmit calls leads to vast
// memory allocation. There might still be bugs lurking in here though
#if 1
        // this causes vkFlushMappedMemoryRanges call to allocate and copy to refData
        // from serialised buffer. We want to copy *precisely* the serialised data,
        // otherwise there is a gap in time between serialising out a snapshot of
        // the buffer and whenever we then copy into the ref data, e.g. below.
        // during this time, data could be written to the buffer and it won't have
        // been caught in the serialised snapshot, and if it doesn't change then
        // it *also* won't be caught in any future FindDiffRange() calls.
        //
        // Likewise once refData is allocated, the call below will also update it
        // with the data serialised out for the same reason.
        //
        // Note: it's still possible that data is being written to by the
        // application while it's being serialised out in the snapshot below. That
        // is OK, since the application is responsible for ensuring it's not writing
        // data that would be needed by the GPU in this submit. As long as the
        // refdata we use for future use is identical to what was serialised, we
        // shouldn't miss anything
        state.needRefData = true;

        // if we have a previous set of data, compare.
        // otherwise just serialise it all
        if(state.refData)
          found = FindDiffRange((byte *)state.mappedPtr, state.refData, (size_t)state.mapSize,
                                diffStart, diffEnd);
        else
#endif
          diffEnd = (size_t)state.mapSize;

        if(found)
        {
          // MULTIDEVICE should find the device for this queue.
          // MULTIDEVICE only want to flush maps associated with this queue
          VkDevice dev = GetDev();

          {
            RDCLOG("Persistent map flush forced for %llu (%llu -> %llu)", record->GetResourceID(),
                   (uint64_t)diffStart, (uint64_t)diffEnd);
            VkMappedMemoryRange range = {VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, NULL,
                                         (VkDeviceMemory)(uint64_t)record->Resource,
                                         state.mapOffset + diffStart, diffEnd - diffStart};
            vkFlushMappedMemoryRanges(dev, 1, &range);
            state.mapFlushed = false;
          }

          GetResourceManager()->MarkPendingDirty(record->GetResourceID());
        }
        else
        {
          RDCDEBUG("Persistent map flush not needed for %llu", record->GetResourceID());
        }
      }
    }

    {
      CACHE_THREAD_SERIALISER();

      for(uint32_t s = 0; s < submitCount; s++)
      {
        SCOPED_SERIALISE_CONTEXT(QUEUE_SUBMIT);
        Serialise_vkQueueSubmit(localSerialiser, queue, 1, &pSubmits[s], fence);

        m_FrameCaptureRecord->AddChunk(scope.Get());

        for(uint32_t sem = 0; sem < pSubmits[s].waitSemaphoreCount; sem++)
          GetResourceManager()->MarkResourceFrameReferenced(
              GetResID(pSubmits[s].pWaitSemaphores[sem]), eFrameRef_Read);

        for(uint32_t sem = 0; sem < pSubmits[s].signalSemaphoreCount; sem++)
          GetResourceManager()->MarkResourceFrameReferenced(
              GetResID(pSubmits[s].pSignalSemaphores[sem]), eFrameRef_Read);
      }
    }
  }

  return ret;
}
Beispiel #16
0
  HRESULT Create_Internal(IUnknown *pAdapter, D3D_FEATURE_LEVEL MinimumFeatureLevel, REFIID riid,
                          void **ppDevice)
  {
    // if we're already inside a wrapped create i.e. this function, then DON'T do anything
    // special. Just grab the trampolined function and call it.
    if(m_InsideCreate)
    {
      PFN_D3D12_CREATE_DEVICE createFunc = NULL;

      // shouldn't ever get in here if we're in the case without hooks but let's be safe.
      if(m_HasHooks)
      {
        createFunc = CreateDevice();
      }
      else
      {
        HMODULE d3d12 = GetModuleHandleA("d3d12.dll");

        if(d3d12)
        {
          createFunc = (PFN_D3D12_CREATE_DEVICE)GetProcAddress(d3d12, "D3D12CreateDevice");
        }
        else
        {
          RDCERR("Something went seriously wrong, d3d12.dll couldn't be loaded!");
          return E_UNEXPECTED;
        }
      }

      return createFunc(pAdapter, MinimumFeatureLevel, riid, ppDevice);
    }

    m_InsideCreate = true;

    if(riid != __uuidof(ID3D12Device))
    {
      RDCERR("Unsupported UUID %s for D3D12CreateDevice", ToStr::Get(riid).c_str());
      return E_NOINTERFACE;
    }

    RDCDEBUG("Call to Create_Internal Feature Level %x", MinimumFeatureLevel,
             ToStr::Get(riid).c_str());

    bool reading = RenderDoc::Inst().IsReplayApp();

    if(reading)
    {
      RDCDEBUG("In replay app");
    }

    const bool EnableDebugLayer =
#if 1    // toggle on/off if you want debug layer during replay
        RenderDoc::Inst().IsReplayApp() ||
#endif
        (m_EnabledHooks && !reading && RenderDoc::Inst().GetCaptureOptions().APIValidation);

    if(EnableDebugLayer)
    {
      PFN_D3D12_GET_DEBUG_INTERFACE getfn = GetDebugInterface();

      if(getfn == NULL)
        getfn = (PFN_D3D12_GET_DEBUG_INTERFACE)GetProcAddress(GetModuleHandleA("d3d12.dll"),
                                                              "D3D12GetDebugInterface");

      if(getfn)
      {
        ID3D12Debug *debug = NULL;
        HRESULT hr = getfn(__uuidof(ID3D12Debug), (void **)&debug);

        if(SUCCEEDED(hr) && debug)
          debug->EnableDebugLayer();
        else
          RDCERR("Couldn't enable debug layer: %x", hr);

        SAFE_RELEASE(debug);
      }
      else
      {
        RDCERR("Couldn't find D3D12GetDebugInterface!");
      }
    }

    RDCDEBUG("Calling real createdevice...");

    PFN_D3D12_CREATE_DEVICE createFunc =
        (PFN_D3D12_CREATE_DEVICE)GetProcAddress(GetModuleHandleA("d3d12.dll"), "D3D12CreateDevice");

    if(createFunc == NULL)
      createFunc = CreateDevice();

    // shouldn't ever get here, we should either have it from procaddress or the trampoline, but
    // let's be safe.
    if(createFunc == NULL)
    {
      RDCERR("Something went seriously wrong with the hooks!");

      m_InsideCreate = false;

      return E_UNEXPECTED;
    }

    HRESULT ret = createFunc(pAdapter, MinimumFeatureLevel, riid, ppDevice);

    RDCDEBUG("Called real createdevice... 0x%08x", ret);

    if(SUCCEEDED(ret) && m_EnabledHooks && ppDevice)
    {
      RDCDEBUG("succeeded and hooking.");

      if(!WrappedID3D12Device::IsAlloc(*ppDevice))
      {
        D3D12InitParams params;
        params.MinimumFeatureLevel = MinimumFeatureLevel;

        ID3D12Device *dev = (ID3D12Device *)*ppDevice;

        WrappedID3D12Device *wrap = new WrappedID3D12Device(dev, &params);

        RDCDEBUG("created wrapped device.");

        *ppDevice = (ID3D12Device *)wrap;
      }
    }
    else if(SUCCEEDED(ret))
    {
      RDCLOG("Created wrapped D3D12 device.");
    }
    else
    {
      RDCDEBUG("failed. 0x%08x", ret);
    }

    m_InsideCreate = false;

    return ret;
  }
Beispiel #17
0
extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_LogText(const char *text)
{
  RDCLOG("%s", text);
}
Beispiel #18
0
ReplayCreateStatus D3D12_CreateReplayDevice(const char *logfile, IReplayDriver **driver)
{
  RDCDEBUG("Creating a D3D12 replay device");

  WrappedIDXGISwapChain3::RegisterD3DDeviceCallback(GetD3D12DeviceIfAlloc);

  HMODULE lib = NULL;
  lib = LoadLibraryA("d3d12.dll");
  if(lib == NULL)
  {
    RDCERR("Failed to load d3d12.dll");
    return eReplayCreate_APIInitFailed;
  }

  lib = LoadLibraryA("dxgi.dll");
  if(lib == NULL)
  {
    RDCERR("Failed to load dxgi.dll");
    return eReplayCreate_APIInitFailed;
  }

  if(GetD3DCompiler() == NULL)
  {
    RDCERR("Failed to load d3dcompiler_??.dll");
    return eReplayCreate_APIInitFailed;
  }

  D3D12InitParams initParams;
  RDCDriver driverFileType = RDC_D3D12;
  string driverName = "D3D12";
  if(logfile)
  {
    auto status = RenderDoc::Inst().FillInitParams(logfile, driverFileType, driverName,
                                                   (RDCInitParams *)&initParams);
    if(status != eReplayCreate_Success)
      return status;
  }

  // initParams.SerialiseVersion is guaranteed to be valid/supported since otherwise the
  // FillInitParams (which calls D3D12InitParams::Serialise) would have failed above, so no need to
  // check it here.

  if(initParams.MinimumFeatureLevel < D3D_FEATURE_LEVEL_11_0)
    initParams.MinimumFeatureLevel = D3D_FEATURE_LEVEL_11_0;

  ID3D12Device *dev = NULL;
  HRESULT hr = RENDERDOC_CreateWrappedD3D12Device(NULL, initParams.MinimumFeatureLevel,
                                                  __uuidof(ID3D12Device), (void **)&dev);

  if(FAILED(hr))
  {
    RDCERR("Couldn't create a d3d12 device :(.");

    return eReplayCreate_APIHardwareUnsupported;
  }

  WrappedID3D12Device *wrappedDev = (WrappedID3D12Device *)dev;
  if(logfile)
    wrappedDev->SetLogFile(logfile);
  wrappedDev->SetLogVersion(initParams.SerialiseVersion);

  RDCLOG("Created device.");
  D3D12Replay *replay = wrappedDev->GetReplay();

  replay->SetProxy(logfile == NULL);

  *driver = (IReplayDriver *)replay;
  return eReplayCreate_Success;
}
Beispiel #19
0
static bool InitDbgHelp()
{
  static bool doinit = true;
  static bool ret = false;

  if(!doinit)
    return ret;

  doinit = false;

  HMODULE module = NULL;

  // can't reliably co-exist with dbghelp already being used in the process
  if(GetModuleHandleA("dbghelp.dll") != NULL)
  {
    RDCLOG(
        "dbghelp.dll is already loaded, can't guarantee thread-safety against application use. "
        "Callstack collection disabled");
    ret = false;
    return false;
  }
  else
  {
    wchar_t path[MAX_PATH] = {0};
    GetModuleFileNameW(GetModuleHandleA(STRINGIZE(RDOC_DLL_FILE) ".dll"), path, MAX_PATH - 1);

    wchar_t *slash = wcsrchr(path, '\\');

    if(slash)
    {
      *slash = 0;
    }
    else
    {
      slash = wcsrchr(path, '/');

      if(slash == 0)
      {
        ret = false;
        return false;
      }

      *slash = 0;
    }

#if ENABLED(RDOC_X64)
    wcscat_s(path, L"/dbghelp.dll");
#else
    wcscat_s(path, L"/dbghelp.dll");
#endif

    module = LoadLibraryW(path);
  }

  if(!module)
  {
    RDCWARN("Couldn't open dbghelp.dll");
    ret = false;
    return false;
  }

  dynSymInitializeW = (PSYMINITIALIZEW)GetProcAddress(module, "SymInitializeW");
  dynSymEnumerateModules64W =
      (PSYMENUMERATEMODULES64W)GetProcAddress(module, "SymEnumerateModulesW64");
  dynSymRefreshModuleList = (PSYMREFRESHMODULELIST)GetProcAddress(module, "SymRefreshModuleList");
  dynSymGetModuleInfo64W = (PSYMGETMODULEINFO64W)GetProcAddress(module, "SymGetModuleInfoW64");
  dynSymFindFileInPathW = (PSYMFINDFILEINPATHW)GetProcAddress(module, "SymFindFileInPathW");

  if(!dynSymInitializeW || !dynSymRefreshModuleList || !dynSymEnumerateModules64W ||
     !dynSymGetModuleInfo64W)
  {
    RDCERR("Couldn't get some dbghelp function");
    ret = false;
    return ret;
  }

  dynSymInitializeW(GetCurrentProcess(), L".", TRUE);

  HMODULE hModule = NULL;
  GetModuleHandleEx(
      GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
      (LPCTSTR)&dllLocator, &hModule);

  if(hModule != NULL)
  {
    MODULEINFO modinfo = {0};

    BOOL result = GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(modinfo));

    if(result != FALSE)
    {
      renderdocBase = modinfo.lpBaseOfDll;
      renderdocSize = modinfo.SizeOfImage;
    }
  }

  if(RenderDoc::Inst().IsReplayApp())
  {
    DIA2::Init();
  }

  ret = true;
  return ret;
}
Beispiel #20
0
static void SetLogFilePathTemplate(const char *logfile)
{
  RDCLOG("Using logfile %s", logfile);
  RenderDoc::Inst().SetLogFile(logfile);
}
Beispiel #21
0
Win32CallstackResolver::Win32CallstackResolver(char *moduleDB, size_t DBSize, string pdbSearchPaths, volatile bool *killSignal)
{
	wstring configPath = StringFormat::UTF82Wide(FileIO::GetAppFolderFilename("config.ini"));
	{
		FILE *f = NULL;
		_wfopen_s(&f, configPath.c_str(), L"a");
		if(f) fclose(f);
	}

	wchar_t inputBuf[2048];
	GetPrivateProfileStringW(L"renderdoc", L"ignores", NULL, &inputBuf[0], 2048, configPath.c_str());
	wstring ignores = inputBuf;
	split(ignores, pdbIgnores, L';');

	wstring widepdbsearch = StringFormat::UTF82Wide(pdbSearchPaths);

	split(widepdbsearch, pdbRememberedPaths, L';');

	pdblocateProcess = NULL;
	pdblocatePipe = NULL;

	OpenPdblocateHandle();
	
	if(memcmp(moduleDB, "WN32CALL", 8))
	{
		RDCWARN("Can't load callstack resolve for this log. Possibly from another platform?");
		return;
	}

	char *chunks = moduleDB + 8;
	char *end = chunks + DBSize - 8;
	
	EnumModChunk *chunk = (EnumModChunk *)(chunks);
	WCHAR *modName = (WCHAR *)(chunks+sizeof(EnumModChunk));

	if(pdblocatePipe == NULL)
		return;

	// loop over all our modules
	for(; chunks < end; chunks += sizeof(EnumModChunk)+(chunk->imageNameLen)*sizeof(WCHAR) )
	{
		chunk = (EnumModChunk *)chunks;
		modName = (WCHAR *)(chunks+sizeof(EnumModChunk));

		if(killSignal && *killSignal)
			break;
		
		Module m;

		m.name = modName;
		m.base = chunk->base;
		m.size = chunk->size;
		m.moduleId = 0;

		if(find(pdbIgnores.begin(), pdbIgnores.end(), m.name) != pdbIgnores.end())
		{
			RDCWARN("Not attempting to get symbols for %ls", m.name.c_str());

			modules.push_back(m);
			continue;
		}

		// get default pdb (this also looks up symbol server etc)
		// relies on pdblocate. Always done in unicode
		std::wstring defaultPdb = LookupModule(modName, chunk->guid, chunk->age);

		// strip newline
		if(defaultPdb != L"" && defaultPdb[defaultPdb.length()-1] == '\n')
			defaultPdb.pop_back();

		// if we didn't even get a default pdb we'll have to prompt first time through
		bool failed = false;

		if(defaultPdb == L"")
		{
			defaultPdb = strlower(basename(m.name));

			size_t it = defaultPdb.find(L".dll");
			if(it != wstring::npos)
			{
				defaultPdb[it+1] = L'p';
				defaultPdb[it+2] = L'd';
				defaultPdb[it+3] = L'b';
			}

			it = defaultPdb.find(L".exe");
			if(it != wstring::npos)
			{
				defaultPdb[it+1] = L'p';
				defaultPdb[it+2] = L'd';
				defaultPdb[it+3] = L'b';
			}
			failed = true;
		}

		std::wstring pdbName = defaultPdb;

		int fallbackIdx = -1;

		while(m.moduleId == 0)
		{
			if(failed)
			{
				fallbackIdx++;
				// try one of the folders we've been given, just in case the symbols
				// are there
				if(fallbackIdx < (int)pdbRememberedPaths.size())
				{
					pdbName = pdbRememberedPaths[fallbackIdx] + L"\\" + basename(pdbName);
				}
				else
				{
					pdbName = dirname(defaultPdb) + L"\\" + basename(defaultPdb);

					// prompt for new pdbName, unless it's renderdoc or dbghelp
					if(pdbName.find(L"renderdoc.") != wstring::npos ||
						pdbName.find(L"dbghelp.") != wstring::npos)
						pdbName = L"";
					else
						pdbName = pdbBrowse(pdbName);

					// user cancelled, just don't load this pdb
					if(pdbName == L"")
						break;
				}

				failed = false;
			}

			m.moduleId = GetModuleID(pdbName, chunk->guid, chunk->age);

			if(m.moduleId == 0)
			{
				failed = true;
			}
			else
			{
				if(fallbackIdx >= (int)pdbRememberedPaths.size())
				{
					wstring dir = dirname(pdbName);
					if(find(pdbRememberedPaths.begin(), pdbRememberedPaths.end(), dir) == pdbRememberedPaths.end())
					{
						pdbRememberedPaths.push_back(dir);
					}
				}
			}
		}

		// didn't load the pdb? go to the next module.
		if (m.moduleId == 0)
		{
			modules.push_back(m); // still add the module, with 0 module id
			
			RDCWARN("Couldn't get symbols for %ls", m.name.c_str());

			// silently ignore renderdoc.dll and dbghelp.dll without asking to permanently ignore
			if(m.name.find(L"renderdoc") != wstring::npos ||
				m.name.find(L"dbghelp") != wstring::npos)
				continue;

			wchar_t text[1024];
			wsprintf(text, L"Do you want to permanently ignore this file?\nPath: %ls", m.name.c_str());

			int ret = MessageBoxW(NULL, text, L"Ignore this pdb?", MB_YESNO);

			if(ret == IDYES)
				pdbIgnores.push_back(m.name);

			continue;
		}

		SetModuleBaseAddress(m.moduleId, chunk->base);
		
		RDCLOG("Loaded Symbols for %ls", m.name.c_str());

		modules.push_back(m); 
	}

	sort( pdbIgnores.begin(), pdbIgnores.end() );
	pdbIgnores.erase( unique( pdbIgnores.begin(), pdbIgnores.end() ), pdbIgnores.end() );
	merge(pdbIgnores, ignores, L';');
	WritePrivateProfileStringW(L"renderdoc", L"ignores", ignores.c_str(), configPath.c_str());
}
Beispiel #22
0
ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver)
{
  RDCDEBUG("Creating an OpenGL replay device");

  HMODULE lib = NULL;
  lib = LoadLibraryA("opengl32.dll");
  if(lib == NULL)
  {
    RDCERR("Failed to load opengl32.dll");
    return eReplayCreate_APIInitFailed;
  }

  GLInitParams initParams;
  RDCDriver driverType = RDC_OpenGL;
  string driverName = "OpenGL";
  uint64_t machineIdent = 0;
  if(logfile)
  {
    auto status = RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, machineIdent,
                                                   (RDCInitParams *)&initParams);
    if(status != eReplayCreate_Success)
      return status;
  }

  PIXELFORMATDESCRIPTOR pfd = {0};

  if(wglGetProc == NULL)
  {
    wglGetProc = (WGLGETPROCADDRESSPROC)GetProcAddress(lib, "wglGetProcAddress");
    wglCreateRC = (WGLCREATECONTEXTPROC)GetProcAddress(lib, "wglCreateContext");
    wglMakeCurrentProc = (WGLMAKECURRENTPROC)GetProcAddress(lib, "wglMakeCurrent");
    wglDeleteRC = (WGLDELETECONTEXTPROC)GetProcAddress(lib, "wglDeleteContext");

    if(wglGetProc == NULL || wglCreateRC == NULL || wglMakeCurrentProc == NULL || wglDeleteRC == NULL)
    {
      RDCERR("Couldn't get wgl function addresses");
      return eReplayCreate_APIInitFailed;
    }

    WNDCLASSEX wc;
    RDCEraseEl(wc);
    wc.style = CS_OWNDC;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.lpfnWndProc = DefWindowProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = L"renderdocGLclass";

    if(!RegisterClassEx(&wc))
    {
      RDCERR("Couldn't register GL window class");
      return eReplayCreate_APIInitFailed;
    }

    RDCEraseEl(pfd);
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iLayerType = PFD_MAIN_PLANE;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.cStencilBits = 0;
  }

  HWND w = CreateWindowEx(WS_EX_CLIENTEDGE, L"renderdocGLclass", L"", WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
                          GetModuleHandle(NULL), NULL);

  HDC dc = GetDC(w);

  int pf = ChoosePixelFormat(dc, &pfd);
  if(pf == 0)
  {
    RDCERR("Couldn't choose pixel format");
    return eReplayCreate_APIInitFailed;
  }

  BOOL res = SetPixelFormat(dc, pf, &pfd);
  if(res == FALSE)
  {
    RDCERR("Couldn't set pixel format");
    return eReplayCreate_APIInitFailed;
  }

  HGLRC rc = wglCreateRC(dc);
  if(rc == NULL)
  {
    RDCERR("Couldn't create simple RC");
    return eReplayCreate_APIInitFailed;
  }

  res = wglMakeCurrentProc(dc, rc);
  if(res == FALSE)
  {
    RDCERR("Couldn't make simple RC current");
    return eReplayCreate_APIInitFailed;
  }

  createContextAttribs =
      (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProc("wglCreateContextAttribsARB");
  getPixelFormatAttrib =
      (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)wglGetProc("wglGetPixelFormatAttribivARB");

  if(createContextAttribs == NULL || getPixelFormatAttrib == NULL)
  {
    RDCERR("RenderDoc requires WGL_ARB_create_context and WGL_ARB_pixel_format");
    return eReplayCreate_APIHardwareUnsupported;
  }

  wglMakeCurrentProc(NULL, NULL);
  wglDeleteRC(rc);
  ReleaseDC(w, dc);
  DestroyWindow(w);

  GLReplay::PreContextInitCounters();

  // we don't use the default framebuffer (backbuffer) for anything, so we make it
  // tiny and with no depth/stencil bits
  pfd.iPixelType = PFD_TYPE_RGBA;
  pfd.cColorBits = 24;
  pfd.cDepthBits = 0;
  pfd.cStencilBits = 0;

  w = CreateWindowEx(WS_EX_CLIENTEDGE, L"renderdocGLclass", L"RenderDoc replay window",
                     WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 32, 32, NULL, NULL,
                     GetModuleHandle(NULL), NULL);

  dc = GetDC(w);

  pf = ChoosePixelFormat(dc, &pfd);
  if(pf == 0)
  {
    RDCERR("Couldn't choose pixel format");
    ReleaseDC(w, dc);
    GLReplay::PostContextShutdownCounters();
    return eReplayCreate_APIInitFailed;
  }

  res = SetPixelFormat(dc, pf, &pfd);
  if(res == FALSE)
  {
    RDCERR("Couldn't set pixel format");
    ReleaseDC(w, dc);
    GLReplay::PostContextShutdownCounters();
    return eReplayCreate_APIInitFailed;
  }

  int attribs[64] = {0};
  int i = 0;

  attribs[i++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
  int &major = attribs[i];
  attribs[i++] = 0;
  attribs[i++] = WGL_CONTEXT_MINOR_VERSION_ARB;
  int &minor = attribs[i];
  attribs[i++] = 0;
  attribs[i++] = WGL_CONTEXT_FLAGS_ARB;
#if ENABLED(RDOC_DEVEL)
  attribs[i++] = WGL_CONTEXT_DEBUG_BIT_ARB;
#else
  attribs[i++] = 0;
#endif
  attribs[i++] = WGL_CONTEXT_PROFILE_MASK_ARB;
  attribs[i++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;

  // try to create all versions from 4.5 down to 3.2 in order to get the
  // highest versioned context we can
  struct
  {
    int major;
    int minor;
  } versions[] = {
      {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3}, {3, 2},
  };

  rc = NULL;

  for(size_t v = 0; v < ARRAY_COUNT(versions); v++)
  {
    major = versions[v].major;
    minor = versions[v].minor;
    rc = createContextAttribs(dc, NULL, attribs);

    if(rc)
      break;
  }
  if(rc == NULL)
  {
    RDCERR("Couldn't create 3.2 RC - RenderDoc requires OpenGL 3.2 availability");
    ReleaseDC(w, dc);
    GLReplay::PostContextShutdownCounters();
    return eReplayCreate_APIHardwareUnsupported;
  }

  GLCoreVersion = major * 10 + minor;

  res = wglMakeCurrentProc(dc, rc);
  if(res == FALSE)
  {
    RDCERR("Couldn't make 3.2 RC current");
    wglMakeCurrentProc(NULL, NULL);
    wglDeleteRC(rc);
    ReleaseDC(w, dc);
    GLReplay::PostContextShutdownCounters();
    return eReplayCreate_APIInitFailed;
  }

  PFNGLGETINTEGERVPROC getInt = (PFNGLGETINTEGERVPROC)GetProcAddress(lib, "glGetIntegerv");
  PFNGLGETSTRINGPROC getStr = (PFNGLGETSTRINGPROC)GetProcAddress(lib, "glGetString");
  PFNGLGETSTRINGIPROC getStri = (PFNGLGETSTRINGIPROC)wglGetProc("glGetStringi");

  if(getInt == NULL || getStr == NULL || getStri == NULL)
  {
    RDCERR("Couldn't get glGetIntegerv (%p), glGetString (%p) or glGetStringi (%p) entry points",
           getInt, getStr, getStri);
    wglMakeCurrentProc(NULL, NULL);
    wglDeleteRC(rc);
    ReleaseDC(w, dc);
    GLReplay::PostContextShutdownCounters();
    return eReplayCreate_APIInitFailed;
  }

  bool missingExt = CheckReplayContext(getStr, getInt, getStri);

  if(missingExt)
  {
    wglMakeCurrentProc(NULL, NULL);
    wglDeleteRC(rc);
    ReleaseDC(w, dc);
    GLReplay::PostContextShutdownCounters();
    return eReplayCreate_APIInitFailed;
  }

  const GLHookSet &real = GetRealGLFunctions();

  bool extensionsValidated = ValidateFunctionPointers(real);

  if(!extensionsValidated)
  {
    wglMakeCurrentProc(NULL, NULL);
    wglDeleteRC(rc);
    ReleaseDC(w, dc);
    GLReplay::PostContextShutdownCounters();
    return eReplayCreate_APIInitFailed;
  }

  WrappedOpenGL *gl = new WrappedOpenGL(logfile, real, GetGLPlatform());
  gl->Initialise(initParams);

  if(gl->GetSerialiser()->HasError())
  {
    delete gl;
    return eReplayCreate_FileIOFailed;
  }

  RDCLOG("Created device.");
  GLReplay *replay = gl->GetReplay();
  replay->SetProxy(logfile == NULL);
  GLWindowingData data;
  data.DC = dc;
  data.ctx = rc;
  data.wnd = w;
  replay->SetReplayData(data);

  *driver = (IReplayDriver *)replay;
  return eReplayCreate_Success;
}
Beispiel #23
0
ReplayCreateStatus GL_CreateReplayDevice(const wchar_t *logfile, IReplayDriver **driver)
{
	RDCDEBUG("Creating an OpenGL replay device");

	if(glXCreateContextAttribsProc == NULL)
	{
		glXGetFuncProc = (PFNGLXGETPROCADDRESSPROC)dlsym(RTLD_NEXT, "glXGetProcAddress");
		glXDestroyCtxProc = (PFNGLXDESTROYCONTEXTPROC)dlsym(RTLD_NEXT, "glXDestroyContext");
		glXSwapProc = (PFNGLXSWAPBUFFERSPROC)dlsym(RTLD_NEXT, "glXSwapBuffers");
		glXChooseFBConfigProc = (PFNGLXCHOOSEFBCONFIGPROC)dlsym(RTLD_NEXT, "glXChooseFBConfig");
		glXCreatePbufferProc = (PFNGLXCREATEPBUFFERPROC)dlsym(RTLD_NEXT, "glXCreatePbuffer");
		glXDestroyPbufferProc = (PFNGLXDESTROYPBUFFERPROC)dlsym(RTLD_NEXT, "glXDestroyPbuffer");
		glXQueryDrawableProc = (PFNGLXQUERYDRAWABLEPROC)dlsym(RTLD_NEXT, "glXQueryDrawable");

		if(glXGetFuncProc == NULL || glXDestroyCtxProc == NULL ||
			 glXSwapProc == NULL || glXChooseFBConfigProc == NULL ||
			 glXCreatePbufferProc == NULL || glXDestroyPbufferProc == NULL ||
			 glXQueryDrawableProc == NULL)
		{
			RDCERR("Couldn't find required entry points, glXGetProcAddress glXDestroyContext glXSwapBuffers");
			return eReplayCreate_APIInitFailed;
		}

		glXCreateContextAttribsProc = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetFuncProc((const GLubyte*)"glXCreateContextAttribsARB");
		glXMakeContextCurrentProc = (PFNGLXMAKECONTEXTCURRENTPROC)glXGetFuncProc((const GLubyte*)"glXMakeContextCurrent");

		if(glXCreateContextAttribsProc == NULL || glXMakeContextCurrentProc == NULL)
		{
			RDCERR("Couldn't get glx function addresses, glXCreateContextAttribsARB glXMakeContextCurrent");
			return eReplayCreate_APIInitFailed;
		}
	}

	GLInitParams initParams;
	RDCDriver driverType = RDC_OpenGL;
	wstring driverName = L"OpenGL";
	if(logfile)
		RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, (RDCInitParams *)&initParams);

	if(initParams.SerialiseVersion != GLInitParams::GL_SERIALISE_VERSION)
	{
		RDCERR("Incompatible OpenGL serialise version, expected %d got %d", GLInitParams::GL_SERIALISE_VERSION, initParams.SerialiseVersion);
		return eReplayCreate_APIIncompatibleVersion;
	}

	int attribs[64] = {0};
	int i=0;

	attribs[i++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
	attribs[i++] = 4;
	attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB;
	attribs[i++] = 3;
	attribs[i++] = GLX_CONTEXT_FLAGS_ARB;
	attribs[i++] = GLX_CONTEXT_DEBUG_BIT_ARB;

	Display *dpy = XOpenDisplay(NULL);

	if(dpy == NULL)
	{
		RDCERR("Couldn't open default X display");
		return eReplayCreate_APIInitFailed;
	}

	// don't need to care about the fb config as we won't be using the default framebuffer (backbuffer)
	static int visAttribs[] = { 0 };
	int numCfgs = 0;
	GLXFBConfig *fbcfg = glXChooseFBConfigProc(dpy, DefaultScreen(dpy), visAttribs, &numCfgs);

	if(fbcfg == NULL)
	{
		XCloseDisplay(dpy);
		RDCERR("Couldn't choose default framebuffer config");
		return eReplayCreate_APIInitFailed;
	}

	GLXContext ctx = glXCreateContextAttribsProc(dpy, fbcfg[0], 0, true, attribs);

	if(ctx == NULL)
	{
		XCloseDisplay(dpy);
		RDCERR("Couldn't create 4.3 context - RenderDoc requires OpenGL 4.3 availability");
		return eReplayCreate_APIHardwareUnsupported;
	}

	// don't care about pbuffer properties for same reason as backbuffer
	int pbAttribs[] = { GLX_PBUFFER_WIDTH, 32, GLX_PBUFFER_HEIGHT, 32, 0 };

	GLXPbuffer pbuffer = glXCreatePbufferProc(dpy, fbcfg[0], pbAttribs);

	XFree(fbcfg);

	Bool res = glXMakeContextCurrentProc(dpy, pbuffer, pbuffer, ctx);

	if(!res)
	{
		glXDestroyPbufferProc(dpy, pbuffer);
		glXDestroyCtxProc(dpy, ctx);
		XCloseDisplay(dpy);
		RDCERR("Couldn't make pbuffer & context current");
		return eReplayCreate_APIInitFailed;
	}

	WrappedOpenGL *gl = new WrappedOpenGL(logfile, GetRealFunctions());
	gl->Initialise(initParams);

	RDCLOG("Created device.");
	GLReplay *replay = gl->GetReplay();
	replay->SetProxy(logfile == NULL);
	GLWindowingData data;
	data.dpy = dpy;
	data.ctx = ctx;
	data.wnd = pbuffer;
	replay->SetReplayData(data);

	*driver = (IReplayDriver *)replay;
	return eReplayCreate_Success;
}
Beispiel #24
0
  void ReceiveMessage(RemoteMessage *msg)
  {
    if(m_Socket == NULL)
    {
      msg->Type = eRemoteMsg_Disconnected;
      return;
    }

    if(!m_Socket->IsRecvDataWaiting())
    {
      if(!m_Socket->Connected())
      {
        SAFE_DELETE(m_Socket);
        msg->Type = eRemoteMsg_Disconnected;
      }
      else
      {
        Threading::Sleep(2);
        msg->Type = eRemoteMsg_Noop;
      }

      return;
    }

    PacketType type;
    Serialiser *ser = NULL;

    GetPacket(type, ser);

    if(m_Socket == NULL)
    {
      SAFE_DELETE(ser);

      msg->Type = eRemoteMsg_Disconnected;
      return;
    }
    else
    {
      if(type == ePacket_Noop)
      {
        SAFE_DELETE(ser);

        msg->Type = eRemoteMsg_Noop;
        return;
      }
      else if(type == ePacket_Busy)
      {
        string existingClient;
        ser->Serialise("", existingClient);

        SAFE_DELETE(ser);

        SAFE_DELETE(m_Socket);

        RDCLOG("Got busy signal: '%s", existingClient.c_str());
        msg->Type = eRemoteMsg_Busy;
        msg->Busy.ClientName = existingClient;
        return;
      }
      else if(type == ePacket_CopyCapture)
      {
        msg->Type = eRemoteMsg_CaptureCopied;

        ser->Serialise("", msg->NewCapture.ID);

        SAFE_DELETE(ser);

        msg->NewCapture.localpath = m_CaptureCopies[msg->NewCapture.ID];

        if(!RecvChunkedFile(m_Socket, ePacket_CopyCapture, msg->NewCapture.localpath.elems, ser, NULL))
        {
          SAFE_DELETE(ser);
          SAFE_DELETE(m_Socket);

          msg->Type = eRemoteMsg_Disconnected;
          return;
        }

        m_CaptureCopies.erase(msg->NewCapture.ID);

        SAFE_DELETE(ser);

        return;
      }
      else if(type == ePacket_NewChild)
      {
        msg->Type = eRemoteMsg_NewChild;

        ser->Serialise("", msg->NewChild.PID);
        ser->Serialise("", msg->NewChild.ident);

        RDCLOG("Got a new child process: %u %u", msg->NewChild.PID, msg->NewChild.ident);

        SAFE_DELETE(ser);

        return;
      }
      else if(type == ePacket_NewCapture)
      {
        msg->Type = eRemoteMsg_NewCapture;

        ser->Serialise("", msg->NewCapture.ID);
        ser->Serialise("", msg->NewCapture.timestamp);

        string path;
        ser->Serialise("", path);
        msg->NewCapture.localpath = path;

        if(!m_Local)
          msg->NewCapture.localpath = "";

        uint32_t thumblen = 0;
        ser->Serialise("", thumblen);

        create_array_uninit(msg->NewCapture.thumbnail, thumblen);

        size_t l = 0;
        byte *buf = &msg->NewCapture.thumbnail[0];
        ser->SerialiseBuffer("", buf, l);

        RDCLOG("Got a new capture: %d (time %llu) %d byte thumbnail", msg->NewCapture.ID,
               msg->NewCapture.timestamp, thumblen);

        SAFE_DELETE(ser);

        return;
      }
      else if(type == ePacket_RegisterAPI)
      {
        msg->Type = eRemoteMsg_RegisterAPI;

        ser->Serialise("", m_API);
        msg->RegisterAPI.APIName = m_API;

        RDCLOG("Used API: %s", m_API.c_str());

        SAFE_DELETE(ser);

        return;
      }
    }

    SAFE_DELETE(ser);

    msg->Type = eRemoteMsg_Noop;
  }
Beispiel #25
0
extern "C" RENDERDOC_API
void RENDERDOC_CC RENDERDOC_SetLogFile(const char *logfile)
{
	RDCLOG("Using logfile %s", logfile);
	RenderDoc::Inst().SetLogFile(logfile);
}
Beispiel #26
0
void VulkanReplay::GetOutputWindowDimensions(uint64_t id, int32_t &w, int32_t &h)
{
  w = 500;
  h = 500;    // FIXME
  RDCLOG("VulkanReplay::GetOutputWindowDimensions: %i, %i", w, h);
}
Beispiel #27
0
extern "C" RENDERDOC_API
void RENDERDOC_CC RENDERDOC_SetCaptureOptions(const CaptureOptions *opts)
{
	RDCLOG("Setting capture options");
	RenderDoc::Inst().SetCaptureOptions(opts);
}
Beispiel #28
0
ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **driver)
{
	RDCDEBUG("Creating an OpenGL replay device");

	if(glXCreateContextAttribsProc == NULL)
	{
		glXGetFuncProc = (PFNGLXGETPROCADDRESSPROC)dlsym(RTLD_NEXT, "glXGetProcAddress");
		glXDestroyCtxProc = (PFNGLXDESTROYCONTEXTPROC)dlsym(RTLD_NEXT, "glXDestroyContext");
		glXSwapProc = (PFNGLXSWAPBUFFERSPROC)dlsym(RTLD_NEXT, "glXSwapBuffers");
		glXChooseFBConfigProc = (PFNGLXCHOOSEFBCONFIGPROC)dlsym(RTLD_NEXT, "glXChooseFBConfig");
		glXCreatePbufferProc = (PFNGLXCREATEPBUFFERPROC)dlsym(RTLD_NEXT, "glXCreatePbuffer");
		glXDestroyPbufferProc = (PFNGLXDESTROYPBUFFERPROC)dlsym(RTLD_NEXT, "glXDestroyPbuffer");
		glXQueryDrawableProc = (PFNGLXQUERYDRAWABLEPROC)dlsym(RTLD_NEXT, "glXQueryDrawable");

		if(glXGetFuncProc == NULL || glXDestroyCtxProc == NULL ||
			 glXSwapProc == NULL || glXChooseFBConfigProc == NULL ||
			 glXCreatePbufferProc == NULL || glXDestroyPbufferProc == NULL ||
			 glXQueryDrawableProc == NULL)
		{
			RDCERR("Couldn't find required entry points, glXGetProcAddress glXDestroyContext glXSwapBuffers");
			return eReplayCreate_APIInitFailed;
		}

		glXCreateContextAttribsProc = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetFuncProc((const GLubyte*)"glXCreateContextAttribsARB");
		glXMakeContextCurrentProc = (PFNGLXMAKECONTEXTCURRENTPROC)glXGetFuncProc((const GLubyte*)"glXMakeContextCurrent");

		if(glXCreateContextAttribsProc == NULL || glXMakeContextCurrentProc == NULL)
		{
			RDCERR("Couldn't get glx function addresses, glXCreateContextAttribsARB glXMakeContextCurrent");
			return eReplayCreate_APIInitFailed;
		}
	}

	GLInitParams initParams;
	RDCDriver driverType = RDC_OpenGL;
	string driverName = "OpenGL";
	if(logfile)
		RenderDoc::Inst().FillInitParams(logfile, driverType, driverName, (RDCInitParams *)&initParams);

	if(initParams.SerialiseVersion != GLInitParams::GL_SERIALISE_VERSION)
	{
		RDCERR("Incompatible OpenGL serialise version, expected %d got %d", GLInitParams::GL_SERIALISE_VERSION, initParams.SerialiseVersion);
		return eReplayCreate_APIIncompatibleVersion;
	}

	int attribs[64] = {0};
	int i=0;

	GLReplay::PreContextInitCounters();

	attribs[i++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
	attribs[i++] = 4;
	attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB;
	attribs[i++] = 3;
	attribs[i++] = GLX_CONTEXT_FLAGS_ARB;
	attribs[i++] = GLX_CONTEXT_DEBUG_BIT_ARB;
	attribs[i++] = GLX_CONTEXT_PROFILE_MASK_ARB;
	attribs[i++] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;

	Display *dpy = XOpenDisplay(NULL);

	if(dpy == NULL)
	{
		RDCERR("Couldn't open default X display");
		return eReplayCreate_APIInitFailed;
	}

	// don't need to care about the fb config as we won't be using the default framebuffer (backbuffer)
	static int visAttribs[] = { 0 };
	int numCfgs = 0;
	GLXFBConfig *fbcfg = glXChooseFBConfigProc(dpy, DefaultScreen(dpy), visAttribs, &numCfgs);

	if(fbcfg == NULL)
	{
		XCloseDisplay(dpy);
		GLReplay::PostContextShutdownCounters();
		RDCERR("Couldn't choose default framebuffer config");
		return eReplayCreate_APIInitFailed;
	}

	GLXContext ctx = glXCreateContextAttribsProc(dpy, fbcfg[0], 0, true, attribs);

	if(ctx == NULL)
	{
		XFree(fbcfg);
		XCloseDisplay(dpy);
		GLReplay::PostContextShutdownCounters();
		RDCERR("Couldn't create 4.3 context - RenderDoc requires OpenGL 4.3 availability");
		return eReplayCreate_APIHardwareUnsupported;
	}

	// don't care about pbuffer properties for same reason as backbuffer
	int pbAttribs[] = { GLX_PBUFFER_WIDTH, 32, GLX_PBUFFER_HEIGHT, 32, 0 };

	GLXPbuffer pbuffer = glXCreatePbufferProc(dpy, fbcfg[0], pbAttribs);

	XFree(fbcfg);

	Bool res = glXMakeContextCurrentProc(dpy, pbuffer, pbuffer, ctx);

	if(!res)
	{
		glXDestroyPbufferProc(dpy, pbuffer);
		glXDestroyCtxProc(dpy, ctx);
		XFree(fbcfg);
		XCloseDisplay(dpy);
		GLReplay::PostContextShutdownCounters();
		RDCERR("Couldn't make pbuffer & context current");
		return eReplayCreate_APIInitFailed;
	}

	PFNGLGETINTEGERVPROC getInt = (PFNGLGETINTEGERVPROC)glXGetFuncProc((const GLubyte *)"glGetIntegerv");
	PFNGLGETSTRINGIPROC getStr = (PFNGLGETSTRINGIPROC)glXGetFuncProc((const GLubyte *)"glGetStringi");

	if(getInt == NULL || getStr == NULL)
	{
		RDCERR("Couldn't get glGetIntegerv (%p) or glGetStringi (%p) entry points", getInt, getStr);
		glXDestroyPbufferProc(dpy, pbuffer);
		glXDestroyCtxProc(dpy, ctx);
		XFree(fbcfg);
		XCloseDisplay(dpy);
		GLReplay::PostContextShutdownCounters();
		return eReplayCreate_APIInitFailed;
	}
	else
	{
		// eventually we want to emulate EXT_dsa on replay if it isn't present, but for
		// now we just require it.
		bool dsa = false;
		bool bufstorage = false;

		if(getStr)
			RDCLOG("Running GL replay on: %s / %s / %s", getStr(eGL_VENDOR), getStr(eGL_RENDERER), getStr(eGL_VERSION));

		GLint numExts = 0;
		getInt(eGL_NUM_EXTENSIONS, &numExts);
		for(GLint e=0; e < numExts; e++)
		{
			const char *ext = (const char *)getStri(eGL_EXTENSIONS, (GLuint)e);

			RDCLOG("Extension % 3d: %s", e, ext);

			if(!strcmp(ext, "GL_EXT_direct_state_access")) dsa = true;
			if(!strcmp(ext, "GL_ARB_buffer_storage")) bufstorage = true;
		}

		if(!dsa)
			RDCERR("RenderDoc requires EXT_direct_state_access availability, and it is not reported. Try updating your drivers.");

		if(!bufstorage)
			RDCERR("RenderDoc requires ARB_buffer_storage availability, and it is not reported. Try updating your drivers.");

		if(!dsa || !bufstorage)
		{
			glXDestroyPbufferProc(dpy, pbuffer);
			glXDestroyCtxProc(dpy, ctx);
			XFree(fbcfg);
			XCloseDisplay(dpy);
			GLReplay::PostContextShutdownCounters();
			return eReplayCreate_APIHardwareUnsupported;
		}
	}

	WrappedOpenGL *gl = new WrappedOpenGL(logfile, GetRealGLFunctions());
	gl->Initialise(initParams);

	RDCLOG("Created device.");
	GLReplay *replay = gl->GetReplay();
	replay->SetProxy(logfile == NULL);
	GLWindowingData data;
	data.dpy = dpy;
	data.ctx = ctx;
	data.wnd = pbuffer;
	replay->SetReplayData(data);

	*driver = (IReplayDriver *)replay;
	return eReplayCreate_Success;
}
void STDMETHODCALLTYPE WrappedID3D12CommandQueue::ExecuteCommandLists(
    UINT NumCommandLists, ID3D12CommandList *const *ppCommandLists)
{
  ID3D12CommandList **unwrapped = m_pDevice->GetTempArray<ID3D12CommandList *>(NumCommandLists);
  for(UINT i = 0; i < NumCommandLists; i++)
    unwrapped[i] = Unwrap(ppCommandLists[i]);

  m_pReal->ExecuteCommandLists(NumCommandLists, unwrapped);

  if(m_State >= WRITING)
  {
    SCOPED_LOCK(m_Lock);
    SCOPED_LOCK(m_pDevice->GetCapTransitionLock());

    bool capframe = (m_State == WRITING_CAPFRAME);
    set<ResourceId> refdIDs;

    for(UINT i = 0; i < NumCommandLists; i++)
    {
      D3D12ResourceRecord *record = GetRecord(ppCommandLists[i]);

      if(record->ContainsExecuteIndirect)
        m_QueueRecord->ContainsExecuteIndirect = true;

      m_pDevice->ApplyBarriers(record->bakedCommands->cmdInfo->barriers);

      // need to lock the whole section of code, not just the check on
      // m_State, as we also need to make sure we don't check the state,
      // start marking dirty resources then while we're doing so the
      // state becomes capframe.
      // the next sections where we mark resources referenced and add
      // the submit chunk to the frame record don't have to be protected.
      // Only the decision of whether we're inframe or not, and marking
      // dirty.
      if(capframe)
      {
        for(auto it = record->bakedCommands->cmdInfo->dirtied.begin();
            it != record->bakedCommands->cmdInfo->dirtied.end(); ++it)
          GetResourceManager()->MarkPendingDirty(*it);
      }
      else
      {
        for(auto it = record->bakedCommands->cmdInfo->dirtied.begin();
            it != record->bakedCommands->cmdInfo->dirtied.end(); ++it)
          GetResourceManager()->MarkDirtyResource(*it);
      }

      if(capframe)
      {
        // any descriptor copies or writes could reference new resources not in the
        // bound descs list yet. So we take all of those referenced descriptors and
        // include them to see if we need to flush
        std::vector<D3D12Descriptor> dynDescRefs;
        m_pDevice->GetDynamicDescriptorReferences(dynDescRefs);

        for(size_t d = 0; d < dynDescRefs.size(); d++)
        {
          ResourceId id, id2;
          FrameRefType ref = eFrameRef_Read;

          dynDescRefs[d].GetRefIDs(id, id2, ref);

          if(id != ResourceId())
          {
            refdIDs.insert(id);
            GetResourceManager()->MarkResourceFrameReferenced(id, ref);
          }

          if(id2 != ResourceId())
          {
            refdIDs.insert(id2);
            GetResourceManager()->MarkResourceFrameReferenced(id2, ref);
          }
        }

        // for each bound descriptor table, mark it referenced as well as all resources currently
        // bound to it
        for(auto it = record->bakedCommands->cmdInfo->boundDescs.begin();
            it != record->bakedCommands->cmdInfo->boundDescs.end(); ++it)
        {
          D3D12Descriptor *desc = *it;

          ResourceId id, id2;
          FrameRefType ref = eFrameRef_Read;

          desc->GetRefIDs(id, id2, ref);

          if(id != ResourceId())
          {
            refdIDs.insert(id);
            GetResourceManager()->MarkResourceFrameReferenced(id, ref);
          }

          if(id2 != ResourceId())
          {
            refdIDs.insert(id2);
            GetResourceManager()->MarkResourceFrameReferenced(id2, ref);
          }
        }

        // pull in frame refs from this baked command list
        record->bakedCommands->AddResourceReferences(GetResourceManager());
        record->bakedCommands->AddReferencedIDs(refdIDs);

        // reference all executed bundles as well
        for(size_t b = 0; b < record->bakedCommands->cmdInfo->bundles.size(); b++)
        {
          record->bakedCommands->cmdInfo->bundles[b]->bakedCommands->AddResourceReferences(
              GetResourceManager());
          record->bakedCommands->cmdInfo->bundles[b]->bakedCommands->AddReferencedIDs(refdIDs);
          GetResourceManager()->MarkResourceFrameReferenced(
              record->bakedCommands->cmdInfo->bundles[b]->GetResourceID(), eFrameRef_Read);

          record->bakedCommands->cmdInfo->bundles[b]->bakedCommands->AddRef();
        }

        {
          m_CmdListRecords.push_back(record->bakedCommands);
          for(size_t sub = 0; sub < record->bakedCommands->cmdInfo->bundles.size(); sub++)
            m_CmdListRecords.push_back(record->bakedCommands->cmdInfo->bundles[sub]->bakedCommands);
        }

        record->bakedCommands->AddRef();
      }

      record->cmdInfo->dirtied.clear();
    }

    if(capframe)
    {
      vector<MapState> maps = m_pDevice->GetMaps();

      for(auto it = maps.begin(); it != maps.end(); ++it)
      {
        WrappedID3D12Resource *res = it->res;
        UINT subres = it->subres;
        size_t size = (size_t)it->totalSize;

        // only need to flush memory that could affect this submitted batch of work
        if(refdIDs.find(res->GetResourceID()) == refdIDs.end())
        {
          RDCDEBUG("Map of memory %llu not referenced in this queue - not flushing",
                   res->GetResourceID());
          continue;
        }

        size_t diffStart = 0, diffEnd = 0;
        bool found = true;

        byte *ref = res->GetShadow(subres);
        byte *data = res->GetMap(subres);

        if(ref)
          found = FindDiffRange(data, ref, size, diffStart, diffEnd);
        else
          diffEnd = size;

        if(found)
        {
          RDCLOG("Persistent map flush forced for %llu (%llu -> %llu)", res->GetResourceID(),
                 (uint64_t)diffStart, (uint64_t)diffEnd);

          D3D12_RANGE range = {diffStart, diffEnd};

          m_pDevice->MapDataWrite(res, subres, data, range);

          if(ref == NULL)
          {
            res->AllocShadow(subres, size);

            ref = res->GetShadow(subres);
          }

          // update comparison shadow for next time
          memcpy(ref, res->GetMap(subres), size);

          GetResourceManager()->MarkPendingDirty(res->GetResourceID());
        }
        else
        {
          RDCDEBUG("Persistent map flush not needed for %llu", res->GetResourceID());
        }
      }

      for(UINT i = 0; i < NumCommandLists; i++)
      {
        SCOPED_SERIALISE_CONTEXT(EXECUTE_CMD_LISTS);
        Serialise_ExecuteCommandLists(1, ppCommandLists + i);

        m_QueueRecord->AddChunk(scope.Get());
      }
    }
  }
}