ReplayCreateStatus CreateProxyRenderer(uint32_t proxyid, const char *logfile, float *progress, ReplayRenderer **rend) { if(rend == NULL) return eReplayCreate_InternalError; if(proxyid >= m_Proxies.size()) { RDCERR("Invalid proxy driver id %d specified for remote renderer", proxyid); return eReplayCreate_InternalError; } float dummy = 0.0f; if(progress == NULL) progress = &dummy; RDCDriver proxydrivertype = m_Proxies[proxyid].first; Serialiser ser("", Serialiser::WRITING, false); if(!SendChunkedFile(m_Socket, ePacket_CopyCapture, logfile, ser, progress)) { SAFE_DELETE(m_Socket); return eReplayCreate_NetworkIOFailed; } RDCLOG("Sent file to replay host. Loading..."); PacketType type = ePacket_Noop; while(m_Socket) { Serialiser *progressSer; GetPacket(type, &progressSer); if(!m_Socket || type != ePacket_LogOpenProgress) break; progressSer->Serialise("", *progress); RDCLOG("% 3.0f%%...", (*progress)*100.0f); } if(!m_Socket || type != ePacket_LogReady) return eReplayCreate_NetworkIOFailed; *progress = 1.0f; RDCLOG("Log ready on replay host"); IReplayDriver *proxyDriver = NULL; auto status = RenderDoc::Inst().CreateReplayDriver(proxydrivertype, NULL, &proxyDriver); if(status != eReplayCreate_Success || !proxyDriver) { if(proxyDriver) proxyDriver->Shutdown(); return status; } ReplayRenderer *ret = new ReplayRenderer(); ProxySerialiser *proxy = new ProxySerialiser(m_Socket, proxyDriver); status = ret->SetDevice(proxy); if(status != eReplayCreate_Success) { SAFE_DELETE(ret); return status; } // ReplayRenderer takes ownership of the ProxySerialiser (as IReplayDriver) // and it cleans itself up in Shutdown. *rend = ret; return eReplayCreate_Success; }
ReplayCreateStatus IMG_CreateReplayDevice(const char *logfile, IReplayDriver **driver) { FILE *f = FileIO::fopen(logfile, "rb"); if(!f) return eReplayCreate_FileIOFailed; // make sure the file is a type we recognise before going further if(is_exr_file(f)) { const char *err = NULL; FileIO::fseek64(f, 0, SEEK_END); uint64_t size = FileIO::ftell64(f); FileIO::fseek64(f, 0, SEEK_SET); std::vector<byte> buffer; buffer.resize((size_t)size); FileIO::fread(&buffer[0], 1, buffer.size(), f); EXRImage exrImage; InitEXRImage(&exrImage); int ret = ParseMultiChannelEXRHeaderFromMemory(&exrImage, &buffer[0], &err); FreeEXRImage(&exrImage); // could be an unsupported form of EXR, like deep image or other if(ret != 0) { FileIO::fclose(f); RDCERR( "EXR file detected, but couldn't load with ParseMultiChannelEXRHeaderFromMemory %d: '%s'", ret, err); return eReplayCreate_APIUnsupported; } } else if(stbi_is_hdr_from_file(f)) { FileIO::fseek64(f, 0, SEEK_SET); int ignore = 0; float *data = stbi_loadf_from_file(f, &ignore, &ignore, &ignore, 4); if(!data) { FileIO::fclose(f); RDCERR("HDR file recognised, but couldn't load with stbi_loadf_from_file"); return eReplayCreate_FileCorrupted; } free(data); } else if(is_dds_file(f)) { FileIO::fseek64(f, 0, SEEK_SET); dds_data read_data = load_dds_from_file(f); if(read_data.subdata == NULL) { FileIO::fclose(f); RDCERR("DDS file recognised, but couldn't load"); return eReplayCreate_FileCorrupted; } for(int i = 0; i < read_data.slices * read_data.mips; i++) delete[] read_data.subdata[i]; delete[] read_data.subdata; delete[] read_data.subsizes; } else { int width = 0, height = 0; int ignore = 0; int ret = stbi_info_from_file(f, &width, &height, &ignore); // just in case (we shouldn't have come in here if this weren't true), make sure // the format is supported if(ret == 0 || width == 0 || width == ~0U || height == 0 || height == ~0U) { FileIO::fclose(f); return eReplayCreate_APIUnsupported; } byte *data = stbi_load_from_file(f, &ignore, &ignore, &ignore, 4); if(!data) { FileIO::fclose(f); RDCERR("File recognised, but couldn't load with stbi_load_from_file"); return eReplayCreate_FileCorrupted; } free(data); } FileIO::fclose(f); IReplayDriver *proxy = NULL; auto status = RenderDoc::Inst().CreateReplayDriver(RDC_Unknown, NULL, &proxy); if(status != eReplayCreate_Success || !proxy) { if(proxy) proxy->Shutdown(); return status; } *driver = new ImageViewer(proxy, logfile); return eReplayCreate_Success; }
ReplayCreateStatus IMG_CreateReplayDevice(const char *logfile, IReplayDriver **driver) { FILE *f = FileIO::fopen(logfile, "rb"); if(!f) return eReplayCreate_FileIOFailed; FetchTexture texDetails; ResourceFormat rgba8_unorm; rgba8_unorm.compByteWidth = 1; rgba8_unorm.compCount = 4; rgba8_unorm.compType = eCompType_UNorm; rgba8_unorm.special = false; ResourceFormat rgba32_float = rgba8_unorm; rgba32_float.compByteWidth = 4; rgba32_float.compType = eCompType_Float; texDetails.creationFlags = eTextureCreate_SwapBuffer|eTextureCreate_RTV; texDetails.cubemap = false; texDetails.customName = true; texDetails.name = logfile; texDetails.ID = ResourceId(); texDetails.byteSize = 0; texDetails.msQual = 0; texDetails.msSamp = 1; // reasonable defaults for everything but dds texDetails.numSubresources = 1; texDetails.dimension = 2; texDetails.arraysize = 1; texDetails.depth = 1; texDetails.mips = 1; byte *data = NULL; size_t datasize = 0; bool dds = false; if(is_exr_file(f)) { texDetails.format = rgba32_float; FileIO::fseek64(f, 0, SEEK_SET); const char *err = NULL; int ret = LoadEXRFP((float **)&data, (int *)&texDetails.width, (int *)&texDetails.height, f, &err); datasize = texDetails.width*texDetails.height*4*sizeof(float); // could be an unsupported form of EXR, like deep image or other if(ret != 0) { if(data) free(data); RDCERR("EXR file detected, but couldn't load with LoadEXR %d: '%s'", ret, err); return eReplayCreate_APIUnsupported; } } else if(stbi_is_hdr_from_file(f)) { texDetails.format = rgba32_float; FileIO::fseek64(f, 0, SEEK_SET); int ignore = 0; data = (byte *)stbi_loadf_from_file(f, (int *)&texDetails.width, (int *)&texDetails.height, &ignore, 4); datasize = texDetails.width*texDetails.height*4*sizeof(float); } else if(is_dds_file(f)) { dds = true; } else { int ignore = 0; int ret = stbi_info_from_file(f, (int *)&texDetails.width, (int *)&texDetails.height, &ignore); // just in case (we shouldn't have come in here if this weren't true), make sure // the format is supported if(ret == 0 || texDetails.width == 0 || texDetails.width == ~0U || texDetails.height == 0 || texDetails.height == ~0U) { return eReplayCreate_APIUnsupported; } texDetails.format = rgba8_unorm; data = stbi_load_from_file(f, (int *)&texDetails.width, (int *)&texDetails.height, &ignore, 4); datasize = texDetails.width*texDetails.height*4*sizeof(byte); } // if we don't have data at this point (and we're not a dds file) then the // file was corrupted and we failed to load it if(!dds && data == NULL) { return eReplayCreate_FileCorrupted; } IReplayDriver *proxy = NULL; auto status = RenderDoc::Inst().CreateReplayDriver(RDC_Unknown, NULL, &proxy); if(status != eReplayCreate_Success || !proxy) { if(proxy) proxy->Shutdown(); return status; } ResourceId id; if(!dds) { id = proxy->CreateProxyTexture(texDetails); proxy->SetProxyTextureData(id, 0, 0, data, datasize); free(data); } else { FileIO::fseek64(f, 0, SEEK_SET); dds_data read_data = load_dds_from_file(f); if(read_data.subdata == NULL) { proxy->Shutdown(); return eReplayCreate_FileCorrupted; } texDetails.cubemap = read_data.cubemap; texDetails.arraysize = read_data.slices; texDetails.width = read_data.width; texDetails.height = read_data.height; texDetails.depth = read_data.depth; texDetails.mips = read_data.mips; texDetails.numSubresources = texDetails.arraysize*texDetails.mips; texDetails.format = read_data.format; texDetails.dimension = 1; if(texDetails.width > 1) texDetails.dimension = 2; if(texDetails.depth > 1) texDetails.dimension = 3; id = proxy->CreateProxyTexture(texDetails); for(uint32_t i=0; i < texDetails.numSubresources; i++) { proxy->SetProxyTextureData(id, i/texDetails.mips, i%texDetails.mips, read_data.subdata[i], (size_t)read_data.subsizes[i]); delete[] read_data.subdata[i]; } delete[] read_data.subdata; delete[] read_data.subsizes; } *driver = new ImageViewer(proxy, logfile, id); FileIO::fclose(f); return eReplayCreate_Success; }