void DoSerialise(SerialiserType &ser, DynamicDescriptorCopy &el) { D3D12ResourceManager *rm = (D3D12ResourceManager *)ser.GetUserData(); SERIALISE_MEMBER(type); PortableHandle dst, src; if(ser.IsWriting()) { dst = ToPortableHandle(el.dst); src = ToPortableHandle(el.src); } ser.Serialise("dst", dst); ser.Serialise("src", src); if(ser.IsReading()) { if(rm) { el.dst = DescriptorFromPortableHandle(rm, dst); el.src = DescriptorFromPortableHandle(rm, src); } else { el.dst = NULL; el.src = NULL; } } }
void DoSerialise(SerialiserType &ser, D3D12_SHADER_BYTECODE &el) { // don't serialise size_t, otherwise capture/replay between different bit-ness won't work { uint64_t BytecodeLength = el.BytecodeLength; ser.Serialise("BytecodeLength", BytecodeLength); if(ser.IsReading()) el.BytecodeLength = (size_t)BytecodeLength; } SERIALISE_MEMBER_ARRAY(pShaderBytecode, BytecodeLength); }
void DoSerialise(SerialiserType &ser, D3D12_RANGE &el) { // serialise as uint64, so we're 32-bit/64-bit compatible uint64_t Begin = el.Begin; uint64_t End = el.End; ser.Serialise("Begin", Begin); ser.Serialise("End", End); if(ser.IsReading()) { el.Begin = (SIZE_T)Begin; el.End = (SIZE_T)End; } }
void DoSerialise(SerialiserType &ser, D3D12_GRAPHICS_PIPELINE_STATE_DESC &el) { SERIALISE_MEMBER(pRootSignature); SERIALISE_MEMBER(VS); SERIALISE_MEMBER(PS); SERIALISE_MEMBER(DS); SERIALISE_MEMBER(HS); SERIALISE_MEMBER(GS); SERIALISE_MEMBER(StreamOutput); SERIALISE_MEMBER(BlendState); SERIALISE_MEMBER(SampleMask); SERIALISE_MEMBER(RasterizerState); SERIALISE_MEMBER(DepthStencilState); SERIALISE_MEMBER(InputLayout); SERIALISE_MEMBER(IBStripCutValue); SERIALISE_MEMBER(PrimitiveTopologyType); SERIALISE_MEMBER(NumRenderTargets); SERIALISE_MEMBER(RTVFormats); SERIALISE_MEMBER(DSVFormat); SERIALISE_MEMBER(SampleDesc); SERIALISE_MEMBER(NodeMask); SERIALISE_MEMBER(Flags); if(ser.IsReading()) { el.CachedPSO.CachedBlobSizeInBytes = 0; el.CachedPSO.pCachedBlob = NULL; } }
void DoSerialise(SerialiserType &ser, D3D12_CACHED_PIPELINE_STATE &el) { // don't serialise these, just set to NULL/0. See the definition of SERIALISE_MEMBER_DUMMY SERIALISE_MEMBER_ARRAY_EMPTY(pCachedBlob); uint64_t CachedBlobSizeInBytes = 0; ser.Serialise("CachedBlobSizeInBytes", CachedBlobSizeInBytes); }
void DoSerialiseViaResourceId(SerialiserType &ser, Interface *&el) { D3D12ResourceManager *rm = (D3D12ResourceManager *)ser.GetUserData(); ResourceId id; if(ser.IsWriting()) id = GetResID(el); DoSerialise(ser, id); if(ser.IsReading()) { if(id != ResourceId() && rm && rm->HasLiveResource(id)) el = rm->GetLiveAs<Interface>(id); else el = NULL; } }
void DoSerialise(SerialiserType &ser, D3D12_GPU_DESCRIPTOR_HANDLE &el) { D3D12ResourceManager *rm = (D3D12ResourceManager *)ser.GetUserData(); PortableHandle ph; if(ser.IsWriting()) ph = ToPortableHandle(el); DoSerialise(ser, ph); if(ser.IsReading()) { if(rm) el.ptr = (SIZE_T)DescriptorFromPortableHandle(rm, ph); else el.ptr = 0; } }
void DoSerialise(SerialiserType &ser, D3D12BufferLocation &el) { D3D12ResourceManager *rm = (D3D12ResourceManager *)ser.GetUserData(); ResourceId buffer; UINT64 offs = 0; if(ser.IsWriting()) WrappedID3D12Resource::GetResIDFromAddr(el.Location, buffer, offs); ser.Serialise("Buffer", buffer); ser.Serialise("Offset", offs); if(ser.IsReading()) { if(rm && buffer != ResourceId() && rm->HasLiveResource(buffer)) el.Location = rm->GetLiveAs<ID3D12Resource>(buffer)->GetGPUVirtualAddress() + offs; else el.Location = 0; } }
void DoSerialise(SerialiserType &ser, D3D12_COMPUTE_PIPELINE_STATE_DESC &el) { SERIALISE_MEMBER(pRootSignature); SERIALISE_MEMBER(CS); SERIALISE_MEMBER(NodeMask); SERIALISE_MEMBER(Flags); if(ser.IsReading()) { el.CachedPSO.CachedBlobSizeInBytes = 0; el.CachedPSO.pCachedBlob = NULL; } }
void SerialiseProgramBindings(SerialiserType &ser, CaptureState state, const GLHookSet &gl, GLuint prog) { std::vector<ProgramBinding> InputBindings; std::vector<ProgramBinding> OutputBindings; if(ser.IsWriting()) { char buf[128] = {}; for(int sigType = 0; sigType < 2; sigType++) { GLenum sigEnum = (sigType == 0 ? eGL_PROGRAM_INPUT : eGL_PROGRAM_OUTPUT); std::vector<ProgramBinding> &bindings = (sigType == 0 ? InputBindings : OutputBindings); int32_t NumAttributes = 0; gl.glGetProgramInterfaceiv(prog, sigEnum, eGL_ACTIVE_RESOURCES, (GLint *)&NumAttributes); bindings.reserve(NumAttributes); for(GLint i = 0; i < NumAttributes; i++) { gl.glGetProgramResourceName(prog, sigEnum, i, 128, NULL, buf); ProgramBinding bind; bind.Name = buf; if(sigType == 0) bind.Binding = gl.glGetAttribLocation(prog, buf); else bind.Binding = gl.glGetFragDataLocation(prog, buf); bindings.push_back(bind); } } } SERIALISE_ELEMENT(InputBindings); SERIALISE_ELEMENT(OutputBindings); if(ser.IsReading() && IsReplayMode(state)) { for(int sigType = 0; sigType < 2; sigType++) { const std::vector<ProgramBinding> &bindings = (sigType == 0 ? InputBindings : OutputBindings); uint64_t used = 0; for(const ProgramBinding &bind : bindings) { if(bind.Binding >= 0) { uint64_t mask = 1ULL << bind.Binding; if(used & mask) { RDCWARN("Multiple %s items bound to location %d, ignoring %s", sigType == 0 ? "attrib" : "fragdata", bind.Binding, bind.Name.c_str()); continue; } used |= mask; if(!strncmp("gl_", bind.Name.c_str(), 3)) continue; // GL_INVALID_OPERATION if name starts with reserved gl_ prefix (for both // glBindAttribLocation and glBindFragDataLocation) if(sigType == 0) { gl.glBindAttribLocation(prog, (GLuint)bind.Binding, bind.Name.c_str()); } else { if(gl.glBindFragDataLocation) { gl.glBindFragDataLocation(prog, (GLuint)bind.Binding, bind.Name.c_str()); } else { // glBindFragDataLocation is not core GLES, but it is in GL_EXT_blend_func_extended // TODO what to do if that extension is not supported RDCERR("glBindFragDataLocation is not supported!"); } } } } } } }
void DoSerialise(SerialiserType &ser, ProgramUniformValue &el) { SERIALISE_MEMBER(Type); SERIALISE_MEMBER(Location); // some special logic here, we decode Type to figure out what the actual data is, and serialise it // with the right type. VarType baseType = VarType::Float; uint32_t elemCount = 1; switch(el.Type) { case eGL_FLOAT_MAT4: case eGL_FLOAT_MAT4x3: case eGL_FLOAT_MAT4x2: case eGL_FLOAT_MAT3: case eGL_FLOAT_MAT3x4: case eGL_FLOAT_MAT3x2: case eGL_FLOAT_MAT2: case eGL_FLOAT_MAT2x4: case eGL_FLOAT_MAT2x3: case eGL_FLOAT: case eGL_FLOAT_VEC2: case eGL_FLOAT_VEC3: case eGL_FLOAT_VEC4: baseType = VarType::Float; break; case eGL_DOUBLE_MAT4: case eGL_DOUBLE_MAT4x3: case eGL_DOUBLE_MAT4x2: case eGL_DOUBLE_MAT3: case eGL_DOUBLE_MAT3x4: case eGL_DOUBLE_MAT3x2: case eGL_DOUBLE_MAT2: case eGL_DOUBLE_MAT2x4: case eGL_DOUBLE_MAT2x3: case eGL_DOUBLE: case eGL_DOUBLE_VEC2: case eGL_DOUBLE_VEC3: case eGL_DOUBLE_VEC4: baseType = VarType::Double; break; case eGL_SAMPLER_1D: case eGL_SAMPLER_2D: case eGL_SAMPLER_3D: case eGL_SAMPLER_CUBE: case eGL_SAMPLER_CUBE_MAP_ARRAY: case eGL_SAMPLER_1D_SHADOW: case eGL_SAMPLER_2D_SHADOW: case eGL_SAMPLER_1D_ARRAY: case eGL_SAMPLER_2D_ARRAY: case eGL_SAMPLER_1D_ARRAY_SHADOW: case eGL_SAMPLER_2D_ARRAY_SHADOW: case eGL_SAMPLER_2D_MULTISAMPLE: case eGL_SAMPLER_2D_MULTISAMPLE_ARRAY: case eGL_SAMPLER_CUBE_SHADOW: case eGL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: case eGL_SAMPLER_BUFFER: case eGL_SAMPLER_2D_RECT: case eGL_SAMPLER_2D_RECT_SHADOW: case eGL_INT_SAMPLER_1D: case eGL_INT_SAMPLER_2D: case eGL_INT_SAMPLER_3D: case eGL_INT_SAMPLER_CUBE: case eGL_INT_SAMPLER_CUBE_MAP_ARRAY: case eGL_INT_SAMPLER_1D_ARRAY: case eGL_INT_SAMPLER_2D_ARRAY: case eGL_INT_SAMPLER_2D_MULTISAMPLE: case eGL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: case eGL_INT_SAMPLER_BUFFER: case eGL_INT_SAMPLER_2D_RECT: case eGL_UNSIGNED_INT_SAMPLER_1D: case eGL_UNSIGNED_INT_SAMPLER_2D: case eGL_UNSIGNED_INT_SAMPLER_3D: case eGL_UNSIGNED_INT_SAMPLER_CUBE: case eGL_UNSIGNED_INT_SAMPLER_1D_ARRAY: case eGL_UNSIGNED_INT_SAMPLER_2D_ARRAY: case eGL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: case eGL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: case eGL_UNSIGNED_INT_SAMPLER_BUFFER: case eGL_UNSIGNED_INT_SAMPLER_2D_RECT: case eGL_IMAGE_1D: case eGL_IMAGE_2D: case eGL_IMAGE_3D: case eGL_IMAGE_2D_RECT: case eGL_IMAGE_CUBE: case eGL_IMAGE_BUFFER: case eGL_IMAGE_1D_ARRAY: case eGL_IMAGE_2D_ARRAY: case eGL_IMAGE_CUBE_MAP_ARRAY: case eGL_IMAGE_2D_MULTISAMPLE: case eGL_IMAGE_2D_MULTISAMPLE_ARRAY: case eGL_INT_IMAGE_1D: case eGL_INT_IMAGE_2D: case eGL_INT_IMAGE_3D: case eGL_INT_IMAGE_2D_RECT: case eGL_INT_IMAGE_CUBE: case eGL_INT_IMAGE_BUFFER: case eGL_INT_IMAGE_1D_ARRAY: case eGL_INT_IMAGE_2D_ARRAY: case eGL_INT_IMAGE_2D_MULTISAMPLE: case eGL_INT_IMAGE_2D_MULTISAMPLE_ARRAY: case eGL_UNSIGNED_INT_IMAGE_1D: case eGL_UNSIGNED_INT_IMAGE_2D: case eGL_UNSIGNED_INT_IMAGE_3D: case eGL_UNSIGNED_INT_IMAGE_2D_RECT: case eGL_UNSIGNED_INT_IMAGE_CUBE: case eGL_UNSIGNED_INT_IMAGE_BUFFER: case eGL_UNSIGNED_INT_IMAGE_1D_ARRAY: case eGL_UNSIGNED_INT_IMAGE_2D_ARRAY: case eGL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: case eGL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE: case eGL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY: case eGL_UNSIGNED_INT_ATOMIC_COUNTER: case eGL_INT: case eGL_INT_VEC2: case eGL_INT_VEC3: case eGL_INT_VEC4: baseType = VarType::Int; break; case eGL_UNSIGNED_INT: case eGL_BOOL: case eGL_UNSIGNED_INT_VEC2: case eGL_BOOL_VEC2: case eGL_UNSIGNED_INT_VEC3: case eGL_BOOL_VEC3: case eGL_UNSIGNED_INT_VEC4: case eGL_BOOL_VEC4: baseType = VarType::UInt; break; default: RDCERR("Unhandled uniform type '%s'", ToStr(el.Type).c_str()); baseType = VarType::Float; elemCount = 1; break; } switch(el.Type) { case eGL_FLOAT_MAT4: case eGL_DOUBLE_MAT4: elemCount = 16; break; case eGL_FLOAT_MAT4x3: case eGL_FLOAT_MAT3x4: case eGL_DOUBLE_MAT4x3: case eGL_DOUBLE_MAT3x4: elemCount = 12; break; case eGL_FLOAT_MAT4x2: case eGL_FLOAT_MAT2x4: case eGL_DOUBLE_MAT4x2: case eGL_DOUBLE_MAT2x4: elemCount = 8; break; case eGL_FLOAT_MAT3: case eGL_DOUBLE_MAT3: elemCount = 9; break; case eGL_FLOAT_MAT3x2: case eGL_DOUBLE_MAT3x2: case eGL_FLOAT_MAT2x3: case eGL_DOUBLE_MAT2x3: elemCount = 6; break; case eGL_FLOAT_MAT2: case eGL_DOUBLE_MAT2: case eGL_FLOAT_VEC4: case eGL_DOUBLE_VEC4: elemCount = 4; break; case eGL_FLOAT_VEC3: case eGL_DOUBLE_VEC3: elemCount = 3; break; case eGL_FLOAT_VEC2: case eGL_DOUBLE_VEC2: elemCount = 2; break; default: // all other types are elemCount = 1 break; } double *dv = el.data.dval; float *fv = el.data.fval; int32_t *iv = el.data.ival; uint32_t *uv = el.data.uval; if(baseType == VarType::Double) ser.Serialise("data", fv, elemCount, SerialiserFlags::NoFlags); else if(baseType == VarType::Float) ser.Serialise("data", dv, elemCount, SerialiserFlags::NoFlags); else if(baseType == VarType::Int) ser.Serialise("data", iv, elemCount, SerialiserFlags::NoFlags); else if(baseType == VarType::UInt) ser.Serialise("data", uv, elemCount, SerialiserFlags::NoFlags); }
void DoSerialise(SerialiserType &ser, D3D12Descriptor &el) { D3D12DescriptorType type = el.GetType(); ser.Serialise("type", type); ID3D12DescriptorHeap *heap = (ID3D12DescriptorHeap *)el.samp.heap; ser.Serialise("heap", heap); ser.Serialise("index", el.samp.idx); if(ser.IsReading()) { el.samp.heap = (WrappedID3D12DescriptorHeap *)heap; // for sampler types, this will be overwritten when serialising the sampler descriptor el.nonsamp.type = type; } switch(type) { case D3D12DescriptorType::Sampler: { ser.Serialise("Descriptor", el.samp.desc); RDCASSERTEQUAL(el.GetType(), D3D12DescriptorType::Sampler); break; } case D3D12DescriptorType::CBV: { ser.Serialise("Descriptor", el.nonsamp.cbv); break; } case D3D12DescriptorType::SRV: { ser.Serialise("Resource", el.nonsamp.resource); ser.Serialise("Descriptor", el.nonsamp.srv); break; } case D3D12DescriptorType::RTV: { ser.Serialise("Resource", el.nonsamp.resource); ser.Serialise("Descriptor", el.nonsamp.rtv); break; } case D3D12DescriptorType::DSV: { ser.Serialise("Resource", el.nonsamp.resource); ser.Serialise("Descriptor", el.nonsamp.dsv); break; } case D3D12DescriptorType::UAV: { ser.Serialise("Resource", el.nonsamp.resource); ser.Serialise("CounterResource", el.nonsamp.uav.counterResource); // special case because of extra resource and squeezed descriptor D3D12_UNORDERED_ACCESS_VIEW_DESC desc = el.nonsamp.uav.desc.AsDesc(); ser.Serialise("Descriptor", desc); el.nonsamp.uav.desc.Init(desc); break; } case D3D12DescriptorType::Undefined: { el.nonsamp.type = type; break; } } }
bool WrappedOpenGL::Serialise_wglDXLockObjectsNV(SerialiserType &ser, GLResource Resource) { SERIALISE_ELEMENT(Resource); SERIALISE_ELEMENT_LOCAL(textype, Resource.Namespace == eResBuffer ? eGL_NONE : m_Textures[GetResourceManager()->GetID(Resource)].curType) .Hidden(); const GLHookSet &gl = m_Real; // buffer contents are easier to save if(textype == eGL_NONE) { byte *Contents = NULL; uint32_t length = 1; // while writing, fetch the buffer's size and contents if(ser.IsWriting()) { gl.glGetNamedBufferParameterivEXT(Resource.name, eGL_BUFFER_SIZE, (GLint *)&length); Contents = new byte[length]; GLuint oldbuf = 0; gl.glGetIntegerv(eGL_COPY_READ_BUFFER_BINDING, (GLint *)&oldbuf); gl.glBindBuffer(eGL_COPY_READ_BUFFER, Resource.name); gl.glGetBufferSubData(eGL_COPY_READ_BUFFER, 0, (GLsizeiptr)length, Contents); gl.glBindBuffer(eGL_COPY_READ_BUFFER, oldbuf); } SERIALISE_ELEMENT_ARRAY(Contents, length); SERIALISE_CHECK_READ_ERRORS(); // restore on replay if(IsReplayingAndReading()) { uint32_t liveLength = 1; gl.glGetNamedBufferParameterivEXT(Resource.name, eGL_BUFFER_SIZE, (GLint *)&liveLength); gl.glNamedBufferSubData(Resource.name, 0, (GLsizeiptr)RDCMIN(length, liveLength), Contents); } } else { GLuint ppb = 0, pub = 0; PixelPackState pack; PixelUnpackState unpack; // save and restore pixel pack/unpack state. We only need one or the other but for clarity we // push and pop both always. if(ser.IsWriting() || !IsStructuredExporting(m_State)) { gl.glGetIntegerv(eGL_PIXEL_PACK_BUFFER_BINDING, (GLint *)&ppb); gl.glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING, (GLint *)&pub); gl.glBindBuffer(eGL_PIXEL_PACK_BUFFER, 0); gl.glBindBuffer(eGL_PIXEL_UNPACK_BUFFER, 0); pack.Fetch(&gl, false); unpack.Fetch(&gl, false); ResetPixelPackState(gl, false, 1); ResetPixelUnpackState(gl, false, 1); } TextureData &details = m_Textures[GetResourceManager()->GetID(Resource)]; GLuint tex = Resource.name; // serialise the metadata for convenience SERIALISE_ELEMENT_LOCAL(internalFormat, details.internalFormat).Hidden(); SERIALISE_ELEMENT_LOCAL(width, details.width).Hidden(); SERIALISE_ELEMENT_LOCAL(height, details.height).Hidden(); SERIALISE_ELEMENT_LOCAL(depth, details.depth).Hidden(); RDCASSERT(internalFormat == details.internalFormat, internalFormat, details.internalFormat); RDCASSERT(width == details.width, width, details.width); RDCASSERT(height == details.height, height, details.height); RDCASSERT(depth == details.depth, depth, details.depth); GLenum fmt = GetBaseFormat(internalFormat); GLenum type = GetDataType(internalFormat); GLint dim = details.dimension; uint32_t size = (uint32_t)GetByteSize(width, height, depth, fmt, type); int mips = 0; if(IsReplayingAndReading()) mips = GetNumMips(gl, textype, tex, width, height, depth); byte *scratchBuf = NULL; // on read and write, we allocate a single buffer big enough for all mips and re-use it // to avoid repeated new/free. scratchBuf = AllocAlignedBuffer(size); GLuint prevtex = 0; if(!IsStructuredExporting(m_State)) { gl.glGetIntegerv(TextureBinding(details.curType), (GLint *)&prevtex); gl.glBindTexture(textype, tex); } for(int i = 0; i < mips; i++) { int w = RDCMAX(details.width >> i, 1); int h = RDCMAX(details.height >> i, 1); int d = RDCMAX(details.depth >> i, 1); if(textype == eGL_TEXTURE_CUBE_MAP_ARRAY || textype == eGL_TEXTURE_1D_ARRAY || textype == eGL_TEXTURE_2D_ARRAY) d = details.depth; size = (uint32_t)GetByteSize(w, h, d, fmt, type); GLenum targets[] = { eGL_TEXTURE_CUBE_MAP_POSITIVE_X, eGL_TEXTURE_CUBE_MAP_NEGATIVE_X, eGL_TEXTURE_CUBE_MAP_POSITIVE_Y, eGL_TEXTURE_CUBE_MAP_NEGATIVE_Y, eGL_TEXTURE_CUBE_MAP_POSITIVE_Z, eGL_TEXTURE_CUBE_MAP_NEGATIVE_Z, }; int count = ARRAY_COUNT(targets); if(textype != eGL_TEXTURE_CUBE_MAP) { targets[0] = textype; count = 1; } for(int trg = 0; trg < count; trg++) { if(ser.IsWriting()) { // we avoid glGetTextureImageEXT as it seems buggy for cubemap faces gl.glGetTexImage(targets[trg], i, fmt, type, scratchBuf); } // serialise without allocating memory as we already have our scratch buf sized. ser.Serialise("SubresourceContents", scratchBuf, size, SerialiserFlags::NoFlags); if(IsReplayingAndReading() && !ser.IsErrored()) { if(dim == 1) gl.glTextureSubImage1DEXT(tex, targets[trg], i, 0, w, fmt, type, scratchBuf); else if(dim == 2) gl.glTextureSubImage2DEXT(tex, targets[trg], i, 0, 0, w, h, fmt, type, scratchBuf); else if(dim == 3) gl.glTextureSubImage3DEXT(tex, targets[trg], i, 0, 0, 0, w, h, d, fmt, type, scratchBuf); } } } FreeAlignedBuffer(scratchBuf); // restore pixel (un)packing state if(ser.IsWriting() || !IsStructuredExporting(m_State)) { gl.glBindBuffer(eGL_PIXEL_PACK_BUFFER, ppb); gl.glBindBuffer(eGL_PIXEL_UNPACK_BUFFER, pub); pack.Apply(&gl, false); unpack.Apply(&gl, false); } if(!IsStructuredExporting(m_State)) gl.glBindTexture(textype, prevtex); SERIALISE_CHECK_READ_ERRORS(); } return true; }
bool WrappedOpenGL::Serialise_wglDXRegisterObjectNV(SerialiserType &ser, GLResource Resource, GLenum type, void *dxObject) { SERIALISE_ELEMENT(Resource); GLenum internalFormat = eGL_NONE; uint32_t width = 0, height = 0, depth = 0, mips = 0, layers = 0, samples = 0; if(ser.IsWriting()) { ResourceFormat format; #if ENABLED(RDOC_WIN32) && ENABLED(RENDERDOC_DX_GL_INTEROP) GetDXTextureProperties(dxObject, format, width, height, depth, mips, layers, samples); if(type != eGL_NONE) internalFormat = MakeGLFormat(format); #else RDCERR("Should never happen - cannot serialise wglDXRegisterObjectNV, interop is disabled"); #endif } SERIALISE_ELEMENT(type); SERIALISE_ELEMENT(internalFormat); SERIALISE_ELEMENT(width); SERIALISE_ELEMENT(height); SERIALISE_ELEMENT(depth); SERIALISE_ELEMENT(mips); SERIALISE_ELEMENT(layers); SERIALISE_ELEMENT(samples); SERIALISE_CHECK_READ_ERRORS(); if(IsReplayingAndReading()) { GLuint name = Resource.name; switch(type) { case eGL_NONE: case eGL_TEXTURE_BUFFER: { m_Real.glNamedBufferDataEXT(name, width, NULL, eGL_STATIC_DRAW); break; } case eGL_TEXTURE_1D: m_Real.glTextureStorage1DEXT(name, type, mips, internalFormat, width); break; case eGL_TEXTURE_1D_ARRAY: m_Real.glTextureStorage2DEXT(name, type, mips, internalFormat, width, layers); break; // treat renderbuffers and texture rects as tex2D just to make things easier case eGL_RENDERBUFFER: case eGL_TEXTURE_RECTANGLE: case eGL_TEXTURE_2D: case eGL_TEXTURE_CUBE_MAP: m_Real.glTextureStorage2DEXT(name, type, mips, internalFormat, width, height); break; case eGL_TEXTURE_2D_ARRAY: case eGL_TEXTURE_CUBE_MAP_ARRAY: m_Real.glTextureStorage3DEXT(name, type, mips, internalFormat, width, height, layers); break; case eGL_TEXTURE_2D_MULTISAMPLE: m_Real.glTextureStorage2DMultisampleEXT(name, type, samples, internalFormat, width, height, GL_TRUE); break; case eGL_TEXTURE_2D_MULTISAMPLE_ARRAY: m_Real.glTextureStorage3DMultisampleEXT(name, type, samples, internalFormat, width, height, layers, GL_TRUE); break; case eGL_TEXTURE_3D: m_Real.glTextureStorage3DEXT(name, type, mips, internalFormat, width, height, depth); break; default: RDCERR("Unexpected type of interop texture: %s", ToStr(type).c_str()); break; } if(type != eGL_NONE) { ResourceId liveId = GetResourceManager()->GetID(Resource); m_Textures[liveId].curType = type; m_Textures[liveId].width = width; m_Textures[liveId].height = height; m_Textures[liveId].depth = RDCMAX(depth, samples); m_Textures[liveId].samples = samples; m_Textures[liveId].dimension = 2; if(type == eGL_TEXTURE_1D || type == eGL_TEXTURE_1D_ARRAY) m_Textures[liveId].dimension = 1; else if(type == eGL_TEXTURE_3D) m_Textures[liveId].dimension = 3; m_Textures[liveId].internalFormat = internalFormat; } AddResourceInitChunk(Resource); } return true; }
bool WrappedOpenGL::Serialise_glObjectLabel(SerialiserType &ser, GLenum identifier, GLuint name, GLsizei length, const GLchar *label) { GLResource Resource; std::string Label; if(ser.IsWriting()) { // we share implementations between KHR_debug and EXT_debug_label, however KHR_debug follows the // pattern elsewhere (e.g. in glShaderSource) of a length of -1 meaning indeterminate // NULL-terminated length, but EXT_debug_label takes length of 0 to mean that. GLsizei realLength = length; if(gl_CurChunk == GLChunk::glLabelObjectEXT && length == 0) realLength = -1; // if length is negative (after above twiddling), it's taken from strlen and the label must be // NULL-terminated if(realLength < 0) realLength = label ? (GLsizei)strlen(label) : 0; if(realLength == 0 || label == NULL) Label = ""; else Label = std::string(label, label + realLength); switch(identifier) { case eGL_TEXTURE: Resource = TextureRes(GetCtx(), name); break; case eGL_BUFFER_OBJECT_EXT: case eGL_BUFFER: Resource = BufferRes(GetCtx(), name); break; case eGL_PROGRAM_OBJECT_EXT: case eGL_PROGRAM: Resource = ProgramRes(GetCtx(), name); break; case eGL_PROGRAM_PIPELINE_OBJECT_EXT: case eGL_PROGRAM_PIPELINE: Resource = ProgramPipeRes(GetCtx(), name); break; case eGL_VERTEX_ARRAY_OBJECT_EXT: case eGL_VERTEX_ARRAY: Resource = VertexArrayRes(GetCtx(), name); break; case eGL_SHADER_OBJECT_EXT: case eGL_SHADER: Resource = ShaderRes(GetCtx(), name); break; case eGL_QUERY_OBJECT_EXT: case eGL_QUERY: Resource = QueryRes(GetCtx(), name); break; case eGL_TRANSFORM_FEEDBACK: Resource = FeedbackRes(GetCtx(), name); break; case eGL_SAMPLER: Resource = SamplerRes(GetCtx(), name); break; case eGL_RENDERBUFFER: Resource = RenderbufferRes(GetCtx(), name); break; case eGL_FRAMEBUFFER: Resource = FramebufferRes(GetCtx(), name); break; default: RDCERR("Unhandled namespace in glObjectLabel"); } } SERIALISE_ELEMENT(Resource); SERIALISE_ELEMENT(length); SERIALISE_ELEMENT(Label); SERIALISE_CHECK_READ_ERRORS(); if(IsReplayingAndReading() && Resource.name) { ResourceId origId = GetResourceManager()->GetOriginalID(GetResourceManager()->GetID(Resource)); GetResourceManager()->SetName(origId, Label); ResourceDescription &descr = GetReplay()->GetResourceDesc(origId); descr.SetCustomName(Label); AddResourceCurChunk(descr); } return true; }