Implement Get*Descriptor for virtual descriptor storage in D3D11 & GL

This commit is contained in:
baldurk
2024-02-20 19:35:38 +00:00
parent ff821b25c8
commit c1d07f6bc3
9 changed files with 866 additions and 8 deletions
+18
View File
@@ -783,6 +783,24 @@ struct State
)");
Shader computeShader;
DOCUMENT(R"(The virtual descriptor storage.
:type: ResourceId
)");
ResourceId descriptorStore;
DOCUMENT(R"(The number of descriptors in the virtual descriptor storage.
:type: int
)");
uint32_t descriptorCount;
DOCUMENT(R"(The byte size of a descriptor in the virtual descriptor storage.
:type: int
)");
uint32_t descriptorByteSize;
DOCUMENT(R"(The stream-out pipeline stage.
:type: D3D11StreamOut
+18
View File
@@ -913,6 +913,24 @@ struct State
)");
rdcarray<ImageLoadStore> images;
DOCUMENT(R"(The virtual descriptor storage.
:type: ResourceId
)");
ResourceId descriptorStore;
DOCUMENT(R"(The number of descriptors in the virtual descriptor storage.
:type: int
)");
uint32_t descriptorCount;
DOCUMENT(R"(The byte size of a descriptor in the virtual descriptor storage.
:type: int
)");
uint32_t descriptorByteSize;
DOCUMENT(R"(The transform feedback stage.
:type: GLFeedback
@@ -33,6 +33,54 @@ class WrappedID3D11Device;
class WrappedID3D11DeviceContext;
class D3D11ResourceManager;
// mapping of 'index in descriptor store' to fixed bindings, linearly in a given stage's members
enum class D3D11DescriptorMapping : uint32_t
{
CBs = 0,
SRVs = CBs + D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
Samplers = SRVs + D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT,
UAVs = Samplers + D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT,
Count = UAVs + D3D11_1_UAV_SLOT_COUNT,
Invalid = ~0U,
};
struct D3D11DescriptorLocation
{
ShaderStage stage;
D3D11DescriptorMapping type;
uint32_t idx;
};
inline D3D11DescriptorLocation DecodeD3D11DescriptorIndex(uint32_t idx)
{
ShaderStage stage = ShaderStage(idx / (uint32_t)D3D11DescriptorMapping::Count);
idx %= (uint32_t)D3D11DescriptorMapping::Count;
if((uint32_t)stage > (uint32_t)ShaderStage::Compute)
return {stage, D3D11DescriptorMapping::Invalid, 0};
// go in reverse order to handle each case with a >=
#define HANDLE_TYPE(type) \
else if(idx >= (uint32_t)D3D11DescriptorMapping::type) return { \
stage, \
D3D11DescriptorMapping::type, \
idx - (uint32_t)D3D11DescriptorMapping::type, \
}
HANDLE_TYPE(UAVs);
HANDLE_TYPE(Samplers);
HANDLE_TYPE(SRVs);
HANDLE_TYPE(CBs);
#undef HANDLE_TYPE
return {stage, D3D11DescriptorMapping::Invalid, 0};
}
inline uint32_t EncodeD3D11DescriptorIndex(const D3D11DescriptorLocation &idx)
{
return (uint32_t)idx.stage * (uint32_t)D3D11DescriptorMapping::Count + (uint32_t)idx.type + idx.idx;
}
struct D3D11RenderState
{
enum EmptyInit
+284 -2
View File
@@ -741,6 +741,11 @@ void D3D11Replay::SavePipelineState(uint32_t eventId)
D3D11ResourceManager *rm = m_pDevice->GetResourceManager();
ret.descriptorStore = m_pImmediateContext->GetDescriptorsID();
ret.descriptorCount =
EncodeD3D11DescriptorIndex({ShaderStage::Compute, D3D11DescriptorMapping::Count, 0});
ret.descriptorByteSize = 1;
ret.inputAssembly.bytecode = NULL;
ret.inputAssembly.resourceId = ResourceId();
ret.inputAssembly.layouts.clear();
@@ -1671,14 +1676,243 @@ rdcarray<Descriptor> D3D11Replay::GetDescriptors(ResourceId descriptorStore,
if(descriptorStore != m_pImmediateContext->GetDescriptorsID())
{
RDCERR("Descriptors query for invalid descriptor store on fixed bindings API (D3D11)");
RDCERR(
"Descriptors query for invalid descriptor descriptorStore on fixed bindings API (D3D11)");
return ret;
}
D3D11RenderState *rs = m_pDevice->GetImmediateContext()->GetCurrentPipelineState();
D3D11ResourceManager *rm = m_pDevice->GetResourceManager();
size_t count = 0;
for(const DescriptorRange &r : ranges)
count += r.count;
ret.resize(count);
const D3D11RenderState::Shader *srcArr[] = {&rs->VS, &rs->HS, &rs->DS, &rs->GS, &rs->PS, &rs->CS};
size_t dst = 0;
for(const DescriptorRange &r : ranges)
{
uint32_t descriptorId = r.offset;
for(uint32_t i = 0; i < r.count; i++, dst++, descriptorId++)
{
D3D11DescriptorLocation idx = DecodeD3D11DescriptorIndex(descriptorId);
const D3D11RenderState::Shader &src = *srcArr[(uint32_t)idx.stage];
if(idx.type == D3D11DescriptorMapping::CBs)
{
ret[dst].type = DescriptorType::ConstantBuffer;
ret[dst].resource = rm->GetOriginalID(GetIDForDeviceChild(src.ConstantBuffers[idx.idx]));
ret[dst].byteOffset = src.CBOffsets[idx.idx] * sizeof(Vec4f);
ret[dst].byteSize = src.CBCounts[idx.idx] * sizeof(Vec4f);
}
else if(idx.type == D3D11DescriptorMapping::SRVs)
{
ID3D11ShaderResourceView *view = src.SRVs[idx.idx];
ret[dst].view = rm->GetOriginalID(GetIDForDeviceChild(view));
ret[dst].type = DescriptorType::Image;
if(ret[dst].view != ResourceId())
{
D3D11_SHADER_RESOURCE_VIEW_DESC desc;
view->GetDesc(&desc);
ret[dst].format = MakeResourceFormat(desc.Format);
ID3D11Resource *res = NULL;
view->GetResource(&res);
ret[dst].elementByteSize =
desc.Format == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, desc.Format, 0);
ret[dst].resource = rm->GetOriginalID(GetIDForDeviceChild(res));
ret[dst].textureType = MakeTextureDim(desc.ViewDimension);
if(desc.ViewDimension == D3D11_SRV_DIMENSION_BUFFER)
{
ret[dst].type = DescriptorType::TypedBuffer;
D3D11_BUFFER_DESC bufdesc;
((ID3D11Buffer *)res)->GetDesc(&bufdesc);
if(bufdesc.StructureByteStride > 0 && desc.Format == DXGI_FORMAT_UNKNOWN)
{
ret[dst].elementByteSize = bufdesc.StructureByteStride;
ret[dst].type = DescriptorType::Buffer;
}
ret[dst].byteOffset = desc.Buffer.FirstElement * ret[dst].elementByteSize;
ret[dst].byteSize = desc.Buffer.NumElements * ret[dst].elementByteSize;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_BUFFEREX)
{
ret[dst].type = DescriptorType::TypedBuffer;
ret[dst].flags = DescriptorFlags(desc.BufferEx.Flags);
D3D11_BUFFER_DESC bufdesc;
((ID3D11Buffer *)res)->GetDesc(&bufdesc);
if(bufdesc.StructureByteStride > 0 && desc.Format == DXGI_FORMAT_UNKNOWN)
{
ret[dst].elementByteSize = bufdesc.StructureByteStride;
ret[dst].type = DescriptorType::Buffer;
}
ret[dst].byteOffset = desc.BufferEx.FirstElement * ret[dst].elementByteSize;
ret[dst].byteSize = desc.BufferEx.NumElements * ret[dst].elementByteSize;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE1D)
{
ret[dst].firstMip = desc.Texture1D.MostDetailedMip & 0xff;
ret[dst].numMips = desc.Texture1D.MipLevels & 0xff;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE1DARRAY)
{
ret[dst].firstMip = desc.Texture1DArray.MostDetailedMip & 0xff;
ret[dst].numMips = desc.Texture1DArray.MipLevels & 0xff;
ret[dst].numSlices = desc.Texture1DArray.ArraySize & 0xffff;
ret[dst].firstSlice = desc.Texture1DArray.FirstArraySlice & 0xffff;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2D)
{
ret[dst].firstMip = desc.Texture2D.MostDetailedMip & 0xff;
ret[dst].numMips = desc.Texture2D.MipLevels & 0xff;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DARRAY)
{
ret[dst].firstMip = desc.Texture2DArray.MostDetailedMip & 0xff;
ret[dst].numMips = desc.Texture2DArray.MipLevels & 0xff;
ret[dst].firstSlice = desc.Texture2DArray.FirstArraySlice & 0xffff;
ret[dst].numSlices = desc.Texture2DArray.ArraySize & 0xffff;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DMS)
{
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY)
{
ret[dst].numSlices = desc.Texture2DMSArray.ArraySize & 0xffff;
ret[dst].firstSlice = desc.Texture2DMSArray.FirstArraySlice & 0xffff;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D)
{
ret[dst].firstMip = desc.Texture3D.MostDetailedMip & 0xff;
ret[dst].numMips = desc.Texture3D.MipLevels & 0xff;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBE)
{
ret[dst].firstMip = desc.TextureCube.MostDetailedMip & 0xff;
ret[dst].numMips = desc.TextureCube.MipLevels & 0xff;
ret[dst].numSlices = 6;
}
else if(desc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY)
{
ret[dst].firstMip = desc.TextureCubeArray.MostDetailedMip & 0xff;
ret[dst].numMips = desc.TextureCubeArray.MipLevels & 0xff;
ret[dst].firstSlice = desc.TextureCubeArray.First2DArrayFace & 0xffff;
ret[dst].numSlices = (desc.TextureCubeArray.NumCubes * 6) & 0xffff;
}
SAFE_RELEASE(res);
}
}
else if(idx.type == D3D11DescriptorMapping::UAVs)
{
ID3D11UnorderedAccessView *view = NULL;
if(idx.stage == ShaderStage::Compute)
view = rs->CSUAVs[idx.idx];
else if(idx.idx >= rs->OM.UAVStartSlot)
view = rs->OM.UAVs[idx.idx - rs->OM.UAVStartSlot];
ret[dst].view = rm->GetOriginalID(GetIDForDeviceChild(view));
ret[dst].type = DescriptorType::ReadWriteImage;
if(ret[dst].view != ResourceId())
{
D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
view->GetDesc(&desc);
ID3D11Resource *res = NULL;
view->GetResource(&res);
ret[dst].bufferStructCount = 0;
ret[dst].elementByteSize =
desc.Format == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, desc.Format, 0);
ret[dst].textureType = MakeTextureDim(desc.ViewDimension);
ret[dst].secondary = ResourceId();
if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER &&
(desc.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER)))
{
ret[dst].bufferStructCount = GetDebugManager()->GetStructCount(view);
ret[dst].secondary = GetDebugManager()->GetCounterBufferID(view);
}
ret[dst].resource = rm->GetOriginalID(GetIDForDeviceChild(res));
ret[dst].format = MakeResourceFormat(desc.Format);
if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER)
{
ret[dst].type = DescriptorType::ReadWriteBuffer;
if(desc.Format != DXGI_FORMAT_UNKNOWN)
ret[dst].type = DescriptorType::ReadWriteTypedBuffer;
ret[dst].flags = DescriptorFlags(desc.Buffer.Flags);
D3D11_BUFFER_DESC bufdesc;
((ID3D11Buffer *)res)->GetDesc(&bufdesc);
if(bufdesc.StructureByteStride > 0 && desc.Format == DXGI_FORMAT_UNKNOWN)
ret[dst].elementByteSize = bufdesc.StructureByteStride;
ret[dst].byteOffset = desc.Buffer.FirstElement * ret[dst].elementByteSize;
ret[dst].byteSize = desc.Buffer.NumElements * ret[dst].elementByteSize;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1D)
{
ret[dst].firstMip = desc.Texture1D.MipSlice & 0xff;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1DARRAY)
{
ret[dst].numSlices = desc.Texture1DArray.ArraySize & 0xffff;
ret[dst].firstSlice = desc.Texture1DArray.FirstArraySlice & 0xffff;
ret[dst].firstMip = desc.Texture1DArray.MipSlice & 0xff;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2D)
{
ret[dst].firstMip = desc.Texture2D.MipSlice & 0xff;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2DARRAY)
{
ret[dst].numSlices = desc.Texture2DArray.ArraySize & 0xffff;
ret[dst].firstSlice = desc.Texture2DArray.FirstArraySlice & 0xffff;
ret[dst].firstMip = desc.Texture2DArray.MipSlice & 0xff;
}
else if(desc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE3D)
{
ret[dst].numSlices = desc.Texture3D.WSize & 0xffff;
ret[dst].firstSlice = desc.Texture3D.FirstWSlice & 0xffff;
ret[dst].firstMip = desc.Texture3D.MipSlice & 0xff;
}
SAFE_RELEASE(res);
}
}
}
}
return ret;
}
@@ -1689,14 +1923,62 @@ rdcarray<SamplerDescriptor> D3D11Replay::GetSamplerDescriptors(ResourceId descri
if(descriptorStore != m_pImmediateContext->GetDescriptorsID())
{
RDCERR("Descriptors query for invalid descriptor store on fixed bindings API (D3D11)");
RDCERR(
"Descriptors query for invalid descriptor descriptorStore on fixed bindings API (D3D11)");
return ret;
}
D3D11RenderState *rs = m_pDevice->GetImmediateContext()->GetCurrentPipelineState();
D3D11ResourceManager *rm = m_pDevice->GetResourceManager();
size_t count = 0;
for(const DescriptorRange &r : ranges)
count += r.count;
ret.resize(count);
const D3D11RenderState::Shader *srcArr[] = {&rs->VS, &rs->HS, &rs->DS, &rs->GS, &rs->PS, &rs->CS};
size_t dst = 0;
for(const DescriptorRange &r : ranges)
{
uint32_t descriptorId = r.offset;
for(uint32_t i = 0; i < r.count; i++, dst++, descriptorId++)
{
D3D11DescriptorLocation idx = DecodeD3D11DescriptorIndex(descriptorId);
if(idx.type != D3D11DescriptorMapping::Samplers)
continue;
ID3D11SamplerState *samp = srcArr[(uint32_t)idx.stage]->Samplers[idx.idx];
ret[dst].type = DescriptorType::Sampler;
ret[dst].object = rm->GetOriginalID(GetIDForDeviceChild(samp));
if(ret[dst].object != ResourceId())
{
D3D11_SAMPLER_DESC desc;
samp->GetDesc(&desc);
ret[dst].addressU = MakeAddressMode(desc.AddressU);
ret[dst].addressV = MakeAddressMode(desc.AddressV);
ret[dst].addressW = MakeAddressMode(desc.AddressW);
ret[dst].borderColorValue.floatValue = desc.BorderColor;
ret[dst].borderColorType = CompType::Float;
ret[dst].compareFunction = MakeCompareFunc(desc.ComparisonFunc);
ret[dst].filter = MakeFilter(desc.Filter);
ret[dst].maxAnisotropy = 0;
if(ret[dst].filter.mip == FilterMode::Anisotropic)
ret[dst].maxAnisotropy = (float)desc.MaxAnisotropy;
ret[dst].maxLOD = desc.MaxLOD;
ret[dst].minLOD = desc.MinLOD;
ret[dst].mipBias = desc.MipLODBias;
}
}
}
return ret;
}
+66
View File
@@ -68,6 +68,72 @@ struct PixelUnpackState : public PixelStorageState
void ResetPixelPackState(bool compressed, GLint alignment);
void ResetPixelUnpackState(bool compressed, GLint alignment);
// mapping of 'index in descriptor store' to fixed bindings, linearly in GLRenderState members
enum class GLDescriptorMapping : uint32_t
{
Tex1D = 0,
Tex2D = Tex1D + 128,
Tex3D = Tex2D + 128,
Tex1DArray = Tex3D + 128,
Tex2DArray = Tex1DArray + 128,
TexCubeArray = Tex2DArray + 128,
TexRect = TexCubeArray + 128,
TexBuffer = TexRect + 128,
TexCube = TexBuffer + 128,
Tex2DMS = TexCube + 128,
Tex2DMSArray = Tex2DMS + 128,
Images = Tex2DMSArray + 128,
AtomicCounter = Images + 8,
ShaderStorage = AtomicCounter + 8,
UniformBinding = ShaderStorage + 96,
BareUniforms = UniformBinding + 84,
Count = BareUniforms + 6,
Invalid = ~0U,
};
struct GLDescriptorLocation
{
GLDescriptorMapping type;
uint32_t idx;
};
inline GLDescriptorLocation DecodeGLDescriptorIndex(uint32_t idx)
{
if(idx >= (uint32_t)GLDescriptorMapping::Count)
return {GLDescriptorMapping::Invalid, 0};
// go in reverse order to handle each case with a >=
#define HANDLE_TYPE(type) \
else if(idx >= (uint32_t)GLDescriptorMapping::type) return { \
GLDescriptorMapping::type, \
idx - (uint32_t)GLDescriptorMapping::type, \
}
HANDLE_TYPE(BareUniforms);
HANDLE_TYPE(UniformBinding);
HANDLE_TYPE(ShaderStorage);
HANDLE_TYPE(AtomicCounter);
HANDLE_TYPE(Images);
HANDLE_TYPE(Tex2DMSArray);
HANDLE_TYPE(Tex2DMS);
HANDLE_TYPE(TexCube);
HANDLE_TYPE(TexBuffer);
HANDLE_TYPE(TexRect);
HANDLE_TYPE(TexCubeArray);
HANDLE_TYPE(Tex2DArray);
HANDLE_TYPE(Tex1DArray);
HANDLE_TYPE(Tex3D);
HANDLE_TYPE(Tex2D);
HANDLE_TYPE(Tex1D);
#undef HANDLE_TYPE
return {GLDescriptorMapping::Invalid, 0};
}
inline uint32_t EncodeGLDescriptorIndex(const GLDescriptorLocation &idx)
{
return (uint32_t)idx.type + idx.idx;
}
struct GLRenderState
{
GLRenderState();
+418
View File
@@ -848,6 +848,10 @@ void GLReplay::SavePipelineState(uint32_t eventId)
ContextPair &ctx = drv.GetCtx();
pipe.descriptorStore = m_pDriver->m_DescriptorsID;
pipe.descriptorCount = EncodeGLDescriptorIndex({GLDescriptorMapping::Count, 0});
pipe.descriptorByteSize = 1;
GLuint vao = 0;
drv.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&vao);
pipe.vertexInput.vertexArrayObject = rm->GetOriginalID(rm->GetResID(VertexArrayRes(ctx, vao)));
@@ -2131,10 +2135,244 @@ rdcarray<Descriptor> GLReplay::GetDescriptors(ResourceId descriptorStore,
return ret;
}
MakeCurrentReplayContext(&m_ReplayCtx);
WrappedOpenGL &drv = *m_pDriver;
GLResourceManager *rm = m_pDriver->GetResourceManager();
ContextPair &ctx = drv.GetCtx();
GLRenderState rs;
rs.FetchState(&drv);
size_t count = 0;
for(const DescriptorRange &r : ranges)
count += r.count;
ret.resize(count);
size_t dst = 0;
for(const DescriptorRange &r : ranges)
{
uint32_t descriptorId = r.offset;
for(uint32_t i = 0; i < r.count; i++, dst++, descriptorId++)
{
GLDescriptorLocation idx = DecodeGLDescriptorIndex(descriptorId);
if(idx.type == GLDescriptorMapping::Invalid)
{
}
else if(idx.type == GLDescriptorMapping::BareUniforms)
{
// not feasible to emulate backing store for bare uniforms. We could synthesise our own byte
// layout and query uniform values into a buffer but... let's not.
ret[dst].type = DescriptorType::ConstantBuffer;
ret[dst].byteSize = 16 * 1024;
}
else if(idx.type == GLDescriptorMapping::UniformBinding)
{
ret[dst].type = DescriptorType::ConstantBuffer;
if(rs.UniformBinding[idx.idx].res.name != 0)
{
ret[dst].resource = rm->GetOriginalID(rm->GetResID(rs.UniformBinding[idx.idx].res));
ret[dst].byteOffset = rs.UniformBinding[idx.idx].start;
ret[dst].byteSize = rs.UniformBinding[idx.idx].size;
}
}
else if(idx.type == GLDescriptorMapping::AtomicCounter)
{
ret[dst].type = DescriptorType::ReadWriteBuffer;
if(rs.AtomicCounter[idx.idx].res.name != 0)
{
ret[dst].resource = rm->GetOriginalID(rm->GetResID(rs.AtomicCounter[idx.idx].res));
ret[dst].byteOffset = rs.AtomicCounter[idx.idx].start;
ret[dst].byteSize = rs.AtomicCounter[idx.idx].size;
}
}
else if(idx.type == GLDescriptorMapping::ShaderStorage)
{
ret[dst].type = DescriptorType::ReadWriteBuffer;
if(rs.ShaderStorage[idx.idx].res.name != 0)
{
ret[dst].resource = rm->GetOriginalID(rm->GetResID(rs.ShaderStorage[idx.idx].res));
ret[dst].byteOffset = rs.ShaderStorage[idx.idx].start;
ret[dst].byteSize = rs.ShaderStorage[idx.idx].size;
}
}
else if(idx.type == GLDescriptorMapping::Images)
{
ret[dst].type = DescriptorType::ReadWriteImage;
if(rs.Images[idx.idx].res.name != 0)
{
ResourceId id = rm->GetResID(rs.Images[idx.idx].res);
ret[dst].resource = rm->GetOriginalID(id);
ret[dst].firstMip = rs.Images[idx.idx].level & 0xff;
ret[dst].numMips = 1;
ret[dst].firstSlice = rs.Images[idx.idx].layer & 0xffff;
if(rs.Images[idx.idx].access == eGL_READ_ONLY)
{
ret[dst].flags = DescriptorFlags::ReadOnlyAccess;
}
else if(rs.Images[idx.idx].access == eGL_WRITE_ONLY)
{
ret[dst].flags = DescriptorFlags::WriteOnlyAccess;
}
ret[dst].format = MakeResourceFormat(eGL_TEXTURE_2D, rs.Images[idx.idx].format);
CacheTexture(id);
ret[dst].textureType = m_CachedTextures[id].type;
if(ret[dst].textureType == TextureType::Texture3D)
ret[dst].numSlices = rs.Images[idx.idx].layered
? (m_CachedTextures[id].depth >> ret[dst].firstMip) & 0xffff
: 1;
else
ret[dst].numSlices =
rs.Images[idx.idx].layered ? m_CachedTextures[id].arraysize & 0xffff : 1;
if(ret[dst].textureType == TextureType::Buffer)
ret[dst].type = DescriptorType::ReadWriteTypedBuffer;
}
}
else
{
ret[dst].type = DescriptorType::ImageSampler;
if(idx.type == GLDescriptorMapping::TexBuffer)
ret[dst].type = DescriptorType::TypedBuffer;
drv.glActiveTexture(GLenum(eGL_TEXTURE0 + idx.idx));
GLuint tex = 0;
GLenum target = eGL_NONE;
if(idx.type == GLDescriptorMapping::TexCubeArray && !HasExt[ARB_texture_cube_map_array])
{
tex = 0;
target = eGL_TEXTURE_CUBE_MAP_ARRAY;
}
else
{
switch(idx.type)
{
case GLDescriptorMapping::Tex1D:
target = eGL_TEXTURE_1D;
ret[dst].textureType = TextureType::Texture1D;
break;
case GLDescriptorMapping::Tex2D:
target = eGL_TEXTURE_2D;
ret[dst].textureType = TextureType::Texture2D;
break;
case GLDescriptorMapping::Tex3D:
target = eGL_TEXTURE_3D;
ret[dst].textureType = TextureType::Texture3D;
break;
case GLDescriptorMapping::Tex1DArray:
target = eGL_TEXTURE_1D_ARRAY;
ret[dst].textureType = TextureType::Texture1DArray;
break;
case GLDescriptorMapping::Tex2DArray:
target = eGL_TEXTURE_2D_ARRAY;
ret[dst].textureType = TextureType::Texture2DArray;
break;
case GLDescriptorMapping::TexCubeArray:
target = eGL_TEXTURE_CUBE_MAP_ARRAY;
ret[dst].textureType = TextureType::TextureCubeArray;
break;
case GLDescriptorMapping::TexRect:
target = eGL_TEXTURE_RECTANGLE;
ret[dst].textureType = TextureType::TextureRect;
break;
case GLDescriptorMapping::TexBuffer:
target = eGL_TEXTURE_BUFFER;
ret[dst].textureType = TextureType::Buffer;
break;
case GLDescriptorMapping::TexCube:
target = eGL_TEXTURE_CUBE_MAP;
ret[dst].textureType = TextureType::TextureCube;
break;
case GLDescriptorMapping::Tex2DMS:
target = eGL_TEXTURE_2D_MULTISAMPLE;
ret[dst].textureType = TextureType::Texture2DMS;
break;
case GLDescriptorMapping::Tex2DMSArray:
target = eGL_TEXTURE_2D_MULTISAMPLE_ARRAY;
ret[dst].textureType = TextureType::Texture2DMSArray;
break;
case GLDescriptorMapping::AtomicCounter:
case GLDescriptorMapping::ShaderStorage:
case GLDescriptorMapping::BareUniforms:
case GLDescriptorMapping::UniformBinding:
case GLDescriptorMapping::Images:
case GLDescriptorMapping::Invalid:
case GLDescriptorMapping::Count: target = eGL_NONE; break;
}
}
if(target == eGL_NONE)
continue;
GLenum binding = TextureBinding(target);
drv.glGetIntegerv(binding, (GLint *)&tex);
if(tex == 0)
continue;
GLint firstMip = 0, numMips = 1;
if(target != eGL_TEXTURE_BUFFER)
{
drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_BASE_LEVEL, &firstMip);
drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_MAX_LEVEL, &numMips);
numMips = numMips - firstMip + 1;
}
ResourceId id = rm->GetResID(TextureRes(ctx, tex));
ret[dst].resource = rm->GetOriginalID(id);
ret[dst].firstMip = firstMip & 0xff;
ret[dst].numMips = numMips & 0xff;
GLenum levelQueryType =
target == eGL_TEXTURE_CUBE_MAP ? eGL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
GLenum fmt = eGL_NONE;
drv.glGetTexLevelParameteriv(levelQueryType, 0, eGL_TEXTURE_INTERNAL_FORMAT, (GLint *)&fmt);
ret[dst].format = MakeResourceFormat(target, fmt);
if(IsDepthStencilFormat(fmt))
{
GLint depthMode = eGL_DEPTH_COMPONENT;
if(HasExt[ARB_stencil_texturing])
drv.glGetTextureParameterivEXT(tex, target, eGL_DEPTH_STENCIL_TEXTURE_MODE, &depthMode);
ret[dst].format = ResourceFormat();
ret[dst].format.type = ResourceFormatType::Regular;
ret[dst].format.compByteWidth = 1;
ret[dst].format.compCount = 1;
if(depthMode == eGL_DEPTH_COMPONENT)
ret[dst].format.compType = CompType::Depth;
else if(depthMode == eGL_STENCIL_INDEX)
ret[dst].format.compType = CompType::UInt;
}
GLenum swizzles[4] = {eGL_RED, eGL_GREEN, eGL_BLUE, eGL_ALPHA};
if(target != eGL_TEXTURE_BUFFER &&
(HasExt[ARB_texture_swizzle] || HasExt[EXT_texture_swizzle]))
GetTextureSwizzle(tex, target, swizzles);
ret[dst].swizzle.red = MakeSwizzle(swizzles[0]);
ret[dst].swizzle.green = MakeSwizzle(swizzles[1]);
ret[dst].swizzle.blue = MakeSwizzle(swizzles[2]);
ret[dst].swizzle.alpha = MakeSwizzle(swizzles[3]);
GLuint samp = 0;
if(HasExt[ARB_sampler_objects])
drv.glGetIntegerv(eGL_SAMPLER_BINDING, (GLint *)&samp);
ret[dst].secondary = rm->GetOriginalID(rm->GetResID(SamplerRes(ctx, samp)));
}
}
}
return ret;
}
@@ -2149,10 +2387,190 @@ rdcarray<SamplerDescriptor> GLReplay::GetSamplerDescriptors(ResourceId descripto
return ret;
}
MakeCurrentReplayContext(&m_ReplayCtx);
WrappedOpenGL &drv = *m_pDriver;
GLResourceManager *rm = m_pDriver->GetResourceManager();
ContextPair &ctx = drv.GetCtx();
size_t count = 0;
for(const DescriptorRange &r : ranges)
count += r.count;
ret.resize(count);
size_t dst = 0;
for(const DescriptorRange &r : ranges)
{
uint32_t descriptorId = r.offset;
for(uint32_t i = 0; i < r.count; i++, dst++, descriptorId++)
{
GLDescriptorLocation idx = DecodeGLDescriptorIndex(descriptorId);
if(idx.type == GLDescriptorMapping::Invalid || idx.type == GLDescriptorMapping::Images ||
idx.type == GLDescriptorMapping::AtomicCounter ||
idx.type == GLDescriptorMapping::ShaderStorage ||
idx.type == GLDescriptorMapping::UniformBinding)
continue;
drv.glActiveTexture(GLenum(eGL_TEXTURE0 + idx.idx));
GLuint tex = 0;
GLenum target = eGL_NONE;
if(idx.type == GLDescriptorMapping::TexCubeArray && !HasExt[ARB_texture_cube_map_array])
{
tex = 0;
target = eGL_TEXTURE_CUBE_MAP_ARRAY;
}
else
{
switch(idx.type)
{
case GLDescriptorMapping::Tex1D: target = eGL_TEXTURE_1D; break;
case GLDescriptorMapping::Tex2D: target = eGL_TEXTURE_2D; break;
case GLDescriptorMapping::Tex3D: target = eGL_TEXTURE_3D; break;
case GLDescriptorMapping::Tex1DArray: target = eGL_TEXTURE_1D_ARRAY; break;
case GLDescriptorMapping::Tex2DArray: target = eGL_TEXTURE_2D_ARRAY; break;
case GLDescriptorMapping::TexCubeArray: target = eGL_TEXTURE_CUBE_MAP_ARRAY; break;
case GLDescriptorMapping::TexRect: target = eGL_TEXTURE_RECTANGLE; break;
case GLDescriptorMapping::TexBuffer: target = eGL_TEXTURE_BUFFER; break;
case GLDescriptorMapping::TexCube: target = eGL_TEXTURE_CUBE_MAP; break;
case GLDescriptorMapping::Tex2DMS: target = eGL_TEXTURE_2D_MULTISAMPLE; break;
case GLDescriptorMapping::Tex2DMSArray: target = eGL_TEXTURE_2D_MULTISAMPLE_ARRAY; break;
case GLDescriptorMapping::AtomicCounter:
case GLDescriptorMapping::ShaderStorage:
case GLDescriptorMapping::BareUniforms:
case GLDescriptorMapping::UniformBinding:
case GLDescriptorMapping::Images:
case GLDescriptorMapping::Invalid:
case GLDescriptorMapping::Count: target = eGL_NONE; break;
}
}
if(target == eGL_NONE)
continue;
GLenum binding = TextureBinding(target);
GLuint samp = 0;
if(HasExt[ARB_sampler_objects])
drv.glGetIntegerv(eGL_SAMPLER_BINDING, (GLint *)&samp);
drv.glGetIntegerv(binding, (GLint *)&tex);
if(samp == 0 && tex == 0)
continue;
ret[dst].object = rm->GetOriginalID(rm->GetResID(SamplerRes(ctx, samp)));
// GL has separate sampler objects but they don't exist as separate sampler descriptors
ret[dst].type = DescriptorType::ImageSampler;
if(samp != 0)
drv.glGetSamplerParameterfv(samp, eGL_TEXTURE_BORDER_COLOR,
ret[dst].borderColorValue.floatValue.data());
else
drv.glGetTextureParameterfvEXT(tex, target, eGL_TEXTURE_BORDER_COLOR,
ret[dst].borderColorValue.floatValue.data());
ret[dst].borderColorType = CompType::Float;
GLint v;
v = 0;
if(samp != 0)
drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_WRAP_S, &v);
else
drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_WRAP_S, &v);
ret[dst].addressU = MakeAddressMode((GLenum)v);
v = 0;
if(samp != 0)
drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_WRAP_T, &v);
else
drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_WRAP_T, &v);
ret[dst].addressV = MakeAddressMode((GLenum)v);
v = 0;
if(samp != 0)
drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_WRAP_R, &v);
else
drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_WRAP_R, &v);
ret[dst].addressW = MakeAddressMode((GLenum)v);
// GLES 3 is always seamless
if(IsGLES && GLCoreVersion > 30)
{
ret[dst].seamlessCubemaps = true;
}
else if(!IsGLES)
{
// on GLES 2 this is always going to be false, GL has a toggle
ret[dst].seamlessCubemaps = drv.glIsEnabled(eGL_TEXTURE_CUBE_MAP_SEAMLESS) != GL_FALSE;
}
v = 0;
if(samp != 0)
drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_COMPARE_FUNC, &v);
else
drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_COMPARE_FUNC, &v);
ret[dst].compareFunction = MakeCompareFunc((GLenum)v);
GLint minf = 0;
GLint magf = 0;
if(samp != 0)
drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_MIN_FILTER, &minf);
else
drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_MIN_FILTER, &minf);
if(samp != 0)
drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_MAG_FILTER, &magf);
else
drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_MAG_FILTER, &magf);
if(HasExt[ARB_texture_filter_anisotropic])
{
if(samp != 0)
drv.glGetSamplerParameterfv(samp, eGL_TEXTURE_MAX_ANISOTROPY, &ret[dst].maxAnisotropy);
else
drv.glGetTextureParameterfvEXT(tex, target, eGL_TEXTURE_MAX_ANISOTROPY,
&ret[dst].maxAnisotropy);
}
else
{
ret[dst].maxAnisotropy = 0.0f;
}
ret[dst].filter = MakeFilter((GLenum)minf, (GLenum)magf, ret[dst].maxAnisotropy);
v = 0;
if(samp != 0)
drv.glGetSamplerParameteriv(samp, eGL_TEXTURE_COMPARE_MODE, &v);
else
drv.glGetTextureParameterivEXT(tex, target, eGL_TEXTURE_COMPARE_MODE, &v);
ret[dst].filter.filter = (GLenum)v == eGL_COMPARE_REF_TO_TEXTURE ? FilterFunction::Comparison
: FilterFunction::Normal;
if(samp != 0)
drv.glGetSamplerParameterfv(samp, eGL_TEXTURE_MAX_LOD, &ret[dst].maxLOD);
else
drv.glGetTextureParameterfvEXT(tex, target, eGL_TEXTURE_MAX_LOD, &ret[dst].maxLOD);
if(samp != 0)
drv.glGetSamplerParameterfv(samp, eGL_TEXTURE_MIN_LOD, &ret[dst].minLOD);
else
drv.glGetTextureParameterfvEXT(tex, target, eGL_TEXTURE_MIN_LOD, &ret[dst].minLOD);
if(!IsGLES)
{
if(samp != 0)
drv.glGetSamplerParameterfv(samp, eGL_TEXTURE_LOD_BIAS, &ret[dst].mipBias);
else
drv.glGetTextureParameterfvEXT(tex, target, eGL_TEXTURE_LOD_BIAS, &ret[dst].mipBias);
}
}
}
return ret;
}
+3 -3
View File
@@ -2052,9 +2052,9 @@ GLint CubeTargetIndex(GLenum face)
return 0;
}
GLenum TextureTarget(GLenum target)
GLenum TextureTarget(GLenum binding)
{
switch(target)
switch(binding)
{
case eGL_TEXTURE_BINDING_1D: return eGL_TEXTURE_1D;
case eGL_TEXTURE_BINDING_1D_ARRAY: return eGL_TEXTURE_1D_ARRAY;
@@ -2076,7 +2076,7 @@ GLenum TextureTarget(GLenum target)
default: break;
}
return target;
return binding;
}
bool IsProxyTarget(GLenum target)
+1 -1
View File
@@ -61,7 +61,7 @@ GLenum GetViewCastedFormat(GLenum internalFormat, CompType typeCast);
bool IsCubeFace(GLenum target);
GLint CubeTargetIndex(GLenum face);
GLenum TextureBinding(GLenum target);
GLenum TextureTarget(GLenum target);
GLenum TextureTarget(GLenum binding);
bool IsProxyTarget(GLenum target);
GLenum BufferBinding(GLenum target);
+10 -2
View File
@@ -1435,6 +1435,10 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::State &el)
SERIALISE_MEMBER(pixelShader);
SERIALISE_MEMBER(computeShader);
SERIALISE_MEMBER(descriptorStore);
SERIALISE_MEMBER(descriptorCount);
SERIALISE_MEMBER(descriptorByteSize);
SERIALISE_MEMBER(streamOut);
SERIALISE_MEMBER(rasterizer);
@@ -1442,7 +1446,7 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::State &el)
SERIALISE_MEMBER(predication);
SIZE_CHECK(2088);
SIZE_CHECK(2104);
}
#pragma endregion D3D11 pipeline state
@@ -2026,6 +2030,10 @@ void DoSerialise(SerialiserType &ser, GLPipe::State &el)
SERIALISE_MEMBER(shaderStorageBuffers);
SERIALISE_MEMBER(images);
SERIALISE_MEMBER(descriptorStore);
SERIALISE_MEMBER(descriptorCount);
SERIALISE_MEMBER(descriptorByteSize);
SERIALISE_MEMBER(transformFeedback);
SERIALISE_MEMBER(rasterizer);
@@ -2036,7 +2044,7 @@ void DoSerialise(SerialiserType &ser, GLPipe::State &el)
SERIALISE_MEMBER(hints);
SIZE_CHECK(1952);
SIZE_CHECK(1968);
}
#pragma endregion OpenGL pipeline state