public override void Load(InstrumentData d) { SamplerData data = d as SamplerData; base.Load(data); speedDial.setPercent(data.speedDial); volumeDial.setPercent(data.ampDial); GetComponent <samplerLoad>().SetSample(data.label, data.file); volumeInput.ID = data.jackInAmpID; speedInput.ID = data.jackInSpeedID; controlInput.ID = data.jackInSeqID; output.ID = data.jackOutID; playButton.startToggled = data.playToggle; dirSwitch.setSwitch(data.dirSwitch); loopSwitch.setSwitch(data.loopSwitch); headSlider.setPercent(data.headPos); tailSlider.setPercent(data.tailPos); turntableButton.startToggled = data.turntable; if (data.turntablePos != Vector3.zero) { turntableObject.transform.localPosition = data.turntablePos; } if (data.turntableRot != Quaternion.identity) { turntableObject.transform.localRotation = data.turntableRot; } }
// Written by hand to include management of input Brushes (which aren't DPs). internal override void ReleaseOnChannelCore(DUCE.Channel channel) { Debug.Assert(_duceResource.IsOnChannel(channel)); if (_duceResource.ReleaseOnChannel(channel)) { // Ensure that brushes are released. if (_samplerCount > 0) { int numSamplers = _samplerData.Count; for (int i = 0; i < numSamplers; i++) { SamplerData?ssn = _samplerData[i]; if (ssn.HasValue) { SamplerData ss = ssn.Value; DUCE.IResource brush = ss._brush as DUCE.IResource; if (brush != null) { brush.ReleaseOnChannel(channel); } } } } PixelShader vPixelShader = PixelShader; if (vPixelShader != null) { ((DUCE.IResource)vPixelShader).ReleaseOnChannel(channel); } ReleaseOnChannelAnimations(channel); } }
public override InstrumentData GetData() { SamplerData data = new SamplerData(); data.deviceType = menuItem.deviceType.Sampler; GetTransformData(data); data.speedDial = speedDial.percent; data.ampDial = volumeDial.percent; data.file = GetComponent <samplerLoad>().CurFile; data.label = GetComponent <samplerLoad>().CurTapeLabel; data.jackInAmpID = volumeInput.transform.GetInstanceID(); data.jackInSpeedID = speedInput.transform.GetInstanceID(); data.jackInSeqID = controlInput.transform.GetInstanceID(); data.jackOutID = output.transform.GetInstanceID(); data.dirSwitch = dirSwitch.switchVal; data.loopSwitch = loopSwitch.switchVal; data.headPos = headSlider.percent; data.tailPos = tailSlider.percent; data.playToggle = playButton.isHit; data.turntable = turntableOn; data.turntablePos = turntableObject.transform.localPosition; data.turntableRot = turntableObject.transform.localRotation; return(data); }
// Ensures that _samplerData is extended to 'position', and that // the specified value is inserted there. private void StashSamplerDataInPosition(int position, SamplerData newSampler, int maxIndex) { if (_samplerData == null) { _samplerData = new List <SamplerData?>(maxIndex); } if (_samplerData.Count <= position) { int numToAdd = position - _samplerData.Count + 1; for (int i = 0; i < numToAdd; i++) { _samplerData.Add((SamplerData?)null); } } if (!_samplerData[position].HasValue) { // Going from null to having a value, so increment count _samplerCount++; } System.Windows.Threading.Dispatcher dispatcher = this.Dispatcher; // Release the old value if it is a resource on channel. AddRef the // new value. if (dispatcher != null) { SamplerData?oldSampler = _samplerData[position]; Brush oldBrush = null; if (oldSampler.HasValue) { SamplerData ss = oldSampler.Value; oldBrush = ss._brush; } Brush newBrush = newSampler._brush; DUCE.IResource targetResource = (DUCE.IResource) this; using (CompositionEngineLock.Acquire()) { int channelCount = targetResource.GetChannelCount(); for (int channelIndex = 0; channelIndex < channelCount; channelIndex++) { DUCE.Channel channel = targetResource.GetChannel(channelIndex); Debug.Assert(!channel.IsOutOfBandChannel); Debug.Assert(!targetResource.GetHandle(channel).IsNull); ReleaseResource(oldBrush, channel); AddRefResource(newBrush, channel); } } } _samplerData[position] = newSampler; }
// Updates the shader sampler referred to by the DP. Converts to the // form that the HLSL shaders want, and stores that value, since it will // be sent on every update. // We WritePreamble/Postscript here since this method is called by the user with the callback // created in PixelShaderSamplerCallback. private void UpdateShaderSampler(DependencyProperty dp, object newValue, int registerIndex, SamplingMode samplingMode) { WritePreamble(); if (newValue != null) { if (!(typeof(VisualBrush).IsInstanceOfType(newValue) || typeof(BitmapCacheBrush).IsInstanceOfType(newValue) || typeof(ImplicitInputBrush).IsInstanceOfType(newValue) || typeof(ImageBrush).IsInstanceOfType(newValue)) ) { // Note that if the type of the brush is ImplicitInputBrush and the value is non null, the value is actually // Effect.ImplicitInput. This is because ImplicitInputBrush is internal and the user can only get to the singleton // Effect.ImplicitInput. throw new ArgumentException(SR.Get(SRID.Effect_ShaderSamplerType), "dp"); } } // // Treat as ps_2_0 by default // int registerMax = PS_2_0_SAMPLER_LIMIT; string srid = SRID.Effect_Shader20SamplerRegisterLimit; if (PixelShader != null && PixelShader.ShaderMajorVersion >= 3) { registerMax = PS_3_0_SAMPLER_LIMIT; srid = SRID.Effect_Shader30SamplerRegisterLimit; } if (registerIndex >= registerMax || registerIndex < 0) { throw new ArgumentException(SR.Get(srid)); } SamplerData sd = new SamplerData() { _brush = (Brush)newValue, _samplingMode = samplingMode }; StashSamplerDataInPosition(registerIndex, sd, registerMax); // Propagate dirty this.PropertyChanged(dp); WritePostscript(); }
// Written by hand to include management of input Brushes (which aren't DPs). internal override DUCE.ResourceHandle AddRefOnChannelCore(DUCE.Channel channel) { if (_duceResource.CreateOrAddRefOnChannel(this, channel, System.Windows.Media.Composition.DUCE.ResourceType.TYPE_SHADEREFFECT)) { // Ensures brushes are property instantiated into Duce resources. if (_samplerCount > 0) { int numSamplers = _samplerData.Count; for (int i = 0; i < numSamplers; i++) { SamplerData?ssn = _samplerData[i]; if (ssn.HasValue) { SamplerData ss = ssn.Value; DUCE.IResource brush = ss._brush as DUCE.IResource; if (brush != null) { brush.AddRefOnChannel(channel); } } } } PixelShader vPixelShader = PixelShader; if (vPixelShader != null) { ((DUCE.IResource)vPixelShader).AddRefOnChannel(channel); } AddRefOnChannelAnimations(channel); UpdateResource(channel, true /* skip "on channel" check - we already know that we're on channel */); } return(_duceResource.GetHandle(channel)); }
private void ManualUpdateResource(DUCE.Channel channel, bool skipOnChannelCheck) { // If we're told we can skip the channel check, then we must be on channel Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel)); if (skipOnChannelCheck || _duceResource.IsOnChannel(channel)) { if (PixelShader == null) { throw new InvalidOperationException(SR.Get(SRID.Effect_ShaderPixelShaderSet)); } checked { DUCE.MILCMD_SHADEREFFECT data; data.Type = MILCMD.MilCmdShaderEffect; data.Handle = _duceResource.GetHandle(channel); data.TopPadding = _topPadding; data.BottomPadding = _bottomPadding; data.LeftPadding = _leftPadding; data.RightPadding = _rightPadding; data.DdxUvDdyUvRegisterIndex = this.DdxUvDdyUvRegisterIndex; data.hPixelShader = ((DUCE.IResource)PixelShader).GetHandle(channel); unsafe { data.ShaderConstantFloatRegistersSize = (uint)(sizeof(Int16) * _floatCount); data.DependencyPropertyFloatValuesSize = (uint)(4 * sizeof(Single) * _floatCount); data.ShaderConstantIntRegistersSize = (uint)(sizeof(Int16) * _intCount); data.DependencyPropertyIntValuesSize = (uint)(4 * sizeof(Int32) * _intCount); data.ShaderConstantBoolRegistersSize = (uint)(sizeof(Int16) * _boolCount); // // Note: the multiply by 4 is not because the boolean register holds 4 // values, but to compensate for the difference between sizeof(bool) // in managed code (1) and sizeof(BOOL) in native code (4). // data.DependencyPropertyBoolValuesSize = (uint)(4 * sizeof(bool) * _boolCount); data.ShaderSamplerRegistrationInfoSize = (uint)(2 * sizeof(uint) * _samplerCount); // 2 pieces of data per sampler. data.DependencyPropertySamplerValuesSize = (uint)(1 * sizeof(DUCE.ResourceHandle) * _samplerCount); channel.BeginCommand( (byte *)&data, sizeof(DUCE.MILCMD_SHADEREFFECT), (int)(data.ShaderConstantFloatRegistersSize + data.DependencyPropertyFloatValuesSize + data.ShaderConstantIntRegistersSize + data.DependencyPropertyIntValuesSize + data.ShaderConstantBoolRegistersSize + data.DependencyPropertyBoolValuesSize + data.ShaderSamplerRegistrationInfoSize + data.DependencyPropertySamplerValuesSize) ); // Arrays appear in this order: // 1) float register indices // 2) float dp values // 3) int register indices // 4) int dp values // 5) bool register indices // 6) bool dp values // 7) sampler registration info // 8) sampler dp values // 1) float register indices AppendRegisters(channel, _floatRegisters); // 2) float dp values if (_floatRegisters != null) { for (int i = 0; i < _floatRegisters.Count; i++) { MilColorF?v = _floatRegisters[i]; if (v.HasValue) { MilColorF valueToPush = v.Value; channel.AppendCommandData((byte *)&valueToPush, sizeof(MilColorF)); } } } // 3) int register indices AppendRegisters(channel, _intRegisters); // 4) int dp values if (_intRegisters != null) { for (int i = 0; i < _intRegisters.Count; i++) { MilColorI?v = _intRegisters[i]; if (v.HasValue) { MilColorI valueToPush = v.Value; channel.AppendCommandData((byte *)&valueToPush, sizeof(MilColorI)); } } } // 5) bool register indices AppendRegisters(channel, _boolRegisters); // 6) bool dp values if (_boolRegisters != null) { for (int i = 0; i < _boolRegisters.Count; i++) { bool?v = _boolRegisters[i]; if (v.HasValue) { // // Note: need 4 bytes for the bool, because the render thread // unmarshals it into a 4-byte BOOL. See the comment above for // DependencyPropertyBoolValuesSize for more details. // Int32 valueToPush = v.Value ? 1 : 0; channel.AppendCommandData((byte *)&valueToPush, sizeof(Int32)); } } } // 7) sampler registration info if (_samplerCount > 0) { int count = _samplerData.Count; for (int i = 0; i < count; i++) { SamplerData?ssn = _samplerData[i]; if (ssn.HasValue) { SamplerData ss = ssn.Value; // add as a 2-tuple (SamplerRegisterIndex, // SamplingMode) channel.AppendCommandData((byte *)&i, sizeof(int)); int value = (int)(ss._samplingMode); channel.AppendCommandData((byte *)&value, sizeof(int)); } } } // 8) sampler dp values if (_samplerCount > 0) { for (int i = 0; i < _samplerData.Count; i++) { SamplerData?ssn = _samplerData[i]; if (ssn.HasValue) { SamplerData ss = ssn.Value; // Making this assumption by storing a collection of // handles as an Int32Collection Debug.Assert(sizeof(DUCE.ResourceHandle) == sizeof(Int32)); DUCE.ResourceHandle hBrush = ss._brush != null ? ((DUCE.IResource)ss._brush).GetHandle(channel) : DUCE.ResourceHandle.Null; Debug.Assert(!hBrush.IsNull || ss._brush == null, "If brush isn't null, hBrush better not be"); channel.AppendCommandData((byte *)&hBrush, sizeof(DUCE.ResourceHandle)); } } } // That's it... channel.EndCommand(); } } } }
private void AddResourceRow(ShaderReflection shaderDetails, VulkanPipelineState.ShaderStage stage, int bindset, int bind, VulkanPipelineState.Pipeline pipe, TreelistView.TreeListView resources, FetchTexture[] texs, FetchBuffer[] bufs, ref Dictionary<ResourceId, SamplerData> samplers) { ShaderResource shaderRes = null; BindpointMap bindMap = null; bool isrw = false; uint bindPoint = 0; if (shaderDetails != null) { for (int i = 0; i < shaderDetails.ReadOnlyResources.Length; i++) { var ro = shaderDetails.ReadOnlyResources[i]; if (stage.BindpointMapping.ReadOnlyResources[ro.bindPoint].bindset == bindset && stage.BindpointMapping.ReadOnlyResources[ro.bindPoint].bind == bind) { bindPoint = (uint)i; shaderRes = ro; bindMap = stage.BindpointMapping.ReadOnlyResources[ro.bindPoint]; } } for (int i = 0; i < shaderDetails.ReadWriteResources.Length; i++) { var rw = shaderDetails.ReadWriteResources[i]; if (stage.BindpointMapping.ReadWriteResources[rw.bindPoint].bindset == bindset && stage.BindpointMapping.ReadWriteResources[rw.bindPoint].bind == bind) { bindPoint = (uint)i; isrw = true; shaderRes = rw; bindMap = stage.BindpointMapping.ReadWriteResources[rw.bindPoint]; } } } VulkanPipelineState.Pipeline.DescriptorSet.DescriptorBinding.BindingElement[] slotBinds = null; ShaderBindType bindType = ShaderBindType.Unknown; ShaderStageBits stageBits = (ShaderStageBits)0; if (bindset < pipe.DescSets.Length && bind < pipe.DescSets[bindset].bindings.Length) { slotBinds = pipe.DescSets[bindset].bindings[bind].binds; bindType = pipe.DescSets[bindset].bindings[bind].type; stageBits = pipe.DescSets[bindset].bindings[bind].stageFlags; } else { if (shaderRes.IsSampler) bindType = ShaderBindType.Sampler; else if (shaderRes.IsSampler && shaderRes.IsTexture) bindType = ShaderBindType.ImageSampler; else if (shaderRes.resType == ShaderResourceType.Buffer) bindType = ShaderBindType.ReadOnlyTBuffer; else bindType = ShaderBindType.ReadOnlyImage; } bool usedSlot = bindMap != null && bindMap.used; bool stageBitsIncluded = stageBits.HasFlag((ShaderStageBits)(1 << (int)stage.stage)); // skip descriptors that aren't for this shader stage if (!usedSlot && !stageBitsIncluded) return; if (bindType == ShaderBindType.ConstantBuffer) return; // TODO - check compatibility between bindType and shaderRes.resType ? // consider it filled if any array element is filled bool filledSlot = false; for (int idx = 0; slotBinds != null && idx < slotBinds.Length; idx++) { filledSlot |= slotBinds[idx].res != ResourceId.Null; if (bindType == ShaderBindType.Sampler || bindType == ShaderBindType.ImageSampler) filledSlot |= slotBinds[idx].sampler != ResourceId.Null; } // if it's masked out by stage bits, act as if it's not filled, so it's marked in red if (!stageBitsIncluded) filledSlot = false; // show if if (usedSlot || // it's referenced by the shader - regardless of empty or not (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled" (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty" ) { TreelistView.NodeCollection parentNodes = resources.Nodes; string setname = bindset.ToString(); string slotname = bind.ToString(); if (shaderRes != null && shaderRes.name.Length > 0) slotname += ": " + shaderRes.name; int arrayLength = 0; if (slotBinds != null) arrayLength = slotBinds.Length; else arrayLength = (int)bindMap.arraySize; // for arrays, add a parent element that we add the real cbuffers below if (arrayLength > 1) { var node = parentNodes.Add(new object[] { "", setname, slotname, String.Format("Array[{0}]", arrayLength), "", "", "", "" }); node.TreeColumn = 0; if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); parentNodes = node.Nodes; } for (int idx = 0; idx < arrayLength; idx++) { VulkanPipelineState.Pipeline.DescriptorSet.DescriptorBinding.BindingElement descriptorBind = null; if (slotBinds != null) descriptorBind = slotBinds[idx]; if (arrayLength > 1) { slotname = String.Format("{0}[{1}]", bind, idx); if (shaderRes != null && shaderRes.name.Length > 0) slotname += ": " + shaderRes.name; } bool isbuf = false; UInt32 w = 1, h = 1, d = 1; UInt32 a = 1; UInt32 samples = 1; UInt64 len = 0; string format = "Unknown"; string name = "Empty"; ShaderResourceType restype = ShaderResourceType.None; object tag = null; bool viewDetails = false; if (filledSlot && descriptorBind != null) { name = "Object " + descriptorBind.res.ToString(); format = descriptorBind.viewfmt.ToString(); // check to see if it's a texture for (int t = 0; t < texs.Length; t++) { if (texs[t].ID == descriptorBind.res) { w = texs[t].width; h = texs[t].height; d = texs[t].depth; a = texs[t].arraysize; name = texs[t].name; restype = texs[t].resType; samples = texs[t].msSamp; if (HasImportantViewParams(descriptorBind, texs[t])) viewDetails = true; tag = new ViewTexTag( descriptorBind.viewfmt, descriptorBind.baseMip, descriptorBind.baseLayer, descriptorBind.numMip, descriptorBind.numLayer, texs[t] ); } } // if not a texture, it must be a buffer for (int t = 0; t < bufs.Length; t++) { if (bufs[t].ID == descriptorBind.res) { len = bufs[t].length; w = 0; h = 0; d = 0; a = 0; name = bufs[t].name; restype = ShaderResourceType.Buffer; ulong descriptorLen = descriptorBind.size; if(descriptorLen == ulong.MaxValue) descriptorLen = len - descriptorBind.offset; tag = new BufferResTag(isrw, bindPoint, bufs[t].ID, descriptorBind.offset, descriptorLen); if (HasImportantViewParams(descriptorBind, bufs[t])) viewDetails = true; isbuf = true; } } } else { name = "Empty"; format = "-"; w = h = d = a = 0; } TreelistView.Node node = null; if (bindType == ShaderBindType.ReadWriteBuffer || bindType == ShaderBindType.ReadOnlyTBuffer || bindType == ShaderBindType.ReadWriteTBuffer ) { if (!isbuf) { node = parentNodes.Add(new object[] { "", bindset, slotname, bindType, "-", "-", "", }); EmptyRow(node); } else { string range = "-"; if (descriptorBind != null) range = String.Format("{0} - {1}", descriptorBind.offset, descriptorBind.size); node = parentNodes.Add(new object[] { "", bindset, slotname, bindType, name, String.Format("{0} bytes", len), range, }); node.Image = global::renderdocui.Properties.Resources.action; node.HoverImage = global::renderdocui.Properties.Resources.action_hover; node.Tag = tag; if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); } } else if (bindType == ShaderBindType.Sampler) { if (descriptorBind == null || descriptorBind.sampler == ResourceId.Null) { node = parentNodes.Add(new object[] { "", bindset, slotname, bindType, "-", "-", "", }); EmptyRow(node); } else { node = parentNodes.Add(MakeSampler(bindset.ToString(), slotname, descriptorBind)); if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); var data = new SamplerData(node); node.Tag = data; if (!samplers.ContainsKey(descriptorBind.sampler)) samplers.Add(descriptorBind.sampler, data); } } else { if (descriptorBind == null || descriptorBind.res == ResourceId.Null) { node = parentNodes.Add(new object[] { "", bindset, slotname, bindType, "-", "-", "", }); EmptyRow(node); } else { string typename = restype.Str() + " " + bindType.Str().Replace("&", "&&"); string dim; if (restype == ShaderResourceType.Texture3D) dim = String.Format("{0}x{1}x{2}", w, h, d); else if (restype == ShaderResourceType.Texture1D || restype == ShaderResourceType.Texture1DArray) dim = w.ToString(); else dim = String.Format("{0}x{1}", w, h); if (descriptorBind.swizzle[0] != TextureSwizzle.Red || descriptorBind.swizzle[1] != TextureSwizzle.Green || descriptorBind.swizzle[2] != TextureSwizzle.Blue || descriptorBind.swizzle[3] != TextureSwizzle.Alpha) { format += String.Format(" swizzle[{0}{1}{2}{3}]", descriptorBind.swizzle[0].Str(), descriptorBind.swizzle[1].Str(), descriptorBind.swizzle[2].Str(), descriptorBind.swizzle[3].Str()); } if (restype == ShaderResourceType.Texture1DArray || restype == ShaderResourceType.Texture2DArray || restype == ShaderResourceType.Texture2DMSArray || restype == ShaderResourceType.TextureCubeArray) { dim += String.Format(" {0}[{1}]", restype.Str(), a); } if (restype == ShaderResourceType.Texture2DMS || restype == ShaderResourceType.Texture2DMSArray) dim += String.Format(", {0}x MSAA", samples); node = parentNodes.Add(new object[] { "", bindset, slotname, typename, name, dim, format, }); node.Image = global::renderdocui.Properties.Resources.action; node.HoverImage = global::renderdocui.Properties.Resources.action_hover; node.Tag = tag; if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); ViewDetailsRow(node, viewDetails); } if (bindType == ShaderBindType.ImageSampler) { if (descriptorBind == null || descriptorBind.sampler == ResourceId.Null) { node = parentNodes.Add(new object[] { "", bindset, slotname, bindType, "-", "-", "", }); EmptyRow(node); } else { var texnode = node; if (!samplers.ContainsKey(descriptorBind.sampler)) { node = parentNodes.Add(MakeSampler("", "", descriptorBind)); if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); var data = new SamplerData(node); node.Tag = data; samplers.Add(descriptorBind.sampler, data); } if (texnode != null) { m_CombinedImageSamplers[texnode] = samplers[descriptorBind.sampler].node; samplers[descriptorBind.sampler].images.Add(texnode); } } } } } } }
public Sampler(SamplerData data) { _data = data; _samplerRes = this.CreateResource(ResourceType.RT_Sampler); RegisterUpdateResource(); }
public void UpdateSampler(IResource res, ref SamplerData data) { _resourceManager.UpdateSampler(res, ref data); }
// Set a shader stage's resources and values private void SetShaderState(FetchTexture[] texs, FetchBuffer[] bufs, VulkanPipelineState.ShaderStage stage, VulkanPipelineState.Pipeline pipe, Label shader, TreelistView.TreeListView resources, TreelistView.TreeListView cbuffers) { ShaderReflection shaderDetails = stage.ShaderDetails; if (stage.Shader == ResourceId.Null) shader.Text = "Unbound"; else shader.Text = stage.ShaderName; if (shaderDetails != null && shaderDetails.DebugInfo.entryFunc.Length > 0) { if (shaderDetails.DebugInfo.files.Length > 0 || shaderDetails.DebugInfo.entryFunc != "main") shader.Text = shaderDetails.DebugInfo.entryFunc + "()"; if (shaderDetails.DebugInfo.files.Length > 0) { string shaderfn = ""; int entryFile = shaderDetails.DebugInfo.entryFile; if (entryFile < 0 || entryFile >= shaderDetails.DebugInfo.files.Length) entryFile = 0; shaderfn = shaderDetails.DebugInfo.files[entryFile].BaseFilename; shader.Text += " - " + shaderfn; } } int vs = 0; vs = resources.VScrollValue(); resources.BeginUpdate(); resources.Nodes.Clear(); var samplers = new Dictionary<ResourceId, SamplerData>(); for(int bindset = 0; bindset < pipe.DescSets.Length; bindset++) { for(int bind = 0; bind < pipe.DescSets[bindset].bindings.Length; bind++) { ShaderResource shaderRes = null; BindpointMap bindMap = null; bool isrw = false; uint bindPoint = 0; if (shaderDetails != null) { for(int i=0; i < shaderDetails.ReadOnlyResources.Length; i++) { var ro = shaderDetails.ReadOnlyResources[i]; if (stage.BindpointMapping.ReadOnlyResources[ro.bindPoint].bindset == bindset && stage.BindpointMapping.ReadOnlyResources[ro.bindPoint].bind == bind) { bindPoint = (uint)i; shaderRes = ro; bindMap = stage.BindpointMapping.ReadOnlyResources[ro.bindPoint]; } } for(int i=0; i < shaderDetails.ReadWriteResources.Length; i++) { var rw = shaderDetails.ReadWriteResources[i]; if (stage.BindpointMapping.ReadWriteResources[rw.bindPoint].bindset == bindset && stage.BindpointMapping.ReadWriteResources[rw.bindPoint].bind == bind) { bindPoint = (uint)i; isrw = true; shaderRes = rw; bindMap = stage.BindpointMapping.ReadWriteResources[rw.bindPoint]; } } } VulkanPipelineState.Pipeline.DescriptorSet.DescriptorBinding.BindingElement[] slotBinds = pipe.DescSets[bindset].bindings[bind].binds; ShaderBindType bindType = pipe.DescSets[bindset].bindings[bind].type; ShaderStageBits stageBits = pipe.DescSets[bindset].bindings[bind].stageFlags; // skip descriptors that aren't for this shader stage if (!stageBits.HasFlag((ShaderStageBits)(1 << (int)stage.stage))) continue; // these are treated as uniform buffers if (bindType == ShaderBindType.ReadOnlyBuffer) continue; // consider it filled if any array element is filled bool filledSlot = false; for (int idx = 0; idx < slotBinds.Length; idx++) { filledSlot |= slotBinds[idx].res != ResourceId.Null; if(bindType == ShaderBindType.Sampler || bindType == ShaderBindType.ImageSampler) filledSlot |= slotBinds[idx].sampler != ResourceId.Null; } bool usedSlot = bindMap != null && bindMap.used; // show if if (usedSlot || // it's referenced by the shader - regardless of empty or not (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled" (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty" ) { TreelistView.NodeCollection parentNodes = resources.Nodes; string setname = bindset.ToString(); string slotname = bind.ToString(); if(shaderRes != null) slotname += ": " + shaderRes.name; // for arrays, add a parent element that we add the real cbuffers below if (slotBinds.Length > 1) { var node = parentNodes.Add(new object[] { "", setname, slotname, String.Format("Array[{0}]", slotBinds.Length), "", "", "", "" }); node.TreeColumn = 0; if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); parentNodes = node.Nodes; } for (int idx = 0; idx < slotBinds.Length; idx++) { var descriptorBind = slotBinds[idx]; if (slotBinds.Length > 1) { slotname = String.Format("{0}[{1}]", bind, idx); if (shaderRes != null && shaderRes.name.Length > 0) slotname += ": " + shaderRes.name; } bool isbuf = false; UInt32 w = 1, h = 1, d = 1; UInt32 a = 1; UInt32 samples = 1; UInt64 len = 0; string format = "Unknown"; string name = "Object " + descriptorBind.res.ToString(); ShaderResourceType restype = ShaderResourceType.None; object tag = null; if (!filledSlot) { name = "Empty"; format = "-"; w = h = d = a = 0; } // check to see if it's a texture for (int t = 0; t < texs.Length; t++) { if (texs[t].ID == descriptorBind.res) { w = texs[t].width; h = texs[t].height; d = texs[t].depth; a = texs[t].arraysize; format = texs[t].format.ToString(); name = texs[t].name; restype = texs[t].resType; samples = texs[t].msSamp; tag = texs[t]; } } // if not a texture, it must be a buffer for (int t = 0; t < bufs.Length; t++) { if (bufs[t].ID == descriptorBind.res) { len = bufs[t].byteSize; w = bufs[t].length; h = 0; d = 0; a = 0; format = ""; name = bufs[t].name; restype = ShaderResourceType.Buffer; tag = new BufferResTag(isrw, bindPoint, bufs[t].ID); isbuf = true; } } TreelistView.Node node = null; if (bindType == ShaderBindType.ReadWriteBuffer || bindType == ShaderBindType.ReadOnlyTBuffer || bindType == ShaderBindType.ReadWriteTBuffer ) { if (!isbuf) { node = parentNodes.Add(new object[] { "", bindset, slotname, bindType, "-", "-", "", "", }); EmptyRow(node); } else { node = parentNodes.Add(new object[] { "", bindset, slotname, bindType, name, String.Format("{0} bytes", len), String.Format("{0} - {1}", descriptorBind.offset, descriptorBind.size), "", }); node.Image = global::renderdocui.Properties.Resources.action; node.HoverImage = global::renderdocui.Properties.Resources.action_hover; node.Tag = tag; if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); } } else if (bindType == ShaderBindType.Sampler) { if (descriptorBind.sampler == ResourceId.Null) { node = parentNodes.Add(new object[] { "", bindset, slotname, bindType, "-", "-", "", "", }); EmptyRow(node); } else { node = parentNodes.Add(MakeSampler(bindset.ToString(), slotname, descriptorBind)); if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); var data = new SamplerData(node); node.Tag = data; if (!samplers.ContainsKey(descriptorBind.sampler)) samplers.Add(descriptorBind.sampler, data); } } else { if (descriptorBind.res == ResourceId.Null) { node = parentNodes.Add(new object[] { "", bindset, slotname, bindType, "-", "-", "", "", }); EmptyRow(node); } else { string typename = restype.Str() + " " + bindType.Str().Replace("&", "&&"); string dim; if (restype == ShaderResourceType.Texture3D) dim = String.Format("{0}x{1}x{2}", w, h, d); else if (restype == ShaderResourceType.Texture1D || restype == ShaderResourceType.Texture1DArray) dim = w.ToString(); else dim = String.Format("{0}x{1}", w, h); string arraydim = "-"; if(restype == ShaderResourceType.Texture1DArray || restype == ShaderResourceType.Texture2DArray || restype == ShaderResourceType.Texture2DMSArray || restype == ShaderResourceType.TextureCubeArray) arraydim = String.Format("{0}[{1}]", restype.Str(), a); if (restype == ShaderResourceType.Texture2DMS || restype == ShaderResourceType.Texture2DMSArray) dim += String.Format(", {0}x MSAA", samples); node = parentNodes.Add(new object[] { "", bindset, slotname, typename, name, dim, format, arraydim, }); node.Image = global::renderdocui.Properties.Resources.action; node.HoverImage = global::renderdocui.Properties.Resources.action_hover; node.Tag = tag; if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); } if (bindType == ShaderBindType.ImageSampler) { if (descriptorBind.sampler == ResourceId.Null) { node = parentNodes.Add(new object[] { "", bindset, slotname, bindType, "-", "-", "", "", }); EmptyRow(node); } else { var texnode = node; if (!samplers.ContainsKey(descriptorBind.sampler)) { node = parentNodes.Add(MakeSampler("", "", descriptorBind)); if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); var data = new SamplerData(node); node.Tag = data; samplers.Add(descriptorBind.sampler, data); } if (texnode != null) { m_CombinedImageSamplers[texnode] = samplers[descriptorBind.sampler].node; samplers[descriptorBind.sampler].images.Add(texnode); } } } } } } } } resources.EndUpdate(); resources.NodesSelection.Clear(); resources.SetVScrollValue(vs); vs = cbuffers.VScrollValue(); cbuffers.BeginUpdate(); cbuffers.Nodes.Clear(); for(int bindset = 0; bindset < pipe.DescSets.Length; bindset++) { for(int bind = 0; bind < pipe.DescSets[bindset].bindings.Length; bind++) { ConstantBlock cblock = null; BindpointMap bindMap = null; uint slot = uint.MaxValue; if (shaderDetails != null) { for (slot = 0; slot < (uint)shaderDetails.ConstantBlocks.Length; slot++) { ConstantBlock cb = shaderDetails.ConstantBlocks[slot]; if (stage.BindpointMapping.ConstantBlocks[cb.bindPoint].bindset == bindset && stage.BindpointMapping.ConstantBlocks[cb.bindPoint].bind == bind) { cblock = cb; bindMap = stage.BindpointMapping.ConstantBlocks[cb.bindPoint]; break; } } if (slot >= (uint)shaderDetails.ConstantBlocks.Length) slot = uint.MaxValue; } var slotBinds = pipe.DescSets[bindset].bindings[bind].binds; ShaderBindType bindType = pipe.DescSets[bindset].bindings[bind].type; ShaderStageBits stageBits = pipe.DescSets[bindset].bindings[bind].stageFlags; // skip descriptors that aren't for this shader stage if (!stageBits.HasFlag((ShaderStageBits)(1 << (int)stage.stage))) continue; // these are treated as uniform buffers if (bindType != ShaderBindType.ReadOnlyBuffer) continue; bool usedSlot = bindMap != null && bindMap.used; // consider it filled if any array element is filled (or it's push constants) bool filledSlot = cblock != null && !cblock.bufferBacked; for (int idx = 0; idx < slotBinds.Length; idx++) filledSlot |= slotBinds[idx].res != ResourceId.Null; // show if if (usedSlot || // it's referenced by the shader - regardless of empty or not (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled" (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty" ) { TreelistView.NodeCollection parentNodes = cbuffers.Nodes; string setname = bindset.ToString(); string slotname = bind.ToString(); if (cblock != null && cblock.name.Length > 0) slotname += ": " + cblock.name; // for arrays, add a parent element that we add the real cbuffers below if (slotBinds.Length > 1) { var node = parentNodes.Add(new object[] { "", setname, slotname, String.Format("Array[{0}]", slotBinds.Length), "", "" }); node.TreeColumn = 0; if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); parentNodes = node.Nodes; } for (int idx = 0; idx < slotBinds.Length; idx++) { var descriptorBind = slotBinds[idx]; if (slotBinds.Length > 1) { slotname = String.Format("{0}[{1}]", bind, idx); if (cblock != null && cblock.name.Length > 0) slotname += ": " + cblock.name; } string name = "UBO " + descriptorBind.res.ToString(); UInt64 length = descriptorBind.size; int numvars = cblock != null ? cblock.variables.Length : 0; if (!filledSlot) { name = "Empty"; length = 0; } for (int t = 0; t < bufs.Length; t++) if (bufs[t].ID == descriptorBind.res) name = bufs[t].name; if (name == "") name = "UBO " + descriptorBind.res.ToString(); string sizestr = String.Format("{0} Variables, {1} bytes", numvars, length); string vecrange = String.Format("{0} - {1}", descriptorBind.offset, descriptorBind.offset + descriptorBind.size); // push constants if (cblock != null && !cblock.bufferBacked) { setname = ""; slotname = cblock.name; name = "Push constants"; vecrange = ""; sizestr = String.Format("{0} Variables", numvars); // could maybe get range from ShaderVariable.reg if it's filled out // from SPIR-V side. } var node = parentNodes.Add(new object[] { "", setname, slotname, name, vecrange, sizestr }); node.Image = global::renderdocui.Properties.Resources.action; node.HoverImage = global::renderdocui.Properties.Resources.action_hover; node.Tag = new CBufferTag(slot, (uint)idx); if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); } } } } // search for push constants and add them last if (shaderDetails != null) { for (int cb = 0; cb < shaderDetails.ConstantBlocks.Length; cb++) { var cblock = shaderDetails.ConstantBlocks[cb]; if (cblock.bufferBacked == false) { // could maybe get range from ShaderVariable.reg if it's filled out // from SPIR-V side. var node = cbuffers.Nodes.Add(new object[] { "", "", cblock.name, "Push constants", "", String.Format("{0} Variables", cblock.variables.Length) }); node.Image = global::renderdocui.Properties.Resources.action; node.HoverImage = global::renderdocui.Properties.Resources.action_hover; node.Tag = new CBufferTag((uint)cb, 0); } } } cbuffers.EndUpdate(); cbuffers.NodesSelection.Clear(); cbuffers.SetVScrollValue(vs); }