diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index 4d537bf9c..52d4a2962 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -74,6 +74,20 @@ enum ShaderResourceType eResType_TextureCubeArray, }; +enum ShaderBindType +{ + eBindType_Unknown = 0, + eBindType_Sampler, + eBindType_ImageSampler, + eBindType_ReadOnlyImage, + eBindType_ReadWriteImage, + eBindType_ReadOnlyTBuffer, + eBindType_ReadWriteTBuffer, + eBindType_ReadOnlyBuffer, + eBindType_ReadWriteBuffer, + eBindType_InputAttachment, +}; + enum SystemAttribute { eAttr_None = 0, @@ -284,6 +298,19 @@ enum ShaderStageType eShaderStage_Compute, }; +enum ShaderStageBits +{ + eStageBits_Vertex = 1< elems; + }; + rdctype::array bindings; + }; + + rdctype::array DescSets; } compute, graphics; // VKTODOMED renderpass/subpass? @@ -47,7 +74,6 @@ struct VulkanPipelineState IndexBuffer() : offs(0) {} ResourceId buf; uint64_t offs; - // byte width is latched per-draw for GL } ibuffer; } IA; @@ -66,7 +92,7 @@ struct VulkanPipelineState struct Binding { Binding() : vbufferBinding(0), bytestride(0), perInstance(false) {} - uint32_t vbufferBinding; // VKTODO I believe this is the meaning + uint32_t vbufferBinding; // VKTODOLOW I believe this is the meaning uint32_t bytestride; bool32 perInstance; }; @@ -88,7 +114,10 @@ struct VulkanPipelineState rdctype::str ShaderName; bool32 customName; ShaderReflection *ShaderDetails; - // VKTODOMED this might no longer make sense + + // this is no longer dynamic, like GL, but it's also not trivial, like D3D11. + // this contains the mapping between the shader objects in the reflection data + // and the descriptor set and binding that they use ShaderBindpointMapping BindpointMapping; ShaderStageType stage; @@ -96,8 +125,6 @@ struct VulkanPipelineState // VKTODOMED specialization info } VS, TCS, TES, GS, FS, CS; - // VKTODOHIGH descriptor sets - struct Tessellation { Tessellation() : numControlPoints(0) { } diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index 3423cf175..cd0488dcb 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -109,10 +109,11 @@ void Serialiser::Serialise(const char *name, ResourceFormat &el) template<> void Serialiser::Serialise(const char *name, BindpointMap &el) { + Serialise("", el.bindset); Serialise("", el.bind); Serialise("", el.used); - SIZE_CHECK(BindpointMap, 8); + SIZE_CHECK(BindpointMap, 12); } template<> diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index 499f60be6..1ae6af0d0 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -528,6 +528,7 @@ D3D11PipelineState D3D11Replay::MakePipelineState() create_array_uninit(dst.BindpointMapping.ConstantBlocks, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); for(int s=0; s < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; s++) { + dst.BindpointMapping.ConstantBlocks[s].bindset = 0; dst.BindpointMapping.ConstantBlocks[s].bind = s; dst.BindpointMapping.ConstantBlocks[s].used = true; } @@ -535,6 +536,7 @@ D3D11PipelineState D3D11Replay::MakePipelineState() create_array_uninit(dst.BindpointMapping.Resources, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT); for(int32_t s=0; s < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; s++) { + dst.BindpointMapping.Resources[s].bindset = 0; dst.BindpointMapping.Resources[s].bind = s; dst.BindpointMapping.Resources[s].used = true; } diff --git a/renderdoc/driver/gl/gl_shader_refl.cpp b/renderdoc/driver/gl/gl_shader_refl.cpp index 3e996cdf5..700873be3 100644 --- a/renderdoc/driver/gl/gl_shader_refl.cpp +++ b/renderdoc/driver/gl/gl_shader_refl.cpp @@ -1808,6 +1808,7 @@ void GetBindpointMapping(const GLHookSet &gl, GLuint curProg, int shadIdx, Shade if(loc >= 0) { gl.glGetUniformiv(curProg, loc, dummyReadback); + mapping.Resources[i].bindset = 0; mapping.Resources[i].bind = dummyReadback[0]; } @@ -1847,6 +1848,7 @@ void GetBindpointMapping(const GLHookSet &gl, GLuint curProg, int shadIdx, Shade if(idx == GL_INVALID_INDEX) { + mapping.Resources[i].bindset = -1; mapping.Resources[i].bind = -1; mapping.Resources[i].used = false; } @@ -1858,6 +1860,7 @@ void GetBindpointMapping(const GLHookSet &gl, GLuint curProg, int shadIdx, Shade if(atomicIndex == GL_INVALID_INDEX) { + mapping.Resources[i].bindset = -1; mapping.Resources[i].bind = -1; mapping.Resources[i].used = false; } @@ -1871,6 +1874,7 @@ void GetBindpointMapping(const GLHookSet &gl, GLuint curProg, int shadIdx, Shade eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER, eGL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER, }; + mapping.Resources[i].bindset = 0; gl.glGetActiveAtomicCounterBufferiv(curProg, atomicIndex, eGL_ATOMIC_COUNTER_BUFFER_BINDING, &mapping.Resources[i].bind); GLint used = 0; gl.glGetActiveAtomicCounterBufferiv(curProg, atomicIndex, atomicRefEnum[shadIdx], &used); @@ -1885,12 +1889,14 @@ void GetBindpointMapping(const GLHookSet &gl, GLuint curProg, int shadIdx, Shade if(idx == GL_INVALID_INDEX) { + mapping.Resources[i].bindset = -1; mapping.Resources[i].bind = -1; mapping.Resources[i].used = false; } else { GLenum prop = eGL_BUFFER_BINDING; + mapping.Resources[i].bindset = 0; gl.glGetProgramResourceiv(curProg, eGL_SHADER_STORAGE_BLOCK, idx, 1, &prop, 1, NULL, &mapping.Resources[i].bind); GLint used = 0; gl.glGetProgramResourceiv(curProg, eGL_SHADER_STORAGE_BLOCK, idx, 1, &refEnum[shadIdx], 1, NULL, &used); @@ -1916,11 +1922,13 @@ void GetBindpointMapping(const GLHookSet &gl, GLuint curProg, int shadIdx, Shade if(loc >= 0) { gl.glGetActiveUniformBlockiv(curProg, loc, eGL_UNIFORM_BLOCK_BINDING, dummyReadback); + mapping.ConstantBlocks[i].bindset = 0; mapping.ConstantBlocks[i].bind = dummyReadback[0]; } } else { + mapping.ConstantBlocks[i].bindset = -1; mapping.ConstantBlocks[i].bind = -1; } diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 5ae68ebcd..23bbfee1c 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -1442,6 +1442,8 @@ void VulkanReplay::SavePipelineState() const WrappedVulkan::PartialReplayData::StateVector &state = m_pDriver->m_PartialReplayData.state; VulkanCreationInfo &c = m_pDriver->m_CreationInfo; + VulkanResourceManager *rm = m_pDriver->GetResourceManager(); + m_VulkanPipelineState = VulkanPipelineState(); // General pipeline properties @@ -1506,6 +1508,76 @@ void VulkanReplay::SavePipelineState() stages[i]->stage = ShaderStageType(eShaderStage_Vertex + i); } + // Descriptor sets + create_array_uninit(m_VulkanPipelineState.graphics.DescSets, state.graphics.descSets.size()); + create_array_uninit(m_VulkanPipelineState.compute.DescSets, state.compute.descSets.size()); + + { + rdctype::array *dsts[] = { + &m_VulkanPipelineState.graphics.DescSets, + &m_VulkanPipelineState.compute.DescSets, + }; + + const vector *srcs[] = { + &state.graphics.descSets, + &state.compute.descSets, + }; + + for(size_t p=0; p < ARRAY_COUNT(srcs); p++) + { + for(size_t i=0; i < srcs[p]->size(); i++) + { + ResourceId src = (*srcs[p])[i]; + VulkanPipelineState::Pipeline::DescriptorSet &dst = (*dsts[p])[i]; + + dst.layout = m_pDriver->m_DescriptorSetInfo[src].layout; + create_array_uninit(dst.bindings, m_pDriver->m_DescriptorSetInfo[src].currentBindings.size()); + for(size_t b=0; b < m_pDriver->m_DescriptorSetInfo[src].currentBindings.size(); b++) + { + VkDescriptorInfo *info = m_pDriver->m_DescriptorSetInfo[src].currentBindings[b]; + const VulkanCreationInfo::DescSetLayout::Binding &layoutBind = c.m_DescSetLayout[dst.layout].bindings[b]; + + dst.bindings[b].arraySize = layoutBind.arraySize; + dst.bindings[b].stageFlags = (ShaderStageBits)layoutBind.stageFlags; + switch(layoutBind.descriptorType) + { + case VK_DESCRIPTOR_TYPE_SAMPLER: dst.bindings[b].type = eBindType_Sampler; break; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: dst.bindings[b].type = eBindType_ImageSampler; break; + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: dst.bindings[b].type = eBindType_ReadOnlyImage; break; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: dst.bindings[b].type = eBindType_ReadWriteImage; break; + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: dst.bindings[b].type = eBindType_ReadOnlyTBuffer; break; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: dst.bindings[b].type = eBindType_ReadWriteTBuffer; break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: dst.bindings[b].type = eBindType_ReadOnlyBuffer; break; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: dst.bindings[b].type = eBindType_ReadWriteBuffer; break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: dst.bindings[b].type = eBindType_ReadOnlyBuffer; break; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: dst.bindings[b].type = eBindType_ReadWriteBuffer; break; + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: dst.bindings[b].type = eBindType_InputAttachment; break; + default: + dst.bindings[b].type = eBindType_Unknown; + RDCERR("Unexpected descriptor type"); + } + + create_array_uninit(dst.bindings[b].elems, layoutBind.arraySize); + for(uint32_t a=0; a < layoutBind.arraySize; a++) + { + if(layoutBind.immutableSampler) + dst.bindings[b].elems[a].sampler = layoutBind.immutableSampler[a]; + else if(info->sampler != VK_NULL_HANDLE) + dst.bindings[b].elems[a].sampler = rm->GetOriginalID(rm->GetID(MakeRes(info->sampler))); + + // only one of these is ever set + if(info->imageView != VK_NULL_HANDLE) + dst.bindings[b].elems[a].view = rm->GetOriginalID(rm->GetID(MakeRes(info->imageView))); + if(info->bufferView != VK_NULL_HANDLE) + dst.bindings[b].elems[a].view = rm->GetOriginalID(rm->GetID(MakeRes(info->bufferView))); + if(info->attachmentView != VK_NULL_HANDLE) + dst.bindings[b].elems[a].view = rm->GetOriginalID(rm->GetID(MakeRes(info->attachmentView))); + } + } + } + } + } + // Tessellation m_VulkanPipelineState.Tess.numControlPoints = p.patchControlPoints;