diff --git a/renderdoc/api/replay/shader_types.h b/renderdoc/api/replay/shader_types.h index eb94ad47e..58eca0625 100644 --- a/renderdoc/api/replay/shader_types.h +++ b/renderdoc/api/replay/shader_types.h @@ -181,7 +181,6 @@ struct ShaderResource bool32 IsSampler; bool32 IsTexture; bool32 IsSRV; - bool32 IsReadWrite; ShaderResourceType resType; @@ -215,7 +214,8 @@ struct ShaderReflection rdctype::array ConstantBlocks; // sparse - index indicates bind point - rdctype::array Resources; // non-sparse, since bind points can overlap. + rdctype::array ReadOnlyResources; // non-sparse, since bind points can overlap. + rdctype::array ReadWriteResources; // non-sparse, since bind points can overlap. // TODO expand this to encompass shader subroutines. rdctype::array Interfaces; @@ -233,5 +233,6 @@ struct ShaderBindpointMapping { rdctype::array InputAttributes; rdctype::array ConstantBlocks; - rdctype::array Resources; + rdctype::array ReadOnlyResources; + rdctype::array ReadWriteResources; }; diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index 6df1b90cb..e19f670ef 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -122,9 +122,10 @@ void Serialiser::Serialise(const char *name, ShaderBindpointMapping &el) { Serialise("", el.InputAttributes); Serialise("", el.ConstantBlocks); - Serialise("", el.Resources); + Serialise("", el.ReadOnlyResources); + Serialise("", el.ReadWriteResources); - SIZE_CHECK(ShaderBindpointMapping, 24); + SIZE_CHECK(ShaderBindpointMapping, 32); } template<> @@ -188,13 +189,12 @@ void Serialiser::Serialise(const char *name, ShaderResource &el) Serialise("", el.IsSampler); Serialise("", el.IsTexture); Serialise("", el.IsSRV); - Serialise("", el.IsReadWrite); Serialise("", el.resType); Serialise("", el.name); Serialise("", el.variableType); Serialise("", el.bindPoint); - SIZE_CHECK(ShaderResource, 68); + SIZE_CHECK(ShaderResource, 64); } template<> @@ -213,11 +213,12 @@ void Serialiser::Serialise(const char *name, ShaderReflection &el) Serialise("", el.ConstantBlocks); - Serialise("", el.Resources); + Serialise("", el.ReadOnlyResources); + Serialise("", el.ReadWriteResources); Serialise("", el.Interfaces); - SIZE_CHECK(ShaderReflection, 84); + SIZE_CHECK(ShaderReflection, 92); } template<> @@ -368,7 +369,7 @@ void Serialiser::Serialise(const char *name, D3D11PipelineState::ShaderStage &el Serialise("", el.ConstantBuffers); Serialise("", el.ClassInstances); - SIZE_CHECK(D3D11PipelineState::ShaderStage, 96); + SIZE_CHECK(D3D11PipelineState::ShaderStage, 104); } template<> @@ -463,7 +464,7 @@ void Serialiser::Serialise(const char *name, D3D11PipelineState &el) Serialise("", el.m_RS); Serialise("", el.m_OM); - SIZE_CHECK(D3D11PipelineState, 1000); + SIZE_CHECK(D3D11PipelineState, 1040); } #pragma endregion D3D11 pipeline state @@ -506,7 +507,7 @@ void Serialiser::Serialise(const char *name, GLPipelineState::ShaderStage &el) if(m_Mode == READING) el.ShaderDetails = NULL; - SIZE_CHECK(GLPipelineState::ShaderStage, 48); + SIZE_CHECK(GLPipelineState::ShaderStage, 56); } template<> @@ -686,7 +687,7 @@ void Serialiser::Serialise(const char *name, GLPipelineState &el) Serialise("", el.m_Hints); - SIZE_CHECK(GLPipelineState, 984); + SIZE_CHECK(GLPipelineState, 1032); } #pragma endregion OpenGL pipeline state @@ -761,7 +762,7 @@ void Serialiser::Serialise(const char *name, VulkanPipelineState::ShaderStage &e if(m_Mode == READING) el.ShaderDetails = NULL; - SIZE_CHECK(VulkanPipelineState::ShaderStage, 56); + SIZE_CHECK(VulkanPipelineState::ShaderStage, 64); } template<> @@ -881,7 +882,7 @@ void Serialiser::Serialise(const char *name, VulkanPipelineState &el) Serialise("", el.DS); Serialise("", el.Pass); - SIZE_CHECK(VulkanPipelineState, 744); + SIZE_CHECK(VulkanPipelineState, 792); } #pragma endregion Vulkan pipeline state diff --git a/renderdoc/driver/d3d11/d3d11_common.cpp b/renderdoc/driver/d3d11/d3d11_common.cpp index 48e21050a..afbe464d2 100644 --- a/renderdoc/driver/d3d11/d3d11_common.cpp +++ b/renderdoc/driver/d3d11/d3d11_common.cpp @@ -974,13 +974,33 @@ ShaderReflection *MakeShaderReflection(DXBC::DXBCFile *dxbc) } } - int numResources = 0; - for(size_t i=0; i < dxbc->m_Resources.size(); i++) - if(dxbc->m_Resources[i].type != DXBC::ShaderInputBind::TYPE_CBUFFER) - numResources++; + int numRWResources = 0; + int numROResources = 0; - create_array_uninit(ret->Resources, numResources); - int32_t idx=0; + for(size_t i=0; i < dxbc->m_Resources.size(); i++) + { + const auto &r = dxbc->m_Resources[i]; + + if(r.type != DXBC::ShaderInputBind::TYPE_CBUFFER) + { + bool IsReadWrite = (r.type == DXBC::ShaderInputBind::TYPE_UAV_RWTYPED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWBYTEADDRESS || + r.type == DXBC::ShaderInputBind::TYPE_UAV_APPEND_STRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_CONSUME_STRUCTURED || + r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED_WITH_COUNTER); + + if(IsReadWrite) + numRWResources++; + else + numROResources++; + } + } + + create_array_uninit(ret->ReadWriteResources, numRWResources); + create_array_uninit(ret->ReadOnlyResources, numROResources); + + int32_t rwidx = 0, roidx = 0; for(size_t i=0; i < dxbc->m_Resources.size(); i++) { const auto &r = dxbc->m_Resources[i]; @@ -1001,7 +1021,7 @@ ShaderReflection *MakeShaderReflection(DXBC::DXBCFile *dxbc) r.type == DXBC::ShaderInputBind::TYPE_TEXTURE || r.type == DXBC::ShaderInputBind::TYPE_STRUCTURED || r.type == DXBC::ShaderInputBind::TYPE_BYTEADDRESS); - res.IsReadWrite = (r.type == DXBC::ShaderInputBind::TYPE_UAV_RWTYPED || + bool IsReadWrite = (r.type == DXBC::ShaderInputBind::TYPE_UAV_RWTYPED || r.type == DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED || r.type == DXBC::ShaderInputBind::TYPE_UAV_RWBYTEADDRESS || r.type == DXBC::ShaderInputBind::TYPE_UAV_APPEND_STRUCTURED || @@ -1088,7 +1108,10 @@ ShaderReflection *MakeShaderReflection(DXBC::DXBCFile *dxbc) } } - ret->Resources[idx++] = res; + if(IsReadWrite) + ret->ReadWriteResources[rwidx++] = res; + else + ret->ReadOnlyResources[roidx++] = res; } uint32_t numInterfaces = 0; diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index 58a8ad9b9..4fd2c288d 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -534,13 +534,22 @@ D3D11PipelineState D3D11Replay::MakePipelineState() dst.BindpointMapping.ConstantBlocks[i].arraySize = 1; } - create_array_uninit(dst.BindpointMapping.Resources, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT); + create_array_uninit(dst.BindpointMapping.ReadOnlyResources, 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; - dst.BindpointMapping.Resources[i].arraySize = 1; + dst.BindpointMapping.ReadOnlyResources[s].bindset = 0; + dst.BindpointMapping.ReadOnlyResources[s].bind = s; + dst.BindpointMapping.ReadOnlyResources[s].used = true; + dst.BindpointMapping.ReadOnlyResources[i].arraySize = 1; + } + + create_array_uninit(dst.BindpointMapping.ReadWriteResources, D3D11_1_UAV_SLOT_COUNT); + for(int32_t s=0; s < D3D11_1_UAV_SLOT_COUNT; s++) + { + dst.BindpointMapping.ReadWriteResources[s].bindset = 0; + dst.BindpointMapping.ReadWriteResources[s].bind = s; + dst.BindpointMapping.ReadWriteResources[s].used = true; + dst.BindpointMapping.ReadWriteResources[i].arraySize = 1; } create_array_uninit(dst.ConstantBuffers, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 7b8a00f2b..1b0bbdd52 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -4173,39 +4173,40 @@ void WrappedOpenGL::AddUsage(FetchDrawcall d) m_ResourceUses[rm->GetID(BufferRes(ctx, rs.UniformBinding[bind].name))].push_back(cb); } - for(int32_t r=0; r < refl[i]->Resources.count; r++) + for(int32_t r=0; r < refl[i]->ReadWriteResources.count; r++) { - int32_t bind = mapping[i].Resources[ refl[i]->Resources[r].bindPoint ].bind; + int32_t bind = mapping[i].ReadWriteResources[ refl[i]->ReadWriteResources[r].bindPoint ].bind; - if(refl[i]->Resources[r].IsReadWrite) + if(refl[i]->ReadWriteResources[r].IsTexture) { - if(refl[i]->Resources[r].IsTexture) + if(rs.Images[bind].name) + m_ResourceUses[rm->GetID(TextureRes(ctx, rs.Images[bind].name))].push_back(rw); + } + else + { + if(refl[i]->ReadWriteResources[r].variableType.descriptor.cols == 1 && + refl[i]->ReadWriteResources[r].variableType.descriptor.rows == 1 && + refl[i]->ReadWriteResources[r].variableType.descriptor.type == eVar_UInt) { - if(rs.Images[bind].name) - m_ResourceUses[rm->GetID(TextureRes(ctx, rs.UniformBinding[bind].name))].push_back(rw); + if(rs.AtomicCounter[bind].name) + m_ResourceUses[rm->GetID(BufferRes(ctx, rs.AtomicCounter[bind].name))].push_back(rw); } else { - if(refl[i]->Resources[r].variableType.descriptor.cols == 1 && - refl[i]->Resources[r].variableType.descriptor.rows == 1 && - refl[i]->Resources[r].variableType.descriptor.type == eVar_UInt) - { - if(rs.AtomicCounter[bind].name) - m_ResourceUses[rm->GetID(BufferRes(ctx, rs.AtomicCounter[bind].name))].push_back(rw); - } - else - { - if(rs.ShaderStorage[bind].name) - m_ResourceUses[rm->GetID(BufferRes(ctx, rs.ShaderStorage[bind].name))].push_back(rw); - } + if(rs.ShaderStorage[bind].name) + m_ResourceUses[rm->GetID(BufferRes(ctx, rs.ShaderStorage[bind].name))].push_back(rw); } - continue; } + } + + for(int32_t r=0; r < refl[i]->ReadOnlyResources.count; r++) + { + int32_t bind = mapping[i].ReadOnlyResources[ refl[i]->ReadOnlyResources[r].bindPoint ].bind; uint32_t *texList = NULL; int32_t listSize = 0; - switch(refl[i]->Resources[r].resType) + switch(refl[i]->ReadOnlyResources[r].resType) { case eResType_None: texList = NULL; diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 3514a446f..f1bc01229 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -1021,7 +1021,8 @@ void GLReplay::SavePipelineState() stages[i]->Shader = ResourceId(); stages[i]->ShaderDetails = NULL; stages[i]->BindpointMapping.ConstantBlocks.Delete(); - stages[i]->BindpointMapping.Resources.Delete(); + stages[i]->BindpointMapping.ReadOnlyResources.Delete(); + stages[i]->BindpointMapping.ReadWriteResources.Delete(); } if(curProg == 0) @@ -1142,19 +1143,17 @@ void GLReplay::SavePipelineState() { if(refls[s] == NULL) continue; - for(int32_t r=0; r < refls[s]->Resources.count; r++) + for(int32_t r=0; r < refls[s]->ReadOnlyResources.count; r++) { - if(refls[s]->Resources[r].IsReadWrite) continue; - // bindPoint is the uniform value for this sampler - if(mappings[s]->Resources[ refls[s]->Resources[r].bindPoint ].bind == unit) + if(mappings[s]->ReadOnlyResources[ refls[s]->ReadOnlyResources[r].bindPoint ].bind == unit) { GLenum t = eGL_NONE; - if(strstr(refls[s]->Resources[r].variableType.descriptor.name.elems, "Shadow")) + if(strstr(refls[s]->ReadOnlyResources[r].variableType.descriptor.name.elems, "Shadow")) shadow = true; - switch(refls[s]->Resources[r].resType) + switch(refls[s]->ReadOnlyResources[r].resType) { case eResType_None: target = eGL_NONE; @@ -1197,7 +1196,7 @@ void GLReplay::SavePipelineState() if(target != eGL_NONE) t = TextureBinding(target); - resType = refls[s]->Resources[r].resType; + resType = refls[s]->ReadOnlyResources[r].resType; if(binding == eGL_NONE) { diff --git a/renderdoc/driver/gl/gl_shader_refl.cpp b/renderdoc/driver/gl/gl_shader_refl.cpp index 003e5a1d4..94aa905a4 100644 --- a/renderdoc/driver/gl/gl_shader_refl.cpp +++ b/renderdoc/driver/gl/gl_shader_refl.cpp @@ -783,7 +783,7 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, RDCEraseEl(refl.DispatchThreadsDimension); } - vector resources; + vector roresources, rwresources; GLint numUniforms = 0; gl.glGetProgramInterfaceiv(sepProg, eGL_UNIFORM, eGL_ACTIVE_RESOURCES, &numUniforms); @@ -798,17 +798,17 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, { GLint values[numProps]; gl.glGetProgramResourceiv(sepProg, eGL_UNIFORM, u, numProps, resProps, numProps, NULL, values); + + bool IsReadWrite = false; ShaderResource res; res.IsSampler = false; // no separate sampler objects in GL res.IsSRV = true; res.IsTexture = true; - res.IsReadWrite = false; res.variableType.descriptor.rows = 1; res.variableType.descriptor.cols = 4; res.variableType.descriptor.elements = 0; res.variableType.descriptor.rowMajorStorage = false; - res.bindPoint = (int32_t)resources.size(); // float samplers if(values[0] == eGL_SAMPLER_BUFFER) @@ -1053,88 +1053,88 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, res.resType = eResType_Buffer; res.variableType.descriptor.name = "imageBuffer"; res.variableType.descriptor.type = eVar_Float; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_IMAGE_1D) { res.resType = eResType_Texture1D; res.variableType.descriptor.name = "image1D"; res.variableType.descriptor.type = eVar_Float; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_IMAGE_1D_ARRAY) { res.resType = eResType_Texture1DArray; res.variableType.descriptor.name = "image1DArray"; res.variableType.descriptor.type = eVar_Float; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_IMAGE_2D) { res.resType = eResType_Texture2D; res.variableType.descriptor.name = "image2D"; res.variableType.descriptor.type = eVar_Float; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_IMAGE_2D_ARRAY) { res.resType = eResType_Texture2DArray; res.variableType.descriptor.name = "image2DArray"; res.variableType.descriptor.type = eVar_Float; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_IMAGE_2D_RECT) { res.resType = eResType_TextureRect; res.variableType.descriptor.name = "image2DRect"; res.variableType.descriptor.type = eVar_Float; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_IMAGE_3D) { res.resType = eResType_Texture3D; res.variableType.descriptor.name = "image3D"; res.variableType.descriptor.type = eVar_Float; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_IMAGE_CUBE) { res.resType = eResType_TextureCube; res.variableType.descriptor.name = "imageCube"; res.variableType.descriptor.type = eVar_Float; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_IMAGE_CUBE_MAP_ARRAY) { res.resType = eResType_TextureCubeArray; res.variableType.descriptor.name = "imageCubeArray"; res.variableType.descriptor.type = eVar_Float; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_IMAGE_2D_MULTISAMPLE) { res.resType = eResType_Texture2DMS; res.variableType.descriptor.name = "image2DMS"; res.variableType.descriptor.type = eVar_Float; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_IMAGE_2D_MULTISAMPLE_ARRAY) { res.resType = eResType_Texture2DMSArray; res.variableType.descriptor.name = "image2DMSArray"; res.variableType.descriptor.type = eVar_Float; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } // int images else if(values[0] == eGL_INT_IMAGE_BUFFER) @@ -1142,88 +1142,88 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, res.resType = eResType_Buffer; res.variableType.descriptor.name = "iimageBuffer"; res.variableType.descriptor.type = eVar_Int; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_INT_IMAGE_1D) { res.resType = eResType_Texture1D; res.variableType.descriptor.name = "iimage1D"; res.variableType.descriptor.type = eVar_Int; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_INT_IMAGE_1D_ARRAY) { res.resType = eResType_Texture1DArray; res.variableType.descriptor.name = "iimage1DArray"; res.variableType.descriptor.type = eVar_Int; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_INT_IMAGE_2D) { res.resType = eResType_Texture2D; res.variableType.descriptor.name = "iimage2D"; res.variableType.descriptor.type = eVar_Int; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_INT_IMAGE_2D_ARRAY) { res.resType = eResType_Texture2DArray; res.variableType.descriptor.name = "iimage2DArray"; res.variableType.descriptor.type = eVar_Int; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_INT_IMAGE_2D_RECT) { res.resType = eResType_TextureRect; res.variableType.descriptor.name = "iimage2DRect"; res.variableType.descriptor.type = eVar_Int; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_INT_IMAGE_3D) { res.resType = eResType_Texture3D; res.variableType.descriptor.name = "iimage3D"; res.variableType.descriptor.type = eVar_Int; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_INT_IMAGE_CUBE) { res.resType = eResType_TextureCube; res.variableType.descriptor.name = "iimageCube"; res.variableType.descriptor.type = eVar_Int; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_INT_IMAGE_CUBE_MAP_ARRAY) { res.resType = eResType_TextureCubeArray; res.variableType.descriptor.name = "iimageCubeArray"; res.variableType.descriptor.type = eVar_Int; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_INT_IMAGE_2D_MULTISAMPLE) { res.resType = eResType_Texture2DMS; res.variableType.descriptor.name = "iimage2DMS"; res.variableType.descriptor.type = eVar_Int; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_INT_IMAGE_2D_MULTISAMPLE_ARRAY) { res.resType = eResType_Texture2DMSArray; res.variableType.descriptor.name = "iimage2DMSArray"; res.variableType.descriptor.type = eVar_Int; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } // unsigned int images else if(values[0] == eGL_UNSIGNED_INT_IMAGE_BUFFER) @@ -1231,88 +1231,88 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, res.resType = eResType_Buffer; res.variableType.descriptor.name = "uimageBuffer"; res.variableType.descriptor.type = eVar_UInt; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_UNSIGNED_INT_IMAGE_1D) { res.resType = eResType_Texture1D; res.variableType.descriptor.name = "uimage1D"; res.variableType.descriptor.type = eVar_UInt; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_UNSIGNED_INT_IMAGE_1D_ARRAY) { res.resType = eResType_Texture1DArray; res.variableType.descriptor.name = "uimage1DArray"; res.variableType.descriptor.type = eVar_UInt; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_UNSIGNED_INT_IMAGE_2D) { res.resType = eResType_Texture2D; res.variableType.descriptor.name = "uimage2D"; res.variableType.descriptor.type = eVar_UInt; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_UNSIGNED_INT_IMAGE_2D_ARRAY) { res.resType = eResType_Texture2DArray; res.variableType.descriptor.name = "uimage2DArray"; res.variableType.descriptor.type = eVar_UInt; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_UNSIGNED_INT_IMAGE_2D_RECT) { res.resType = eResType_TextureRect; res.variableType.descriptor.name = "uimage2DRect"; res.variableType.descriptor.type = eVar_UInt; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_UNSIGNED_INT_IMAGE_3D) { res.resType = eResType_Texture3D; res.variableType.descriptor.name = "uimage3D"; res.variableType.descriptor.type = eVar_UInt; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_UNSIGNED_INT_IMAGE_CUBE) { res.resType = eResType_TextureCube; res.variableType.descriptor.name = "uimageCube"; res.variableType.descriptor.type = eVar_UInt; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY) { res.resType = eResType_TextureCubeArray; res.variableType.descriptor.name = "uimageCubeArray"; res.variableType.descriptor.type = eVar_UInt; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE) { res.resType = eResType_Texture2DMS; res.variableType.descriptor.name = "uimage2DMS"; res.variableType.descriptor.type = eVar_UInt; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } else if(values[0] == eGL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY) { res.resType = eResType_Texture2DMSArray; res.variableType.descriptor.name = "uimage2DMSArray"; res.variableType.descriptor.type = eVar_UInt; - res.IsReadWrite = true; res.IsSRV = false; + IsReadWrite = true; } // atomic counter else if(values[0] == eGL_UNSIGNED_INT_ATOMIC_COUNTER) @@ -1320,10 +1320,10 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, res.resType = eResType_Buffer; res.variableType.descriptor.name = "atomic_uint"; res.variableType.descriptor.type = eVar_UInt; - res.IsReadWrite = true; res.IsSRV = false; res.IsTexture = false; res.variableType.descriptor.cols = 1; + IsReadWrite = true; } else { @@ -1339,7 +1339,10 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, res.name = name; - resources.push_back(res); + vector &reslist = (IsReadWrite ? rwresources : roresources); + + res.bindPoint = (int32_t)reslist.size(); + reslist.push_back(res); // array of samplers if(values[4] > 1) @@ -1349,10 +1352,10 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, { string arrname = StringFormat::Fmt("%s[%d]", name.c_str(), i); - res.bindPoint = (int32_t)resources.size(); + res.bindPoint = (int32_t)reslist.size(); res.name = arrname; - resources.push_back(res); + reslist.push_back(res); } } } @@ -1377,7 +1380,6 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, res.IsSampler = false; res.IsSRV = false; res.IsTexture = false; - res.IsReadWrite = true; res.resType = eResType_Buffer; res.variableType.descriptor.rows = 0; res.variableType.descriptor.cols = 0; @@ -1385,13 +1387,13 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, res.variableType.descriptor.rowMajorStorage = false; res.variableType.descriptor.name = "buffer"; res.variableType.descriptor.type = eVar_UInt; - res.bindPoint = (int32_t)resources.size(); + res.bindPoint = (int32_t)rwresources.size(); res.name = nm; propName = eGL_NUM_ACTIVE_VARIABLES; gl.glGetProgramResourceiv(sepProg, eGL_SHADER_STORAGE_BLOCK, u, 1, &propName, 1, NULL, (GLint *)&res.variableType.descriptor.elements); - resources.push_back(res); + rwresources.push_back(res); ssbos.push_back(res.bindPoint); ssboMembers += res.variableType.descriptor.elements; @@ -1410,7 +1412,7 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, for(size_t ssbo=0; ssbo < ssbos.size(); ssbo++) { sort(members[ssbo]); - copy(resources[ ssbos[ssbo] ].variableType.members, members[ssbo]); + copy(rwresources[ ssbos[ssbo] ].variableType.members, members[ssbo]); } delete[] members; @@ -1772,7 +1774,8 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg, // TODO: fill in Interfaces with shader subroutines? - refl.Resources = resources; + refl.ReadOnlyResources = roresources; + refl.ReadWriteResources = rwresources; refl.ConstantBlocks = cbuffers; } @@ -1795,26 +1798,26 @@ void GetBindpointMapping(const GLHookSet &gl, GLuint curProg, int shadIdx, Shade eGL_REFERENCED_BY_COMPUTE_SHADER, }; - int32_t numResources = refl ? refl->Resources.count : 0; + int32_t numResources = refl ? refl->ReadOnlyResources.count : 0; - create_array_uninit(mapping.Resources, numResources); + create_array_uninit(mapping.ReadOnlyResources, numResources); for(int32_t i=0; i < numResources; i++) { - if(refl->Resources.elems[i].IsTexture) + if(refl->ReadOnlyResources.elems[i].IsTexture) { // normal sampler or image load/store - GLint loc = gl.glGetUniformLocation(curProg, refl->Resources.elems[i].name.elems); + GLint loc = gl.glGetUniformLocation(curProg, refl->ReadOnlyResources.elems[i].name.elems); if(loc >= 0) { gl.glGetUniformiv(curProg, loc, dummyReadback); - mapping.Resources[i].bindset = 0; - mapping.Resources[i].bind = dummyReadback[0]; - mapping.Resources[i].arraySize = 1; + mapping.ReadOnlyResources[i].bindset = 0; + mapping.ReadOnlyResources[i].bind = dummyReadback[0]; + mapping.ReadOnlyResources[i].arraySize = 1; } // handle sampler arrays, use the base name - string name = refl->Resources.elems[i].name.elems; + string name = refl->ReadOnlyResources.elems[i].name.elems; if(name.back() == ']') { do @@ -1829,30 +1832,80 @@ void GetBindpointMapping(const GLHookSet &gl, GLuint curProg, int shadIdx, Shade if(idx == GL_INVALID_INDEX) { - mapping.Resources[i].used = false; + mapping.ReadOnlyResources[i].used = false; } else { GLint used = 0; gl.glGetProgramResourceiv(curProg, eGL_UNIFORM, idx, 1, &refEnum[shadIdx], 1, NULL, &used); - mapping.Resources[i].used = (used != 0); + mapping.ReadOnlyResources[i].used = (used != 0); } } - else if(refl->Resources.elems[i].IsReadWrite && !refl->Resources.elems[i].IsTexture) + else { - if(refl->Resources.elems[i].variableType.descriptor.cols == 1 && - refl->Resources.elems[i].variableType.descriptor.rows == 1 && - refl->Resources.elems[i].variableType.descriptor.type == eVar_UInt) + mapping.ReadOnlyResources[i].bindset = -1; + mapping.ReadOnlyResources[i].bind = -1; + mapping.ReadOnlyResources[i].used = false; + mapping.ReadOnlyResources[i].arraySize = 1; + } + } + + create_array_uninit(mapping.ReadWriteResources, refl->ReadWriteResources.count); + for(int32_t i=0; i < refl->ReadWriteResources.count; i++) + { + if(refl->ReadWriteResources.elems[i].IsTexture) + { + // image load/store + + GLint loc = gl.glGetUniformLocation(curProg, refl->ReadWriteResources.elems[i].name.elems); + if(loc >= 0) + { + gl.glGetUniformiv(curProg, loc, dummyReadback); + mapping.ReadWriteResources[i].bindset = 0; + mapping.ReadWriteResources[i].bind = dummyReadback[0]; + mapping.ReadWriteResources[i].arraySize = 1; + } + + // handle sampler arrays, use the base name + string name = refl->ReadWriteResources.elems[i].name.elems; + if(name.back() == ']') + { + do + { + name.pop_back(); + } while(name.back() != '['); + name.pop_back(); + } + + GLuint idx = 0; + idx = gl.glGetProgramResourceIndex(curProg, eGL_UNIFORM, name.c_str()); + + if(idx == GL_INVALID_INDEX) + { + mapping.ReadWriteResources[i].used = false; + } + else + { + GLint used = 0; + gl.glGetProgramResourceiv(curProg, eGL_UNIFORM, idx, 1, &refEnum[shadIdx], 1, NULL, &used); + mapping.ReadWriteResources[i].used = (used != 0); + } + } + else if(!refl->ReadWriteResources.elems[i].IsTexture) + { + if(refl->ReadWriteResources.elems[i].variableType.descriptor.cols == 1 && + refl->ReadWriteResources.elems[i].variableType.descriptor.rows == 1 && + refl->ReadWriteResources.elems[i].variableType.descriptor.type == eVar_UInt) { // atomic uint - GLuint idx = gl.glGetProgramResourceIndex(curProg, eGL_UNIFORM, refl->Resources.elems[i].name.elems); + GLuint idx = gl.glGetProgramResourceIndex(curProg, eGL_UNIFORM, refl->ReadWriteResources.elems[i].name.elems); if(idx == GL_INVALID_INDEX) { - mapping.Resources[i].bindset = -1; - mapping.Resources[i].bind = -1; - mapping.Resources[i].used = false; - mapping.Resources[i].arraySize = 1; + mapping.ReadWriteResources[i].bindset = -1; + mapping.ReadWriteResources[i].bind = -1; + mapping.ReadWriteResources[i].used = false; + mapping.ReadWriteResources[i].arraySize = 1; } else { @@ -1862,10 +1915,10 @@ 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; - mapping.Resources[i].arraySize = 1; + mapping.ReadWriteResources[i].bindset = -1; + mapping.ReadWriteResources[i].bind = -1; + mapping.ReadWriteResources[i].used = false; + mapping.ReadWriteResources[i].arraySize = 1; } else { @@ -1877,45 +1930,45 @@ 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); + mapping.ReadWriteResources[i].bindset = 0; + gl.glGetActiveAtomicCounterBufferiv(curProg, atomicIndex, eGL_ATOMIC_COUNTER_BUFFER_BINDING, &mapping.ReadWriteResources[i].bind); GLint used = 0; gl.glGetActiveAtomicCounterBufferiv(curProg, atomicIndex, atomicRefEnum[shadIdx], &used); - mapping.Resources[i].used = (used != 0); - mapping.Resources[i].arraySize = 1; + mapping.ReadWriteResources[i].used = (used != 0); + mapping.ReadWriteResources[i].arraySize = 1; } } } else { // shader storage buffer object - GLuint idx = gl.glGetProgramResourceIndex(curProg, eGL_SHADER_STORAGE_BLOCK, refl->Resources.elems[i].name.elems); + GLuint idx = gl.glGetProgramResourceIndex(curProg, eGL_SHADER_STORAGE_BLOCK, refl->ReadWriteResources.elems[i].name.elems); if(idx == GL_INVALID_INDEX) { - mapping.Resources[i].bindset = -1; - mapping.Resources[i].bind = -1; - mapping.Resources[i].used = false; - mapping.Resources[i].arraySize = 1; + mapping.ReadWriteResources[i].bindset = -1; + mapping.ReadWriteResources[i].bind = -1; + mapping.ReadWriteResources[i].used = false; + mapping.ReadWriteResources[i].arraySize = 1; } 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); + mapping.ReadWriteResources[i].bindset = 0; + gl.glGetProgramResourceiv(curProg, eGL_SHADER_STORAGE_BLOCK, idx, 1, &prop, 1, NULL, &mapping.ReadWriteResources[i].bind); GLint used = 0; gl.glGetProgramResourceiv(curProg, eGL_SHADER_STORAGE_BLOCK, idx, 1, &refEnum[shadIdx], 1, NULL, &used); - mapping.Resources[i].used = (used != 0); - mapping.Resources[i].arraySize = 1; + mapping.ReadWriteResources[i].used = (used != 0); + mapping.ReadWriteResources[i].arraySize = 1; } } } else { - mapping.Resources[i].bindset = -1; - mapping.Resources[i].bind = -1; - mapping.Resources[i].used = false; - mapping.Resources[i].arraySize = 1; + mapping.ReadWriteResources[i].bindset = -1; + mapping.ReadWriteResources[i].bind = -1; + mapping.ReadWriteResources[i].used = false; + mapping.ReadWriteResources[i].arraySize = 1; } } diff --git a/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp b/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp index 2d8da4d70..cd6202d4e 100644 --- a/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_disassemble.cpp @@ -2329,7 +2329,6 @@ void SPVModule::MakeReflection(ShaderReflection *reflection, ShaderBindpointMapp res.IsSampler = true; res.IsTexture = true; res.IsSRV = true; - res.IsReadWrite = false; SPVTypeData *sampledType = type->baseType; if(sampledType->type == SPVTypeData::eImage) @@ -2397,8 +2396,8 @@ void SPVModule::MakeReflection(ShaderReflection *reflection, ShaderBindpointMapp create_array_uninit(mapping->ConstantBlocks, cblocks.size()); create_array_uninit(reflection->ConstantBlocks, cblocks.size()); - create_array_uninit(mapping->Resources, resources.size()); - create_array_uninit(reflection->Resources, resources.size()); + create_array_uninit(mapping->ReadOnlyResources, resources.size()); + create_array_uninit(reflection->ReadOnlyResources, resources.size()); for(size_t i=0; i < cblocks.size(); i++) { @@ -2409,9 +2408,9 @@ void SPVModule::MakeReflection(ShaderReflection *reflection, ShaderBindpointMapp for(size_t i=0; i < resources.size(); i++) { - mapping->Resources[i] = resources[i].map; - reflection->Resources[i] = resources[i].bindres; - reflection->Resources[i].bindPoint = (int32_t)i; + mapping->ReadOnlyResources[i] = resources[i].map; + reflection->ReadOnlyResources[i] = resources[i].bindres; + reflection->ReadOnlyResources[i].bindPoint = (int32_t)i; } } diff --git a/renderdocui/Interop/Shader.cs b/renderdocui/Interop/Shader.cs index bca74810f..0cac737a2 100644 --- a/renderdocui/Interop/Shader.cs +++ b/renderdocui/Interop/Shader.cs @@ -344,7 +344,6 @@ namespace renderdoc public bool IsSampler; public bool IsTexture; public bool IsSRV; - public bool IsReadWrite; public ShaderResourceType resType; @@ -430,10 +429,13 @@ namespace renderdoc public SigParameter[] OutputSig; [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] - public ConstantBlock[] ConstantBlocks; // sparse - index indicates bind point + public ConstantBlock[] ConstantBlocks; [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] - public ShaderResource[] Resources; // non-sparse, since bind points can overlap. + public ShaderResource[] ReadOnlyResources; + + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public ShaderResource[] ReadWriteResources; [StructLayout(LayoutKind.Sequential)] public struct Interface @@ -463,6 +465,8 @@ namespace renderdoc [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] public BindpointMap[] ConstantBlocks; [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] - public BindpointMap[] Resources; + public BindpointMap[] ReadOnlyResources; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public BindpointMap[] ReadWriteResources; }; }; \ No newline at end of file diff --git a/renderdocui/Windows/PipelineState/D3D11PipelineStateViewer.cs b/renderdocui/Windows/PipelineState/D3D11PipelineStateViewer.cs index f50f5f028..2d20c0ef8 100644 --- a/renderdocui/Windows/PipelineState/D3D11PipelineStateViewer.cs +++ b/renderdocui/Windows/PipelineState/D3D11PipelineStateViewer.cs @@ -248,7 +248,7 @@ namespace renderdocui.Windows.PipelineState if (shaderDetails != null) { - foreach (var bind in shaderDetails.Resources) + foreach (var bind in shaderDetails.ReadOnlyResources) { if (bind.IsSRV && bind.bindPoint == i) { @@ -372,7 +372,7 @@ namespace renderdocui.Windows.PipelineState if (shaderDetails != null) { - foreach (var bind in shaderDetails.Resources) + foreach (var bind in shaderDetails.ReadOnlyResources) { if (bind.IsSampler && bind.bindPoint == i) { @@ -926,9 +926,9 @@ namespace renderdocui.Windows.PipelineState if (state.m_CS.ShaderDetails != null) { - foreach (var bind in state.m_CS.ShaderDetails.Resources) + foreach (var bind in state.m_CS.ShaderDetails.ReadWriteResources) { - if (bind.IsReadWrite && bind.bindPoint == i) + if (bind.bindPoint == i) { shaderInput = bind; break; @@ -1254,9 +1254,9 @@ namespace renderdocui.Windows.PipelineState if (state.m_PS.ShaderDetails != null) { - foreach (var bind in state.m_PS.ShaderDetails.Resources) + foreach (var bind in state.m_PS.ShaderDetails.ReadWriteResources) { - if (bind.IsReadWrite && bind.bindPoint == i + state.m_OM.UAVStartSlot) + if (bind.bindPoint == i + state.m_OM.UAVStartSlot) { shaderInput = bind; break; @@ -1612,72 +1612,70 @@ namespace renderdocui.Windows.PipelineState if (deets != null) { - foreach (var r in deets.Resources) + ShaderResource[] resources = uav ? deets.ReadWriteResources : deets.ReadOnlyResources; + foreach (var r in resources) { - if(r.IsTexture) + if (r.IsTexture) continue; - if ((r.IsSRV && !uav) || (r.IsReadWrite && uav)) + if (r.bindPoint == bind) { - if (r.bindPoint == bind) + if (r.variableType.members.Length == 0) { - if (r.variableType.members.Length == 0) + if (view != null) { - if (view != null) + if (view.Format.special && view.Format.specialFormat == SpecialFormat.R10G10B10A2) { - if (view.Format.special && view.Format.specialFormat == SpecialFormat.R10G10B10A2) - { - if (view.Format.compType == FormatComponentType.UInt) format = "uintten"; - if (view.Format.compType == FormatComponentType.UNorm) format = "unormten"; - } - else if (!view.Format.special) - { - switch (view.Format.compByteWidth) - { - case 1: - { - if (view.Format.compType == FormatComponentType.UNorm) format = "unormb"; - if (view.Format.compType == FormatComponentType.SNorm) format = "snormb"; - if (view.Format.compType == FormatComponentType.UInt) format = "ubyte"; - if (view.Format.compType == FormatComponentType.SInt) format = "byte"; - break; - } - case 2: - { - if (view.Format.compType == FormatComponentType.UNorm) format = "unormh"; - if (view.Format.compType == FormatComponentType.SNorm) format = "snormh"; - if (view.Format.compType == FormatComponentType.UInt) format = "ushort"; - if (view.Format.compType == FormatComponentType.SInt) format = "short"; - if (view.Format.compType == FormatComponentType.Float) format = "half"; - break; - } - case 4: - { - if (view.Format.compType == FormatComponentType.UNorm) format = "unormf"; - if (view.Format.compType == FormatComponentType.SNorm) format = "snormf"; - if (view.Format.compType == FormatComponentType.UInt) format = "uint"; - if (view.Format.compType == FormatComponentType.SInt) format = "int"; - if (view.Format.compType == FormatComponentType.Float) format = "float"; - break; - } - } - - format += view.Format.compCount; - } + if (view.Format.compType == FormatComponentType.UInt) format = "uintten"; + if (view.Format.compType == FormatComponentType.UNorm) format = "unormten"; } + else if (!view.Format.special) + { + switch (view.Format.compByteWidth) + { + case 1: + { + if (view.Format.compType == FormatComponentType.UNorm) format = "unormb"; + if (view.Format.compType == FormatComponentType.SNorm) format = "snormb"; + if (view.Format.compType == FormatComponentType.UInt) format = "ubyte"; + if (view.Format.compType == FormatComponentType.SInt) format = "byte"; + break; + } + case 2: + { + if (view.Format.compType == FormatComponentType.UNorm) format = "unormh"; + if (view.Format.compType == FormatComponentType.SNorm) format = "snormh"; + if (view.Format.compType == FormatComponentType.UInt) format = "ushort"; + if (view.Format.compType == FormatComponentType.SInt) format = "short"; + if (view.Format.compType == FormatComponentType.Float) format = "half"; + break; + } + case 4: + { + if (view.Format.compType == FormatComponentType.UNorm) format = "unormf"; + if (view.Format.compType == FormatComponentType.SNorm) format = "snormf"; + if (view.Format.compType == FormatComponentType.UInt) format = "uint"; + if (view.Format.compType == FormatComponentType.SInt) format = "int"; + if (view.Format.compType == FormatComponentType.Float) format = "float"; + break; + } + } - if (format == "" && r.variableType.Name.Length > 0) - format = r.variableType.Name; + format += view.Format.compCount; + } + } - format += " " + r.name + ";"; - } - else - { - format = "// struct " + r.variableType.Name + Environment.NewLine + - "{" + Environment.NewLine + FormatMembers(1, "", r.variableType.members) + "}"; - } - break; + if (format == "" && r.variableType.Name.Length > 0) + format = r.variableType.Name; + + format += " " + r.name + ";"; } + else + { + format = "// struct " + r.variableType.Name + Environment.NewLine + + "{" + Environment.NewLine + FormatMembers(1, "", r.variableType.members) + "}"; + } + break; } } } @@ -1936,33 +1934,37 @@ namespace renderdocui.Windows.PipelineState var shType = String.Format("{0}S", stage.stage.ToString()[0]); - foreach (var res in shaderDetails.Resources) + for (int i = 0; i < 2; i++) { - if (res.IsSampler) + ShaderResource[] resources = (i == 0 ? shaderDetails.ReadOnlyResources : shaderDetails.ReadWriteResources); + foreach (var res in resources) { - hlsl += String.Format("//SamplerComparisonState {0} : register(s{1}); // can't disambiguate", res.name, res.bindPoint) + nl; - hlsl += String.Format("SamplerState {0} : register(s{1}); // can't disambiguate", res.name, res.bindPoint) + nl; - } - else - { - char regChar = 't'; - - if (res.IsReadWrite) + if (res.IsSampler) { - hlsl += "RW"; - regChar = 'u'; - } - - if (res.IsTexture) - { - hlsl += String.Format("{0}<{1}> {2} : register({3}{4});", res.resType.ToString(), res.variableType.descriptor.name, res.name, regChar, res.bindPoint) + nl; + hlsl += String.Format("//SamplerComparisonState {0} : register(s{1}); // can't disambiguate", res.name, res.bindPoint) + nl; + hlsl += String.Format("SamplerState {0} : register(s{1}); // can't disambiguate", res.name, res.bindPoint) + nl; } else { - if (res.variableType.descriptor.rows == 1) - hlsl += String.Format("Buffer<{0}> {1} : register({2}{3});", res.variableType.descriptor.name, res.name, regChar, res.bindPoint) + nl; + char regChar = 't'; + + if (i == 1) + { + hlsl += "RW"; + regChar = 'u'; + } + + if (res.IsTexture) + { + hlsl += String.Format("{0}<{1}> {2} : register({3}{4});", res.resType.ToString(), res.variableType.descriptor.name, res.name, regChar, res.bindPoint) + nl; + } else - hlsl += String.Format("StructuredBuffer<{0}> {1} : register({2}{3});", res.variableType.descriptor.name, res.name, regChar, res.bindPoint) + nl; + { + if (res.variableType.descriptor.rows == 1) + hlsl += String.Format("Buffer<{0}> {1} : register({2}{3});", res.variableType.descriptor.name, res.name, regChar, res.bindPoint) + nl; + else + hlsl += String.Format("StructuredBuffer<{0}> {1} : register({2}{3});", res.variableType.descriptor.name, res.name, regChar, res.bindPoint) + nl; + } } } } @@ -2518,9 +2520,9 @@ namespace renderdocui.Windows.PipelineState if (refl != null) { - foreach (var bind in refl.Resources) + foreach (var bind in refl.ReadWriteResources) { - if (bind.IsReadWrite && bind.bindPoint == i) + if (bind.bindPoint == i) { shaderInput = bind; break; diff --git a/renderdocui/Windows/PipelineState/GLPipelineStateViewer.cs b/renderdocui/Windows/PipelineState/GLPipelineStateViewer.cs index 657d1f1b4..4a83256df 100644 --- a/renderdocui/Windows/PipelineState/GLPipelineStateViewer.cs +++ b/renderdocui/Windows/PipelineState/GLPipelineStateViewer.cs @@ -270,12 +270,12 @@ namespace renderdocui.Windows.PipelineState if (shaderDetails != null) { - foreach (var bind in shaderDetails.Resources) + foreach (var bind in shaderDetails.ReadOnlyResources) { - if (bind.IsSRV && !bind.IsReadWrite && mapping.Resources[bind.bindPoint].bind == i) + if (bind.IsSRV && mapping.ReadOnlyResources[bind.bindPoint].bind == i) { shaderInput = bind; - map = mapping.Resources[bind.bindPoint]; + map = mapping.ReadOnlyResources[bind.bindPoint]; } } } @@ -557,20 +557,14 @@ namespace renderdocui.Windows.PipelineState if (shaderDetails != null) { UInt32 i = 0; - foreach (var res in shaderDetails.Resources) + foreach (var res in shaderDetails.ReadWriteResources) { - int bindPoint = stage.BindpointMapping.Resources[i].bind; + int bindPoint = stage.BindpointMapping.ReadWriteResources[i].bind; bool atomic = false; bool ssbo = false; bool image = false; - if (!res.IsReadWrite) - { - i++; - continue; - } - GLPipelineState.Buffer bf = null; GLPipelineState.ImageLoadStore im = null; ResourceId id = ResourceId.Null; @@ -609,7 +603,7 @@ namespace renderdocui.Windows.PipelineState } bool filledSlot = id != ResourceId.Null; - bool usedSlot = stage.BindpointMapping.Resources[i].used; + bool usedSlot = stage.BindpointMapping.ReadWriteResources[i].used; // show if if (usedSlot || // it's referenced by the shader - regardless of empty or not @@ -1658,7 +1652,7 @@ namespace renderdocui.Windows.PipelineState var deets = stage.ShaderDetails; - ShaderResource r = deets.Resources[rwtag.idx]; + ShaderResource r = deets.ReadWriteResources[rwtag.idx]; if (deets != null) { diff --git a/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.cs b/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.cs index 37659526a..e86121c4a 100644 --- a/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.cs +++ b/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.cs @@ -335,9 +335,9 @@ namespace renderdocui.Windows.PipelineState // string formatted with all the relevant data if (stage.ShaderDetails != null) { - foreach (var shaderRes in stage.ShaderDetails.Resources) + foreach (var shaderRes in stage.ShaderDetails.ReadOnlyResources) { - BindpointMap bindMap = stage.BindpointMapping.Resources[shaderRes.bindPoint]; + BindpointMap bindMap = stage.BindpointMapping.ReadOnlyResources[shaderRes.bindPoint]; VulkanPipelineState.Pipeline.DescriptorSet.DescriptorBinding.BindingElement[] slotBinds = null; ShaderBindType bindType = ShaderBindType.Unknown; @@ -1562,223 +1562,6 @@ namespace renderdocui.Windows.PipelineState // HLSL source available for this shader. private void shaderedit_Click(object sender, EventArgs e) { - VulkanPipelineState.ShaderStage stage = GetStageForSender(sender); - - if (stage == null) return; - - ShaderReflection shaderDetails = stage.ShaderDetails; - - if (stage.Shader == ResourceId.Null || shaderDetails == null) return; - - var entryFunc = String.Format("EditedShader{0}S", stage.stage.ToString()[0]); - - string mainfile = ""; - - var files = new Dictionary(StringComparer.InvariantCultureIgnoreCase); - if (shaderDetails.DebugInfo.entryFunc.Length > 0 && shaderDetails.DebugInfo.files.Length > 0) - { - entryFunc = shaderDetails.DebugInfo.entryFunc; - - foreach (var s in shaderDetails.DebugInfo.files) - files.Add(s.BaseFilename, s.filetext); - - int entryFile = shaderDetails.DebugInfo.entryFile; - if (entryFile < 0 || entryFile >= shaderDetails.DebugInfo.files.Length) - entryFile = 0; - - mainfile = shaderDetails.DebugInfo.files[entryFile].BaseFilename; - } - else - { - var nl = Environment.NewLine; - var nl2 = Environment.NewLine + Environment.NewLine; - - string hlsl = "// No HLSL available - function stub generated" + nl2; - - var shType = String.Format("{0}S", stage.stage.ToString()[0]); - - foreach (var res in shaderDetails.Resources) - { - if (res.IsSampler) - { - hlsl += String.Format("//SamplerComparisonState {0} : register(s{1}); // can't disambiguate", res.name, res.bindPoint) + nl; - hlsl += String.Format("SamplerState {0} : register(s{1}); // can't disambiguate", res.name, res.bindPoint) + nl; - } - else - { - char regChar = 't'; - - if (res.IsReadWrite) - { - hlsl += "RW"; - regChar = 'u'; - } - - if (res.IsTexture) - { - hlsl += String.Format("{0}<{1}> {2} : register({3}{4});", res.resType.ToString(), res.variableType.descriptor.name, res.name, regChar, res.bindPoint) + nl; - } - else - { - if (res.variableType.descriptor.rows == 1) - hlsl += String.Format("Buffer<{0}> {1} : register({2}{3});", res.variableType.descriptor.name, res.name, regChar, res.bindPoint) + nl; - else - hlsl += String.Format("StructuredBuffer<{0}> {1} : register({2}{3});", res.variableType.descriptor.name, res.name, regChar, res.bindPoint) + nl; - } - } - } - - hlsl += nl2; - - string cbuffers = ""; - - int cbufIdx = 0; - foreach (var cbuf in shaderDetails.ConstantBlocks) - { - if (cbuf.name.Length > 0 && cbuf.variables.Length > 0) - { - cbuffers += String.Format("cbuffer {0} : register(b{1}) {{", cbuf.name, cbufIdx) + nl; - MakeShaderVariablesHLSL(true, cbuf.variables, ref cbuffers, ref hlsl); - cbuffers += "};" + nl2; - } - cbufIdx++; - } - - hlsl += cbuffers + nl2; - - hlsl += String.Format("struct {0}Input{1}{{{1}", shType, nl); - foreach(var sig in shaderDetails.InputSig) - hlsl += String.Format("\t{0} {1} : {2};" + nl, sig.TypeString, sig.varName.Length > 0 ? sig.varName : ("param" + sig.regIndex), sig.D3D11SemanticString); - hlsl += "};" + nl2; - - hlsl += String.Format("struct {0}Output{1}{{{1}", shType, nl); - foreach (var sig in shaderDetails.OutputSig) - hlsl += String.Format("\t{0} {1} : {2};" + nl, sig.TypeString, sig.varName.Length > 0 ? sig.varName : ("param" + sig.regIndex), sig.D3D11SemanticString); - hlsl += "};" + nl2; - - hlsl += String.Format("{0}Output {1}(in {0}Input IN){2}{{{2}\t{0}Output OUT = ({0}Output)0;{2}{2}\t// ...{2}{2}\treturn OUT;{2}}}{2}", shType, entryFunc, nl); - - mainfile = "generated.hlsl"; - - files.Add(mainfile, hlsl); - } - - if (files.Count == 0) - return; - - ShaderViewer sv = new ShaderViewer(m_Core, false, entryFunc, files, - - // Save Callback - (ShaderViewer viewer, Dictionary updatedfiles) => - { - string compileSource = updatedfiles[mainfile]; - - // try and match up #includes against the files that we have. This isn't always - // possible as fxc only seems to include the source for files if something in - // that file was included in the compiled output. So you might end up with - // dangling #includes - we just have to ignore them - int offs = compileSource.IndexOf("#include"); - - while(offs >= 0) - { - // search back to ensure this is a valid #include (ie. not in a comment). - // Must only see whitespace before, then a newline. - int ws = Math.Max(0, offs-1); - while (ws >= 0 && (compileSource[ws] == ' ' || compileSource[ws] == '\t')) - ws--; - - // not valid? jump to next. - if (ws > 0 && compileSource[ws] != '\n') - { - offs = compileSource.IndexOf("#include", offs + 1); - continue; - } - - int start = ws+1; - - bool tail = true; - - int lineEnd = compileSource.IndexOf("\n", start+1); - if(lineEnd == -1) - { - lineEnd = compileSource.Length; - tail = false; - } - - ws = offs + "#include".Length; - while (compileSource[ws] == ' ' || compileSource[ws] == '\t') - ws++; - - string line = compileSource.Substring(offs, lineEnd-offs+1); - - if (compileSource[ws] != '<' && compileSource[ws] != '"') - { - viewer.ShowErrors("Invalid #include directive found:\r\n" + line); - return; - } - - // find matching char, either <> or ""; - int end = compileSource.IndexOf(compileSource[ws] == '"' ? '"' : '>', ws + 1); - - if (end == -1) - { - viewer.ShowErrors("Invalid #include directive found:\r\n" + line); - return; - } - - string fname = compileSource.Substring(ws + 1, end - ws - 1); - - string fileText = ""; - - if (updatedfiles.ContainsKey(fname)) - fileText = updatedfiles[fname]; - else - fileText = "// Can't find file " + fname + "\n"; - - compileSource = compileSource.Substring(0, offs) + "\n\n" + fileText + "\n\n" + (tail ? compileSource.Substring(lineEnd + 1) : ""); - - // need to start searching from the beginning - wasteful but allows nested includes to work - offs = compileSource.IndexOf("#include"); - } - - if (updatedfiles.ContainsKey("@cmdline")) - compileSource = updatedfiles["@cmdline"] + "\n\n" + compileSource; - - // invoke off to the ReplayRenderer to replace the log's shader - // with our edited one - m_Core.Renderer.BeginInvoke((ReplayRenderer r) => - { - string errs = ""; - - uint flags = shaderDetails.DebugInfo.compileFlags; - - ResourceId from = stage.Shader; - ResourceId to = r.BuildTargetShader(entryFunc, compileSource, flags, stage.stage, out errs); - - viewer.BeginInvoke((MethodInvoker)delegate { viewer.ShowErrors(errs); }); - if (to == ResourceId.Null) - { - r.RemoveReplacement(from); - } - else - { - r.ReplaceResource(from, to); - } - }); - }, - - // Close Callback - () => - { - // remove the replacement on close (we could make this more sophisticated if there - // was a place to control replaced resources/shaders). - m_Core.Renderer.BeginInvoke((ReplayRenderer r) => - { - r.RemoveReplacement(stage.Shader); - }); - }); - - sv.Show(m_DockContent.DockPanel); } private void ShowCBuffer(VulkanPipelineState.ShaderStage stage, CBufferTag tag) diff --git a/renderdocui/Windows/ShaderViewer.cs b/renderdocui/Windows/ShaderViewer.cs index 2ce7792e0..40dd804c6 100644 --- a/renderdocui/Windows/ShaderViewer.cs +++ b/renderdocui/Windows/ShaderViewer.cs @@ -466,7 +466,7 @@ namespace renderdocui.Windows disasm = FriendlyName(disasm, stem, "", cbuf.variables); } - foreach (var r in m_ShaderDetails.Resources) + foreach (var r in m_ShaderDetails.ReadOnlyResources) { if (r.IsSRV) { @@ -484,14 +484,14 @@ namespace renderdocui.Windows Regex rgx = new Regex(needle); disasm = rgx.Replace(disasm, replacement); } - if (r.IsReadWrite) - { - var needle = string.Format(", u{0}([^0-9])", r.bindPoint); - var replacement = string.Format(", {0}$1", r.name); + } + foreach (var r in m_ShaderDetails.ReadWriteResources) + { + var needle = string.Format(", u{0}([^0-9])", r.bindPoint); + var replacement = string.Format(", {0}$1", r.name); - Regex rgx = new Regex(needle); - disasm = rgx.Replace(disasm, replacement); - } + Regex rgx = new Regex(needle); + disasm = rgx.Replace(disasm, replacement); } } @@ -1304,6 +1304,70 @@ namespace renderdocui.Windows return var.Row(0, VarType.Float).ToString(); } + private void AddResourceRegister(ShaderResource slot, D3D11PipelineState.ShaderStage.ResourceView res) + { + bool found = false; + + var name = slot.bindPoint + " (" + slot.name + ")"; + + foreach (var tex in m_Core.CurTextures) + { + if (tex.ID == res.Resource) + { + var node = new TreelistView.Node(new object[] { + "t" + name, "Texture", + tex.width + "x" + tex.height + "x" + (tex.depth > 1 ? tex.depth : tex.arraysize) + + "[" + tex.mips + "] @ " + tex.format + " - " + tex.name + }); + node.Tag = null; + + constantRegs.Nodes.Add(node); + + found = true; + break; + } + } + + if (!found) + { + foreach (var buf in m_Core.CurBuffers) + { + if (buf.ID == res.Resource) + { + string prefix = "u"; + + if (slot.IsSRV) + prefix = "t"; + + var node = new TreelistView.Node(new object[] { + prefix + name, "Buffer", + buf.length + " - " + buf.name + }); + node.Tag = null; + constantRegs.Nodes.Add(node); + + found = true; + break; + } + } + } + + if (!found) + { + string prefix = "u"; + + if (slot.IsSRV) + prefix = "t"; + + var node = new TreelistView.Node(new object[] { + prefix + name, "Resource", + "unknown" + }); + node.Tag = null; + constantRegs.Nodes.Add(node); + } + } + public void UpdateDebugging() { if (m_Trace == null || m_Trace.states == null || m_Trace.states.Length == 0) @@ -1381,81 +1445,24 @@ namespace renderdocui.Windows var pipestate = m_Core.CurD3D11PipelineState; - foreach (var slot in m_ShaderDetails.Resources) + foreach (ShaderResource slot in m_ShaderDetails.ReadWriteResources) + { + D3D11PipelineState.ShaderStage.ResourceView res = null; + + if (m_Stage.stage == ShaderStageType.Pixel) + res = pipestate.m_OM.UAVs[slot.bindPoint - pipestate.m_OM.UAVStartSlot]; + else + res = m_Stage.UAVs[slot.bindPoint]; + + AddResourceRegister(slot, res); + } + + foreach (ShaderResource slot in m_ShaderDetails.ReadOnlyResources) { if (slot.IsSampler) continue; - var res = m_Stage.SRVs[slot.bindPoint]; - - if (slot.IsReadWrite) - { - if(m_Stage.stage == ShaderStageType.Pixel) - res = pipestate.m_OM.UAVs[slot.bindPoint - pipestate.m_OM.UAVStartSlot]; - else - res = m_Stage.UAVs[slot.bindPoint]; - } - - bool found = false; - - var name = slot.bindPoint + " (" + slot.name + ")"; - - foreach (var tex in m_Core.CurTextures) - { - if (tex.ID == res.Resource) - { - var node = new TreelistView.Node(new object[] { - "t" + name, "Texture", - tex.width + "x" + tex.height + "x" + (tex.depth > 1 ? tex.depth : tex.arraysize) + - "[" + tex.mips + "] @ " + tex.format + " - " + tex.name - }); - node.Tag = null; - - constantRegs.Nodes.Add(node); - - found = true; - break; - } - } - - if (!found) - { - foreach (var buf in m_Core.CurBuffers) - { - if (buf.ID == res.Resource) - { - string prefix = "u"; - - if (slot.IsSRV) - prefix = "t"; - - var node = new TreelistView.Node(new object[] { - prefix + name, "Buffer", - buf.length + " - " + buf.name - }); - node.Tag = null; - constantRegs.Nodes.Add(node); - - found = true; - break; - } - } - } - - if (!found) - { - string prefix = "u"; - - if (slot.IsSRV) - prefix = "t"; - - var node = new TreelistView.Node(new object[] { - prefix + name, "Resource", - "unknown" - }); - node.Tag = null; - constantRegs.Nodes.Add(node); - } + AddResourceRegister(slot, m_Stage.SRVs[slot.bindPoint]); } constantRegs.EndUpdate(); diff --git a/renderdocui/Windows/TextureViewer.cs b/renderdocui/Windows/TextureViewer.cs index 8bdfe64a8..9c2c5a4b9 100644 --- a/renderdocui/Windows/TextureViewer.cs +++ b/renderdocui/Windows/TextureViewer.cs @@ -1218,9 +1218,9 @@ namespace renderdocui.Windows if (details != null) { - foreach (var bind in details.Resources) + foreach (var bind in details.ReadWriteResources) { - if (mapping.Resources[bind.bindPoint].bind == rw && bind.IsReadWrite) + if (mapping.ReadWriteResources[bind.bindPoint].bind == rw) { used = true; bindName = "<" + bind.name + ">"; @@ -1376,9 +1376,9 @@ namespace renderdocui.Windows if (details != null) { - foreach (var bind in details.Resources) + foreach (var bind in details.ReadOnlyResources) { - if (mapping.Resources[bind.bindPoint].bind == i && bind.IsSRV) + if (mapping.ReadOnlyResources[bind.bindPoint].bind == i && bind.IsSRV) { used = true; bindName = "<" + bind.name + ">";